[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: ['https://raw.githubusercontent.com/wiki/liuyangming/ByteTCC/resources/donation/liuyangming%40alipay.png', 'https://raw.githubusercontent.com/wiki/liuyangming/ByteTCC/resources/donation/liuyangming%40weixin.png'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".gitignore",
    "content": "*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n.settings\n/bytejta-core/.classpath\n/bytejta-core/.project\n/bytejta-core/.gitignore\n/bytejta-supports/.classpath\n/bytejta-supports/.gitignore\n/bytejta-supports/.project\ntarget\n/bytejta-supports-dubbo/.classpath\n/bytejta-supports-dubbo/.project\n/bytejta-supports-springcloud/.classpath\n/bytejta-supports-springcloud/.project\n/bytejta-logger/.classpath\n/bytejta-logger/.project\n/bytejta-transaction-logger/.classpath\n/bytejta-transaction-logger/.project\n"
  },
  {
    "path": "LICENSE",
    "content": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\n  This version of the GNU Lesser General Public License incorporates\nthe terms and conditions of version 3 of the GNU General Public\nLicense, supplemented by the additional permissions listed below.\n\n  0. Additional Definitions.\n\n  As used herein, \"this License\" refers to version 3 of the GNU Lesser\nGeneral Public License, and the \"GNU GPL\" refers to version 3 of the GNU\nGeneral Public License.\n\n  \"The Library\" refers to a covered work governed by this License,\nother than an Application or a Combined Work as defined below.\n\n  An \"Application\" is any work that makes use of an interface provided\nby the Library, but which is not otherwise based on the Library.\nDefining a subclass of a class defined by the Library is deemed a mode\nof using an interface provided by the Library.\n\n  A \"Combined Work\" is a work produced by combining or linking an\nApplication with the Library.  The particular version of the Library\nwith which the Combined Work was made is also called the \"Linked\nVersion\".\n\n  The \"Minimal Corresponding Source\" for a Combined Work means the\nCorresponding Source for the Combined Work, excluding any source code\nfor portions of the Combined Work that, considered in isolation, are\nbased on the Application, and not on the Linked Version.\n\n  The \"Corresponding Application Code\" for a Combined Work means the\nobject code and/or source code for the Application, including any data\nand utility programs needed for reproducing the Combined Work from the\nApplication, but excluding the System Libraries of the Combined Work.\n\n  1. Exception to Section 3 of the GNU GPL.\n\n  You may convey a covered work under sections 3 and 4 of this License\nwithout being bound by section 3 of the GNU GPL.\n\n  2. Conveying Modified Versions.\n\n  If you modify a copy of the Library, and, in your modifications, a\nfacility refers to a function or data to be supplied by an Application\nthat uses the facility (other than as an argument passed when the\nfacility is invoked), then you may convey a copy of the modified\nversion:\n\n   a) under this License, provided that you make a good faith effort to\n   ensure that, in the event an Application does not supply the\n   function or data, the facility still operates, and performs\n   whatever part of its purpose remains meaningful, or\n\n   b) under the GNU GPL, with none of the additional permissions of\n   this License applicable to that copy.\n\n  3. Object Code Incorporating Material from Library Header Files.\n\n  The object code form of an Application may incorporate material from\na header file that is part of the Library.  You may convey such object\ncode under terms of your choice, provided that, if the incorporated\nmaterial is not limited to numerical parameters, data structure\nlayouts and accessors, or small macros, inline functions and templates\n(ten or fewer lines in length), you do both of the following:\n\n   a) Give prominent notice with each copy of the object code that the\n   Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the object code with a copy of the GNU GPL and this license\n   document.\n\n  4. Combined Works.\n\n  You may convey a Combined Work under terms of your choice that,\ntaken together, effectively do not restrict modification of the\nportions of the Library contained in the Combined Work and reverse\nengineering for debugging such modifications, if you also do each of\nthe following:\n\n   a) Give prominent notice with each copy of the Combined Work that\n   the Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the Combined Work with a copy of the GNU GPL and this license\n   document.\n\n   c) For a Combined Work that displays copyright notices during\n   execution, include the copyright notice for the Library among\n   these notices, as well as a reference directing the user to the\n   copies of the GNU GPL and this license document.\n\n   d) Do one of the following:\n\n       0) Convey the Minimal Corresponding Source under the terms of this\n       License, and the Corresponding Application Code in a form\n       suitable for, and under terms that permit, the user to\n       recombine or relink the Application with a modified version of\n       the Linked Version to produce a modified Combined Work, in the\n       manner specified by section 6 of the GNU GPL for conveying\n       Corresponding Source.\n\n       1) Use a suitable shared library mechanism for linking with the\n       Library.  A suitable mechanism is one that (a) uses at run time\n       a copy of the Library already present on the user's computer\n       system, and (b) will operate properly with a modified version\n       of the Library that is interface-compatible with the Linked\n       Version.\n\n   e) Provide Installation Information, but only if you would otherwise\n   be required to provide such information under section 6 of the\n   GNU GPL, and only to the extent that such information is\n   necessary to install and execute a modified version of the\n   Combined Work produced by recombining or relinking the\n   Application with a modified version of the Linked Version. (If\n   you use option 4d0, the Installation Information must accompany\n   the Minimal Corresponding Source and Corresponding Application\n   Code. If you use option 4d1, you must provide the Installation\n   Information in the manner specified by section 6 of the GNU GPL\n   for conveying Corresponding Source.)\n\n  5. Combined Libraries.\n\n  You may place library facilities that are a work based on the\nLibrary side by side in a single library together with other library\nfacilities that are not Applications and are not covered by this\nLicense, and convey such a combined library under terms of your\nchoice, if you do both of the following:\n\n   a) Accompany the combined library with a copy of the same work based\n   on the Library, uncombined with any other library facilities,\n   conveyed under the terms of this License.\n\n   b) Give prominent notice with the combined library that part of it\n   is a work based on the Library, and explaining where to find the\n   accompanying uncombined form of the same work.\n\n  6. Revised Versions of the GNU Lesser General Public License.\n\n  The Free Software Foundation may publish revised and/or new versions\nof the GNU Lesser General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\n  Each version is given a distinguishing version number. If the\nLibrary as you received it specifies that a certain numbered version\nof the GNU Lesser General Public License \"or any later version\"\napplies to it, you have the option of following the terms and\nconditions either of that published version or of any later version\npublished by the Free Software Foundation. If the Library as you\nreceived it does not specify a version number of the GNU Lesser\nGeneral Public License, you may choose any version of the GNU Lesser\nGeneral Public License ever published by the Free Software Foundation.\n\n  If the Library as you received it specifies that a proxy can decide\nwhether future versions of the GNU Lesser General Public License shall\napply, that proxy's public statement of acceptance of any version is\npermanent authorization for you to choose that version for the\nLibrary.\n\n"
  },
  {
    "path": "README-zh.md",
    "content": "﻿ByteJTA是一个基于XA/2PC机制的分布式事务管理器。实现了JTA接口，可以很好的与EJB、Spring等容器（本文档下文说明中将以Spring容器为例）进行集成。\n\n## 一、文档 & 样例\n* 使用文档： https://github.com/liuyangming/ByteJTA/wiki\n* 使用样例： https://github.com/liuyangming/ByteJTA-sample\n\n## 二、ByteJTA特性\n* 1、支持Spring容器的声明式事务管理；\n* 2、支持多数据源、跨应用、跨服务器等分布式事务场景；\n* 3、支持spring cloud；\n* 4、支持dubbo服务框架；\n\n## 三、建议及改进\n若您有任何建议，可以通过1）加入qq群537445956/606453172向群主提出，或2）发送邮件至bytefox#126.com向我反馈。本人承诺，任何建议都将会被认真考虑，优秀的建议将会被采用，但不保证一定会在当前版本中实现。\n"
  },
  {
    "path": "README.md",
    "content": "﻿\n**ByteJTA** is an implementation of Distributed Transaction Manager, based on the XA/2PC mechanism. \n\n**ByteJTA** is comptible with JTA and could be seamlessly integrated with Spring and other Java containers.\n\n\n## 1. Quick Start\n\n#### 1.1 Add maven depenency\n###### 1.1.1. Spring Cloud\n```xml\n<dependency>\n\t<groupId>org.bytesoft</groupId>\n\t<artifactId>bytejta-supports-springcloud</artifactId>\n\t<version>0.5.0-BETA9</version>\n</dependency>\n```\n###### 1.1.2. dubbo\n```xml\n<dependency>\n\t<groupId>org.bytesoft</groupId>\n\t<artifactId>bytejta-supports-dubbo</artifactId>\n\t<version>0.5.0-BETA9</version>\n</dependency>\n```\n\n\n\n## 2. Documentation & Samples\n* [Document](https://github.com/liuyangming/ByteJTA/wiki)\n* [Sample](https://github.com/liuyangming/ByteJTA-sample)\n\n\n\n## 3. Features\n* support declarative transaction management\n* support distributed transaction scenarios. e.g. multi-datasource, cross-applications and cross-servers transaction\n* support Dubbo framework\n* support Spring Cloud\n\n\n\n## 4. Contact Me\nIf you have any questions or comments regarding this project, please feel free to contact me at:\n\n1. send mail to _[bytefox#126.com](bytefox@126.com)_\n~OR~\n2. add Tecent QQ group 537445956/606453172\n\nWe will review all the suggestions and implement good ones in future release.\n"
  },
  {
    "path": "bytejta-core/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.bytesoft</groupId>\n\t\t<artifactId>bytejta-parent</artifactId>\n\t\t<version>0.5.0-BETA9</version>\n\t</parent>\n\t<artifactId>bytejta-core</artifactId>\n\n\t<packaging>jar</packaging>\n\n\t<name>bytejta-core</name>\n\t<description>The bytejta-core project is the core module of ByteJTA.</description>\n\t<url>http://www.bytesoft.org</url>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>javax.transaction</groupId>\n\t\t\t<artifactId>javax.transaction-api</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.jms</groupId>\n\t\t\t<artifactId>javax.jms-api</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.resource</groupId>\n\t\t\t<artifactId>javax.resource-api</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-io</groupId>\n\t\t\t<artifactId>commons-io</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.caucho</groupId>\n\t\t\t<artifactId>hessian</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.esotericsoftware</groupId>\n\t\t\t<artifactId>kryo</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>javax.annotation</groupId>\n\t\t\t<artifactId>javax.annotation-api</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.inject</groupId>\n\t\t\t<artifactId>javax.inject</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionBeanFactoryImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionLock;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.TransactionRecovery;\nimport org.bytesoft.transaction.TransactionRepository;\nimport org.bytesoft.transaction.logging.ArchiveDeserializer;\nimport org.bytesoft.transaction.logging.TransactionLogger;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.supports.TransactionTimer;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;\nimport org.bytesoft.transaction.xa.XidFactory;\n\npublic class TransactionBeanFactoryImpl implements TransactionBeanFactory {\n\tprivate static final TransactionBeanFactoryImpl instance = new TransactionBeanFactoryImpl();\n\n\tprivate TransactionManager transactionManager;\n\tprivate XidFactory xidFactory;\n\tprivate TransactionTimer transactionTimer;\n\tprivate TransactionLogger transactionLogger;\n\tprivate TransactionRepository transactionRepository;\n\tprivate TransactionInterceptor transactionInterceptor;\n\tprivate TransactionRecovery transactionRecovery;\n\tprivate RemoteCoordinator transactionCoordinator;\n\tprivate TransactionLock transactionLock;\n\n\tprivate ArchiveDeserializer archiveDeserializer;\n\tprivate XAResourceDeserializer resourceDeserializer;\n\n\tprivate TransactionBeanFactoryImpl() {\n\t\tif (instance != null) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic static TransactionBeanFactoryImpl getInstance() {\n\t\treturn instance;\n\t}\n\n\tpublic TransactionManager getTransactionManager() {\n\t\treturn transactionManager;\n\t}\n\n\tpublic void setTransactionManager(TransactionManager transactionManager) {\n\t\tthis.transactionManager = transactionManager;\n\t}\n\n\tpublic XidFactory getXidFactory() {\n\t\treturn xidFactory;\n\t}\n\n\tpublic void setXidFactory(XidFactory xidFactory) {\n\t\tthis.xidFactory = xidFactory;\n\t}\n\n\tpublic TransactionTimer getTransactionTimer() {\n\t\treturn transactionTimer;\n\t}\n\n\tpublic void setTransactionTimer(TransactionTimer transactionTimer) {\n\t\tthis.transactionTimer = transactionTimer;\n\t}\n\n\tpublic TransactionRepository getTransactionRepository() {\n\t\treturn transactionRepository;\n\t}\n\n\tpublic void setTransactionRepository(TransactionRepository transactionRepository) {\n\t\tthis.transactionRepository = transactionRepository;\n\t}\n\n\tpublic TransactionInterceptor getTransactionInterceptor() {\n\t\treturn transactionInterceptor;\n\t}\n\n\tpublic void setTransactionInterceptor(TransactionInterceptor transactionInterceptor) {\n\t\tthis.transactionInterceptor = transactionInterceptor;\n\t}\n\n\tpublic TransactionLock getTransactionLock() {\n\t\treturn transactionLock;\n\t}\n\n\tpublic void setTransactionLock(TransactionLock transactionLock) {\n\t\tthis.transactionLock = transactionLock;\n\t}\n\n\tpublic TransactionRecovery getTransactionRecovery() {\n\t\treturn transactionRecovery;\n\t}\n\n\tpublic void setTransactionRecovery(TransactionRecovery transactionRecovery) {\n\t\tthis.transactionRecovery = transactionRecovery;\n\t}\n\n\tpublic RemoteCoordinator getNativeParticipant() {\n\t\treturn transactionCoordinator;\n\t}\n\n\tpublic void setTransactionCoordinator(RemoteCoordinator remoteCoordinator) {\n\t\tthis.transactionCoordinator = remoteCoordinator;\n\t}\n\n\tpublic TransactionLogger getTransactionLogger() {\n\t\treturn transactionLogger;\n\t}\n\n\tpublic void setTransactionLogger(TransactionLogger transactionLogger) {\n\t\tthis.transactionLogger = transactionLogger;\n\t}\n\n\tpublic ArchiveDeserializer getArchiveDeserializer() {\n\t\treturn archiveDeserializer;\n\t}\n\n\tpublic void setArchiveDeserializer(ArchiveDeserializer archiveDeserializer) {\n\t\tthis.archiveDeserializer = archiveDeserializer;\n\t}\n\n\tpublic XAResourceDeserializer getResourceDeserializer() {\n\t\treturn resourceDeserializer;\n\t}\n\n\tpublic void setResourceDeserializer(XAResourceDeserializer resourceDeserializer) {\n\t\tthis.resourceDeserializer = resourceDeserializer;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionCoordinator.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.bytejta;\r\n\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\nimport java.util.concurrent.locks.Lock;\r\nimport java.util.concurrent.locks.ReentrantLock;\r\n\r\nimport javax.transaction.HeuristicMixedException;\r\nimport javax.transaction.HeuristicRollbackException;\r\nimport javax.transaction.RollbackException;\r\nimport javax.transaction.Status;\r\nimport javax.transaction.SystemException;\r\nimport javax.transaction.xa.XAException;\r\nimport javax.transaction.xa.XAResource;\r\nimport javax.transaction.xa.Xid;\r\n\r\nimport org.bytesoft.common.utils.ByteUtils;\r\nimport org.bytesoft.common.utils.CommonUtils;\r\nimport org.bytesoft.transaction.CommitRequiredException;\r\nimport org.bytesoft.transaction.RollbackRequiredException;\r\nimport org.bytesoft.transaction.Transaction;\r\nimport org.bytesoft.transaction.TransactionBeanFactory;\r\nimport org.bytesoft.transaction.TransactionContext;\r\nimport org.bytesoft.transaction.TransactionException;\r\nimport org.bytesoft.transaction.TransactionManager;\r\nimport org.bytesoft.transaction.TransactionRepository;\r\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\r\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\r\nimport org.bytesoft.transaction.remote.RemoteAddr;\r\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\r\nimport org.bytesoft.transaction.remote.RemoteNode;\r\nimport org.bytesoft.transaction.xa.TransactionXid;\r\nimport org.bytesoft.transaction.xa.XidFactory;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\npublic class TransactionCoordinator implements RemoteCoordinator, TransactionBeanFactoryAware, TransactionEndpointAware {\r\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionCoordinator.class);\r\n\r\n\t@javax.inject.Inject\r\n\tprivate TransactionBeanFactory beanFactory;\r\n\tprivate String endpoint;\r\n\r\n\tprivate transient boolean ready = false;\r\n\tprivate final Lock lock = new ReentrantLock();\r\n\r\n\tpublic Transaction getTransactionQuietly() {\r\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\r\n\t\treturn transactionManager.getTransactionQuietly();\r\n\t}\r\n\r\n\tpublic Transaction start(TransactionContext transactionContext, int flags) throws XAException {\r\n\r\n\t\tTransactionRepository transactionRepository = this.beanFactory.getTransactionRepository();\r\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\r\n\t\tif (transactionManager.getTransactionQuietly() != null) {\r\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\r\n\t\t}\r\n\r\n\t\tTransactionXid globalXid = (TransactionXid) transactionContext.getXid();\r\n\t\tTransaction transaction = null;\r\n\t\ttry {\r\n\t\t\ttransaction = transactionRepository.getTransaction(globalXid);\r\n\t\t} catch (TransactionException tex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\r\n\t\tif (transaction == null) {\r\n\t\t\ttransaction = new TransactionImpl(transactionContext);\r\n\t\t\t((TransactionImpl) transaction).setBeanFactory(this.beanFactory);\r\n\r\n\t\t\tlong expired = transactionContext.getExpiredTime();\r\n\t\t\tlong current = System.currentTimeMillis();\r\n\t\t\tlong timeoutMillis = (expired - current) / 1000L;\r\n\t\t\ttransaction.setTransactionTimeout((int) timeoutMillis);\r\n\r\n\t\t\ttransactionRepository.putTransaction(globalXid, transaction);\r\n\t\t\tlogger.info(\"{}> begin-participant\", ByteUtils.byteArrayToString(globalXid.getGlobalTransactionId()));\r\n\t\t}\r\n\r\n\t\ttransactionManager.associateThread(transaction);\r\n\t\t// this.transactionStatistic.fireBeginTransaction(transaction);\r\n\r\n\t\treturn transaction;\r\n\t}\r\n\r\n\tpublic Transaction end(TransactionContext transactionContext, int flags) throws XAException {\r\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\r\n\t\treturn transactionManager.desociateThread();\r\n\t}\r\n\r\n\t/** supports resume only, for tcc transaction manager. */\r\n\tpublic void start(Xid xid, int flags) throws XAException {\r\n\t\tif (XAResource.TMRESUME != flags) {\r\n\t\t\tthrow new XAException(XAException.XAER_INVAL);\r\n\t\t}\r\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\r\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\r\n\t\tTransaction current = transactionManager.getTransactionQuietly();\r\n\t\tif (current != null) {\r\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\r\n\t\t}\r\n\r\n\t\tTransactionRepository transactionRepository = this.beanFactory.getTransactionRepository();\r\n\r\n\t\tTransactionXid branchXid = (TransactionXid) xid;\r\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());\r\n\r\n\t\tTransaction transaction = null;\r\n\t\ttry {\r\n\t\t\ttransaction = transactionRepository.getTransaction(globalXid);\r\n\t\t} catch (TransactionException tex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\r\n\t\tif (transaction == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_NOTA);\r\n\t\t}\r\n\t\ttransactionManager.associateThread(transaction);\r\n\t}\r\n\r\n\t/** supports suspend only, for tcc transaction manager. */\r\n\tpublic void end(Xid xid, int flags) throws XAException {\r\n\t\tif (XAResource.TMSUSPEND != flags) {\r\n\t\t\tthrow new XAException(XAException.XAER_INVAL);\r\n\t\t}\r\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\r\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\r\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\r\n\t\tif (transaction == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_NOTA);\r\n\t\t}\r\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\r\n\t\tTransactionXid transactionXid = transactionContext.getXid();\r\n\r\n\t\tTransactionXid branchXid = (TransactionXid) xid;\r\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());\r\n\r\n\t\tif (CommonUtils.equals(globalXid, transactionXid) == false) {\r\n\t\t\tthrow new XAException(XAException.XAER_INVAL);\r\n\t\t}\r\n\t\ttransactionManager.desociateThread();\r\n\t}\r\n\r\n\tpublic void commit(Xid xid, boolean onePhaseCommit) throws XAException {\r\n\t\tthis.checkParticipantReadyIfNecessary();\r\n\r\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\r\n\t\tTransactionXid branchXid = (TransactionXid) xid;\r\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());\r\n\t\tTransactionRepository repository = beanFactory.getTransactionRepository();\r\n\t\tTransaction transaction = null;\r\n\t\ttry {\r\n\t\t\ttransaction = repository.getTransaction(globalXid);\r\n\t\t} catch (TransactionException tex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\r\n\t\tif (transaction == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_NOTA);\r\n\t\t}\r\n\r\n\t\tif (onePhaseCommit) {\r\n\t\t\ttry {\r\n\t\t\t\tthis.beanFactory.getTransactionManager().associateThread(transaction);\r\n\t\t\t\ttransaction.fireBeforeTransactionCompletion();\r\n\t\t\t\tthis.beanFactory.getTransactionTimer().stopTiming(transaction);\r\n\t\t\t} catch (RollbackRequiredException rrex) {\r\n\t\t\t\tthis.rollback(xid);\r\n\t\t\t\tXAException xaex = new XAException(XAException.XA_HEURRB);\r\n\t\t\t\txaex.initCause(rrex);\r\n\t\t\t\tthrow xaex;\r\n\t\t\t} catch (SystemException ex) {\r\n\t\t\t\tthis.rollback(xid);\r\n\t\t\t\tXAException xaex = new XAException(XAException.XA_HEURRB);\r\n\t\t\t\txaex.initCause(ex);\r\n\t\t\t\tthrow xaex;\r\n\t\t\t} catch (RuntimeException rex) {\r\n\t\t\t\tthis.rollback(xid);\r\n\t\t\t\tXAException xaex = new XAException(XAException.XA_HEURRB);\r\n\t\t\t\txaex.initCause(rex);\r\n\t\t\t\tthrow xaex;\r\n\t\t\t} finally {\r\n\t\t\t\tthis.beanFactory.getTransactionManager().desociateThread();\r\n\t\t\t}\r\n\t\t} // end-if (onePhaseCommit)\r\n\r\n\t\ttry {\r\n\t\t\ttransaction.participantCommit(onePhaseCommit);\r\n\t\t\ttransaction.forgetQuietly(); // forget transaction\r\n\t\t} catch (SecurityException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (CommitRequiredException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (RollbackException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator, tx has been rolled back.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\r\n\t\t\t// don't forget if branch-transaction has been hueristic completed.\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XA_HEURRB);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (HeuristicMixedException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator, tx has been completed mixed.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\r\n\t\t\t// don't forget if branch-transaction has been hueristic completed.\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XA_HEURMIX);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (HeuristicRollbackException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator, tx has been rolled back heuristically.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\r\n\t\t\t// don't forget if branch-transaction has been hueristic completed.\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XA_HEURRB);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (SystemException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (RuntimeException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while committing remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} finally {\r\n\t\t\ttransaction.fireAfterTransactionCompletion();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void forgetQuietly(Xid xid) {\r\n\t\ttry {\r\n\t\t\tthis.forget(xid);\r\n\t\t} catch (XAException ex) {\r\n\t\t\tswitch (ex.errorCode) {\r\n\t\t\tcase XAException.XAER_NOTA:\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tlogger.error(\"{}> Error occurred while forgeting remote coordinator.\",\r\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\t}\r\n\t\t} catch (RuntimeException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while forgeting remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void forget(Xid xid) throws XAException {\r\n\t\tthis.checkParticipantReadyIfNecessary();\r\n\r\n\t\tif (xid == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_INVAL);\r\n\t\t}\r\n\r\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\r\n\t\tTransactionXid branchXid = (TransactionXid) xid;\r\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());\r\n\t\tTransactionRepository transactionRepository = beanFactory.getTransactionRepository();\r\n\t\tTransaction transaction = null;\r\n\t\ttry {\r\n\t\t\ttransaction = transactionRepository.getErrorTransaction(globalXid);\r\n\t\t} catch (TransactionException tex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\r\n\t\tif (transaction == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_NOTA);\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\ttransaction.forget();\r\n\t\t} catch (SystemException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while forgeting remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t} catch (RuntimeException rex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while forgeting remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), rex);\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic int getTransactionTimeout() throws XAException {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tpublic boolean isSameRM(XAResource xares) throws XAException {\r\n\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t}\r\n\r\n\tpublic int prepare(Xid xid) throws XAException {\r\n\t\tthis.checkParticipantReadyIfNecessary();\r\n\r\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\r\n\t\tTransactionXid branchXid = (TransactionXid) xid;\r\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());\r\n\t\tTransactionRepository repository = beanFactory.getTransactionRepository();\r\n\t\tTransaction transaction = null;\r\n\t\ttry {\r\n\t\t\ttransaction = repository.getTransaction(globalXid);\r\n\t\t} catch (TransactionException tex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\r\n\t\tif (transaction == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_NOTA);\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tthis.beanFactory.getTransactionManager().associateThread(transaction);\r\n\t\t\ttransaction.fireBeforeTransactionCompletion();\r\n\t\t\tthis.beanFactory.getTransactionTimer().stopTiming(transaction);\r\n\t\t} catch (RollbackRequiredException rrex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t} catch (SystemException ex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t} catch (RuntimeException rex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t} finally {\r\n\t\t\tthis.beanFactory.getTransactionManager().desociateThread();\r\n\t\t}\r\n\r\n\t\tint participantVote = XAResource.XA_OK;\r\n\t\ttry {\r\n\t\t\tparticipantVote = transaction.participantPrepare();\r\n\t\t} catch (CommitRequiredException crex) {\r\n\t\t\tparticipantVote = XAResource.XA_OK;\r\n\t\t} catch (RollbackRequiredException rrex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t} finally {\r\n\t\t\tif (participantVote == XAResource.XA_RDONLY) {\r\n\t\t\t\ttransaction.fireAfterTransactionCompletion();\r\n\t\t\t} // end-if (participantVote == XAResource.XA_RDONLY)\r\n\t\t}\r\n\r\n\t\treturn participantVote;\r\n\t}\r\n\r\n\tpublic Xid[] recover(int flag) throws XAException {\r\n\t\tthis.checkParticipantReadyIfNecessary();\r\n\r\n\t\tTransactionRepository repository = beanFactory.getTransactionRepository();\r\n\t\tList<Transaction> allTransactionList = repository.getActiveTransactionList();\r\n\r\n\t\tList<Transaction> transactions = new ArrayList<Transaction>();\r\n\t\tfor (int i = 0; i < allTransactionList.size(); i++) {\r\n\t\t\tTransaction transaction = allTransactionList.get(i);\r\n\t\t\tint transactionStatus = transaction.getTransactionStatus();\r\n\t\t\tif (transactionStatus == Status.STATUS_PREPARED || transactionStatus == Status.STATUS_COMMITTING\r\n\t\t\t\t\t|| transactionStatus == Status.STATUS_ROLLING_BACK || transactionStatus == Status.STATUS_COMMITTED\r\n\t\t\t\t\t|| transactionStatus == Status.STATUS_ROLLEDBACK) {\r\n\t\t\t\ttransactions.add(transaction);\r\n\t\t\t} else if (transaction.getTransactionContext().isRecoveried()) {\r\n\t\t\t\ttransactions.add(transaction);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tTransactionXid[] xidArray = new TransactionXid[transactions.size()];\r\n\t\tfor (int i = 0; i < transactions.size(); i++) {\r\n\t\t\tTransaction transaction = transactions.get(i);\r\n\t\t\txidArray[i] = transaction.getTransactionContext().getXid();\r\n\t\t}\r\n\r\n\t\treturn xidArray;\r\n\t}\r\n\r\n\tpublic void rollback(Xid xid) throws XAException {\r\n\t\tthis.checkParticipantReadyIfNecessary();\r\n\r\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\r\n\t\tTransactionXid branchXid = (TransactionXid) xid;\r\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());\r\n\t\tTransactionRepository repository = beanFactory.getTransactionRepository();\r\n\t\tTransaction transaction = null;\r\n\t\ttry {\r\n\t\t\ttransaction = repository.getTransaction(globalXid);\r\n\t\t} catch (TransactionException tex) {\r\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\r\n\t\t}\r\n\r\n\t\tif (transaction == null) {\r\n\t\t\tthrow new XAException(XAException.XAER_NOTA);\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tthis.beanFactory.getTransactionManager().associateThread(transaction);\r\n\t\t\ttransaction.fireBeforeTransactionCompletionQuietly();\r\n\t\t\tthis.beanFactory.getTransactionManager().desociateThread();\r\n\r\n\t\t\tthis.beanFactory.getTransactionTimer().stopTiming(transaction);\r\n\r\n\t\t\ttransaction.participantRollback();\r\n\t\t\ttransaction.forgetQuietly(); // forget transaction\r\n\t\t} catch (RollbackRequiredException rrex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while rolling back remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), rrex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(rrex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (SystemException ex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while rolling back remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), ex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(ex);\r\n\t\t\tthrow xaex;\r\n\t\t} catch (RuntimeException rrex) {\r\n\t\t\tlogger.error(\"{}> Error occurred while rolling back remote coordinator.\",\r\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()), rrex);\r\n\t\t\trepository.putErrorTransaction(globalXid, transaction);\r\n\r\n\t\t\tXAException xaex = new XAException(XAException.XAER_RMERR);\r\n\t\t\txaex.initCause(rrex);\r\n\t\t\tthrow xaex;\r\n\t\t} finally {\r\n\t\t\ttransaction.fireAfterTransactionCompletion();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void markParticipantReady() {\r\n\t\ttry {\r\n\t\t\tthis.lock.lock();\r\n\t\t\tthis.ready = true;\r\n\t\t} finally {\r\n\t\t\tthis.lock.unlock();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void checkParticipantReadyIfNecessary() throws XAException {\r\n\t\tif (this.ready == false) {\r\n\t\t\tthis.checkParticipantReady();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void checkParticipantReady() throws XAException {\r\n\t\ttry {\r\n\t\t\tthis.lock.lock();\r\n\t\t\tif (this.ready == false) {\r\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\r\n\t\t\t}\r\n\t\t} finally {\r\n\t\t\tthis.lock.unlock();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic boolean setTransactionTimeout(int seconds) throws XAException {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tpublic String getEndpoint() {\r\n\t\treturn endpoint;\r\n\t}\r\n\r\n\tpublic void setEndpoint(String identifier) {\r\n\t\tthis.endpoint = identifier;\r\n\t}\r\n\r\n\tpublic RemoteAddr getRemoteAddr() {\r\n\t\treturn CommonUtils.getRemoteAddr(this.endpoint);\r\n\t}\r\n\r\n\tpublic RemoteNode getRemoteNode() {\r\n\t\treturn CommonUtils.getRemoteNode(this.endpoint);\r\n\t}\r\n\r\n\tpublic String getIdentifier() {\r\n\t\treturn this.endpoint;\r\n\t}\r\n\r\n\tpublic String getApplication() {\r\n\t\treturn CommonUtils.getApplication(this.endpoint);\r\n\t}\r\n\r\n\tpublic TransactionBeanFactory getBeanFactory() {\r\n\t\treturn this.beanFactory;\r\n\t}\r\n\r\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\r\n\t\tthis.beanFactory = tbf;\r\n\t}\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.transaction.HeuristicCommitException;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.RollbackException;\nimport javax.transaction.Status;\nimport javax.transaction.Synchronization;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.resource.XATerminatorImpl;\nimport org.bytesoft.bytejta.resource.XATerminatorOptd;\nimport org.bytesoft.bytejta.strategy.CommonTransactionStrategy;\nimport org.bytesoft.bytejta.strategy.LastResourceOptimizeStrategy;\nimport org.bytesoft.bytejta.strategy.SimpleTransactionStrategy;\nimport org.bytesoft.bytejta.strategy.VacantTransactionStrategy;\nimport org.bytesoft.bytejta.supports.jdbc.LocalXAResource;\nimport org.bytesoft.bytejta.supports.resource.CommonResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.LocalXAResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.UnidentifiedResourceDescriptor;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionRepository;\nimport org.bytesoft.transaction.archive.TransactionArchive;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.internal.SynchronizationList;\nimport org.bytesoft.transaction.internal.TransactionListenerList;\nimport org.bytesoft.transaction.internal.TransactionResourceListenerList;\nimport org.bytesoft.transaction.logging.TransactionLogger;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.bytesoft.transaction.supports.TransactionExtra;\nimport org.bytesoft.transaction.supports.TransactionListener;\nimport org.bytesoft.transaction.supports.TransactionResourceListener;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionImpl implements Transaction {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionImpl.class);\n\n\tprivate transient boolean timing = true;\n\tprivate TransactionBeanFactory beanFactory;\n\n\tprivate TransactionStrategy transactionStrategy;\n\n\tprivate int transactionStatus;\n\tprivate int transactionTimeout;\n\tprivate int transactionVote;\n\tprivate TransactionExtra transactionalExtra;\n\tprivate final TransactionContext transactionContext;\n\n\tprivate final TransactionResourceListenerList resourceListenerList = new TransactionResourceListenerList();\n\n\tprivate final Map<RemoteSvc, XAResourceArchive> remoteParticipantMap = new HashMap<RemoteSvc, XAResourceArchive>();\n\tprivate final Map<String, XAResourceArchive> nativeParticipantMap = new HashMap<String, XAResourceArchive>();\n\tprivate XAResourceArchive participant; // last resource\n\tprivate final List<XAResourceArchive> participantList = new ArrayList<XAResourceArchive>();\n\tprivate final List<XAResourceArchive> nativeParticipantList = new ArrayList<XAResourceArchive>();\n\tprivate final List<XAResourceArchive> remoteParticipantList = new ArrayList<XAResourceArchive>();\n\n\tprivate final SynchronizationList synchronizationList = new SynchronizationList();\n\tprivate final TransactionListenerList transactionListenerList = new TransactionListenerList();\n\n\tprivate transient Exception createdAt;\n\n\tpublic TransactionImpl(TransactionContext txContext) {\n\t\tthis.transactionContext = txContext;\n\t}\n\n\tpublic synchronized int participantPrepare() throws RollbackRequiredException, CommitRequiredException {\n\n\t\tif (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLING_BACK) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_UNKNOWN) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_NO_TRANSACTION) {\n\t\t\t// it's impossible\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_PREPARED) {\n\t\t\tthrow new CommitRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTING) {\n\t\t\tthrow new CommitRequiredException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) {\n\t\t\tthrow new CommitRequiredException();\n\t\t} /* else active, preparing {} */\n\n\t\tTransactionLogger transactionLogger = beanFactory.getTransactionLogger();\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\n\t\tthis.transactionStatus = Status.STATUS_PREPARING;\n\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\ttransactionLogger.createTransaction(archive);\n\t\tthis.transactionListenerList.onPrepareStart(xid);\n\t\tlogger.info(\"{}> prepare-participant start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t\ttry {\n\t\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\t\tint vote = currentStrategy.prepare(xid);\n\n\t\t\tthis.transactionStatus = Status.STATUS_PREPARED;\n\t\t\tarchive.setStatus(this.transactionStatus);\n\t\t\tthis.transactionVote = vote;\n\t\t\tarchive.setVote(vote);\n\n\t\t\tthis.transactionListenerList.onPrepareSuccess(xid);\n\t\t\tlogger.info(\"{}> prepare-participant complete successfully\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\treturn vote;\n\t\t} catch (CommitRequiredException crex) {\n\t\t\tthis.transactionVote = XAResource.XA_OK;\n\t\t\tarchive.setVote(this.transactionVote);\n\n\t\t\tthis.transactionStatus = Status.STATUS_COMMITTING;\n\t\t\tarchive.setStatus(this.transactionStatus);\n\n\t\t\tthis.transactionListenerList.onPrepareSuccess(xid);\n\t\t\tlogger.info(\"{}> prepare-participant complete successfully\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\tthrow crex;\n\t\t} catch (RollbackRequiredException rrex) {\n\t\t\tthis.transactionStatus = Status.STATUS_ROLLING_BACK;\n\t\t\tarchive.setStatus(this.transactionStatus);\n\n\t\t\tthis.transactionListenerList.onPrepareFailure(xid);\n\t\t\tlogger.info(\"{}> prepare-participant failed\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\tthrow rrex;\n\t\t} catch (RuntimeException xaex) {\n\t\t\tthis.transactionStatus = Status.STATUS_ROLLING_BACK;\n\t\t\tarchive.setStatus(this.transactionStatus);\n\n\t\t\tthis.transactionListenerList.onPrepareFailure(xid);\n\t\t\tlogger.info(\"{}> prepare-participant failed\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\tRollbackRequiredException rrex = new RollbackRequiredException();\n\t\t\trrex.initCause(xaex);\n\t\t\tthrow rrex;\n\t\t} finally {\n\t\t\ttransactionLogger.updateTransaction(archive);\n\t\t}\n\t}\n\n\tpublic synchronized void recoveryCommit() throws CommitRequiredException, SystemException {\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\ttry {\n\t\t\tthis.recoverIfNecessary(); // Recover if transaction is recovered from tx-log.\n\n\t\t\tthis.transactionContext.setRecoveredTimes(this.transactionContext.getRecoveredTimes() + 1);\n\t\t\tthis.transactionContext.setCreatedTime(System.currentTimeMillis());\n\n\t\t\tthis.invokeParticipantCommit(false);\n\t\t} catch (HeuristicMixedException ex) {\n\t\t\tlogger.error(\"{}> recover: branch={}, status= mixed, message= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()),\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getBranchQualifier()), ex.getMessage(), ex);\n\t\t\tSystemException sysEx = new SystemException();\n\t\t\tsysEx.initCause(ex);\n\t\t\tthrow sysEx;\n\t\t} catch (HeuristicRollbackException ex) {\n\t\t\tlogger.error(\"{}> recover: branch={}, status= rolledback\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()),\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getBranchQualifier()), ex);\n\t\t\tSystemException sysEx = new SystemException();\n\t\t\tsysEx.initCause(ex);\n\t\t\tthrow sysEx;\n\t\t}\n\t}\n\n\t/* opc: true, compensable-transaction & remote-coordinator; false, remote-coordinator */\n\tpublic synchronized void participantCommit(boolean opc) throws RollbackException, HeuristicMixedException,\n\t\t\tHeuristicRollbackException, SecurityException, IllegalStateException, CommitRequiredException, SystemException {\n\t\tif (this.transactionContext.isRecoveried()) {\n\t\t\tthis.recover(); // Execute recoveryInit if transaction is recovered from tx-log.\n\t\t\tthis.invokeParticipantCommit(opc);\n\t\t\treturn;\n\t\t} // end-if (this.transactionContext.isRecoveried())\n\n\t\tTransaction transaction = //\n\t\t\t\tTransaction.class.isInstance(this.transactionalExtra) ? (Transaction) this.transactionalExtra : null;\n\t\tTransactionContext transactionContext = transaction == null ? null : transaction.getTransactionContext();\n\t\tTransactionXid transactionXid = transactionContext == null ? null : transactionContext.getXid();\n\t\tboolean compensable = transactionXid != null && XidFactory.TCC_FORMAT_ID == transactionXid.getFormatId();\n\t\tif (compensable) {\n\t\t\tthis.compensableOnePhaseCommit();\n\t\t} else if (opc) {\n\t\t\tthis.participantOnePhaseCommit();\n\t\t} else {\n\t\t\tthis.participantTwoPhaseCommit();\n\t\t}\n\t}\n\n\tprivate void checkForTransactionExtraIfNecessary() throws RollbackException, HeuristicMixedException,\n\t\t\tHeuristicRollbackException, SecurityException, IllegalStateException, CommitRequiredException, SystemException {\n\n\t\tif (this.transactionalExtra != null) /* for ByteTCC */ {\n\t\t\tif (this.participantList.isEmpty() == false && this.participant == null) /* see initGetTransactionStrategy */ {\n\t\t\t\tthis.participantRollback();\n\t\t\t\tthrow new HeuristicRollbackException();\n\t\t\t} else if (this.participantList.size() > 1) {\n\t\t\t\tthis.participantRollback();\n\t\t\t\tthrow new HeuristicRollbackException();\n\t\t\t}\n\t\t} // end-if (this.transactionalExtra != null)\n\n\t}\n\n\tprivate void compensableOnePhaseCommit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,\n\t\t\tSecurityException, IllegalStateException, CommitRequiredException, SystemException {\n\t\tthis.checkForTransactionExtraIfNecessary();\n\n\t\tif (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthis.participantRollback();\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLING_BACK) {\n\t\t\tthrow new HeuristicMixedException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) {\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_UNKNOWN) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_NO_TRANSACTION) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) {\n\t\t\treturn;\n\t\t} /* else active, preparing, prepared, committing {} */\n\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\ttry {\n\t\t\tthis.transactionStatus = Status.STATUS_COMMITTING;\n\t\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\t\tthis.transactionListenerList.onCommitStart(xid);\n\t\t\tlogger.info(\"{}> commit-participant start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t\t\t// transactionLogger.updateTransaction(archive); // unneccessary\n\t\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\t\tcurrentStrategy.commit(xid, true);\n\n\t\t\tthis.transactionStatus = Status.STATUS_COMMITTED; // Status.STATUS_COMMITTED;\n\t\t\tarchive.setStatus(this.transactionStatus);\n\t\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t\t\tlogger.info(\"{}> commit-participant complete successfully\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\t// transactionLogger.updateTransaction(archive); // unneccessary\n\t\t} catch (HeuristicMixedException ex) {\n\t\t\tthis.transactionListenerList.onCommitHeuristicMixed(xid); // should never happen\n\t\t\tthrow ex;\n\t\t} catch (HeuristicRollbackException ex) {\n\t\t\tthis.transactionListenerList.onCommitHeuristicRolledback(xid);\n\t\t\tthrow ex;\n\t\t} catch (SystemException ex) {\n\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\tSystemException error = new SystemException();\n\t\t\terror.initCause(ex);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate void participantOnePhaseCommit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,\n\t\t\tSecurityException, IllegalStateException, CommitRequiredException, SystemException {\n\n\t\tthis.checkForTransactionExtraIfNecessary();\n\n\t\tif (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthis.participantRollback();\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLING_BACK) {\n\t\t\tthrow new HeuristicMixedException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) {\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_UNKNOWN) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_NO_TRANSACTION) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) {\n\t\t\treturn;\n\t\t} /* else active, preparing, prepared, committing {} */\n\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tthis.invokeParticipantPrepare();\n\t\t\t} catch (CommitRequiredException crex) {\n\t\t\t\t/* some RMs has already been committed. */\n\t\t\t}\n\n\t\t\tthis.invokeParticipantCommit(true);\n\t\t} catch (RollbackRequiredException rrex) {\n\t\t\tthis.participantRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rrex);\n\t\t\tthrow hrex;\n\t\t} catch (SystemException ex) {\n\t\t\tthis.participantRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(ex);\n\t\t\tthrow hrex;\n\t\t} catch (RuntimeException rex) {\n\t\t\tthis.participantRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rex);\n\t\t\tthrow hrex;\n\t\t}\n\n\t}\n\n\tprivate void participantTwoPhaseCommit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,\n\t\t\tSecurityException, IllegalStateException, CommitRequiredException, SystemException {\n\n\t\tif (this.transactionStatus == Status.STATUS_ACTIVE) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthis.participantRollback();\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLING_BACK) {\n\t\t\tthrow new HeuristicMixedException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) {\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_UNKNOWN) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_NO_TRANSACTION) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) {\n\t\t\treturn;\n\t\t} /* else preparing, prepared, committing {} */\n\n\t\ttry {\n\t\t\tthis.invokeParticipantCommit(false);\n\t\t} catch (RollbackRequiredException rrex) {\n\t\t\tthis.participantRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rrex);\n\t\t\tthrow hrex;\n\t\t} catch (SystemException ex) {\n\t\t\tthis.participantRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(ex);\n\t\t\tthrow hrex;\n\t\t} catch (RuntimeException rex) {\n\t\t\tthis.participantRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rex);\n\t\t\tthrow hrex;\n\t\t}\n\n\t}\n\n\tprivate void invokeParticipantPrepare() throws RollbackRequiredException, CommitRequiredException {\n\t\tTransactionLogger transactionLogger = beanFactory.getTransactionLogger();\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tlogger.info(\"{}> prepare-participant start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tthis.transactionStatus = Status.STATUS_PREPARING;\n\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\tthis.transactionListenerList.onPrepareStart(xid);\n\t\ttransactionLogger.createTransaction(archive); // transactionLogger.updateTransaction(archive);\n\n\t\tCommitRequiredException commitRequired = null;\n\t\ttry {\n\t\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\t\tcurrentStrategy.prepare(xid);\n\t\t} catch (CommitRequiredException ex) {\n\t\t\tcommitRequired = ex;\n\t\t} catch (RollbackRequiredException ex) {\n\t\t\tthis.transactionListenerList.onPrepareFailure(xid);\n\t\t\tlogger.info(\"{}> prepare-participant failed\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tthis.transactionListenerList.onPrepareFailure(xid);\n\t\t\tlogger.info(\"{}> prepare-participant failed\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t\t\tthrow ex;\n\t\t}\n\n\t\tthis.transactionStatus = Status.STATUS_PREPARED;\n\t\tarchive.setStatus(this.transactionStatus);\n\t\tthis.transactionListenerList.onPrepareSuccess(xid);\n\t\ttransactionLogger.updateTransaction(archive);\n\t\tlogger.info(\"{}> prepare-participant complete successfully\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tif (commitRequired != null) {\n\t\t\tthrow commitRequired;\n\t\t} // end-if (commitRequired != null)\n\n\t}\n\n\tprivate void invokeParticipantCommit(boolean onePhaseCommit)\n\t\t\tthrows HeuristicMixedException, HeuristicRollbackException, SystemException {\n\t\tTransactionLogger transactionLogger = beanFactory.getTransactionLogger();\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tlogger.info(\"{}> commit-participant start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tthis.transactionStatus = Status.STATUS_COMMITTING;\n\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\tthis.transactionListenerList.onCommitStart(xid);\n\t\ttransactionLogger.updateTransaction(archive);\n\n\t\tboolean unFinishExists = true;\n\t\ttry {\n\t\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\t\tcurrentStrategy.commit(xid, onePhaseCommit);\n\n\t\t\tunFinishExists = false;\n\t\t} catch (HeuristicMixedException ex) {\n\t\t\tthis.transactionListenerList.onCommitHeuristicMixed(xid);\n\t\t\tthrow ex;\n\t\t} catch (HeuristicRollbackException ex) {\n\t\t\tthis.transactionListenerList.onCommitHeuristicRolledback(xid);\n\t\t\tthrow ex;\n\t\t} catch (SystemException ex) {\n\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\tif (unFinishExists == false) {\n\t\t\t\tthis.transactionStatus = Status.STATUS_COMMITTED; // Status.STATUS_COMMITTED;\n\t\t\t\tarchive.setStatus(this.transactionStatus);\n\t\t\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t\t\t\ttransactionLogger.updateTransaction(archive);\n\n\t\t\t\tlogger.info(\"{}> commit-participant complete successfully\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic synchronized void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,\n\t\t\tSecurityException, IllegalStateException, CommitRequiredException, SystemException {\n\n\t\tif (this.transactionStatus == Status.STATUS_ACTIVE) {\n\t\t\tthis.fireCommit();\n\t\t} else if (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthis.fireRollback();\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) /* should never happen */ {\n\t\t\tthrow new RollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) /* should never happen */ {\n\t\t\tlogger.debug(\"Current transaction has already been committed.\");\n\t\t} else {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t}\n\n\tprivate void fireCommit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException,\n\t\t\tIllegalStateException, CommitRequiredException, SystemException {\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tlogger.info(\"{}> commit-transaction start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tif (this.participantList.size() == 0) {\n\t\t\tthis.skipOnePhaseCommit();\n\t\t} else if (this.participantList.size() == 1 && (this.nativeParticipantList.size() == 1 || this.participant != null)) {\n\t\t\tthis.fireOnePhaseCommit();\n\t\t} else {\n\t\t\tthis.fireTwoPhaseCommit();\n\t\t}\n\n\t\tlogger.info(\"{}> commit-transaction complete successfully\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t}\n\n\tpublic synchronized void skipOnePhaseCommit()\n\t\t\tthrows HeuristicRollbackException, HeuristicMixedException, CommitRequiredException, SystemException {\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tthis.transactionListenerList.onCommitStart(xid);\n\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t}\n\n\tpublic synchronized void fireOnePhaseCommit()\n\t\t\tthrows HeuristicRollbackException, HeuristicMixedException, CommitRequiredException, SystemException {\n\n\t\tXAResourceArchive archive = null;\n\t\tif (this.nativeParticipantList.size() > 0) {\n\t\t\tarchive = this.nativeParticipantList.get(0);\n\t\t} else if (this.remoteParticipantList.size() > 0) {\n\t\t\tarchive = this.remoteParticipantList.get(0);\n\t\t} else {\n\t\t\tarchive = this.participant;\n\t\t}\n\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\ttry {\n\t\t\tthis.transactionListenerList.onCommitStart(xid);\n\t\t\tarchive.commit(xid, true);\n\t\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t\t} catch (XAException xaex) {\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tthis.transactionListenerList.onCommitHeuristicMixed(xid);\n\t\t\t\tHeuristicMixedException hmex = new HeuristicMixedException();\n\t\t\t\thmex.initCause(xaex);\n\t\t\t\tthrow hmex;\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tthis.transactionListenerList.onCommitHeuristicRolledback(xid);\n\t\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\t\threx.initCause(xaex);\n\t\t\t\tthrow hrex;\n\t\t\tdefault:\n\t\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\t\tSystemException ex = new SystemException();\n\t\t\t\tex.initCause(xaex);\n\t\t\t\tthrow ex;\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\tSystemException sysEx = new SystemException();\n\t\t\tsysEx.initCause(rex);\n\t\t\tthrow sysEx;\n\t\t}\n\t}\n\n\tpublic synchronized void fireTwoPhaseCommit()\n\t\t\tthrows HeuristicRollbackException, HeuristicMixedException, CommitRequiredException, SystemException {\n\t\tTransactionLogger transactionLogger = beanFactory.getTransactionLogger();\n\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tlogger.info(\"{}> prepare-participant start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tthis.transactionStatus = Status.STATUS_PREPARING;// .setStatusPreparing();\n\n\t\tTransactionArchive archive = this.getTransactionArchive();// new TransactionArchive();\n\t\ttransactionLogger.createTransaction(archive);\n\n\t\tthis.transactionListenerList.onPrepareStart(xid);\n\n\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\tint vote = XAResource.XA_RDONLY;\n\t\ttry {\n\t\t\tvote = currentStrategy.prepare(xid);\n\t\t} catch (RollbackRequiredException xaex) {\n\t\t\tthis.transactionListenerList.onPrepareFailure(xid);\n\t\t\tlogger.info(\"{}> prepare-participant failed\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\tthis.invokeParticipantRollback(); // this.fireRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(xaex);\n\t\t\tthrow hrex;\n\t\t} catch (CommitRequiredException xaex) {\n\t\t\tvote = XAResource.XA_OK;\n\t\t\t// committed = true;\n\t\t} catch (RuntimeException rex) {\n\t\t\tthis.transactionListenerList.onPrepareFailure(xid);\n\t\t\tlogger.info(\"{}> prepare-participant failed\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\tthis.invokeParticipantRollback(); // this.fireRollback();\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rex);\n\t\t\tthrow hrex;\n\t\t}\n\n\t\tthis.transactionListenerList.onPrepareSuccess(xid);\n\n\t\tif (vote == XAResource.XA_RDONLY) {\n\t\t\tthis.transactionStatus = Status.STATUS_PREPARED;// .setStatusPrepared();\n\t\t\tthis.transactionVote = XAResource.XA_RDONLY;\n\t\t\tarchive.setVote(XAResource.XA_RDONLY);\n\t\t\tarchive.setStatus(this.transactionStatus);\n\t\t\tthis.transactionListenerList.onCommitStart(xid);\n\t\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t\t\tlogger.info(\"{}> prepare-participant & commit-participant complete successfully\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\ttransactionLogger.updateTransaction(archive);\n\t\t} else {\n\t\t\t// this.transactionStatus = Status.STATUS_PREPARED;// .setStatusPrepared();\n\n\t\t\tlogger.info(\"{}> prepare-participant complete successfully, and commit-participant start\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\t\tthis.transactionStatus = Status.STATUS_COMMITTING;// .setStatusCommiting();\n\t\t\tthis.transactionVote = XAResource.XA_OK;\n\t\t\tarchive.setVote(this.transactionVote);\n\t\t\tarchive.setStatus(this.transactionStatus);\n\t\t\tthis.transactionListenerList.onCommitStart(xid);\n\t\t\ttransactionLogger.updateTransaction(archive);\n\n\t\t\ttry {\n\t\t\t\tcurrentStrategy.commit(xid, false);\n\t\t\t} catch (HeuristicMixedException ex) {\n\t\t\t\tthis.transactionListenerList.onCommitHeuristicMixed(xid);\n\t\t\t\tthrow ex;\n\t\t\t} catch (HeuristicRollbackException ex) {\n\t\t\t\tthis.transactionListenerList.onCommitHeuristicRolledback(xid);\n\t\t\t\tthrow ex;\n\t\t\t} catch (SystemException ex) {\n\t\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\t\tthrow ex;\n\t\t\t} catch (RuntimeException ex) {\n\t\t\t\tthis.transactionListenerList.onCommitFailure(xid);\n\t\t\t\tthrow ex;\n\t\t\t}\n\n\t\t\tthis.transactionStatus = Status.STATUS_COMMITTED; // Status.STATUS_COMMITTED;\n\t\t\tarchive.setStatus(this.transactionStatus);\n\t\t\tthis.transactionListenerList.onCommitSuccess(xid);\n\t\t\ttransactionLogger.updateTransaction(archive);\n\n\t\t\tlogger.info(\"{}> commit-participant complete successfully\",\n\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t\t} // end-else-if (vote == XAResource.XA_RDONLY)\n\n\t}\n\n\tpublic synchronized boolean delistResource(XAResource xaRes, int flag) throws IllegalStateException, SystemException {\n\t\tif (this.transactionStatus != Status.STATUS_ACTIVE && this.transactionStatus != Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tif (XAResourceDescriptor.class.isInstance(xaRes)) {\n\t\t\treturn this.delistResource((XAResourceDescriptor) xaRes, flag);\n\t\t} else {\n\t\t\tXAResourceDescriptor descriptor = new UnidentifiedResourceDescriptor();\n\t\t\t((UnidentifiedResourceDescriptor) descriptor).setDelegate(xaRes);\n\t\t\t((UnidentifiedResourceDescriptor) descriptor).setIdentifier(\"\");\n\t\t\treturn this.delistResource(descriptor, flag);\n\t\t}\n\t}\n\n\tpublic boolean delistResource(XAResourceDescriptor descriptor, int flag) throws IllegalStateException, SystemException {\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) this.beanFactory.getNativeParticipant();\n\t\tif (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\tRemoteSvc nativeSvc = CommonUtils.getRemoteSvc(transactionCoordinator.getIdentifier());\n\t\t\tRemoteSvc parentSvc = CommonUtils.getRemoteSvc(String.valueOf(this.transactionContext.getPropagatedBy()));\n\t\t\tRemoteSvc remoteSvc = ((RemoteResourceDescriptor) descriptor).getRemoteSvc();\n\n\t\t\tboolean nativeFlag = StringUtils.equalsIgnoreCase(remoteSvc.getServiceKey(), nativeSvc.getServiceKey());\n\t\t\tboolean parentFlag = StringUtils.equalsIgnoreCase(remoteSvc.getServiceKey(), parentSvc.getServiceKey());\n\t\t\tif (nativeFlag || parentFlag) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tXAResourceArchive archive = this.getEnlistedResourceArchive(descriptor);\n\t\tif (archive == null) {\n\t\t\tthrow new SystemException();\n\t\t}\n\n\t\ttry {\n\t\t\treturn this.delistResource(archive, flag);\n\t\t} finally {\n\t\t\tthis.resourceListenerList.onDelistResource(archive.getXid(), descriptor);\n\t\t}\n\n\t}\n\n\tprivate boolean delistResource(XAResourceArchive archive, int flag) throws SystemException {\n\t\ttry {\n\t\t\tXid branchXid = archive.getXid();\n\n\t\t\tlogger.info(\"{}> delist: xares= {}, branch= {}, flags= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(branchXid.getBranchQualifier()), flag);\n\n\t\t\tswitch (flag) {\n\t\t\tcase XAResource.TMSUSPEND:\n\t\t\t\tarchive.end(branchXid, flag);\n\t\t\t\tarchive.setDelisted(true);\n\t\t\t\tarchive.setSuspended(true);\n\t\t\t\treturn true;\n\t\t\tcase XAResource.TMFAIL:\n\t\t\t\tthis.setRollbackOnlyQuietly();\n\t\t\tcase XAResource.TMSUCCESS:\n\t\t\t\tarchive.end(branchXid, flag);\n\t\t\t\tarchive.setDelisted(true);\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch (XAException xae) {\n\t\t\tlogger.error(\"XATerminatorImpl.delistResource(XAResourceArchive, int)\", xae);\n\n\t\t\t// Possible XAException values are XAER_RMERR, XAER_RMFAIL,\n\t\t\t// XAER_NOTA, XAER_INVAL, XAER_PROTO, or XA_RB*.\n\t\t\tswitch (xae.errorCode) {\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t// The specified XID is not known by the resource manager.\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t// Invalid arguments were specified.\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t// The routine was invoked in an improper context.\n\t\t\t\treturn false;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t// An error occurred that makes the resource manager unavailable.\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t// An error occurred in dissociating the transaction branch from the thread of control.\n\t\t\t\treturn false; // throw new SystemException();\n\t\t\tdefault /* XA_RB* */ :\n\t\t\t\treturn false; // throw new RollbackRequiredException();\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"XATerminatorImpl.delistResource(XAResourceArchive, int)\", ex);\n\t\t\tthrow new SystemException();\n\t\t}\n\t}\n\n\tpublic synchronized boolean enlistResource(XAResource xaRes)\n\t\t\tthrows RollbackException, IllegalStateException, SystemException {\n\n\t\tif (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\t// When a RollbackException is received, DBCP treats the state as STATUS_ROLLEDBACK,\n\t\t\t// but the actual state is still STATUS_MARKED_ROLLBACK.\n\t\t\tthrow new IllegalStateException(); // throw new RollbackException();\n\t\t} else if (this.transactionStatus != Status.STATUS_ACTIVE) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tif (XAResourceDescriptor.class.isInstance(xaRes)) {\n\t\t\treturn this.enlistResource((XAResourceDescriptor) xaRes);\n\t\t} else if (XAResourceDescriptor.class.isInstance(xaRes) == false && this.transactionContext.isCoordinator()) {\n\t\t\tXAResourceDescriptor descriptor = new UnidentifiedResourceDescriptor();\n\t\t\t((UnidentifiedResourceDescriptor) descriptor).setIdentifier(\"\");\n\t\t\t((UnidentifiedResourceDescriptor) descriptor).setDelegate(xaRes);\n\t\t\treturn this.enlistResource(descriptor);\n\t\t} else {\n\t\t\tthrow new SystemException(\"Unknown xa resource!\");\n\t\t}\n\n\t}\n\n\tprivate XAResourceArchive getEnlistedResourceArchive(XAResourceDescriptor descriptor) {\n\t\tif (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\tRemoteSvc remoteSvc = CommonUtils.getRemoteSvc(descriptor.getIdentifier()); // dubbo: old identifier\n\t\t\treturn this.remoteParticipantMap.get(remoteSvc);\n\t\t} else {\n\t\t\treturn this.nativeParticipantMap.get(descriptor.getIdentifier());\n\t\t}\n\t}\n\n\tprivate void putEnlistedResourceArchive(XAResourceArchive archive) {\n\t\tXAResourceDescriptor descriptor = archive.getDescriptor();\n\t\tString identifier = descriptor.getIdentifier();\n\t\tif (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\tRemoteSvc remoteSvc = CommonUtils.getRemoteSvc(identifier);\n\t\t\tthis.remoteParticipantMap.put(remoteSvc, archive);\n\t\t} else {\n\t\t\tthis.nativeParticipantMap.put(identifier, archive);\n\t\t}\n\t}\n\n\tpublic boolean enlistResource(XAResourceDescriptor descriptor)\n\t\t\tthrows RollbackException, IllegalStateException, SystemException {\n\t\tXAResourceArchive archive = null;\n\n\t\tXAResourceArchive enlisted = this.getEnlistedResourceArchive(descriptor);\n\t\tif (enlisted != null) {\n\t\t\tXAResourceDescriptor xard = enlisted.getDescriptor();\n\t\t\ttry {\n\t\t\t\tarchive = xard.isSameRM(descriptor) ? enlisted : archive;\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t\t}\n\t\t}\n\n\t\tint flags = XAResource.TMNOFLAGS;\n\t\tif (archive == null) {\n\t\t\tarchive = new XAResourceArchive();\n\t\t\tarchive.setDescriptor(descriptor);\n\t\t\tarchive.setIdentified(true);\n\n\t\t\tif (this.transactionalExtra != null && this.transactionalExtra.getTransactionXid() != null) {\n\t\t\t\tarchive.setXid(this.transactionalExtra.getTransactionXid());\n\t\t\t} else {\n\t\t\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\t\t\tarchive.setXid(xidFactory.createBranchXid(this.transactionContext.getXid()));\n\t\t\t}\n\t\t} else {\n\t\t\tflags = XAResource.TMJOIN;\n\t\t}\n\n\t\tdescriptor.setTransactionTimeoutQuietly(this.transactionTimeout);\n\n\t\tif (this.participant != null && (LocalXAResourceDescriptor.class.isInstance(descriptor)\n\t\t\t\t|| UnidentifiedResourceDescriptor.class.isInstance(descriptor))) {\n\t\t\tXAResourceDescriptor lro = this.participant.getDescriptor();\n\t\t\ttry {\n\t\t\t\tif (lro.isSameRM(descriptor) == false) {\n\t\t\t\t\tthrow new SystemException(\"Only one non-XA resource is allowed to participate in global transaction.\");\n\t\t\t\t}\n\t\t\t} catch (XAException ex) {\n\t\t\t\tSystemException sysEx = new SystemException();\n\t\t\t\tsysEx.initCause(ex);\n\t\t\t\tthrow sysEx;\n\t\t\t} catch (RuntimeException ex) {\n\t\t\t\tSystemException sysEx = new SystemException();\n\t\t\t\tsysEx.initCause(ex);\n\t\t\t\tthrow sysEx;\n\t\t\t}\n\t\t}\n\n\t\tboolean success = false;\n\t\ttry {\n\t\t\tBoolean enlistValue = this.enlistResource(archive, flags);\n\t\t\tsuccess = enlistValue != null && enlistValue;\n\t\t\treturn enlistValue != null;\n\t\t} finally {\n\t\t\tif (success) {\n\t\t\t\tString identifier = descriptor.getIdentifier(); // dubbo: new identifier\n\n\t\t\t\tboolean resourceValid = true;\n\t\t\t\tif (CommonResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\t\t\tthis.nativeParticipantList.add(archive);\n\t\t\t\t} else if (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\t\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) this.beanFactory.getNativeParticipant();\n\n\t\t\t\t\tRemoteSvc nativeSvc = CommonUtils.getRemoteSvc(transactionCoordinator.getIdentifier());\n\t\t\t\t\tRemoteSvc parentSvc = CommonUtils.getRemoteSvc(String.valueOf(this.transactionContext.getPropagatedBy()));\n\t\t\t\t\tRemoteSvc remoteSvc = ((RemoteResourceDescriptor) descriptor).getRemoteSvc();\n\n\t\t\t\t\tboolean nativeFlag = StringUtils.equalsIgnoreCase(remoteSvc.getServiceKey(), nativeSvc.getServiceKey());\n\t\t\t\t\tboolean parentFlag = StringUtils.equalsIgnoreCase(remoteSvc.getServiceKey(), parentSvc.getServiceKey());\n\t\t\t\t\tif (nativeFlag || parentFlag) {\n\t\t\t\t\t\tlogger.warn(\"Endpoint {} can not be its own remote branch!\", identifier);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.remoteParticipantList.add(archive);\n\t\t\t\t\tthis.putEnlistedResourceArchive(archive);\n\t\t\t\t} else if (this.participant == null) {\n\t\t\t\t\t// this.participant = this.participant == null ? archive : this.participant;\n\t\t\t\t\tthis.participant = archive;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new SystemException(\"There already has a local-resource exists!\");\n\t\t\t\t}\n\n\t\t\t\tif (resourceValid) {\n\t\t\t\t\tthis.participantList.add(archive);\n\t\t\t\t\tthis.putEnlistedResourceArchive(archive);\n\n\t\t\t\t\tthis.resourceListenerList.onEnlistResource(archive.getXid(), descriptor);\n\t\t\t\t} // end-if (resourceValid)\n\t\t\t}\n\t\t}\n\n\t}\n\n\t// result description:\n\t// 1) true, success(current resource should be added to archive list);\n\t// 2) false, success(resource has already been added to archive list);\n\t// 3) null, failure.\n\tprivate Boolean enlistResource(XAResourceArchive archive, int flag) throws SystemException {\n\t\ttry {\n\t\t\tXid branchXid = archive.getXid();\n\t\t\tlogger.info(\"{}> enlist: xares= {}, branch= {}, flags: {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(branchXid.getBranchQualifier()), flag);\n\n\t\t\tswitch (flag) {\n\t\t\tcase XAResource.TMNOFLAGS:\n\t\t\t\tlong expired = this.transactionContext.getExpiredTime();\n\t\t\t\tlong current = System.currentTimeMillis();\n\t\t\t\tlong remains = expired - current;\n\t\t\t\tint timeout = (int) (remains / 1000L);\n\t\t\t\tarchive.setTransactionTimeout(timeout);\n\t\t\t\tarchive.start(branchXid, flag);\n\t\t\t\treturn true;\n\t\t\tcase XAResource.TMJOIN:\n\t\t\t\tarchive.start(branchXid, flag);\n\t\t\t\tarchive.setDelisted(false);\n\t\t\t\treturn false;\n\t\t\tcase XAResource.TMRESUME:\n\t\t\t\tarchive.start(branchXid, flag);\n\t\t\t\tarchive.setDelisted(false);\n\t\t\t\tarchive.setSuspended(false);\n\t\t\t\treturn false;\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch (XAException xae) {\n\t\t\tlogger.error(\"XATerminatorImpl.enlistResource(XAResourceArchive, int)\", xae);\n\n\t\t\t// Possible exceptions are XA_RB*, XAER_RMERR, XAER_RMFAIL,\n\t\t\t// XAER_DUPID, XAER_OUTSIDE, XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\tswitch (xae.errorCode) {\n\t\t\tcase XAException.XAER_DUPID:\n\t\t\t\t// * If neither TMJOIN nor TMRESUME is specified and the transaction\n\t\t\t\t// * specified by xid has previously been seen by the resource manager,\n\t\t\t\t// * the resource manager throws the XAException exception with XAER_DUPID error code.\n\t\t\t\treturn null;\n\t\t\tcase XAException.XAER_OUTSIDE:\n\t\t\t\t// The resource manager is doing work outside any global transaction\n\t\t\t\t// on behalf of the application.\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t// Either TMRESUME or TMJOIN was set inflags, and the specified XID is not\n\t\t\t\t// known by the resource manager.\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t// Invalid arguments were specified.\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t// The routine was invoked in an improper context.\n\t\t\t\treturn null;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t// An error occurred that makes the resource manager unavailable\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t// An error occurred in associating the transaction branch with the thread of control\n\t\t\t\treturn null;\n\t\t\tdefault /* XA_RB **/ :\n\t\t\t\t// When a RollbackException is received, DBCP treats the state as STATUS_ROLLEDBACK,\n\t\t\t\t// but the actual state is still STATUS_MARKED_ROLLBACK.\n\t\t\t\treturn null; // throw new RollbackException();\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"XATerminatorImpl.enlistResource(XAResourceArchive, int)\", ex);\n\t\t\tthrow new SystemException();\n\t\t}\n\n\t}\n\n\tpublic int getStatus() /* throws SystemException */ {\n\t\treturn this.transactionStatus;\n\t}\n\n\tpublic synchronized void registerSynchronization(Synchronization sync)\n\t\t\tthrows RollbackException, IllegalStateException, SystemException {\n\n\t\tif (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthrow new RollbackException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ACTIVE) {\n\t\t\tthis.synchronizationList.registerSynchronizationQuietly(sync);\n\t\t\tlogger.debug(\"{}> register-sync: sync= {}\"//\n\t\t\t\t\t, ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), sync);\n\t\t} else {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t}\n\n\tpublic synchronized void rollback() throws IllegalStateException, RollbackRequiredException, SystemException {\n\t\tif (this.transactionStatus == Status.STATUS_UNKNOWN) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_NO_TRANSACTION) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) /* should never happen */ {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) /* should never happen */ {\n\t\t\tlogger.debug(\"Current transaction has already been rolled back.\");\n\t\t} else {\n\t\t\tthis.fireRollback();\n\t\t}\n\t}\n\n\tprivate void fireRollback() throws IllegalStateException, RollbackRequiredException, SystemException {\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tlogger.info(\"{}> rollback-transaction start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tthis.invokeParticipantRollback();\n\n\t\tlogger.info(\"{}> rollback-transaction complete successfully\",\n\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t}\n\n\tpublic synchronized void recoveryRollback() throws RollbackRequiredException, SystemException {\n\t\tthis.recoverIfNecessary(); // Recover if transaction is recovered from tx-log.\n\n\t\tthis.transactionContext.setRecoveredTimes(this.transactionContext.getRecoveredTimes() + 1);\n\t\tthis.transactionContext.setCreatedTime(System.currentTimeMillis());\n\n\t\tthis.invokeParticipantRollback();\n\t}\n\n\tpublic synchronized void participantRollback() throws IllegalStateException, RollbackRequiredException, SystemException {\n\n\t\tif (this.transactionStatus == Status.STATUS_UNKNOWN) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_NO_TRANSACTION) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_COMMITTED) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.transactionContext.isRecoveried()) {\n\t\t\tthis.recover(); // Execute recoveryInit if transaction is recovered from tx-log.\n\t\t\tthis.invokeParticipantRollback();\n\t\t} else {\n\t\t\tthis.invokeParticipantRollback();\n\t\t}\n\n\t}\n\n\tprivate void invokeParticipantRollback() throws SystemException {\n\t\tTransactionLogger transactionLogger = beanFactory.getTransactionLogger();\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\tlogger.info(\"{}> rollback-participant start\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\n\t\tthis.transactionStatus = Status.STATUS_ROLLING_BACK;\n\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\tthis.transactionListenerList.onRollbackStart(xid);\n\t\ttransactionLogger.updateTransaction(archive); // don't create!\n\n\t\ttry {\n\t\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\t\tcurrentStrategy.rollback(xid);\n\t\t} catch (HeuristicMixedException ex) {\n\t\t\tthis.transactionListenerList.onRollbackFailure(xid);\n\t\t\tSystemException sysEx = new SystemException();\n\t\t\tsysEx.initCause(ex);\n\t\t\tthrow sysEx;\n\t\t} catch (HeuristicCommitException ex) {\n\t\t\tthis.transactionListenerList.onRollbackFailure(xid);\n\t\t\tSystemException sysEx = new SystemException();\n\t\t\tsysEx.initCause(ex);\n\t\t\tthrow sysEx;\n\t\t} catch (SystemException ex) {\n\t\t\tthis.transactionListenerList.onRollbackFailure(xid);\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tthis.transactionListenerList.onRollbackFailure(xid);\n\t\t\tSystemException sysEx = new SystemException();\n\t\t\tsysEx.initCause(ex);\n\t\t\tthrow sysEx;\n\t\t}\n\n\t\tthis.transactionStatus = Status.STATUS_ROLLEDBACK; // Status.STATUS_ROLLEDBACK;\n\t\tarchive.setStatus(this.transactionStatus);\n\t\tthis.transactionListenerList.onRollbackSuccess(xid);\n\t\ttransactionLogger.updateTransaction(archive);\n\n\t\tlogger.info(\"{}> rollback-participant complete successfully\",\n\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()));\n\t}\n\n\tpublic void suspend() throws RollbackRequiredException, SystemException {\n\t\tboolean rollbackRequired = false;\n\t\tboolean errorExists = false;\n\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive xares = this.participantList.get(i);\n\t\t\tif (xares.isDelisted() == false) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.delistResource(xares, XAResource.TMSUSPEND);\n\t\t\t\t} catch (RollbackRequiredException ex) {\n\t\t\t\t\trollbackRequired = true;\n\t\t\t\t} catch (SystemException ex) {\n\t\t\t\t\terrorExists = true;\n\t\t\t\t} catch (RuntimeException ex) {\n\t\t\t\t\terrorExists = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (rollbackRequired) {\n\t\t\tthis.setRollbackOnlyQuietly();\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (errorExists) {\n\t\t\tthrow new SystemException(XAException.XAER_RMERR);\n\t\t}\n\n\t}\n\n\tpublic void resume() throws RollbackRequiredException, SystemException {\n\t\t// boolean rollbackRequired = false;\n\t\tboolean errorExists = false;\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive xares = this.participantList.get(i);\n\t\t\tif (xares.isDelisted()) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.enlistResource(xares, XAResource.TMRESUME);\n\t\t\t\t} catch (SystemException rex) {\n\t\t\t\t\terrorExists = true;\n\t\t\t\t} catch (RuntimeException rex) {\n\t\t\t\t\terrorExists = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (errorExists) {\n\t\t\tthrow new SystemException(XAException.XAER_RMERR);\n\t\t}\n\n\t}\n\n\tpublic synchronized void fireBeforeTransactionCompletionQuietly() {\n\t\tthis.synchronizationList.beforeCompletion();\n\t\tthis.delistAllResourceQuietly();\n\t}\n\n\tpublic synchronized void fireBeforeTransactionCompletion() throws RollbackRequiredException, SystemException {\n\t\tthis.synchronizationList.beforeCompletion();\n\t\tthis.delistAllResource();\n\t}\n\n\tpublic synchronized void fireAfterTransactionCompletion() {\n\t\tthis.synchronizationList.afterCompletion(this.transactionStatus);\n\t}\n\n\tpublic void delistAllResourceQuietly() {\n\t\ttry {\n\t\t\tthis.delistAllResource();\n\t\t} catch (RollbackRequiredException rrex) {\n\t\t\tlogger.warn(rrex.getMessage(), rrex);\n\t\t} catch (SystemException ex) {\n\t\t\tlogger.warn(ex.getMessage(), ex);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.warn(rex.getMessage(), rex);\n\t\t}\n\t}\n\n\tprivate void delistAllResource() throws RollbackRequiredException, SystemException {\n\t\tboolean rollbackRequired = false;\n\t\tboolean errorExists = false;\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive xares = this.participantList.get(i);\n\t\t\tif (this.transactionContext.isRecoveried()) {\n\t\t\t\tcontinue;\n\t\t\t} // end-if (this.transactionContext.isRecoveried())\n\n\t\t\tif (xares.isDelisted() == false) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.delistResource(xares, XAResource.TMSUCCESS);\n\t\t\t\t} catch (RollbackRequiredException ex) {\n\t\t\t\t\trollbackRequired = true;\n\t\t\t\t} catch (SystemException ex) {\n\t\t\t\t\terrorExists = true;\n\t\t\t\t} catch (RuntimeException ex) {\n\t\t\t\t\terrorExists = true;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.resourceListenerList.onDelistResource(xares.getXid(), xares.getDescriptor());\n\t\t\t\t}\n\t\t\t}\n\t\t} // end-for\n\n\t\tif (rollbackRequired) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t} else if (errorExists) {\n\t\t\tthrow new SystemException(XAException.XAER_RMERR);\n\t\t}\n\t}\n\n\tpublic boolean isMarkedRollbackOnly() {\n\t\treturn this.transactionContext.isRollbackOnly();\n\t}\n\n\tpublic void setRollbackOnlyQuietly() {\n\t\ttry {\n\t\t\tthis.setRollbackOnly();\n\t\t} catch (Exception ex) {\n\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t}\n\t}\n\n\tpublic synchronized void setRollbackOnly() throws IllegalStateException, SystemException {\n\t\tif (this.transactionStatus == Status.STATUS_ACTIVE || this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthis.transactionContext.setRollbackOnly(true);\n\t\t\tthis.transactionStatus = Status.STATUS_MARKED_ROLLBACK;\n\t\t} else {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic void recoverIfNecessary() throws SystemException {\n\t\tif (this.transactionContext.isRecoveried()) {\n\t\t\tthis.recover();\n\t\t}\n\t}\n\n\tpublic synchronized void recover() throws SystemException {\n\t\tif (transactionStatus == Status.STATUS_PREPARING) {\n\t\t\tthis.recover4PreparingStatus();\n\t\t} else if (transactionStatus == Status.STATUS_COMMITTING) {\n\t\t\tthis.recover4CommittingStatus();\n\t\t} else if (transactionStatus == Status.STATUS_ROLLING_BACK) {\n\t\t\tthis.recover4RollingBackStatus();\n\t\t}\n\t}\n\n\tpublic void recover4PreparingStatus() throws SystemException {\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean unPrepareExists = false;\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive archive = this.participantList.get(i);\n\n\t\t\tboolean prepareFlag = archive.getVote() != XAResourceArchive.DEFAULT_VOTE;\n\t\t\tboolean preparedVal = archive.isReadonly() || prepareFlag;\n\n\t\t\tif (archive.isRecovered()) {\n\t\t\t\tunPrepareExists = preparedVal ? unPrepareExists : true;\n\t\t\t\tcontinue;\n\t\t\t} else if (preparedVal) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tboolean xidExists = this.recover(archive);\n\t\t\tunPrepareExists = xidExists ? false : true;\n\t\t}\n\n\t\tif (unPrepareExists == false) {\n\t\t\tthis.transactionStatus = Status.STATUS_PREPARED;\n\n\t\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\t\ttransactionLogger.updateTransaction(archive);\n\t\t}\n\n\t}\n\n\tpublic void recover4CommittingStatus() throws SystemException {\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean rollbackExists = false;\n\t\tboolean unCommitExists = false;\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive archive = this.participantList.get(i);\n\n\t\t\tXAResourceDescriptor descriptor = archive.getDescriptor();\n\t\t\tXAResource delegate = descriptor.getDelegate();\n\t\t\tboolean localFlag = LocalXAResource.class.isInstance(delegate);\n\n\t\t\tif (localFlag //\n\t\t\t\t\t&& LastResourceOptimizeStrategy.class.isInstance(this.transactionStrategy)) {\n\t\t\t\tthrow new SystemException();\n\t\t\t}\n\n\t\t\tif (archive.isRecovered()) {\n\t\t\t\tunCommitExists = archive.isCommitted() ? unCommitExists : true;\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isCommitted()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tboolean xidExists = this.recover(archive);\n\t\t\tif (localFlag) {\n\t\t\t\trollbackExists = xidExists ? rollbackExists : true;\n\t\t\t} else {\n\t\t\t\tunCommitExists = xidExists ? true : unCommitExists;\n\t\t\t}\n\n\t\t}\n\n\t\tif (rollbackExists) {\n\t\t\tthis.transactionStatus = Status.STATUS_ROLLING_BACK;\n\n\t\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\t\ttransactionLogger.updateTransaction(archive);\n\t\t} else if (unCommitExists == false) {\n\t\t\tthis.transactionStatus = Status.STATUS_COMMITTED;\n\n\t\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\t\ttransactionLogger.updateTransaction(archive);\n\t\t}\n\n\t}\n\n\tpublic void recover4RollingBackStatus() throws SystemException {\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean unRollbackExists = false;\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive archive = this.participantList.get(i);\n\n\t\t\tif (archive.isRecovered()) {\n\t\t\t\tunRollbackExists = archive.isRolledback() ? unRollbackExists : true;\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isRolledback()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tboolean xidExists = this.recover(archive);\n\t\t\tunRollbackExists = xidExists ? true : unRollbackExists;\n\t\t}\n\n\t\tif (unRollbackExists == false) {\n\t\t\tthis.transactionStatus = Status.STATUS_ROLLEDBACK;\n\n\t\t\tTransactionArchive archive = this.getTransactionArchive();\n\t\t\ttransactionLogger.updateTransaction(archive);\n\t\t}\n\n\t}\n\n\tprivate boolean recover(XAResourceArchive archive) throws SystemException {\n\t\tTransactionXid globalXid = this.transactionContext.getXid();\n\n\t\tboolean xidRecovered = false;\n\n\t\tXAResourceDescriptor descriptor = archive.getDescriptor();\n\t\tXAResource delegate = descriptor.getDelegate();\n\t\tboolean nativeFlag = LocalXAResource.class.isInstance(delegate);\n\t\tboolean remoteFlag = RemoteCoordinator.class.isInstance(delegate);\n\t\tif (nativeFlag) {\n\t\t\ttry {\n\t\t\t\t((LocalXAResource) delegate).recoverable(archive.getXid());\n\t\t\t\txidRecovered = true;\n\t\t\t} catch (XAException ex) {\n\t\t\t\tswitch (ex.errorCode) {\n\t\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tlogger.error(\"{}> recover-resource failed. branch= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(globalXid.getGlobalTransactionId()),\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(globalXid.getBranchQualifier()), ex);\n\t\t\t\t\tthrow new SystemException();\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (archive.isIdentified()) {\n\t\t\tXid thisXid = archive.getXid();\n\t\t\tbyte[] thisGlobalTransactionId = thisXid.getGlobalTransactionId();\n\t\t\tbyte[] thisBranchQualifier = thisXid.getBranchQualifier();\n\t\t\ttry {\n\t\t\t\tXid[] array = archive.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);\n\t\t\t\tfor (int j = 0; xidRecovered == false && array != null && j < array.length; j++) {\n\t\t\t\t\tXid thatXid = array[j];\n\t\t\t\t\tbyte[] thatGlobalTransactionId = thatXid.getGlobalTransactionId();\n\t\t\t\t\tbyte[] thatBranchQualifier = thatXid.getBranchQualifier();\n\t\t\t\t\tboolean formatIdEquals = thisXid.getFormatId() == thatXid.getFormatId();\n\t\t\t\t\tboolean transactionIdEquals = Arrays.equals(thisGlobalTransactionId, thatGlobalTransactionId);\n\t\t\t\t\tboolean qualifierEquals = Arrays.equals(thisBranchQualifier, thatBranchQualifier);\n\t\t\t\t\txidRecovered = formatIdEquals && transactionIdEquals && (remoteFlag || qualifierEquals);\n\t\t\t\t}\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.error(\"{}> recover-resource failed. branch= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(globalXid.getGlobalTransactionId()),\n\t\t\t\t\t\tByteUtils.byteArrayToString(globalXid.getBranchQualifier()), ex);\n\t\t\t\tthrow new SystemException();\n\t\t\t}\n\t\t}\n\n\t\tarchive.setRecovered(true);\n\n\t\treturn xidRecovered;\n\t}\n\n\tpublic synchronized void forgetQuietly() {\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\t\ttry {\n\t\t\tthis.forget();\n\t\t} catch (SystemException ex) {\n\t\t\tlogger.error(\"Error occurred while forgetting transaction: {}\",\n\t\t\t\t\tByteUtils.byteArrayToInt(xid.getGlobalTransactionId()), ex);\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while forgetting transaction: {}\",\n\t\t\t\t\tByteUtils.byteArrayToInt(xid.getGlobalTransactionId()), ex);\n\t\t}\n\t}\n\n\tpublic synchronized void forget() throws SystemException {\n\t\tTransactionRepository repository = beanFactory.getTransactionRepository();\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tTransactionXid xid = this.transactionContext.getXid();\n\n\t\tthis.cleanup(); // forget branch-transaction has been hueristic completed.\n\n\t\trepository.removeErrorTransaction(xid);\n\t\trepository.removeTransaction(xid);\n\n\t\ttransactionLogger.deleteTransaction(this.getTransactionArchive());\n\t}\n\n\tpublic synchronized void cleanup() throws SystemException {\n\t\tboolean unFinishExists = false;\n\n\t\tfor (int i = 0; i < this.participantList.size(); i++) {\n\t\t\tXAResourceArchive archive = this.participantList.get(i);\n\t\t\tXid currentXid = archive.getXid();\n\t\t\tif (archive.isHeuristic()) {\n\t\t\t\ttry {\n\t\t\t\t\tXid branchXid = archive.getXid();\n\t\t\t\t\tarchive.forget(branchXid);\n\t\t\t\t} catch (XAException xae) {\n\t\t\t\t\t// Possible exception values are XAER_RMERR, XAER_RMFAIL\n\t\t\t\t\t// , XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t\t\tswitch (xae.errorCode) {\n\t\t\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} // end-if\n\t\t} // end-for\n\n\t\tif (unFinishExists) {\n\t\t\tthrow new SystemException(\"Error occurred while cleaning branch transaction!\");\n\t\t}\n\n\t}\n\n\tpublic TransactionArchive getTransactionArchive() {\n\t\tTransactionArchive transactionArchive = new TransactionArchive();\n\t\ttransactionArchive.setVote(this.transactionVote);\n\t\ttransactionArchive.setXid(this.transactionContext.getXid());\n\t\ttransactionArchive.setCoordinator(this.transactionContext.isCoordinator());\n\t\ttransactionArchive.setOptimizedResource(this.participant);\n\t\ttransactionArchive.getNativeResources().addAll(this.nativeParticipantList);\n\t\ttransactionArchive.getRemoteResources().addAll(this.remoteParticipantList);\n\t\ttransactionArchive.setStatus(this.transactionStatus);\n\t\t// transactionArchive.setPropagated(this.transactionContext.isPropagated());\n\t\ttransactionArchive.setPropagatedBy(this.transactionContext.getPropagatedBy());\n\n\t\tTransactionStrategy currentStrategy = this.getTransactionStrategy();\n\t\tif (CommonTransactionStrategy.class.isInstance(currentStrategy)) {\n\t\t\ttransactionArchive.setTransactionStrategyType(TransactionStrategy.TRANSACTION_STRATEGY_COMMON);\n\t\t} else if (SimpleTransactionStrategy.class.isInstance(currentStrategy)) {\n\t\t\ttransactionArchive.setTransactionStrategyType(TransactionStrategy.TRANSACTION_STRATEGY_SIMPLE);\n\t\t} else if (LastResourceOptimizeStrategy.class.isInstance(currentStrategy)) {\n\t\t\ttransactionArchive.setTransactionStrategyType(TransactionStrategy.TRANSACTION_STRATEGY_LRO);\n\t\t} else {\n\t\t\ttransactionArchive.setTransactionStrategyType(TransactionStrategy.TRANSACTION_STRATEGY_VACANT);\n\t\t}\n\n\t\treturn transactionArchive;\n\t}\n\n\tpublic int hashCode() {\n\t\tTransactionXid transactionXid = this.transactionContext == null ? null : this.transactionContext.getXid();\n\t\treturn transactionXid == null ? 0 : Arrays.hashCode(transactionXid.getGlobalTransactionId());\n\t}\n\n\tpublic boolean equals(Object obj) {\n\t\tif (obj == null) {\n\t\t\treturn false;\n\t\t} else if (TransactionImpl.class.equals(obj.getClass()) == false) {\n\t\t\treturn false;\n\t\t}\n\t\tTransactionImpl that = (TransactionImpl) obj;\n\t\tTransactionContext thisContext = this.transactionContext;\n\t\tTransactionContext thatContext = that.transactionContext;\n\t\tTransactionXid thisXid = thisContext == null ? null : thisContext.getXid();\n\t\tTransactionXid thatXid = thatContext == null ? null : thatContext.getXid();\n\t\treturn thisXid == null || thatXid == null ? false\n\t\t\t\t: Arrays.equals(thisXid.getGlobalTransactionId(), thatXid.getGlobalTransactionId());\n\t}\n\n\tpublic void registerTransactionListener(TransactionListener listener) {\n\t\tthis.transactionListenerList.registerTransactionListener(listener);\n\t}\n\n\tpublic void registerTransactionResourceListener(TransactionResourceListener listener) {\n\t\tthis.resourceListenerList.registerTransactionResourceListener(listener);\n\t}\n\n\tpublic synchronized void stopTiming() {\n\t\tthis.setTiming(false);\n\t}\n\n\tpublic synchronized void changeTransactionTimeout(int timeout) {\n\t\tlong created = this.transactionContext.getCreatedTime();\n\t\ttransactionContext.setExpiredTime(created + timeout);\n\t}\n\n\tpublic TransactionStrategy getTransactionStrategy() {\n\t\tTransactionStrategy strategy = //\n\t\t\t\tthis.transactionStrategy == null ? this.initGetTransactionStrategy() : this.transactionStrategy;\n\t\tif (Status.STATUS_ACTIVE == this.transactionStatus || Status.STATUS_MARKED_ROLLBACK == this.transactionStatus) {\n\t\t\treturn strategy;\n\t\t} else {\n\t\t\treturn this.transactionStrategy = this.transactionStrategy == null ? strategy : this.transactionStrategy;\n\t\t}\n\t}\n\n\tprivate TransactionStrategy initGetTransactionStrategy() {\n\t\tint nativeResNum = this.nativeParticipantList.size();\n\t\tint remoteResNum = this.remoteParticipantList.size();\n\n\t\tTransactionStrategy transactionStrategy = null;\n\t\tif (this.participantList.isEmpty()) {\n\t\t\ttransactionStrategy = new VacantTransactionStrategy();\n\t\t} else if (this.participant == null) /* TODO: LRO */ {\n\t\t\tXATerminatorImpl nativeTerminator = new XATerminatorImpl();\n\t\t\tnativeTerminator.setBeanFactory(this.beanFactory);\n\t\t\tnativeTerminator.getResourceArchives().addAll(this.nativeParticipantList);\n\n\t\t\tXATerminatorImpl remoteTerminator = new XATerminatorImpl();\n\t\t\tremoteTerminator.setBeanFactory(this.beanFactory);\n\t\t\tremoteTerminator.getResourceArchives().addAll(this.remoteParticipantList);\n\n\t\t\tif (nativeResNum == 0) {\n\t\t\t\ttransactionStrategy = new SimpleTransactionStrategy(remoteTerminator);\n\t\t\t} else if (remoteResNum == 0) {\n\t\t\t\ttransactionStrategy = new SimpleTransactionStrategy(nativeTerminator);\n\t\t\t} else {\n\t\t\t\ttransactionStrategy = new CommonTransactionStrategy(nativeTerminator, remoteTerminator);\n\t\t\t}\n\n\t\t} else {\n\t\t\tXATerminatorOptd terminatorOne = new XATerminatorOptd();\n\t\t\tterminatorOne.setBeanFactory(this.beanFactory);\n\t\t\tterminatorOne.getResourceArchives().add(this.participant);\n\n\t\t\tXATerminatorImpl terminatorTwo = new XATerminatorImpl();\n\t\t\tterminatorTwo.setBeanFactory(this.beanFactory);\n\t\t\tterminatorTwo.getResourceArchives().addAll(this.nativeParticipantList);\n\t\t\tterminatorTwo.getResourceArchives().addAll(this.remoteParticipantList);\n\n\t\t\tint resNumber = nativeResNum + remoteResNum;\n\t\t\tif (resNumber == 0) {\n\t\t\t\ttransactionStrategy = new SimpleTransactionStrategy(terminatorOne);\n\t\t\t} else {\n\t\t\t\ttransactionStrategy = new LastResourceOptimizeStrategy(terminatorOne, terminatorTwo);\n\t\t\t}\n\t\t}\n\n\t\treturn transactionStrategy;\n\t}\n\n\tpublic void recoverTransactionStrategy(int transactionStrategyType) {\n\t\tint nativeResNum = this.nativeParticipantList.size();\n\t\tint remoteResNum = this.remoteParticipantList.size();\n\n\t\tXATerminatorImpl nativeTerminator = new XATerminatorImpl();\n\t\tnativeTerminator.setBeanFactory(this.beanFactory);\n\t\tnativeTerminator.getResourceArchives().addAll(this.nativeParticipantList);\n\n\t\tXATerminatorImpl remoteTerminator = new XATerminatorImpl();\n\t\tremoteTerminator.setBeanFactory(this.beanFactory);\n\t\tremoteTerminator.getResourceArchives().addAll(this.remoteParticipantList);\n\n\t\tif (TransactionStrategy.TRANSACTION_STRATEGY_COMMON == transactionStrategyType) {\n\t\t\tif (this.participant != null) {\n\t\t\t\tthrow new IllegalStateException();\n\t\t\t} else if (nativeResNum == 0 || remoteResNum == 0) {\n\t\t\t\tthrow new IllegalStateException();\n\t\t\t}\n\t\t\tthis.transactionStrategy = new CommonTransactionStrategy(nativeTerminator, remoteTerminator);\n\t\t} else if (TransactionStrategy.TRANSACTION_STRATEGY_SIMPLE == transactionStrategyType) {\n\t\t\tif (this.participant == null) {\n\t\t\t\tif (nativeResNum > 0 && remoteResNum > 0) {\n\t\t\t\t\tthrow new IllegalStateException();\n\t\t\t\t} else if (nativeResNum == 0 && remoteResNum == 0) {\n\t\t\t\t\tthrow new IllegalStateException();\n\t\t\t\t} else if (nativeResNum == 0) {\n\t\t\t\t\tthis.transactionStrategy = new SimpleTransactionStrategy(remoteTerminator);\n\t\t\t\t} else {\n\t\t\t\t\tthis.transactionStrategy = new SimpleTransactionStrategy(nativeTerminator);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tint resNumber = nativeResNum + remoteResNum;\n\t\t\t\tif (resNumber > 0) {\n\t\t\t\t\tthrow new IllegalStateException();\n\t\t\t\t}\n\t\t\t\tXATerminatorOptd terminatorOne = new XATerminatorOptd();\n\t\t\t\tterminatorOne.setBeanFactory(this.beanFactory);\n\t\t\t\tterminatorOne.getResourceArchives().add(this.participant);\n\t\t\t\tthis.transactionStrategy = new SimpleTransactionStrategy(terminatorOne);\n\t\t\t}\n\t\t} else if (TransactionStrategy.TRANSACTION_STRATEGY_LRO == transactionStrategyType) {\n\t\t\tif (this.participant == null) {\n\t\t\t\tthrow new IllegalStateException();\n\t\t\t}\n\t\t\tXATerminatorOptd terminatorOne = new XATerminatorOptd();\n\t\t\tterminatorOne.setBeanFactory(this.beanFactory);\n\t\t\tterminatorOne.getResourceArchives().add(this.participant);\n\n\t\t\tXATerminatorImpl terminatorTwo = new XATerminatorImpl();\n\t\t\tterminatorTwo.setBeanFactory(this.beanFactory);\n\t\t\tterminatorTwo.getResourceArchives().addAll(this.nativeParticipantList);\n\t\t\tterminatorTwo.getResourceArchives().addAll(this.remoteParticipantList);\n\n\t\t\tthis.transactionStrategy = new LastResourceOptimizeStrategy(terminatorOne, terminatorTwo);\n\t\t} else {\n\t\t\tif (this.participant != null || nativeResNum > 0 || remoteResNum > 0) {\n\t\t\t\tthrow new IllegalStateException();\n\t\t\t}\n\t\t\tthis.transactionStrategy = new VacantTransactionStrategy();\n\t\t}\n\n\t}\n\n\tpublic XAResourceDescriptor getResourceDescriptor(String beanId) {\n\t\tXAResourceArchive archive = this.nativeParticipantMap.get(beanId);\n\t\treturn archive == null ? null : archive.getDescriptor();\n\t}\n\n\tpublic XAResourceDescriptor getRemoteCoordinator(RemoteSvc remoteSvc) {\n\t\tXAResourceArchive archive = this.remoteParticipantMap.get(remoteSvc);\n\t\treturn archive == null ? null : archive.getDescriptor();\n\t}\n\n\tpublic XAResourceDescriptor getRemoteCoordinator(String application) {\n\t\tRemoteSvc remoteSvc = new RemoteSvc();\n\t\tremoteSvc.setServiceKey(application);\n\t\tXAResourceArchive archive = this.remoteParticipantMap.get(remoteSvc);\n\t\treturn archive == null ? null : archive.getDescriptor();\n\t}\n\n\tpublic TransactionXid getTransactionXid() {\n\t\tthrow new IllegalStateException();\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n\tpublic boolean isLocalTransaction() {\n\t\treturn this.participantList.size() <= 1;\n\t}\n\n\tpublic Exception getCreatedAt() {\n\t\treturn createdAt;\n\t}\n\n\tpublic void setCreatedAt(Exception createdAt) {\n\t\tthis.createdAt = createdAt;\n\t}\n\n\tpublic void setTransactionStrategy(TransactionStrategy transactionStrategy) {\n\t\tthis.transactionStrategy = transactionStrategy;\n\t}\n\n\tpublic TransactionExtra getTransactionalExtra() {\n\t\treturn transactionalExtra;\n\t}\n\n\tpublic void setTransactionalExtra(TransactionExtra transactionalExtra) {\n\t\tthis.transactionalExtra = transactionalExtra;\n\t}\n\n\tpublic TransactionContext getTransactionContext() {\n\t\treturn transactionContext;\n\t}\n\n\tpublic boolean isTiming() {\n\t\treturn timing;\n\t}\n\n\tpublic void setTiming(boolean timing) {\n\t\tthis.timing = timing;\n\t}\n\n\tpublic int getTransactionStatus() {\n\t\treturn transactionStatus;\n\t}\n\n\tpublic void setTransactionStatus(int transactionStatus) {\n\t\tthis.transactionStatus = transactionStatus;\n\t}\n\n\tpublic int getTransactionTimeout() {\n\t\treturn transactionTimeout;\n\t}\n\n\tpublic void setTransactionTimeout(int transactionTimeout) {\n\t\tthis.transactionTimeout = transactionTimeout;\n\t}\n\n\tpublic XAResourceArchive getParticipant() {\n\t\treturn participant;\n\t}\n\n\tpublic Map<RemoteSvc, XAResourceArchive> getRemoteParticipantMap() {\n\t\treturn remoteParticipantMap;\n\t}\n\n\tpublic Map<String, XAResourceArchive> getNativeParticipantMap() {\n\t\treturn nativeParticipantMap;\n\t}\n\n\tpublic List<XAResourceArchive> getParticipantList() {\n\t\treturn participantList;\n\t}\n\n\tpublic void setParticipant(XAResourceArchive participant) {\n\t\tthis.participant = participant;\n\t}\n\n\tpublic List<XAResourceArchive> getNativeParticipantList() {\n\t\treturn nativeParticipantList;\n\t}\n\n\tpublic List<XAResourceArchive> getRemoteParticipantList() {\n\t\treturn remoteParticipantList;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionManagerImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.InvalidTransactionException;\nimport javax.transaction.NotSupportedException;\nimport javax.transaction.RollbackException;\nimport javax.transaction.Status;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.RollbackRequiredException;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.TransactionRepository;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.aware.TransactionDebuggable;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.supports.TransactionTimer;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionManagerImpl\n\t\timplements TransactionManager, TransactionTimer, TransactionBeanFactoryAware, TransactionDebuggable {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionManagerImpl.class);\n\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate int timeoutSeconds = 5 * 60;\n\tprivate final Map<Thread, Transaction> thread2txMap = new ConcurrentHashMap<Thread, Transaction>();\n\tprivate final Map<Xid, Transaction> xid2txMap = new ConcurrentHashMap<Xid, Transaction>();\n\tprivate boolean debuggingEnabled;\n\n\tpublic void begin() throws NotSupportedException, SystemException {\n\t\tif (this.getTransaction() != null) {\n\t\t\tthrow new NotSupportedException();\n\t\t}\n\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) this.beanFactory.getNativeParticipant();\n\n\t\tint timeoutSeconds = this.timeoutSeconds;\n\n\t\tTransactionContext transactionContext = new TransactionContext();\n\t\ttransactionContext.setPropagatedBy(transactionCoordinator.getIdentifier());\n\t\ttransactionContext.setCoordinator(true);\n\t\tlong createdTime = System.currentTimeMillis();\n\t\tlong expiredTime = createdTime + (timeoutSeconds * 1000L);\n\t\ttransactionContext.setCreatedTime(createdTime);\n\t\ttransactionContext.setExpiredTime(expiredTime);\n\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid();\n\t\ttransactionContext.setXid(globalXid);\n\n\t\tTransactionImpl transaction = new TransactionImpl(transactionContext);\n\t\ttransaction.setBeanFactory(this.beanFactory);\n\t\ttransaction.setTransactionTimeout(this.timeoutSeconds);\n\n\t\tif (this.debuggingEnabled) {\n\t\t\ttransaction.setCreatedAt(new Exception());\n\t\t} // end-if (this.debuggingEnabled)\n\n\t\tthis.associateThread(transaction);\n\t\tTransactionRepository transactionRepository = this.beanFactory.getTransactionRepository();\n\t\ttransactionRepository.putTransaction(globalXid, transaction);\n\t\t// this.transactionStatistic.fireBeginTransaction(transaction);\n\n\t\tlogger.info(\"{}> begin-transaction\", ByteUtils.byteArrayToString(globalXid.getGlobalTransactionId()));\n\t}\n\n\tpublic void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException,\n\t\t\tIllegalStateException, SystemException {\n\t\tTransaction transaction = this.getTransactionQuietly(); // this.desociateThread();\n\t\tif (transaction == null) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (transaction.getTransactionStatus() == Status.STATUS_ROLLEDBACK) {\n\t\t\tthis.desociateThread();\n\t\t\tthrow new RollbackException();\n\t\t} else if (transaction.getTransactionStatus() == Status.STATUS_COMMITTED) {\n\t\t\tthis.desociateThread();\n\t\t\treturn;\n\t\t} else if (transaction.getTransactionStatus() == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthis.rollback(transaction);\n\t\t\tthrow new HeuristicRollbackException();\n\t\t} else if (transaction.getTransactionStatus() != Status.STATUS_ACTIVE) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tTransactionRepository transactionRepository = this.beanFactory.getTransactionRepository();\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\tTransactionXid transactionXid = transactionContext.getXid();\n\n\t\tboolean beforeCompletionFailure = true;\n\t\ttry {\n\t\t\ttransaction.fireBeforeTransactionCompletion();\n\t\t\tthis.desociateThread();\n\n\t\t\tthis.stopTiming(transaction); // stop timing\n\n\t\t\tbeforeCompletionFailure = false;\n\t\t} catch (RollbackRequiredException rrex) {\n\t\t\tthis.desociateThread();\n\t\t\ttransaction.rollback();\n\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rrex);\n\t\t\tthrow hrex;\n\t\t} catch (SystemException ex) {\n\t\t\tthis.desociateThread();\n\t\t\ttransaction.rollback();\n\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(ex);\n\t\t\tthrow hrex;\n\t\t} catch (RuntimeException rex) {\n\t\t\tthis.desociateThread();\n\t\t\ttransaction.rollback();\n\n\t\t\tHeuristicRollbackException hrex = new HeuristicRollbackException();\n\t\t\threx.initCause(rex);\n\t\t\tthrow hrex;\n\t\t} finally {\n\t\t\tif (beforeCompletionFailure) {\n\t\t\t\ttransaction.fireAfterTransactionCompletion();\n\t\t\t} // end-if (beforeCompletionFailure)\n\t\t}\n\n\t\ttry {\n\t\t\ttransaction.commit();\n\t\t\ttransaction.forgetQuietly(); // forget transaction\n\t\t} catch (IllegalStateException ex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} catch (SecurityException ex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} catch (RollbackException rex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", rex);\n\t\t\ttransaction.forgetQuietly(); // forget transaction\n\t\t\tthrow rex;\n\t\t} catch (HeuristicMixedException hmex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", hmex);\n\t\t\ttransaction.forgetQuietly(); // forget transaction\n\t\t\tthrow hmex;\n\t\t} catch (HeuristicRollbackException hrex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", hrex);\n\t\t\ttransaction.forgetQuietly(); // forget transaction\n\t\t\tthrow hrex;\n\t\t} catch (SystemException ex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction.\", rex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow rex;\n\t\t} finally {\n\t\t\ttransaction.fireAfterTransactionCompletion();\n\t\t}\n\t}\n\n\tpublic void rollback() throws IllegalStateException, SecurityException, SystemException {\n\t\tTransaction transaction = this.getTransactionQuietly(); // this.desociateThread();\n\n\t\tif (transaction == null) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (transaction.getTransactionStatus() == Status.STATUS_ROLLEDBACK) {\n\t\t\tthis.desociateThread();\n\t\t\treturn;\n\t\t} else if (transaction.getTransactionStatus() == Status.STATUS_COMMITTED) {\n\t\t\tthis.desociateThread();\n\t\t\tthrow new SystemException();\n\t\t}\n\n\t\tthis.rollback(transaction);\n\t}\n\n\tprotected void rollback(Transaction transaction) throws IllegalStateException, SecurityException, SystemException {\n\t\tTransactionRepository transactionRepository = this.beanFactory.getTransactionRepository();\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\tTransactionXid transactionXid = transactionContext.getXid();\n\n\t\ttry {\n\t\t\ttransaction.fireBeforeTransactionCompletionQuietly();\n\t\t\tthis.desociateThread();\n\n\t\t\tthis.stopTiming(transaction); // stop timing\n\n\t\t\ttransaction.rollback();\n\t\t\ttransaction.forgetQuietly();\n\t\t} catch (IllegalStateException ex) {\n\t\t\tlogger.error(\"Error occurred while rolling back transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} catch (SecurityException ex) {\n\t\t\tlogger.error(\"Error occurred while rolling back transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} catch (SystemException ex) {\n\t\t\tlogger.error(\"Error occurred while rolling back transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while rolling back transaction.\", ex);\n\t\t\ttransactionRepository.putErrorTransaction(transactionXid, transaction);\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\ttransaction.fireAfterTransactionCompletion();\n\t\t}\n\t}\n\n\tpublic void associateThread(Transaction transaction) {\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\tTransactionXid transactionXid = transactionContext.getXid();\n\t\tthis.xid2txMap.put(transactionXid, transaction);\n\t\tthis.thread2txMap.put(Thread.currentThread(), transaction);\n\t}\n\n\tpublic Transaction desociateThread() {\n\t\tTransaction transaction = this.thread2txMap.remove(Thread.currentThread());\n\t\tif (transaction == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\tthis.xid2txMap.remove(transactionContext.getXid());\n\t\treturn transaction;\n\t}\n\n\tpublic Transaction suspend() throws RollbackRequiredException, SystemException {\n\t\tTransaction transaction = this.desociateThread();\n\t\tif (transaction == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttransaction.suspend();\n\t\treturn transaction;\n\t}\n\n\tpublic void resume(javax.transaction.Transaction tobj)\n\t\t\tthrows InvalidTransactionException, IllegalStateException, RollbackRequiredException, SystemException {\n\n\t\tif (tobj == null) {\n\t\t\tthrow new InvalidTransactionException();\n\t\t}\n\n\t\tif (TransactionImpl.class.isInstance(tobj) == false) {\n\t\t\tthrow new InvalidTransactionException();\n\t\t} else if (this.getTransaction() != null) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tTransactionImpl transaction = (TransactionImpl) tobj;\n\t\ttransaction.resume();\n\t\tthis.associateThread(transaction);\n\n\t}\n\n\tpublic int getStatus() throws SystemException {\n\t\tTransaction transaction = this.getTransaction();\n\t\treturn transaction == null ? Status.STATUS_NO_TRANSACTION : transaction.getTransactionStatus();\n\t}\n\n\tpublic Transaction getTransaction(Xid transactionXid) {\n\t\treturn this.xid2txMap.get(transactionXid);\n\t}\n\n\tpublic Transaction getTransaction(Thread thread) {\n\t\treturn this.thread2txMap.get(thread);\n\t}\n\n\tpublic Transaction getTransactionQuietly() {\n\t\ttry {\n\t\t\treturn this.getTransaction();\n\t\t} catch (SystemException ex) {\n\t\t\treturn null;\n\t\t} catch (RuntimeException ex) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic Transaction getTransaction() throws SystemException {\n\t\treturn this.thread2txMap.get(Thread.currentThread());\n\t}\n\n\tpublic void setRollbackOnlyQuietly() {\n\t\tTransaction transaction = this.getTransactionQuietly();\n\t\tif (transaction != null) {\n\t\t\ttransaction.setRollbackOnlyQuietly();\n\t\t}\n\t}\n\n\tpublic void setRollbackOnly() throws IllegalStateException, SystemException {\n\t\tTransaction transaction = this.getTransaction();\n\t\tif (transaction == null) {\n\t\t\tthrow new SystemException();\n\t\t}\n\t\ttransaction.setRollbackOnly();\n\t}\n\n\tpublic void setTransactionTimeout(int seconds) throws SystemException {\n\t\tTransaction transaction = this.getTransaction();\n\t\tif (transaction == null) {\n\t\t\tthrow new SystemException();\n\t\t} else if (seconds < 0) {\n\t\t\tthrow new SystemException();\n\t\t} else if (seconds == 0) {\n\t\t\t// ignore\n\t\t} else {\n\t\t\t((TransactionImpl) transaction).changeTransactionTimeout(seconds * 1000);\n\t\t}\n\t}\n\n\tpublic void timingExecution() {\n\t\tList<Transaction> expiredTransactions = new ArrayList<Transaction>();\n\t\tList<Transaction> activeTransactions = new ArrayList<Transaction>(this.thread2txMap.values());\n\t\tlong current = System.currentTimeMillis();\n\t\tIterator<Transaction> activeItr = activeTransactions.iterator();\n\t\twhile (activeItr.hasNext()) {\n\t\t\tTransaction transaction = activeItr.next();\n\t\t\tif (transaction.isTiming()) {\n\t\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\t\tif (transactionContext.getExpiredTime() <= current) {\n\t\t\t\t\texpiredTransactions.add(transaction);\n\t\t\t\t}\n\t\t\t} // end-if (transaction.isTiming())\n\t\t}\n\n\t\tIterator<Transaction> expiredItr = expiredTransactions.iterator();\n\t\twhile (activeItr.hasNext()) {\n\t\t\tTransaction transaction = expiredItr.next();\n\t\t\tif (transaction.getTransactionStatus() == Status.STATUS_ACTIVE\n\t\t\t\t\t|| transaction.getTransactionStatus() == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\t\tthis.timingRollback(transaction);\n\t\t\t}\n\t\t}\n\n\t}\n\n\tprivate void timingRollback(Transaction transaction) {\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\tTransactionXid globalXid = transactionContext.getXid();\n\t\tTransactionRepository transactionRepository = this.beanFactory.getTransactionRepository();\n\n\t\ttry {\n\t\t\tthis.associateThread(transaction);\n\t\t\ttransaction.fireBeforeTransactionCompletionQuietly();\n\t\t\tthis.desociateThread();\n\n\t\t\ttransaction.rollback();\n\t\t\ttransaction.forgetQuietly(); // forget transaction\n\t\t} catch (Exception ex) {\n\t\t\ttransactionRepository.putErrorTransaction(globalXid, transaction);\n\t\t} finally {\n\t\t\ttransaction.fireAfterTransactionCompletion();\n\t\t}\n\t}\n\n\tpublic void stopTiming(Transaction transaction) {\n\t\tif (TransactionImpl.class.isInstance(transaction)) {\n\t\t\t((TransactionImpl) transaction).stopTiming();\n\t\t}\n\t}\n\n\tpublic boolean isDebuggingEnabled() {\n\t\treturn debuggingEnabled;\n\t}\n\n\tpublic void setDebuggingEnabled(boolean debuggingEnabled) {\n\t\tthis.debuggingEnabled = debuggingEnabled;\n\t}\n\n\tpublic int getTimeoutSeconds() {\n\t\treturn timeoutSeconds;\n\t}\n\n\tpublic void setTimeoutSeconds(int timeoutSeconds) {\n\t\tthis.timeoutSeconds = timeoutSeconds;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn this.beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionRecoveryImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.transaction.Status;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAResource;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionRecovery;\nimport org.bytesoft.transaction.TransactionRepository;\nimport org.bytesoft.transaction.archive.TransactionArchive;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.logging.TransactionLogger;\nimport org.bytesoft.transaction.recovery.TransactionRecoveryCallback;\nimport org.bytesoft.transaction.recovery.TransactionRecoveryListener;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionRecoveryImpl implements TransactionRecovery, TransactionBeanFactoryAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionRecoveryImpl.class);\n\tstatic final long SECOND_MILLIS = 1000L;\n\n\tprivate TransactionRecoveryListener listener;\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate volatile boolean initialized;\n\n\tpublic synchronized void timingRecover() {\n\t\tTransactionRepository transactionRepository = beanFactory.getTransactionRepository();\n\t\tList<Transaction> transactions = transactionRepository.getErrorTransactionList();\n\t\tint total = transactions == null ? 0 : transactions.size(), value = 0;\n\t\tfor (int i = 0; transactions != null && i < transactions.size(); i++) {\n\t\t\tTransaction transaction = transactions.get(i);\n\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\tTransactionXid xid = transactionContext.getXid();\n\t\t\tint recoveredTimes = transactionContext.getRecoveredTimes() > 10 ? 10 : transactionContext.getRecoveredTimes();\n\t\t\tlong recoverMillis = transactionContext.getCreatedTime() + SECOND_MILLIS * 60L * (long) Math.pow(2, recoveredTimes);\n\n\t\t\tif (System.currentTimeMillis() < recoverMillis) {\n\t\t\t\tcontinue;\n\t\t\t} // end-if (System.currentTimeMillis() < recoverMillis)\n\n\t\t\ttry {\n\t\t\t\tthis.recoverTransaction(transaction);\n\t\t\t\tvalue++;\n\t\t\t} catch (CommitRequiredException ex) {\n\t\t\t\tlogger.debug(\"{}> recover: branch={}, message= commit-required\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()),\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getBranchQualifier()), ex);\n\t\t\t\tcontinue;\n\t\t\t} catch (RollbackRequiredException ex) {\n\t\t\t\tlogger.debug(\"{}> recover: branch={}, message= rollback-required\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getGlobalTransactionId()),\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getBranchQualifier()), ex);\n\t\t\t\tcontinue;\n\t\t\t} catch (SystemException ex) {\n\t\t\t\tlogger.debug(\"{}> recover: branch={}, message= {}\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()),\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getBranchQualifier()), ex.getMessage(), ex);\n\t\t\t\tcontinue;\n\t\t\t} catch (RuntimeException ex) {\n\t\t\t\tlogger.debug(\"{}> recover: branch={}, message= {}\", ByteUtils.byteArrayToString(xid.getGlobalTransactionId()),\n\t\t\t\t\t\tByteUtils.byteArrayToString(xid.getBranchQualifier()), ex.getMessage(), ex);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tlogger.debug(\"[transaction-recovery] total= {}, success= {}\", total, value);\n\t}\n\n\tpublic void recoverTransaction(Transaction transaction)\n\t\t\tthrows CommitRequiredException, RollbackRequiredException, SystemException {\n\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\tboolean coordinator = transactionContext.isCoordinator();\n\t\tif (coordinator) {\n\t\t\ttransaction.recover();\n\t\t\tthis.recoverCoordinator(transaction);\n\t\t} else {\n\t\t\ttransaction.recover();\n\t\t\tthis.recoverParticipant(transaction);\n\t\t}\n\n\t}\n\n\tprotected void recoverCoordinator(Transaction transaction)\n\t\t\tthrows CommitRequiredException, RollbackRequiredException, SystemException {\n\n\t\tswitch (transaction.getTransactionStatus()) {\n\t\tcase Status.STATUS_ACTIVE:\n\t\tcase Status.STATUS_MARKED_ROLLBACK:\n\t\tcase Status.STATUS_PREPARING:\n\t\tcase Status.STATUS_ROLLING_BACK:\n\t\tcase Status.STATUS_UNKNOWN:\n\t\t\ttransaction.recoveryRollback();\n\t\t\ttransaction.forgetQuietly();\n\t\t\tbreak;\n\t\tcase Status.STATUS_PREPARED:\n\t\tcase Status.STATUS_COMMITTING:\n\t\t\ttransaction.recoveryCommit();\n\t\t\ttransaction.forgetQuietly();\n\t\t\tbreak;\n\t\tcase Status.STATUS_COMMITTED:\n\t\tcase Status.STATUS_ROLLEDBACK:\n\t\t\ttransaction.forgetQuietly();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tlogger.debug(\"Current transaction has already been completed.\");\n\t\t}\n\t}\n\n\tprotected void recoverParticipant(Transaction transaction)\n\t\t\tthrows CommitRequiredException, RollbackRequiredException, SystemException {\n\n\t\tTransactionImpl transactionImpl = (TransactionImpl) transaction;\n\t\tswitch (transaction.getTransactionStatus()) {\n\t\tcase Status.STATUS_PREPARED:\n\t\tcase Status.STATUS_COMMITTING:\n\t\t\tbreak;\n\t\tcase Status.STATUS_COMMITTED:\n\t\tcase Status.STATUS_ROLLEDBACK:\n\t\t\tbreak;\n\t\tcase Status.STATUS_ACTIVE:\n\t\tcase Status.STATUS_MARKED_ROLLBACK:\n\t\tcase Status.STATUS_PREPARING:\n\t\tcase Status.STATUS_UNKNOWN:\n\t\tcase Status.STATUS_ROLLING_BACK:\n\t\tdefault:\n\t\t\ttransactionImpl.recoveryRollback();\n\t\t\ttransactionImpl.forgetQuietly();\n\t\t}\n\t}\n\n\tpublic synchronized void startRecovery() {\n\t\tfinal TransactionRepository transactionRepository = beanFactory.getTransactionRepository();\n\t\tfinal TransactionLogger transactionLogger = beanFactory.getTransactionLogger();\n\t\ttransactionLogger.recover(new TransactionRecoveryCallback() {\n\t\t\tpublic void recover(TransactionArchive archive) {\n\t\t\t\ttry {\n\t\t\t\t\tTransactionImpl transaction = (TransactionImpl) reconstruct(archive);\n\t\t\t\t\tif (listener != null) {\n\t\t\t\t\t\tlistener.onRecovery(transaction);\n\t\t\t\t\t}\n\t\t\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\t\t\tTransactionXid globalXid = transactionContext.getXid();\n\t\t\t\t\ttransactionRepository.putTransaction(globalXid, transaction);\n\t\t\t\t\ttransactionRepository.putErrorTransaction(globalXid, transaction);\n\t\t\t\t} catch (IllegalStateException ex) {\n\t\t\t\t\ttransactionLogger.deleteTransaction(archive);\n\t\t\t\t}\n\n\t\t\t}\n\t\t});\n\n\t\tTransactionCoordinator transactionCoordinator = //\n\t\t\t\t(TransactionCoordinator) this.beanFactory.getNativeParticipant();\n\t\ttransactionCoordinator.markParticipantReady();\n\t\tthis.initialized = true; // timingRecovery should be executed after initialization\n\t}\n\n\tpublic org.bytesoft.transaction.Transaction reconstruct(TransactionArchive archive) throws IllegalStateException {\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\tTransactionContext transactionContext = new TransactionContext();\n\t\tTransactionXid xid = (TransactionXid) archive.getXid();\n\t\ttransactionContext.setXid(xidFactory.createGlobalXid(xid.getGlobalTransactionId()));\n\t\ttransactionContext.setRecoveried(true);\n\t\ttransactionContext.setCoordinator(archive.isCoordinator());\n\t\ttransactionContext.setPropagatedBy(archive.getPropagatedBy());\n\t\ttransactionContext.setRecoveredTimes(archive.getRecoveredTimes());\n\t\ttransactionContext.setCreatedTime(archive.getRecoveredAt());\n\n\t\tTransactionImpl transaction = new TransactionImpl(transactionContext);\n\t\ttransaction.setBeanFactory(this.beanFactory);\n\t\ttransaction.setTransactionStatus(archive.getStatus());\n\n\t\tList<XAResourceArchive> nativeResources = archive.getNativeResources();\n\t\ttransaction.getNativeParticipantList().addAll(nativeResources);\n\n\t\ttransaction.setParticipant(archive.getOptimizedResource());\n\n\t\tList<XAResourceArchive> remoteResources = archive.getRemoteResources();\n\t\ttransaction.getRemoteParticipantList().addAll(remoteResources);\n\n\t\tList<XAResourceArchive> participants = transaction.getParticipantList();\n\t\tMap<String, XAResourceArchive> nativeParticipantMap = transaction.getNativeParticipantMap();\n\t\tMap<RemoteSvc, XAResourceArchive> remoteParticipantMap = transaction.getRemoteParticipantMap();\n\n\t\tif (archive.getOptimizedResource() != null) {\n\t\t\tXAResourceArchive optimized = archive.getOptimizedResource();\n\t\t\tXAResourceDescriptor descriptor = optimized.getDescriptor();\n\t\t\tString identifier = descriptor.getIdentifier();\n\t\t\tif (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\t\tRemoteSvc remoteSvc = CommonUtils.getRemoteSvc(identifier);\n\t\t\t\tremoteParticipantMap.put(remoteSvc, optimized);\n\t\t\t} else {\n\t\t\t\tnativeParticipantMap.put(identifier, optimized);\n\t\t\t}\n\n\t\t\tparticipants.add(optimized);\n\t\t}\n\n\t\tfor (int i = 0; i < nativeResources.size(); i++) {\n\t\t\tXAResourceArchive element = nativeResources.get(i);\n\t\t\tXAResourceDescriptor descriptor = element.getDescriptor();\n\t\t\tString identifier = StringUtils.trimToEmpty(descriptor.getIdentifier());\n\t\t\tnativeParticipantMap.put(identifier, element);\n\t\t}\n\t\tparticipants.addAll(nativeResources);\n\n\t\tfor (int i = 0; i < remoteResources.size(); i++) {\n\t\t\tXAResourceArchive element = remoteResources.get(i);\n\t\t\tXAResourceDescriptor descriptor = element.getDescriptor();\n\t\t\tString identifier = StringUtils.trimToEmpty(descriptor.getIdentifier());\n\n\t\t\tif (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\t\tRemoteSvc remoteSvc = CommonUtils.getRemoteSvc(identifier);\n\t\t\t\tremoteParticipantMap.put(remoteSvc, element);\n\t\t\t} // end-if (RemoteResourceDescriptor.class.isInstance(descriptor))\n\t\t}\n\t\tparticipants.addAll(remoteResources);\n\n\t\ttransaction.recoverTransactionStrategy(archive.getTransactionStrategyType());\n\n\t\tif (archive.getVote() == XAResource.XA_RDONLY) {\n\t\t\tthrow new IllegalStateException(\"Transaction has already been completed!\");\n\t\t}\n\n\t\treturn transaction;\n\t}\n\n\tpublic synchronized void branchRecover() {\n\t\t// For a completed global transaction, if its branch receives a business request again, it will be rolled back by the\n\t\t// RM's timeout mechanism, there is no need to deal with it.\n\t}\n\n\tpublic boolean isInitialized() {\n\t\treturn initialized;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n\tpublic TransactionRecoveryListener getListener() {\n\t\treturn listener;\n\t}\n\n\tpublic void setListener(TransactionRecoveryListener listener) {\n\t\tthis.listener = listener;\n\t}\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionRepositoryImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionRepository;\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic class TransactionRepositoryImpl implements TransactionRepository {\n\tprivate final Map<TransactionXid, Transaction> xidToTxMap = new ConcurrentHashMap<TransactionXid, Transaction>();\n\tprivate final Map<TransactionXid, Transaction> xidToErrTxMap = new ConcurrentHashMap<TransactionXid, Transaction>();\n\n\tpublic void putTransaction(TransactionXid globalXid, Transaction transaction) {\n\t\tthis.xidToTxMap.put(globalXid, transaction);\n\t}\n\n\tpublic Transaction getTransaction(TransactionXid globalXid) {\n\t\treturn this.xidToTxMap.get(globalXid);\n\t}\n\n\tpublic Transaction removeTransaction(TransactionXid globalXid) {\n\t\treturn this.xidToTxMap.remove(globalXid);\n\t}\n\n\tpublic void putErrorTransaction(TransactionXid globalXid, Transaction transaction) {\n\t\tthis.xidToErrTxMap.put(globalXid, transaction);\n\t}\n\n\tpublic Transaction getErrorTransaction(TransactionXid globalXid) {\n\t\treturn this.xidToErrTxMap.get(globalXid);\n\t}\n\n\tpublic Transaction removeErrorTransaction(TransactionXid globalXid) {\n\t\treturn this.xidToErrTxMap.remove(globalXid);\n\t}\n\n\tpublic List<Transaction> getErrorTransactionList() {\n\t\treturn new ArrayList<Transaction>(this.xidToErrTxMap.values());\n\t}\n\n\tpublic List<Transaction> getActiveTransactionList() {\n\t\treturn new ArrayList<Transaction>(this.xidToTxMap.values());\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/TransactionStrategy.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport javax.transaction.HeuristicCommitException;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\n\npublic interface TransactionStrategy /* extends TransactionBeanFactoryAware */ {\n\n\tpublic int TRANSACTION_STRATEGY_VACANT = 0;\n\tpublic int TRANSACTION_STRATEGY_SIMPLE = 1;\n\tpublic int TRANSACTION_STRATEGY_COMMON = 2;\n\tpublic int TRANSACTION_STRATEGY_LRO = 3;\n\n\tpublic int prepare(Xid xid) throws RollbackRequiredException, CommitRequiredException;\n\n\tpublic void commit(Xid xid, boolean onePhaseCommit)\n\t\t\tthrows HeuristicMixedException, HeuristicRollbackException, IllegalStateException, SystemException;\n\n\tpublic void rollback(Xid xid)\n\t\t\tthrows HeuristicMixedException, HeuristicCommitException, IllegalStateException, SystemException;\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/UserTransactionImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport java.io.Serializable;\n\nimport javax.naming.NamingException;\nimport javax.naming.Reference;\nimport javax.naming.Referenceable;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.NotSupportedException;\nimport javax.transaction.RollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.TransactionManager;\nimport javax.transaction.UserTransaction;\n\npublic class UserTransactionImpl implements UserTransaction, Referenceable, Serializable {\n\tprivate static final long serialVersionUID = 1L;\n\n\t@javax.inject.Inject\n\tprivate transient TransactionManager transactionManager;\n\n\tpublic void begin() throws NotSupportedException, SystemException {\n\t\tthis.transactionManager.begin();\n\t}\n\n\tpublic void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException,\n\t\t\tRollbackException, SecurityException, SystemException {\n\t\tthis.transactionManager.commit();\n\t}\n\n\tpublic int getStatus() throws SystemException {\n\t\treturn this.transactionManager.getStatus();\n\t}\n\n\tpublic void rollback() throws IllegalStateException, SecurityException, SystemException {\n\t\tthis.transactionManager.rollback();\n\t}\n\n\tpublic void setRollbackOnly() throws IllegalStateException, SystemException {\n\t\tthis.transactionManager.setRollbackOnly();\n\t}\n\n\tpublic void setTransactionTimeout(int timeout) throws SystemException {\n\t\tthis.transactionManager.setTransactionTimeout(timeout);\n\t}\n\n\tpublic Reference getReference() throws NamingException {\n\t\tthrow new NamingException(\"Not supported yet!\");\n\t}\n\n\tpublic TransactionManager getTransactionManager() {\n\t\treturn transactionManager;\n\t}\n\n\tpublic void setTransactionManager(TransactionManager transactionManager) {\n\t\tthis.transactionManager = transactionManager;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/VacantTransactionLock.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta;\n\nimport org.bytesoft.transaction.TransactionLock;\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic class VacantTransactionLock implements TransactionLock {\n\n\tpublic boolean lockTransaction(TransactionXid transactionXid, String identifier) {\n\t\treturn true;\n\t}\n\n\tpublic void unlockTransaction(TransactionXid transactionXid, String identifier) {\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/logging/ArchiveDeserializerImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.logging;\n\nimport org.bytesoft.transaction.archive.TransactionArchive;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.logging.ArchiveDeserializer;\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic class ArchiveDeserializerImpl implements ArchiveDeserializer {\n\tstatic final byte TYPE_TRANSACTION = 0x0;\n\tstatic final byte TYPE_XA_RESOURCE = 0x1;\n\n\tprivate ArchiveDeserializer xaResourceArchiveDeserializer;\n\tprivate ArchiveDeserializer transactionArchiveDeserializer;\n\n\tpublic byte[] serialize(TransactionXid xid, Object archive) {\n\n\t\tif (TransactionArchive.class.isInstance(archive)) {\n\t\t\tbyte[] array = this.transactionArchiveDeserializer.serialize(xid, archive);\n\t\t\tbyte[] byteArray = new byte[array.length + 1];\n\t\t\tbyteArray[0] = TYPE_TRANSACTION;\n\t\t\tSystem.arraycopy(array, 0, byteArray, 1, array.length);\n\t\t\treturn byteArray;\n\t\t} else if (XAResourceArchive.class.isInstance(archive)) {\n\t\t\tbyte[] array = this.xaResourceArchiveDeserializer.serialize(xid, archive);\n\t\t\tbyte[] byteArray = new byte[array.length + 1];\n\t\t\tbyteArray[0] = TYPE_XA_RESOURCE;\n\t\t\tSystem.arraycopy(array, 0, byteArray, 1, array.length);\n\t\t\treturn byteArray;\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t}\n\n\tpublic Object deserialize(TransactionXid xid, byte[] array) {\n\t\tif (array == null || array.length <= 1) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t\tbyte type = array[0];\n\t\tif (type == TYPE_TRANSACTION) {\n\t\t\tbyte[] byteArray = new byte[array.length - 1];\n\t\t\tSystem.arraycopy(array, 1, byteArray, 0, byteArray.length);\n\t\t\treturn this.transactionArchiveDeserializer.deserialize(xid, byteArray);\n\t\t} else if (type == TYPE_XA_RESOURCE) {\n\t\t\tbyte[] byteArray = new byte[array.length - 1];\n\t\t\tSystem.arraycopy(array, 1, byteArray, 0, byteArray.length);\n\t\t\treturn this.xaResourceArchiveDeserializer.deserialize(xid, byteArray);\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t}\n\n\tpublic ArchiveDeserializer getXaResourceArchiveDeserializer() {\n\t\treturn xaResourceArchiveDeserializer;\n\t}\n\n\tpublic void setXaResourceArchiveDeserializer(ArchiveDeserializer xaResourceArchiveDeserializer) {\n\t\tthis.xaResourceArchiveDeserializer = xaResourceArchiveDeserializer;\n\t}\n\n\tpublic ArchiveDeserializer getTransactionArchiveDeserializer() {\n\t\treturn transactionArchiveDeserializer;\n\t}\n\n\tpublic void setTransactionArchiveDeserializer(ArchiveDeserializer transactionArchiveDeserializer) {\n\t\tthis.transactionArchiveDeserializer = transactionArchiveDeserializer;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/logging/SampleTransactionLogger.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.logging;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.annotation.PostConstruct;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.logging.store.VirtualLoggingSystemImpl;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.archive.TransactionArchive;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.bytesoft.transaction.logging.ArchiveDeserializer;\nimport org.bytesoft.transaction.logging.LoggingFlushable;\nimport org.bytesoft.transaction.logging.TransactionLogger;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingListener;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingRecord;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingSystem;\nimport org.bytesoft.transaction.recovery.TransactionRecoveryCallback;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class SampleTransactionLogger extends VirtualLoggingSystemImpl\n\t\timplements TransactionLogger, LoggingFlushable, TransactionBeanFactoryAware, TransactionEndpointAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(SampleTransactionLogger.class);\n\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate String identifier;\n\n\t@PostConstruct\n\tpublic void construct() throws IOException {\n\t\tthis.initializeIfNecessary();\n\t}\n\n\tprivate void initializeIfNecessary() throws IllegalStateException {\n\t\tif (StringUtils.isNotBlank(this.identifier)) {\n\t\t\ttry {\n\t\t\t\tsuper.construct();\n\t\t\t} catch (IOException error) {\n\t\t\t\tthrow new IllegalStateException(\"Error occurred while initializing tx-log!\", error);\n\t\t\t}\n\t\t} // end-if (StringUtils.isNotBlank(this.endpoint))\n\t}\n\n\tpublic void createTransaction(TransactionArchive archive) {\n\t\tArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();\n\n\t\ttry {\n\t\t\tbyte[] byteArray = deserializer.serialize((TransactionXid) archive.getXid(), archive);\n\t\t\tthis.create(archive.getXid(), byteArray);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred while creating transaction-archive.\", rex);\n\t\t}\n\t}\n\n\tpublic void updateTransaction(TransactionArchive archive) {\n\t\tArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();\n\n\t\ttry {\n\t\t\tbyte[] byteArray = deserializer.serialize((TransactionXid) archive.getXid(), archive);\n\t\t\tthis.modify(archive.getXid(), byteArray);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred while modifying transaction-archive.\", rex);\n\t\t}\n\t}\n\n\tpublic void deleteTransaction(TransactionArchive archive) {\n\t\ttry {\n\t\t\tthis.delete(archive.getXid());\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred while deleting transaction-archive.\", rex);\n\t\t}\n\t}\n\n\tpublic void createParticipant(XAResourceArchive archive) {\n\t}\n\n\tpublic void updateParticipant(XAResourceArchive archive) {\n\t\tArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();\n\n\t\ttry {\n\t\t\tbyte[] byteArray = deserializer.serialize((TransactionXid) archive.getXid(), archive);\n\t\t\tthis.modify(archive.getXid(), byteArray);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred while modifying resource-archive.\", rex);\n\t\t}\n\t}\n\n\tpublic void deleteParticipant(XAResourceArchive archive) {\n\t}\n\n\tpublic void createResource(XAResourceArchive archive) {\n\t}\n\n\tpublic void updateResource(XAResourceArchive archive) {\n\t}\n\n\tpublic void deleteResource(XAResourceArchive archive) {\n\t}\n\n\tpublic List<VirtualLoggingRecord> compressIfNecessary(List<VirtualLoggingRecord> recordList) {\n\t\tArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\n\t\tList<VirtualLoggingRecord> resultList = new ArrayList<VirtualLoggingRecord>();\n\n\t\tMap<TransactionXid, TransactionArchive> xidMap = new HashMap<TransactionXid, TransactionArchive>();\n\t\tfor (int index = 0; recordList != null && index < recordList.size(); index++) {\n\t\t\tVirtualLoggingRecord record = recordList.get(index);\n\t\t\tbyte[] byteArray = record.getContent();\n\t\t\tbyte[] keyByteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH];\n\t\t\tSystem.arraycopy(byteArray, 0, keyByteArray, 0, keyByteArray.length);\n\t\t\t// int operator = byteArray[keyByteArray.length];\n\t\t\tbyte[] valueByteArray = new byte[byteArray.length - XidFactory.GLOBAL_TRANSACTION_LENGTH - 1 - 4];\n\t\t\tSystem.arraycopy(byteArray, XidFactory.GLOBAL_TRANSACTION_LENGTH + 1 + 4, valueByteArray, 0, valueByteArray.length);\n\n\t\t\tTransactionXid xid = xidFactory.createGlobalXid(keyByteArray);\n\n\t\t\tObject obj = deserializer.deserialize(xid, valueByteArray);\n\t\t\tif (TransactionArchive.class.isInstance(obj)) {\n\t\t\t\txidMap.put(xid, (TransactionArchive) obj);\n\t\t\t} else if (XAResourceArchive.class.isInstance(obj)) {\n\t\t\t\tTransactionArchive archive = xidMap.get(xid);\n\t\t\t\tif (archive == null) {\n\t\t\t\t\tlogger.error(\"Error occurred while compressing resource archive: {}\", obj);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tXAResourceArchive resourceArchive = (XAResourceArchive) obj;\n\t\t\t\tboolean matched = false;\n\n\t\t\t\tList<XAResourceArchive> nativeResources = archive.getNativeResources();\n\t\t\t\tfor (int i = 0; matched == false && nativeResources != null && i < nativeResources.size(); i++) {\n\t\t\t\t\tXAResourceArchive element = nativeResources.get(i);\n\t\t\t\t\tif (resourceArchive.getXid().equals(element.getXid())) {\n\t\t\t\t\t\tmatched = true;\n\t\t\t\t\t\tnativeResources.set(i, resourceArchive);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tXAResourceArchive optimizedResource = archive.getOptimizedResource();\n\t\t\t\tif (matched == false && optimizedResource != null) {\n\t\t\t\t\tif (resourceArchive.getXid().equals(optimizedResource.getXid())) {\n\t\t\t\t\t\tmatched = true;\n\t\t\t\t\t\tarchive.setOptimizedResource(resourceArchive);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tList<XAResourceArchive> remoteResources = archive.getRemoteResources();\n\t\t\t\tfor (int i = 0; matched == false && remoteResources != null && i < remoteResources.size(); i++) {\n\t\t\t\t\tXAResourceArchive element = remoteResources.get(i);\n\t\t\t\t\tif (resourceArchive.getXid().equals(element.getXid())) {\n\t\t\t\t\t\tmatched = true;\n\t\t\t\t\t\tremoteResources.set(i, resourceArchive);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (matched == false) {\n\t\t\t\t\tlogger.error(\"Error occurred while compressing resource archive: {}, invalid resoure!\", obj);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tlogger.error(\"unkown resource: {}!\", obj);\n\t\t\t}\n\t\t}\n\n\t\tfor (Iterator<Map.Entry<TransactionXid, TransactionArchive>> itr = xidMap.entrySet().iterator(); itr.hasNext();) {\n\t\t\tMap.Entry<TransactionXid, TransactionArchive> entry = itr.next();\n\t\t\tTransactionXid xid = entry.getKey();\n\t\t\tTransactionArchive value = entry.getValue();\n\n\t\t\tbyte[] globalByteArray = xid.getGlobalTransactionId();\n\n\t\t\tbyte[] keyByteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH];\n\t\t\tbyte[] valueByteArray = deserializer.serialize(xid, value);\n\t\t\tbyte[] sizeByteArray = ByteUtils.intToByteArray(valueByteArray.length);\n\n\t\t\tSystem.arraycopy(globalByteArray, 0, keyByteArray, 0, XidFactory.GLOBAL_TRANSACTION_LENGTH);\n\n\t\t\tbyte[] byteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH + 1 + 4 + valueByteArray.length];\n\n\t\t\tSystem.arraycopy(keyByteArray, 0, byteArray, 0, keyByteArray.length);\n\t\t\tbyteArray[keyByteArray.length] = OPERATOR_CREATE;\n\t\t\tSystem.arraycopy(sizeByteArray, 0, byteArray, XidFactory.GLOBAL_TRANSACTION_LENGTH + 1, sizeByteArray.length);\n\t\t\tSystem.arraycopy(valueByteArray, 0, byteArray, XidFactory.GLOBAL_TRANSACTION_LENGTH + 1 + 4, valueByteArray.length);\n\n\t\t\tVirtualLoggingRecord record = new VirtualLoggingRecord();\n\t\t\trecord.setIdentifier(xid);\n\t\t\trecord.setOperator(OPERATOR_CREATE);\n\t\t\trecord.setValue(valueByteArray);\n\t\t\trecord.setContent(byteArray);\n\n\t\t\tresultList.add(record);\n\t\t}\n\n\t\treturn resultList;\n\t}\n\n\tpublic void recover(TransactionRecoveryCallback callback) {\n\n\t\tfinal Map<Xid, TransactionArchive> xidMap = new HashMap<Xid, TransactionArchive>();\n\t\tfinal ArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();\n\t\tfinal XidFactory xidFactory = this.beanFactory.getXidFactory();\n\n\t\tthis.traversal(new VirtualLoggingListener() {\n\t\t\tpublic void recvOperation(VirtualLoggingRecord action) {\n\t\t\t\tXid xid = action.getIdentifier();\n\t\t\t\tint operator = action.getOperator();\n\t\t\t\tif (VirtualLoggingSystem.OPERATOR_DELETE == operator) {\n\t\t\t\t\txidMap.remove(xid);\n\t\t\t\t} else if (xidMap.containsKey(xid) == false) {\n\t\t\t\t\txidMap.put(xid, null);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.traversal(new VirtualLoggingListener() {\n\t\t\tpublic void recvOperation(VirtualLoggingRecord action) {\n\t\t\t\tXid xid = action.getIdentifier();\n\t\t\t\tif (xidMap.containsKey(xid)) {\n\t\t\t\t\tthis.execOperation(action);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic void execOperation(VirtualLoggingRecord action) {\n\t\t\t\tXid identifier = action.getIdentifier();\n\n\t\t\t\tTransactionXid xid = xidFactory.createGlobalXid(identifier.getGlobalTransactionId());\n\n\t\t\t\tObject obj = deserializer.deserialize(xid, action.getValue());\n\t\t\t\tif (TransactionArchive.class.isInstance(obj)) {\n\t\t\t\t\tTransactionArchive archive = (TransactionArchive) obj;\n\t\t\t\t\txidMap.put(identifier, archive);\n\t\t\t\t} else if (XAResourceArchive.class.isInstance(obj)) {\n\t\t\t\t\tTransactionArchive archive = xidMap.get(identifier);\n\t\t\t\t\tif (archive == null) {\n\t\t\t\t\t\tlogger.error(\"Error occurred while recovering resource archive: {}\", obj);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tXAResourceArchive resourceArchive = (XAResourceArchive) obj;\n\t\t\t\t\tboolean matched = false;\n\n\t\t\t\t\tList<XAResourceArchive> nativeResources = archive.getNativeResources();\n\t\t\t\t\tfor (int i = 0; matched == false && nativeResources != null && i < nativeResources.size(); i++) {\n\t\t\t\t\t\tXAResourceArchive element = nativeResources.get(i);\n\t\t\t\t\t\tif (resourceArchive.getXid().equals(element.getXid())) {\n\t\t\t\t\t\t\tmatched = true;\n\t\t\t\t\t\t\tnativeResources.set(i, resourceArchive);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tXAResourceArchive optimizedResource = archive.getOptimizedResource();\n\t\t\t\t\tif (matched == false && optimizedResource != null) {\n\t\t\t\t\t\tif (resourceArchive.getXid().equals(optimizedResource.getXid())) {\n\t\t\t\t\t\t\tmatched = true;\n\t\t\t\t\t\t\tarchive.setOptimizedResource(resourceArchive);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tList<XAResourceArchive> remoteResources = archive.getRemoteResources();\n\t\t\t\t\tfor (int i = 0; matched == false && remoteResources != null && i < remoteResources.size(); i++) {\n\t\t\t\t\t\tXAResourceArchive element = remoteResources.get(i);\n\t\t\t\t\t\tif (resourceArchive.getXid().equals(element.getXid())) {\n\t\t\t\t\t\t\tmatched = true;\n\t\t\t\t\t\t\tremoteResources.set(i, resourceArchive);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (matched == false) {\n\t\t\t\t\t\tlogger.error(\"Error occurred while recovering resource archive: {}, invalid resoure!\", obj);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t});\n\n\t\tfor (Iterator<Map.Entry<Xid, TransactionArchive>> itr = xidMap.entrySet().iterator(); itr.hasNext();) {\n\t\t\tMap.Entry<Xid, TransactionArchive> entry = itr.next();\n\t\t\tTransactionArchive archive = entry.getValue();\n\t\t\tif (archive == null) {\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tcallback.recover(archive);\n\t\t\t\t} catch (RuntimeException rex) {\n\t\t\t\t\tlogger.error(\"Error occurred while recovering transaction(xid= {}).\", archive.getXid(), rex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic File getDefaultDirectory() {\n\t\tString address = StringUtils.trimToEmpty(this.identifier);\n\t\tFile directory = new File(String.format(\"bytejta/%s\", address.replaceAll(\"\\\\W\", \"_\")));\n\t\tif (directory.exists() == false) {\n\t\t\ttry {\n\t\t\t\tboolean created = directory.mkdirs();\n\t\t\t\tif (created == false) {\n\t\t\t\t\tlogger.error(\"Failed to create directory {}!\", directory.getAbsolutePath());\n\t\t\t\t} // end-if (created == false)\n\t\t\t} catch (SecurityException ex) {\n\t\t\t\tlogger.error(\"Error occurred while creating directory {}!\", directory.getAbsolutePath(), ex);\n\t\t\t}\n\t\t}\n\t\treturn directory;\n\t}\n\n\tpublic int getMajorVersion() {\n\t\treturn 0;\n\t}\n\n\tpublic int getMinorVersion() {\n\t\treturn 6;\n\t}\n\n\tpublic String getLoggingFilePrefix() {\n\t\treturn \"bytejta-\";\n\t}\n\n\tpublic String getLoggingIdentifier() {\n\t\treturn \"org.bytesoft.bytejta.logging.sample\";\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.identifier = identifier;\n\t\tthis.initializeIfNecessary();\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory beanFactory) {\n\t\tthis.beanFactory = beanFactory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/logging/deserializer/TransactionArchiveDeserializer.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.logging.deserializer;\n\nimport java.nio.ByteBuffer;\nimport java.util.List;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.archive.TransactionArchive;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.logging.ArchiveDeserializer;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionArchiveDeserializer implements ArchiveDeserializer {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionArchiveDeserializer.class);\n\n\tprivate ArchiveDeserializer resourceArchiveDeserializer;\n\n\tpublic byte[] serialize(TransactionXid xid, Object obj) {\n\t\tTransactionArchive archive = (TransactionArchive) obj;\n\n\t\tString propagatedBy = String.valueOf(archive.getPropagatedBy());\n\t\t// String[] address = propagatedBy.split(\"\\\\s*\\\\:\\\\s*\");\n\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(propagatedBy);\n\t\tbyte[] hostByteArray = new byte[4];\n\t\tbyte[] nameByteArray = new byte[0];\n\t\tbyte[] portByteArray = new byte[2];\n\t\tif (remoteNode != null) {\n\t\t\tString hostStr = remoteNode.getServerHost();\n\t\t\tString nameStr = remoteNode.getServiceKey();\n\t\t\tString portStr = String.valueOf(remoteNode.getServerPort());\n\n\t\t\tString[] hostArray = hostStr.split(\"\\\\s*\\\\.\\\\s*\");\n\t\t\tfor (int i = 0; hostArray.length == 4 && i < hostArray.length; i++) {\n\t\t\t\ttry {\n\t\t\t\t\tint value = Integer.valueOf(hostArray[i]);\n\t\t\t\t\thostByteArray[i] = (byte) (value - 128);\n\t\t\t\t} catch (RuntimeException rex) {\n\t\t\t\t\tlogger.debug(rex.getMessage(), rex);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnameByteArray = StringUtils.isBlank(nameStr) ? new byte[0] : nameStr.getBytes();\n\n\t\t\ttry {\n\t\t\t\tshort port = (short) (Integer.valueOf(portStr) - 32768);\n\t\t\t\tbyte[] byteArray = ByteUtils.shortToByteArray(port);\n\t\t\t\tSystem.arraycopy(byteArray, 0, portByteArray, 0, 2);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.debug(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\n\t\tlong recoveredMillis = archive.getRecoveredAt();\n\t\tint recoveredTimes = archive.getRecoveredTimes();\n\n\t\tXAResourceArchive optimizedArchive = archive.getOptimizedResource();\n\n\t\tList<XAResourceArchive> nativeArchiveList = archive.getNativeResources();\n\t\tList<XAResourceArchive> remoteArchiveList = archive.getRemoteResources();\n\n\t\tint optimizedArchiveNumber = optimizedArchive == null ? 0 : 1;\n\n\t\tint nativeArchiveNumber = nativeArchiveList.size();\n\t\tint remoteArchiveNumber = remoteArchiveList.size();\n\n\t\tint transactionStrategy = archive.getTransactionStrategyType();\n\n\t\tint length = 3 + 3 + 1 + 4 + 1 + nameByteArray.length + 2 + 8 + 1;\n\t\tbyte[][] nativeByteArray = new byte[nativeArchiveNumber][];\n\t\tfor (int i = 0; i < nativeArchiveNumber; i++) {\n\t\t\tXAResourceArchive resourceArchive = nativeArchiveList.get(i);\n\n\t\t\tbyte[] resourceByteArray = this.resourceArchiveDeserializer.serialize(xid, resourceArchive);\n\t\t\tbyte[] lengthByteArray = ByteUtils.shortToByteArray((short) resourceByteArray.length);\n\n\t\t\tbyte[] elementByteArray = new byte[resourceByteArray.length + 2];\n\t\t\tSystem.arraycopy(lengthByteArray, 0, elementByteArray, 0, lengthByteArray.length);\n\t\t\tSystem.arraycopy(resourceByteArray, 0, elementByteArray, 2, resourceByteArray.length);\n\n\t\t\tnativeByteArray[i] = elementByteArray;\n\t\t\tlength = length + elementByteArray.length;\n\t\t}\n\n\t\tbyte[] optimizedByteArray = new byte[0];\n\t\tif (optimizedArchiveNumber > 0) {\n\t\t\tbyte[] resourceByteArray = this.resourceArchiveDeserializer.serialize(xid, optimizedArchive);\n\t\t\tbyte[] lengthByteArray = ByteUtils.shortToByteArray((short) resourceByteArray.length);\n\n\t\t\tbyte[] elementByteArray = new byte[resourceByteArray.length + 2];\n\t\t\tSystem.arraycopy(lengthByteArray, 0, elementByteArray, 0, lengthByteArray.length);\n\t\t\tSystem.arraycopy(resourceByteArray, 0, elementByteArray, 2, resourceByteArray.length);\n\n\t\t\toptimizedByteArray = elementByteArray;\n\t\t\tlength = length + elementByteArray.length;\n\t\t}\n\n\t\tbyte[][] remoteByteArray = new byte[remoteArchiveNumber][];\n\t\tfor (int i = 0; i < remoteArchiveNumber; i++) {\n\t\t\tXAResourceArchive resourceArchive = remoteArchiveList.get(i);\n\n\t\t\tbyte[] resourceByteArray = this.resourceArchiveDeserializer.serialize(xid, resourceArchive);\n\t\t\tbyte[] lengthByteArray = ByteUtils.shortToByteArray((short) resourceByteArray.length);\n\n\t\t\tbyte[] elementByteArray = new byte[resourceByteArray.length + 2];\n\t\t\tSystem.arraycopy(lengthByteArray, 0, elementByteArray, 0, lengthByteArray.length);\n\t\t\tSystem.arraycopy(resourceByteArray, 0, elementByteArray, 2, resourceByteArray.length);\n\n\t\t\tremoteByteArray[i] = elementByteArray;\n\t\t\tlength = length + elementByteArray.length;\n\t\t}\n\n\t\tint position = 0;\n\n\t\tbyte[] byteArray = new byte[length];\n\t\tbyteArray[position++] = (byte) archive.getStatus();\n\t\tbyteArray[position++] = (byte) archive.getVote();\n\t\tbyteArray[position++] = archive.isCoordinator() ? (byte) 0x1 : (byte) 0x0;\n\n\t\tbyteArray[position++] = (byte) nativeArchiveNumber;\n\t\tbyteArray[position++] = (byte) optimizedArchiveNumber;\n\t\tbyteArray[position++] = (byte) remoteArchiveNumber;\n\n\t\tbyteArray[position++] = (byte) transactionStrategy;\n\n\t\tSystem.arraycopy(hostByteArray, 0, byteArray, position, 4);\n\t\tposition = position + 4;\n\n\t\tbyteArray[position++] = (byte) (nameByteArray.length - 128);\n\t\tSystem.arraycopy(nameByteArray, 0, byteArray, position, nameByteArray.length);\n\t\tposition = position + nameByteArray.length;\n\n\t\tSystem.arraycopy(portByteArray, 0, byteArray, position, 2);\n\t\tposition = position + 2;\n\n\t\tbyteArray[position++] = (byte) (recoveredTimes - 128);\n\t\tbyte[] millisByteArray = ByteUtils.longToByteArray(recoveredMillis);\n\t\tSystem.arraycopy(millisByteArray, 0, byteArray, position, millisByteArray.length);\n\t\tposition = position + millisByteArray.length;\n\n\t\tfor (int i = 0; i < nativeArchiveNumber; i++) {\n\t\t\tbyte[] elementByteArray = nativeByteArray[i];\n\t\t\tSystem.arraycopy(elementByteArray, 0, byteArray, position, elementByteArray.length);\n\t\t\tposition = position + elementByteArray.length;\n\t\t}\n\n\t\tif (optimizedArchiveNumber > 0) {\n\t\t\tSystem.arraycopy(optimizedByteArray, 0, byteArray, position, optimizedByteArray.length);\n\t\t\tposition = position + optimizedByteArray.length;\n\t\t}\n\n\t\tfor (int i = 0; i < remoteArchiveNumber; i++) {\n\t\t\tbyte[] elementByteArray = remoteByteArray[i];\n\t\t\tSystem.arraycopy(elementByteArray, 0, byteArray, position, elementByteArray.length);\n\t\t\tposition = position + elementByteArray.length;\n\t\t}\n\n\t\treturn byteArray;\n\t}\n\n\tpublic Object deserialize(TransactionXid xid, byte[] array) {\n\t\tByteBuffer buffer = ByteBuffer.wrap(array);\n\n\t\tTransactionArchive archive = new TransactionArchive();\n\t\tarchive.setXid(xid);\n\n\t\tint status = buffer.get();\n\t\tint vote = buffer.get();\n\t\tint coordinatorValue = buffer.get();\n\n\t\tarchive.setStatus(status);\n\t\tarchive.setVote(vote);\n\t\tarchive.setCoordinator(coordinatorValue != 0);\n\n\t\tint nativeArchiveNumber = buffer.get();\n\t\tint optimizedArchiveNumber = buffer.get();\n\t\tint remoteArchiveNumber = buffer.get();\n\n\t\tint transactionStrategyType = buffer.get();\n\t\tarchive.setTransactionStrategyType(transactionStrategyType);\n\n\t\tbyte[] hostByteArray = new byte[4];\n\t\tbuffer.get(hostByteArray);\n\t\tStringBuilder ber = new StringBuilder();\n\t\tfor (int i = 0; i < hostByteArray.length; i++) {\n\t\t\tint value = hostByteArray[i] + 128;\n\t\t\tif (i == 0) {\n\t\t\t\tber.append(value);\n\t\t\t} else {\n\t\t\t\tber.append(\".\");\n\t\t\t\tber.append(value);\n\t\t\t}\n\t\t}\n\t\tString host = ber.toString();\n\n\t\tint sizeOfName = 128 + buffer.get();\n\t\tbyte[] nameByteArray = new byte[sizeOfName];\n\t\tbuffer.get(nameByteArray);\n\t\tString name = new String(nameByteArray);\n\n\t\tint port = 32768 + buffer.getShort();\n\t\tarchive.setPropagatedBy(String.format(\"%s:%s:%s\", host, name, port));\n\n\t\tint recoveredTimes = 128 + buffer.get();\n\t\tbyte[] millisByteArray = new byte[8];\n\t\tbuffer.get(millisByteArray);\n\t\tlong recoveredAt = ByteUtils.byteArrayToLong(millisByteArray);\n\n\t\tarchive.setRecoveredTimes(recoveredTimes);\n\t\tarchive.setRecoveredAt(recoveredAt);\n\n\t\tfor (int i = 0; i < nativeArchiveNumber; i++) {\n\t\t\tint length = buffer.getShort();\n\t\t\tbyte[] resourceByteArray = new byte[length];\n\t\t\tbuffer.get(resourceByteArray);\n\n\t\t\tXAResourceArchive resourceArchive = //\n\t\t\t\t\t(XAResourceArchive) this.resourceArchiveDeserializer.deserialize(xid, resourceByteArray);\n\n\t\t\tarchive.getNativeResources().add(resourceArchive);\n\t\t}\n\n\t\tif (optimizedArchiveNumber > 0) {\n\t\t\tint length = buffer.getShort();\n\t\t\tbyte[] resourceByteArray = new byte[length];\n\t\t\tbuffer.get(resourceByteArray);\n\n\t\t\tXAResourceArchive resourceArchive = //\n\t\t\t\t\t(XAResourceArchive) this.resourceArchiveDeserializer.deserialize(xid, resourceByteArray);\n\n\t\t\tarchive.setOptimizedResource(resourceArchive);\n\t\t}\n\n\t\tfor (int i = 0; i < remoteArchiveNumber; i++) {\n\t\t\tint length = buffer.getShort();\n\t\t\tbyte[] resourceByteArray = new byte[length];\n\t\t\tbuffer.get(resourceByteArray);\n\n\t\t\tXAResourceArchive resourceArchive = //\n\t\t\t\t\t(XAResourceArchive) this.resourceArchiveDeserializer.deserialize(xid, resourceByteArray);\n\n\t\t\tarchive.getRemoteResources().add(resourceArchive);\n\t\t}\n\n\t\treturn archive;\n\t}\n\n\tpublic ArchiveDeserializer getResourceArchiveDeserializer() {\n\t\treturn resourceArchiveDeserializer;\n\t}\n\n\tpublic void setResourceArchiveDeserializer(ArchiveDeserializer resourceArchiveDeserializer) {\n\t\tthis.resourceArchiveDeserializer = resourceArchiveDeserializer;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/logging/deserializer/XAResourceArchiveDeserializer.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.logging.deserializer;\n\nimport java.nio.ByteBuffer;\n\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.bytejta.supports.resource.CommonResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.LocalXAResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.UnidentifiedResourceDescriptor;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.logging.ArchiveDeserializer;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\n\npublic class XAResourceArchiveDeserializer implements ArchiveDeserializer, TransactionBeanFactoryAware {\n\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\t// private XAResourceDeserializer deserializer;\n\n\tpublic byte[] serialize(TransactionXid xid, Object obj) {\n\t\tXAResourceArchive archive = (XAResourceArchive) obj;\n\n\t\tXid branchXid = archive.getXid();\n\t\tbyte[] branchQualifier = branchXid.getBranchQualifier();\n\n\t\tXAResourceDescriptor descriptor = archive.getDescriptor();\n\t\tbyte[] identifierByteArray = new byte[0];\n\t\tbyte typeByte = 0x0;\n\t\tif (CommonResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\ttypeByte = (byte) 0x1;\n\t\t\tidentifierByteArray = descriptor.getIdentifier().getBytes();\n\t\t} else if (RemoteResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\ttypeByte = (byte) 0x2;\n\t\t\tidentifierByteArray = descriptor.getIdentifier().getBytes();\n\t\t} else if (LocalXAResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\ttypeByte = (byte) 0x3;\n\t\t\tidentifierByteArray = descriptor.getIdentifier().getBytes();\n\t\t}\n\n\t\tbyte branchVote = (byte) archive.getVote();\n\t\tbyte readonly = archive.isReadonly() ? (byte) 1 : (byte) 0;\n\t\tbyte committed = archive.isCommitted() ? (byte) 1 : (byte) 0;\n\t\tbyte rolledback = archive.isRolledback() ? (byte) 1 : (byte) 0;\n\t\tbyte completed = archive.isCompleted() ? (byte) 1 : (byte) 0;\n\t\tbyte heuristic = archive.isHeuristic() ? (byte) 1 : (byte) 0;\n\n\t\tbyte[] byteArray = new byte[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length + 6];\n\t\tSystem.arraycopy(branchQualifier, 0, byteArray, 0, branchQualifier.length);\n\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH] = typeByte;\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 1] = (byte) identifierByteArray.length;\n\t\tif (identifierByteArray.length > 0) {\n\t\t\tSystem.arraycopy(identifierByteArray, 0, byteArray, XidFactory.BRANCH_QUALIFIER_LENGTH + 2,\n\t\t\t\t\tidentifierByteArray.length);\n\t\t}\n\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length] = branchVote;\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length + 1] = readonly;\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length + 2] = committed;\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length + 3] = rolledback;\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length + 4] = completed;\n\t\tbyteArray[XidFactory.BRANCH_QUALIFIER_LENGTH + 2 + identifierByteArray.length + 5] = heuristic;\n\n\t\treturn byteArray;\n\t}\n\n\tpublic Object deserialize(TransactionXid xid, byte[] array) {\n\t\tXAResourceDeserializer deserializer = this.beanFactory.getResourceDeserializer();\n\n\t\tByteBuffer buffer = ByteBuffer.wrap(array);\n\n\t\tXAResourceArchive archive = new XAResourceArchive();\n\n\t\tbyte[] branchQualifier = new byte[XidFactory.BRANCH_QUALIFIER_LENGTH];\n\t\tbuffer.get(branchQualifier);\n\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\tTransactionXid branchXid = xidFactory.createBranchXid(xid, branchQualifier);\n\t\tarchive.setXid(branchXid);\n\n\t\tbyte resourceType = buffer.get();\n\t\tbyte length = buffer.get();\n\t\tbyte[] byteArray = new byte[length];\n\t\tbuffer.get(byteArray);\n\t\tString identifier = new String(byteArray);\n\n\t\tXAResourceDescriptor descriptor = null;\n\t\tif (resourceType == 0x01) {\n\t\t\tarchive.setIdentified(true);\n\t\t\tdescriptor = deserializer.deserialize(identifier);\n\t\t} else if (resourceType == 0x02) {\n\t\t\tarchive.setIdentified(true);\n\t\t\tdescriptor = deserializer.deserialize(identifier);\n\t\t} else if (resourceType == 0x03) {\n\t\t\tarchive.setIdentified(true);\n\t\t\tdescriptor = deserializer.deserialize(identifier);\n\t\t} else {\n\t\t\tdescriptor = new UnidentifiedResourceDescriptor();\n\t\t}\n\n\t\tif (CommonResourceDescriptor.class.isInstance(descriptor)) {\n\t\t\t((CommonResourceDescriptor) descriptor).setRecoverXid(branchXid);\n\t\t}\n\n\t\tarchive.setDescriptor(descriptor);\n\n\t\tint branchVote = buffer.get();\n\t\tint readonly = buffer.get();\n\t\tint committedValue = buffer.get();\n\t\tint rolledbackValue = buffer.get();\n\t\tint completedValue = buffer.get();\n\t\tint heuristicValue = buffer.get();\n\t\tarchive.setVote(branchVote);\n\t\tarchive.setReadonly(readonly != 0);\n\t\tarchive.setCommitted(committedValue != 0);\n\t\tarchive.setRolledback(rolledbackValue != 0);\n\t\tarchive.setCompleted(completedValue != 0);\n\t\tarchive.setHeuristic(heuristicValue != 0);\n\n\t\treturn archive;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn this.beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/logging/store/VirtualLoggingFile.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.logging.store;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.RandomAccessFile;\nimport java.nio.MappedByteBuffer;\nimport java.nio.channels.FileChannel.MapMode;\nimport java.util.Arrays;\n\nimport org.bytesoft.transaction.logging.store.VirtualLoggingTrigger;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class VirtualLoggingFile {\n\tstatic final Logger logger = LoggerFactory.getLogger(VirtualLoggingFile.class);\n\n\tstatic final long DEFAULT_SIZE = 1024 * 1024;\n\tstatic final long INCREASE_SIZE = 1024 * 512;\n\n\tstatic final int DEFAULT_MAJOR_VERSION = 0;\n\tstatic final int DEFAULT_MINOR_VERSION = 2;\n\n\tprivate MappedByteBuffer readable;\n\tprivate MappedByteBuffer writable;\n\n\tprivate RandomAccessFile raf;\n\n\tprivate byte[] identifier;\n\n\tprivate boolean initialized;\n\n\tprivate int startIdx;\n\tprivate int endIndex;\n\n\tprivate boolean marked;\n\tprivate boolean master;\n\n\tprivate int majorVersion = DEFAULT_MAJOR_VERSION;\n\tprivate int minorVersion = DEFAULT_MINOR_VERSION;\n\n\tprivate VirtualLoggingTrigger trigger;\n\n\tpublic VirtualLoggingFile(File file) throws IOException {\n\t\tthis(file, DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION);\n\t}\n\n\tpublic VirtualLoggingFile(File file, int major, int minor) throws IOException {\n\t\tthis.majorVersion = major;\n\t\tthis.minorVersion = minor;\n\n\t\tthis.initialized = file.exists();\n\t\tthis.raf = new RandomAccessFile(file, \"rw\");\n\t\tif (this.initialized == false) {\n\t\t\tthis.configMappedByteBuffer(DEFAULT_SIZE);\n\t\t} else {\n\t\t\tthis.configMappedByteBuffer(this.raf.length());\n\t\t}\n\t}\n\n\tpublic void clearMarkedFlag() {\n\t\tint pos = this.writable.position();\n\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4);\n\t\tthis.writable.put((byte) 0x0);\n\n\t\tthis.marked = false;\n\n\t\tthis.writable.position(pos);\n\t}\n\n\tpublic void fixSwitchError() {\n\t\tint pos = this.writable.position();\n\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4 + 1);\n\t\tthis.writable.put((byte) 0x1);\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4);\n\t\tthis.writable.put((byte) 0x0);\n\n\t\tthis.marked = false;\n\t\tthis.master = true;\n\n\t\tthis.writable.position(pos);\n\t}\n\n\tpublic void initialize(boolean master) {\n\t\tthis.checkLoggingIdentifier();\n\t\tthis.checkLoggingVersion();\n\t\tthis.checkCreatedTime();\n\t\tthis.checkStartIndex();\n\t\tthis.checkMasterFlag(master);\n\t\tthis.checkModifiedTime();\n\t\tthis.checkEndIndex();\n\n\t\tthis.initialized = true;\n\t}\n\n\tprivate void checkLoggingIdentifier() {\n\t\tbyte[] array = new byte[identifier.length];\n\t\tthis.writable.position(0);\n\t\tthis.writable.get(array);\n\t\tif (Arrays.equals(identifier, array)) {\n\t\t\t// ignore\n\t\t} else if (this.initialized == false) {\n\t\t\twritable.position(0);\n\t\t\twritable.put(identifier);\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\"Illegal file format!\");\n\t\t}\n\t}\n\n\tprivate void checkLoggingVersion() {\n\t\tthis.writable.position(identifier.length);\n\t\tint major = this.writable.get();\n\t\tint minor = this.writable.get();\n\t\tif (major == this.majorVersion && minor == this.minorVersion) {\n\t\t\t// ignore\n\t\t} else if (this.initialized == false) {\n\t\t\twritable.position(identifier.length);\n\t\t\twritable.put((byte) this.majorVersion);\n\t\t\twritable.put((byte) this.minorVersion);\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\"Incompatible version!\");\n\t\t}\n\t}\n\n\tprivate void checkCreatedTime() {\n\t\tif (this.initialized == false) {\n\t\t\twritable.position(identifier.length + 2);\n\t\t\twritable.putLong(System.currentTimeMillis());\n\t\t}\n\t}\n\n\tprivate void checkStartIndex() {\n\t\tthis.writable.position(identifier.length + 2 + 8);\n\t\tint start = this.writable.getInt();\n\t\tif (start == identifier.length + 2 + 8 + 4 + 2 + 8 + 4) {\n\t\t\tthis.startIdx = start;\n\t\t} else if (this.initialized == false) {\n\t\t\tthis.startIdx = identifier.length + 2 + 8 + 4 + 2 + 8 + 4;\n\t\t\twritable.position(identifier.length + 2 + 8);\n\t\t\twritable.putInt(identifier.length + 2 + 8 + 4 + 2 + 8 + 4);\n\t\t} else {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tprivate void checkMasterFlag(boolean master) {\n\t\tif (this.initialized == false) {\n\t\t\tthis.master = master;\n\t\t\tthis.marked = false;\n\t\t\twritable.position(identifier.length + 2 + 8 + 4);\n\t\t\twritable.put((byte) 0x0);\n\t\t\twritable.put(master ? (byte) 0x1 : (byte) 0x0);\n\t\t} else {\n\t\t\tthis.writable.position(identifier.length + 2 + 8 + 4);\n\t\t\tthis.marked = this.writable.get() == 0x1;\n\t\t\tthis.master = this.writable.get() == 0x1;\n\t\t}\n\t}\n\n\tprivate void checkModifiedTime() {\n\t\tif (this.initialized == false) {\n\t\t\twritable.position(identifier.length + 2 + 8 + 4 + 2);\n\t\t\twritable.putLong(System.currentTimeMillis());\n\t\t}\n\t}\n\n\tprivate void checkEndIndex() {\n\t\tif (this.initialized == false) {\n\t\t\tthis.endIndex = identifier.length + 2 + 8 + 4 + 2 + 8 + 4;\n\t\t\twritable.position(identifier.length + 2 + 8 + 4 + 2 + 8);\n\t\t\twritable.putInt(identifier.length + 2 + 8 + 4 + 2 + 8 + 4);\n\t\t} else {\n\t\t\tthis.writable.position(identifier.length + 2 + 8 + 4 + 2 + 8);\n\t\t\tthis.endIndex = this.writable.getInt();\n\t\t}\n\t}\n\n\tpublic void markAsMaster() {\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4);\n\t\tthis.writable.put((byte) 0x1);\n\t}\n\n\tpublic void switchToMaster() {\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4 + 1);\n\t\tthis.writable.put((byte) 0x1);\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4);\n\t\tthis.writable.put((byte) 0x0);\n\n\t\tthis.master = true;\n\t\tthis.marked = false;\n\n\t\tthis.readable.position(this.startIdx);\n\t}\n\n\tpublic void switchToSlaver() {\n\t\tthis.writable.position(identifier.length + 2 + 8 + 4);\n\t\tthis.writable.put((byte) 0x0);\n\t\tthis.writable.put((byte) 0x0);\n\n\t\tthis.master = false;\n\t\tthis.marked = false;\n\n\t\twritable.position(identifier.length + 2 + 8 + 4 + 2);\n\t\tthis.writable.putLong(System.currentTimeMillis());\n\t\tthis.endIndex = this.startIdx;\n\t\tthis.writable.putInt(this.endIndex);\n\t}\n\n\tpublic void prepareForReading() {\n\t\tthis.readable.position(this.startIdx);\n\t}\n\n\tpublic byte[] read() {\n\t\tif (this.readable.position() < this.endIndex) {\n\t\t\tint pos = this.readable.position();\n\t\t\tthis.readable.position(pos + XidFactory.GLOBAL_TRANSACTION_LENGTH + 1);\n\t\t\tint size = this.readable.getInt();\n\t\t\tbyte[] byteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH + 1 + 4 + size];\n\t\t\tthis.readable.position(pos);\n\t\t\tthis.readable.get(byteArray);\n\t\t\treturn byteArray;\n\t\t} else {\n\t\t\treturn new byte[0];\n\t\t}\n\t}\n\n\tpublic void write(byte[] byteArray) {\n\t\tif (this.writable.capacity() < this.endIndex + byteArray.length) {\n\t\t\tthis.resizeMappedByteBuffer(this.endIndex + INCREASE_SIZE);\n\t\t}\n\t\tthis.writable.position(this.endIndex);\n\t\tthis.writable.put(byteArray);\n\n\t\twritable.position(identifier.length + 2 + 8 + 4 + 2);\n\t\tthis.writable.putLong(System.currentTimeMillis());\n\t\tthis.endIndex = this.endIndex + byteArray.length;\n\t\tthis.writable.putInt(this.endIndex);\n\n\t\tint threshold = (this.writable.capacity() * 2) / 3;\n\t\tif (this.endIndex > threshold) {\n\t\t\tthis.trigger.fireSwapImmediately();\n\t\t}\n\n\t}\n\n\tprivate void resizeMappedByteBuffer(long size) {\n\t\ttry {\n\t\t\tthis.raf.setLength(this.endIndex + INCREASE_SIZE);\n\t\t\tthis.readable = this.raf.getChannel().map(MapMode.READ_ONLY, 0, size);\n\t\t\tthis.writable = this.raf.getChannel().map(MapMode.READ_WRITE, 0, size);\n\t\t} catch (IOException ex) {\n\t\t\tlogger.error(\"Error occurred while resizing the logging file!\", ex);\n\t\t}\n\t}\n\n\tprivate void configMappedByteBuffer(long size) throws IOException {\n\t\tthis.readable = this.raf.getChannel().map(MapMode.READ_ONLY, 0, size);\n\t\tthis.writable = this.raf.getChannel().map(MapMode.READ_WRITE, 0, size);\n\t}\n\n\tpublic void flushImmediately() {\n\t\tif (this.writable != null) {\n\t\t\tthis.writable.force();\n\t\t}\n\t}\n\n\tpublic void closeQuietly() {\n\t\tif (this.raf != null) {\n\t\t\ttry {\n\t\t\t\tthis.raf.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic byte[] getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(byte[] identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic VirtualLoggingTrigger getTrigger() {\n\t\treturn trigger;\n\t}\n\n\tpublic void setTrigger(VirtualLoggingTrigger trigger) {\n\t\tthis.trigger = trigger;\n\t}\n\n\tpublic boolean isMarked() {\n\t\treturn marked;\n\t}\n\n\tpublic void setMarked(boolean marked) {\n\t\tthis.marked = marked;\n\t}\n\n\tpublic boolean isMaster() {\n\t\treturn master;\n\t}\n\n\tpublic void setMaster(boolean master) {\n\t\tthis.master = master;\n\t}\n\n\tpublic int getStartIdx() {\n\t\treturn startIdx;\n\t}\n\n\tpublic int getEndIndex() {\n\t\treturn endIndex;\n\t}\n\n\tpublic int getMajorVersion() {\n\t\treturn majorVersion;\n\t}\n\n\tpublic int getMinorVersion() {\n\t\treturn minorVersion;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/logging/store/VirtualLoggingSystemImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.logging.store;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport javax.resource.spi.work.Work;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingKey;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingListener;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingRecord;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingSystem;\nimport org.bytesoft.transaction.logging.store.VirtualLoggingTrigger;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic abstract class VirtualLoggingSystemImpl implements VirtualLoggingSystem, VirtualLoggingTrigger, Work {\n\tstatic final Logger logger = LoggerFactory.getLogger(VirtualLoggingSystemImpl.class);\n\tstatic final int COMPRESS_BATCH_SIZE = 10000;\n\n\tprivate final Lock lock = new ReentrantLock();\n\tprivate final Lock timingLock = new ReentrantLock();\n\tprivate final Condition timingCondition = this.timingLock.newCondition();\n\n\tprivate boolean released;\n\n\tprivate File directory;\n\n\tprivate VirtualLoggingFile master;\n\tprivate VirtualLoggingFile slaver;\n\n\tprivate boolean optimized = true;\n\tprivate boolean initialized;\n\n\tprivate int switchThreshold = 1024 * 1024 * 8;\n\tprivate int switchInterval = 60;\n\n\tpublic synchronized void construct() throws IOException {\n\t\tif (this.initialized == false) {\n\t\t\tthis.initialize();\n\t\t\tthis.initialized = true;\n\t\t}\n\t}\n\n\tprivate void initialize() throws IOException {\n\t\tif (this.directory == null) {\n\t\t\tthis.directory = this.getDefaultDirectory();\n\t\t}\n\n\t\tif (this.directory.exists() == false) {\n\t\t\tif (this.directory.mkdirs() == false) {\n\t\t\t\tthrow new RuntimeException(String.format(\"Failed to create directory %s!\", this.directory.getAbsolutePath()));\n\t\t\t}\n\t\t}\n\n\t\tFile fmaster = new File(this.directory, String.format(\"%s1.log\", this.getLoggingFilePrefix()));\n\t\tFile fslaver = new File(this.directory, String.format(\"%s2.log\", this.getLoggingFilePrefix()));\n\n\t\tVirtualLoggingFile masterMgr = this.createTransactionLogging(fmaster);\n\t\tVirtualLoggingFile slaverMgr = this.createTransactionLogging(fslaver);\n\n\t\tmasterMgr.initialize(true);\n\t\tslaverMgr.initialize(false);\n\n\t\tthis.initialize(masterMgr, slaverMgr);\n\n\t\tthis.flushAllIfNecessary();\n\t}\n\n\tprivate void initialize(VirtualLoggingFile prev, VirtualLoggingFile next) {\n\t\tboolean prevMaster = prev.isMaster();\n\t\tboolean nextMaster = next.isMaster();\n\n\t\tif (prevMaster && nextMaster) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (prevMaster == false && nextMaster == false) {\n\t\t\tthis.fixSwitchError(prev, next);\n\t\t} else if (prevMaster) {\n\t\t\tthis.master = prev;\n\t\t\tthis.slaver = next;\n\n\t\t\tthis.master.clearMarkedFlag();\n\t\t\tthis.slaver.clearMarkedFlag();\n\t\t} else {\n\t\t\tthis.master = next;\n\t\t\tthis.slaver = prev;\n\n\t\t\tthis.master.clearMarkedFlag();\n\t\t\tthis.slaver.clearMarkedFlag();\n\t\t}\n\n\t}\n\n\tprivate void fixSwitchError(VirtualLoggingFile prev, VirtualLoggingFile next) {\n\t\tboolean prevMarked = prev.isMarked();\n\t\tboolean nextMarked = next.isMarked();\n\t\tif (prevMarked && nextMarked) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (prevMarked == false && nextMarked == false) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (prevMarked) {\n\t\t\tprev.fixSwitchError();\n\n\t\t\tthis.master = prev;\n\t\t\tthis.slaver = next;\n\t\t} else {\n\t\t\tnext.fixSwitchError();\n\n\t\t\tthis.master = next;\n\t\t\tthis.slaver = prev;\n\t\t}\n\t}\n\n\tpublic void run() {\n\t\tint lastEndIndex = this.master.getEndIndex();\n\t\twhile (this.released == false) {\n\t\t\ttry {\n\t\t\t\tthis.timingLock.lock();\n\t\t\t\tthis.timingCondition.await(this.switchInterval, TimeUnit.SECONDS);\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t\t} finally {\n\t\t\t\tthis.timingLock.unlock();\n\t\t\t}\n\n\t\t\tint increment = this.master.getEndIndex() - lastEndIndex;\n\t\t\tif (increment < this.switchThreshold) {\n\t\t\t\tcontinue;\n\t\t\t} // end-if (increasement < this.switchThreshold)\n\n\t\t\tthis.syncMasterAndSlaver();\n\t\t\tthis.swapMasterAndSlaver();\n\n\t\t\tlastEndIndex = this.master.getEndIndex();\n\t\t}\n\t}\n\n\tpublic void fireSwapImmediately() {\n\t\ttry {\n\t\t\tthis.timingLock.lock();\n\t\t\tthis.timingCondition.signalAll();\n\t\t} finally {\n\t\t\tthis.timingLock.unlock();\n\t\t}\n\t}\n\n\tpublic void traversal(VirtualLoggingListener listener) {\n\t\tthis.master.prepareForReading();\n\t\twhile (true) {\n\t\t\tbyte[] byteArray = null;\n\t\t\ttry {\n\t\t\t\tbyteArray = this.master.read();\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tbyteArray = new byte[0];\n\t\t\t}\n\n\t\t\tif (byteArray.length == 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbyte[] keyByteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH];\n\t\t\tSystem.arraycopy(byteArray, 0, keyByteArray, 0, keyByteArray.length);\n\t\t\tint operator = byteArray[keyByteArray.length];\n\t\t\tbyte[] valueByteArray = new byte[byteArray.length - XidFactory.GLOBAL_TRANSACTION_LENGTH - 1 - 4];\n\t\t\tSystem.arraycopy(byteArray, XidFactory.GLOBAL_TRANSACTION_LENGTH + 1 + 4, valueByteArray, 0, valueByteArray.length);\n\n\t\t\tVirtualLoggingKey xid = new VirtualLoggingKey();\n\t\t\txid.setGlobalTransactionId(keyByteArray);\n\n\t\t\tVirtualLoggingRecord record = new VirtualLoggingRecord();\n\t\t\trecord.setIdentifier(xid);\n\t\t\trecord.setOperator(operator);\n\t\t\trecord.setContent(byteArray);\n\t\t\trecord.setValue(valueByteArray);\n\n\t\t\tlistener.recvOperation(record);\n\t\t}\n\n\t}\n\n\tpublic void create(Xid xid, byte[] textByteArray) {\n\t\tbyte[] keyByteArray = xid.getGlobalTransactionId();\n\t\tbyte[] sizeByteArray = ByteUtils.intToByteArray(textByteArray.length);\n\n\t\tbyte[] byteArray = new byte[keyByteArray.length + 1 + sizeByteArray.length + textByteArray.length];\n\n\t\tSystem.arraycopy(keyByteArray, 0, byteArray, 0, keyByteArray.length);\n\t\tbyteArray[keyByteArray.length] = (byte) (OPERATOR_CREATE & 0xFF);\n\t\tSystem.arraycopy(sizeByteArray, 0, byteArray, keyByteArray.length + 1, sizeByteArray.length);\n\t\tSystem.arraycopy(textByteArray, 0, byteArray, keyByteArray.length + 1 + sizeByteArray.length, textByteArray.length);\n\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\tthis.master.write(byteArray);\n\n\t\t\tthis.flushMasterIfNecessary();\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic void delete(Xid xid) {\n\t\tbyte[] keyByteArray = xid.getGlobalTransactionId();\n\t\tbyte[] sizeByteArray = ByteUtils.intToByteArray(0);\n\n\t\tbyte[] byteArray = new byte[keyByteArray.length + 1 + sizeByteArray.length];\n\n\t\tSystem.arraycopy(keyByteArray, 0, byteArray, 0, keyByteArray.length);\n\t\tbyteArray[keyByteArray.length] = (byte) (OPERATOR_DELETE & 0xFF);\n\t\tSystem.arraycopy(sizeByteArray, 0, byteArray, keyByteArray.length + 1, sizeByteArray.length);\n\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\tthis.master.write(byteArray);\n\n\t\t\tthis.flushMasterIfNecessary();\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic void modify(Xid xid, byte[] textByteArray) {\n\t\tbyte[] keyByteArray = xid.getGlobalTransactionId();\n\t\tbyte[] sizeByteArray = ByteUtils.intToByteArray(textByteArray.length);\n\n\t\tbyte[] byteArray = new byte[keyByteArray.length + 1 + sizeByteArray.length + textByteArray.length];\n\n\t\tSystem.arraycopy(keyByteArray, 0, byteArray, 0, keyByteArray.length);\n\t\tbyteArray[keyByteArray.length] = (byte) (OPERATOR_MOFIFY & 0xFF);\n\t\tSystem.arraycopy(sizeByteArray, 0, byteArray, keyByteArray.length + 1, sizeByteArray.length);\n\t\tSystem.arraycopy(textByteArray, 0, byteArray, keyByteArray.length + 1 + sizeByteArray.length, textByteArray.length);\n\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\tthis.master.write(byteArray);\n\n\t\t\tthis.flushMasterIfNecessary();\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic void syncMasterAndSlaver() {\n\t\tthis.master.prepareForReading();\n\t\tMap<Xid, Boolean> recordMap = this.syncStepOne();\n\t\tthis.master.prepareForReading();\n\t\tthis.syncStepTwo(recordMap, true);\n\n\t\tthis.flushSlaverIfNecessary();\n\t}\n\n\tpublic Map<Xid, Boolean> syncStepOne() {\n\t\tMap<Xid, Boolean> recordMap = new HashMap<Xid, Boolean>();\n\t\twhile (true) {\n\t\t\tbyte[] byteArray = null;\n\t\t\ttry {\n\t\t\t\tbyteArray = this.master.read();\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tbyteArray = new byte[0];\n\t\t\t}\n\n\t\t\tif (byteArray.length == 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbyte[] keyByteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH];\n\t\t\tSystem.arraycopy(byteArray, 0, keyByteArray, 0, keyByteArray.length);\n\t\t\tint operator = byteArray[keyByteArray.length];\n\n\t\t\tVirtualLoggingKey xid = new VirtualLoggingKey();\n\t\t\txid.setGlobalTransactionId(keyByteArray);\n\n\t\t\tVirtualLoggingRecord record = new VirtualLoggingRecord();\n\t\t\trecord.setIdentifier(xid);\n\t\t\trecord.setOperator(operator);\n\t\t\trecord.setContent(byteArray);\n\n\t\t\tif (operator == OPERATOR_DELETE) {\n\t\t\t\trecordMap.put(xid, true);\n\t\t\t}\n\n\t\t}\n\n\t\treturn recordMap;\n\n\t}\n\n\tpublic List<VirtualLoggingRecord> compressIfNecessary(List<VirtualLoggingRecord> recordList) {\n\t\treturn recordList;\n\t}\n\n\tpublic void syncStepTwo(Map<Xid, Boolean> recordMap, boolean compressRequired) {\n\t\tfinal List<VirtualLoggingRecord> recordList = new ArrayList<VirtualLoggingRecord>(COMPRESS_BATCH_SIZE);\n\t\twhile (true) {\n\t\t\tbyte[] byteArray = null;\n\t\t\ttry {\n\t\t\t\tbyteArray = this.master.read();\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tbyteArray = new byte[0];\n\t\t\t}\n\n\t\t\tif (byteArray.length == 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbyte[] keyByteArray = new byte[XidFactory.GLOBAL_TRANSACTION_LENGTH];\n\t\t\tSystem.arraycopy(byteArray, 0, keyByteArray, 0, keyByteArray.length);\n\t\t\tint operator = byteArray[keyByteArray.length];\n\t\t\tbyte[] valueByteArray = new byte[byteArray.length - XidFactory.GLOBAL_TRANSACTION_LENGTH - 1 - 4];\n\t\t\tSystem.arraycopy(byteArray, XidFactory.GLOBAL_TRANSACTION_LENGTH + 1 + 4, valueByteArray, 0, valueByteArray.length);\n\n\t\t\tVirtualLoggingKey xid = new VirtualLoggingKey();\n\t\t\txid.setGlobalTransactionId(keyByteArray);\n\n\t\t\tif (recordMap.containsKey(xid)) /* deleted */ {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tVirtualLoggingRecord record = new VirtualLoggingRecord();\n\t\t\trecord.setIdentifier(xid);\n\t\t\trecord.setOperator(operator);\n\t\t\trecord.setContent(byteArray);\n\t\t\trecord.setValue(valueByteArray);\n\n\t\t\trecordList.add(record);\n\n\t\t\tif (compressRequired == false) {\n\t\t\t\tcontinue;\n\t\t\t} else if (recordList.size() % COMPRESS_BATCH_SIZE != 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tList<VirtualLoggingRecord> compressedList = this.compressIfNecessary(recordList);\n\t\t\tif (compressedList != recordList && compressedList != null) {\n\t\t\t\trecordList.clear();\n\t\t\t\trecordList.addAll(compressedList);\n\t\t\t} // end-if (compressedList != recordList && compressedList != null)\n\n\t\t}\n\n\t\tfor (int i = 0; recordList != null && i < recordList.size(); i++) {\n\t\t\tVirtualLoggingRecord record = recordList.get(i);\n\t\t\tXid xid = record.getIdentifier();\n\t\t\tif (recordMap.containsKey(xid) == false) {\n\t\t\t\tbyte[] byteArray = record.getContent();\n\t\t\t\tthis.slaver.write(byteArray);\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic void swapMasterAndSlaver() {\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\tthis.syncStepTwo(new HashMap<Xid, Boolean>(), false);\n\n\t\t\tthis.slaver.markAsMaster();\n\t\t\tthis.master.switchToSlaver();\n\t\t\tthis.slaver.switchToMaster();\n\n\t\t\tthis.flushAllIfNecessary();\n\n\t\t\tVirtualLoggingFile theNextMaster = this.slaver;\n\t\t\tthis.slaver = this.master;\n\t\t\tthis.master = theNextMaster;\n\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tprivate void flushAllIfNecessary() {\n\t\tthis.flushMasterIfNecessary();\n\t\tthis.flushSlaverIfNecessary();\n\t}\n\n\tprivate void flushMasterIfNecessary() {\n\t\tif (this.optimized == false) {\n\t\t\tthis.master.flushImmediately();\n\t\t}\n\t}\n\n\tprivate void flushSlaverIfNecessary() {\n\t\tif (this.optimized == false) {\n\t\t\tthis.slaver.flushImmediately();\n\t\t}\n\t}\n\n\tpublic void flushImmediately() {\n\t\tthis.master.flushImmediately();\n\t}\n\n\tpublic void shutdown() {\n\t\tthis.master.flushImmediately();\n\t\tthis.slaver.flushImmediately();\n\n\t\tthis.master.closeQuietly();\n\t\tthis.slaver.closeQuietly();\n\t}\n\n\tpublic void release() {\n\t\tthis.released = true;\n\t}\n\n\tpublic abstract File getDefaultDirectory();\n\n\tpublic abstract int getMajorVersion();\n\n\tpublic abstract int getMinorVersion();\n\n\tpublic abstract String getLoggingIdentifier();\n\n\tpublic abstract String getLoggingFilePrefix();\n\n\tpublic VirtualLoggingFile createTransactionLogging(File file) throws IOException {\n\t\tint major = this.getMajorVersion();\n\t\tint minor = this.getMinorVersion();\n\n\t\tVirtualLoggingFile logging = new VirtualLoggingFile(file, major, minor);\n\t\tlogging.setTrigger(this);\n\t\tlogging.setIdentifier(this.getLoggingIdentifier().getBytes());\n\t\treturn logging;\n\t}\n\n\tpublic int getSwitchThreshold() {\n\t\treturn switchThreshold;\n\t}\n\n\tpublic void setSwitchThreshold(int switchThreshold) {\n\t\tthis.switchThreshold = switchThreshold;\n\t}\n\n\tpublic int getSwitchInterval() {\n\t\treturn switchInterval;\n\t}\n\n\tpublic void setSwitchInterval(int switchInterval) {\n\t\tthis.switchInterval = switchInterval;\n\t}\n\n\tpublic boolean isOptimized() {\n\t\treturn optimized;\n\t}\n\n\tpublic void setOptimized(boolean optimized) {\n\t\tthis.optimized = optimized;\n\t}\n\n\tpublic File getDirectory() {\n\t\treturn directory;\n\t}\n\n\tpublic void setDirectory(File directory) {\n\t\tthis.directory = directory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/resource/XATerminatorImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.resource;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.logging.TransactionLogger;\nimport org.bytesoft.transaction.resource.XATerminator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class XATerminatorImpl implements XATerminator {\n\tstatic final Logger logger = LoggerFactory.getLogger(XATerminatorImpl.class);\n\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate final List<XAResourceArchive> resources = new ArrayList<XAResourceArchive>();\n\n\tpublic synchronized int prepare(Xid xid) throws XAException {\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tint globalVote = XAResource.XA_RDONLY;\n\t\tfor (int i = 0; i < this.resources.size(); i++) {\n\t\t\tXAResourceArchive archive = this.resources.get(i);\n\n\t\t\tboolean prepared = archive.getVote() != XAResourceArchive.DEFAULT_VOTE;\n\t\t\tif (prepared) {\n\t\t\t\tglobalVote = archive.getVote() == XAResource.XA_RDONLY ? globalVote : XAResource.XA_OK;\n\t\t\t} else {\n\t\t\t\tint branchVote = archive.prepare(archive.getXid());\n\t\t\t\tarchive.setVote(branchVote);\n\n\t\t\t\tif (branchVote == XAResource.XA_RDONLY) {\n\t\t\t\t\tarchive.setReadonly(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t} else {\n\t\t\t\t\tglobalVote = XAResource.XA_OK;\n\t\t\t\t}\n\n\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t}\n\n\t\t\tlogger.info(\"{}> prepare: xares= {}, branch= {}, vote= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), archive.getVote());\n\t\t}\n\n\t\treturn globalVote;\n\t}\n\n\t/** error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR */\n\tpublic synchronized void commit(Xid xid, boolean onePhase) throws XAException {\n\t\tif (onePhase) {\n\t\t\tthis.fireOnePhaseCommit(xid);\n\t\t} else {\n\t\t\tthis.fireTwoPhaseCommit(xid);\n\t\t}\n\t}\n\n\tprivate void fireOnePhaseCommit(Xid xid) throws XAException {\n\n\t\tif (this.resources.size() == 0) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t} else if (this.resources.size() > 1) {\n\t\t\tthis.rollback(xid);\n\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t}\n\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tXAResourceArchive archive = this.resources.get(0);\n\n\t\tif (archive.isCommitted() && archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURMIX);\n\t\t} else if (archive.isCommitted()) {\n\t\t\treturn;\n\t\t} else if (archive.isReadonly()) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t} else if (archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t}\n\n\t\tboolean updateRequired = true;\n\t\ttry {\n\t\t\tthis.invokeOnePhaseCommit(archive);\n\n\t\t\tarchive.setCommitted(true);\n\t\t\tarchive.setCompleted(true);\n\n\t\t\tlogger.info(\"{}> commit: xares= {}, branch= {}, opc= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), true);\n\t\t} catch (XAException xaex) {\n\t\t\tlogger.error(\"{}> Error occurred while committing xa-resource: xares= {}, branch= {}, code= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), xaex.errorCode, xaex);\n\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\tupdateRequired = false;\n\t\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\tdefault:\n\t\t\t\tupdateRequired = false;\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"{}> Error occurred while committing xa-resource: xares= {}, branch= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), rex);\n\t\t\tupdateRequired = false;\n\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t} finally {\n\t\t\tif (updateRequired) {\n\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void fireTwoPhaseCommit(Xid xid) throws XAException {\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean committedExists = false;\n\t\tboolean rolledbackExists = false;\n\t\tboolean unFinishExists = false;\n\t\tboolean errorExists = false;\n\n\t\tfor (int i = this.resources.size() - 1; i >= 0; i--) {\n\t\t\tXAResourceArchive archive = this.resources.get(i);\n\n\t\t\tif (archive.isCommitted() && archive.isRolledback()) {\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isCommitted()) {\n\t\t\t\tcommittedExists = true;\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isReadonly()) {\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isRolledback()) {\n\t\t\t\trolledbackExists = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tXid branchXid = archive.getXid();\n\t\t\tboolean updateRequired = true;\n\t\t\ttry {\n\t\t\t\tthis.invokeTwoPhaseCommit(archive);\n\t\t\t\tcommittedExists = true;\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tlogger.info(\"{}> commit: xares= {}, branch= {}, onePhaseCommit= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\tByteUtils.byteArrayToString(branchXid.getBranchQualifier()), false);\n\t\t\t} catch (XAException xaex) {\n\t\t\t\tlogger.error(\"{}> Error occurred while committing xa-resource: xares= {}, branch= {}, code= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), xaex.errorCode, xaex);\n\n\t\t\t\tswitch (xaex.errorCode) {\n\t\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\t\tcommittedExists = true;\n\t\t\t\t\trolledbackExists = true;\n\n\t\t\t\t\tarchive.setCommitted(true);\n\t\t\t\t\tarchive.setRolledback(true);\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\t\tcommittedExists = true;\n\t\t\t\t\tarchive.setCommitted(true);\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\t\trolledbackExists = true;\n\t\t\t\t\tarchive.setRolledback(true);\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\tupdateRequired = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\t\tarchive.setReadonly(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\tdefault:\n\t\t\t\t\terrorExists = true;\n\t\t\t\t\tupdateRequired = false;\n\t\t\t\t}\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(\"{}> Error occurred while committing xa-resource: xares= {}, branch= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), rex);\n\t\t\t\tunFinishExists = true;\n\t\t\t\tupdateRequired = false;\n\t\t\t} finally {\n\t\t\t\tif (updateRequired) {\n\t\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} // end-for\n\n\t\tif (committedExists && rolledbackExists) {\n\t\t\tthrow new XAException(XAException.XA_HEURMIX);\n\t\t} else if (unFinishExists) {\n\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t} else if (errorExists) {\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} else if (rolledbackExists) {\n\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t} else if (committedExists == false) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t}\n\n\t}\n\n\tprivate void invokeOnePhaseCommit(XAResourceArchive archive) throws XAException {\n\t\ttry {\n\t\t\tarchive.commit(archive.getXid(), true);\n\t\t} catch (XAException xaex) {\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}, transaction has been completed!\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\tcase XAException.XA_RBCOMMFAIL:\n\t\t\tcase XAException.XA_RBDEADLOCK:\n\t\t\tcase XAException.XA_RBINTEGRITY:\n\t\t\tcase XAException.XA_RBOTHER:\n\t\t\tcase XAException.XA_RBPROTO:\n\t\t\tcase XAException.XA_RBROLLBACK:\n\t\t\tcase XAException.XA_RBTIMEOUT:\n\t\t\tcase XAException.XA_RBTRANSIENT:\n\t\t\tdefault:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}, transaction has been rolled back!\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void invokeTwoPhaseCommit(XAResourceArchive archive) throws XAException {\n\t\ttry {\n\t\t\tarchive.commit(archive.getXid(), false);\n\t\t} catch (XAException xaex) {\n\t\t\t// * @exception XAException An error has occurred. Possible XAExceptions\n\t\t\t// * are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,\n\t\t\t// * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t// * <P>If the resource manager did not commit the transaction and the\n\t\t\t// * parameter onePhase is set to true, the resource manager may throw\n\t\t\t// * one of the XA_RB* exceptions. Upon return, the resource manager has\n\t\t\t// * rolled back the branch's work and has released all held resources.\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\t// OSI-TP: The condition that arises when, as a result of communication failure with a\n\t\t\t\t// subordinate, the bound data of the subordinate's subtree are in an unknown state.\n\n\t\t\t\t// XA: Due to some failure, the work done on behalf of the specified\n\t\t\t\t// transaction branch may have been heuristically completed.\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified\n\t\t\t\t// transaction branch was partially committed and partially rolled back.\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of\n\t\t\t\t// the specified transaction branch was committed.\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of\n\t\t\t\t// the specified transaction branch was rolled back.\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t// The specified XID is not known by the resource manager.\n\t\t\t\tthrow new XAException(XAException.XA_RDONLY); // read-only\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t// An error occurred that makes the resource manager unavailable.\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t// Invalid arguments were specified.\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t// The routine was invoked in an improper context.\n\t\t\t\tXAException error = new XAException(XAException.XAER_RMERR);\n\t\t\t\terror.initCause(xaex);\n\t\t\t\tthrow error;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t// An error occurred in committing the work performed on behalf of the transaction\n\t\t\t\t// branch and the branch’s work has been rolled back. Note that returning this error\n\t\t\t\t// signals a catastrophic event to a transaction manager since other resource\n\t\t\t\t// managers may successfully commit their work on behalf of this branch. This error\n\t\t\t\t// should be returned only when a resource manager concludes that it can never\n\t\t\t\t// commit the branch and that it cannot hold the branch’s resources in a prepared\n\t\t\t\t// state. Otherwise, [XA_RETRY] should be returned.\n\t\t\t\tthrow xaex; // TODO XA_RETRY is not defined by the JTA specification\n\t\t\tdefault:// XA_RB*\n\t\t\t\tXAException xarb = new XAException(XAException.XA_HEURRB);\n\t\t\t\txarb.initCause(xaex);\n\t\t\t\tthrow xarb;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR */\n\tpublic synchronized void rollback(Xid xid) throws XAException {\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean committedExists = false;\n\t\tboolean rolledbackExists = false;\n\t\tboolean unFinishExists = false;\n\t\tboolean errorExists = false;\n\t\tfor (int i = 0; i < this.resources.size(); i++) {\n\t\t\tXAResourceArchive archive = this.resources.get(i);\n\n\t\t\tif (archive.isCommitted() && archive.isRolledback()) {\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isRolledback()) {\n\t\t\t\trolledbackExists = true;\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isReadonly()) {\n\t\t\t\tcontinue;\n\t\t\t} else if (archive.isCommitted()) {\n\t\t\t\tcommittedExists = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tboolean updateRequired = true;\n\t\t\ttry {\n\t\t\t\tthis.invokeRollback(archive);\n\t\t\t\trolledbackExists = true;\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tlogger.info(\"{}> rollback: xares= {}, branch= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()));\n\t\t\t} catch (XAException xaex) {\n\t\t\t\tlogger.error(\"{}> Error occurred while rolling back xa-resource: xares= {}, branch= {}, code= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), xaex.errorCode, xaex);\n\n\t\t\t\tswitch (xaex.errorCode) {\n\t\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\t\tcommittedExists = true;\n\t\t\t\t\trolledbackExists = true;\n\t\t\t\t\tarchive.setCommitted(true);\n\t\t\t\t\tarchive.setRolledback(true);\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\t\tcommittedExists = true;\n\t\t\t\t\tarchive.setCommitted(true);\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\t\trolledbackExists = true;\n\t\t\t\t\tarchive.setRolledback(true);\n\t\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\t\tarchive.setReadonly(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t\tunFinishExists = true;\n\t\t\t\t\tupdateRequired = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\tdefault:\n\t\t\t\t\terrorExists = true;\n\t\t\t\t\tupdateRequired = false;\n\t\t\t\t}\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tunFinishExists = true;\n\t\t\t\tupdateRequired = false;\n\t\t\t\tlogger.error(\"{}> Error occurred while rolling back xa-resource: xares= {}, branch= {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), rex);\n\t\t\t} finally {\n\t\t\t\tif (updateRequired) {\n\t\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (committedExists && rolledbackExists) {\n\t\t\tthrow new XAException(XAException.XA_HEURMIX);\n\t\t} else if (unFinishExists) {\n\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t} else if (errorExists) {\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} else if (committedExists) {\n\t\t\tthrow new XAException(XAException.XA_HEURCOM);\n\t\t} else if (rolledbackExists == false) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t}\n\n\t}\n\n\tprivate void invokeRollback(XAResourceArchive archive) throws XAException {\n\t\ttry {\n\t\t\tarchive.rollback(archive.getXid());\n\t\t} catch (XAException xaex) {\n\t\t\t// * @exception XAException An error has occurred. Possible XAExceptions are\n\t\t\t// * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR, XAER_RMFAIL,\n\t\t\t// * XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t// * <p>If the transaction branch is already marked rollback-only the\n\t\t\t// * resource manager may throw one of the XA_RB* exceptions. Upon return,\n\t\t\t// * the resource manager has rolled back the branch's work and has released\n\t\t\t// * all held resources.\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\t// Due to some failure, the work done on behalf of the specified transaction branch\n\t\t\t\t// may have been heuristically completed. A resource manager may return this\n\t\t\t\t// value only if it has successfully prepared xid.\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified transaction\n\t\t\t\t// branch was partially committed and partially rolled back. A resource manager\n\t\t\t\t// may return this value only if it has successfully prepared xid.\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified transaction\n\t\t\t\t// branch was committed. A resource manager may return this value only if it has\n\t\t\t\t// successfully prepared xid.\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified transaction\n\t\t\t\t// branch was rolled back. A resource manager may return this value only if it has\n\t\t\t\t// successfully prepared xid.\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t// An error occurred that makes the resource manager unavailable.\n\t\t\t\tXAException xrhaz = new XAException(XAException.XA_HEURHAZ);\n\t\t\t\txrhaz.initCause(xaex);\n\t\t\t\tthrow xrhaz;\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t// The specified XID is not known by the resource manager.\n\t\t\t\tif (archive.isReadonly()) {\n\t\t\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t\t\t} else if (archive.getVote() == XAResourceArchive.DEFAULT_VOTE) {\n\t\t\t\t\tbreak; // rolled back\n\t\t\t\t} else if (archive.getVote() == XAResource.XA_RDONLY) {\n\t\t\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t\t\t} else if (archive.getVote() == XAResource.XA_OK) {\n\t\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t\t}\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t// The routine was invoked in an improper context.\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t// Invalid arguments were specified.\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t// An error occurred in rolling back the transaction branch. The resource manager is\n\t\t\t\t// free to forget about the branch when returning this error so long as all accessing\n\t\t\t\t// threads of control have been notified of the branch’s state.\n\t\t\tdefault: // XA_RB*\n\t\t\t\t// The resource manager has rolled back the transaction branch’s work and has\n\t\t\t\t// released all held resources. These values are typically returned when the\n\t\t\t\t// branch was already marked rollback-only.\n\t\t\t\tXAException xarb = new XAException(XAException.XA_HEURRB);\n\t\t\t\txarb.initCause(xaex);\n\t\t\t\tthrow xarb;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic boolean setTransactionTimeout(int seconds) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic void start(Xid xid, int flags) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic void end(Xid xid, int flags) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic boolean isSameRM(XAResource xares) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic Xid[] recover(int flag) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic void forget(Xid xid) throws XAException {\n\t\tfor (int i = 0; i < this.resources.size(); i++) {\n\t\t\tXAResourceArchive archive = this.resources.get(i);\n\t\t\tXid currentXid = archive.getXid();\n\t\t\tif (archive.isHeuristic() == false) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tXid branchXid = archive.getXid();\n\t\t\t\tarchive.forget(branchXid);\n\t\t\t} catch (XAException xae) {\n\t\t\t\t// Possible exception values are XAER_RMERR, XAER_RMFAIL\n\t\t\t\t// , XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t\tswitch (xae.errorCode) {\n\t\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} // end-for\n\t}\n\n\tpublic List<XAResourceArchive> getResourceArchives() {\n\t\treturn this.resources;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory beanFactory) {\n\t\tthis.beanFactory = beanFactory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/resource/XATerminatorOptd.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.resource;\n\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ListIterator;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.logging.TransactionLogger;\nimport org.bytesoft.transaction.resource.XATerminator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class XATerminatorOptd implements XATerminator {\n\tstatic final Logger logger = LoggerFactory.getLogger(XATerminatorOptd.class);\n\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate XAResourceArchive archive;\n\n\tpublic synchronized int prepare(Xid xid) throws XAException {\n\t\tif (this.archive == null) {\n\t\t\treturn XAResource.XA_RDONLY;\n\t\t}\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean prepared = archive.getVote() != XAResourceArchive.DEFAULT_VOTE;\n\n\t\tint globalVote = XAResource.XA_RDONLY;\n\t\tif (prepared) {\n\t\t\tglobalVote = archive.getVote();\n\t\t} else {\n\t\t\tglobalVote = archive.prepare(archive.getXid());\n\t\t\tarchive.setVote(globalVote);\n\n\t\t\tif (globalVote == XAResource.XA_RDONLY) {\n\t\t\t\tarchive.setReadonly(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t} else {\n\t\t\t\tglobalVote = XAResource.XA_OK;\n\t\t\t}\n\n\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t}\n\n\t\tlogger.info(\"{}> prepare: xares= {}, branch= {}, vote= {}\",\n\t\t\t\tByteUtils.byteArrayToString(this.archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\tByteUtils.byteArrayToString(this.archive.getXid().getBranchQualifier()), globalVote);\n\n\t\treturn globalVote;\n\t}\n\n\t/** error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR */\n\tpublic synchronized void commit(Xid xid, boolean onePhase) throws XAException {\n\t\tif (onePhase) {\n\t\t\tthis.fireOnePhaseCommit(xid);\n\t\t} else {\n\t\t\tthis.fireTwoPhaseCommit(xid);\n\t\t}\n\t}\n\n\tprivate void fireOnePhaseCommit(Xid xid) throws XAException {\n\t\tif (archive.isCommitted() && archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURMIX);\n\t\t} else if (archive.isCommitted()) {\n\t\t\treturn;\n\t\t} else if (archive.isReadonly()) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY); // XAException.XAER_NOTA\n\t\t} else if (archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t}\n\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean updateRequired = true;\n\t\ttry {\n\t\t\tarchive.commit(archive.getXid(), true);\n\t\t\tarchive.setCommitted(true);\n\t\t\tarchive.setCompleted(true);\n\n\t\t\tlogger.info(\"{}> commit: xares= {}, branch= {}, opc= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), false);\n\t\t} catch (XAException xaex) {\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tupdateRequired = false;\n\t\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tupdateRequired = false;\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\tcase XAException.XA_RBCOMMFAIL:\n\t\t\tcase XAException.XA_RBDEADLOCK:\n\t\t\tcase XAException.XA_RBINTEGRITY:\n\t\t\tcase XAException.XA_RBOTHER:\n\t\t\tcase XAException.XA_RBPROTO:\n\t\t\tcase XAException.XA_RBROLLBACK:\n\t\t\tcase XAException.XA_RBTIMEOUT:\n\t\t\tcase XAException.XA_RBTRANSIENT:\n\t\t\tdefault:\n\t\t\t\tlogger.warn(\"An error occurred in one phase commit: {}, transaction has been rolled back!\",\n\t\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()));\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"{}> Error occurred while committing xa-resource: xares= {}, branch= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), rex);\n\t\t\tupdateRequired = false;\n\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t} finally {\n\t\t\tif (updateRequired) {\n\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void fireTwoPhaseCommit(Xid xid) throws XAException {\n\t\tif (archive.isCommitted() && archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURMIX);\n\t\t} else if (archive.isCommitted()) {\n\t\t\treturn;\n\t\t} else if (archive.isReadonly()) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY); // XAException.XAER_NOTA\n\t\t} else if (archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t}\n\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean updateRequired = true;\n\t\ttry {\n\t\t\tarchive.commit(archive.getXid(), false);\n\t\t\tarchive.setCommitted(true);\n\t\t\tarchive.setCompleted(true);\n\n\t\t\tlogger.info(\"{}> commit: xares= {}, branch= {}, opc= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), false);\n\t\t} catch (XAException xaex) {\n\t\t\t// * @exception XAException An error has occurred. Possible XAExceptions\n\t\t\t// * are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,\n\t\t\t// * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t// * <P>If the resource manager did not commit the transaction and the\n\t\t\t// * parameter onePhase is set to true, the resource manager may throw\n\t\t\t// * one of the XA_RB* exceptions. Upon return, the resource manager has\n\t\t\t// * rolled back the branch's work and has released all held resources.\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\t// OSI-TP: The condition that arises when, as a result of communication failure with a\n\t\t\t\t// subordinate, the bound data of the subordinate's subtree are in an unknown state.\n\n\t\t\t\t// XA: Due to some failure, the work done on behalf of the specified\n\t\t\t\t// transaction branch may have been heuristically completed.\n\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified\n\t\t\t\t// transaction branch was partially committed and partially rolled back.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of\n\t\t\t\t// the specified transaction branch was committed.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of\n\t\t\t\t// the specified transaction branch was rolled back.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t// The specified XID is not known by the resource manager.\n\t\t\t\tarchive.setReadonly(true);\n\t\t\t\tthrow new XAException(XAException.XA_RDONLY); // read-only\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t// An error occurred that makes the resource manager unavailable.\n\n\t\t\t\tupdateRequired = false;\n\t\t\t\tXAException xahaz = new XAException(XAException.XA_HEURHAZ);\n\t\t\t\txahaz.initCause(xaex);\n\t\t\t\tthrow xahaz;\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t// Invalid arguments were specified.\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t// The routine was invoked in an improper context.\n\n\t\t\t\tupdateRequired = false;\n\t\t\t\tXAException error = new XAException(XAException.XAER_RMERR);\n\t\t\t\terror.initCause(xaex);\n\t\t\t\tthrow error;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t// An error occurred in committing the work performed on behalf of the transaction\n\t\t\t\t// branch and the branch’s work has been rolled back. Note that returning this error\n\t\t\t\t// signals a catastrophic event to a transaction manager since other resource\n\t\t\t\t// managers may successfully commit their work on behalf of this branch. This error\n\t\t\t\t// should be returned only when a resource manager concludes that it can never\n\t\t\t\t// commit the branch and that it cannot hold the branch’s resources in a prepared\n\t\t\t\t// state. Otherwise, [XA_RETRY] should be returned.\n\t\t\tdefault: // XA_RB*\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tXAException xarb = new XAException(XAException.XA_HEURRB);\n\t\t\t\txarb.initCause(xaex);\n\t\t\t\tthrow xarb;\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"{}> Error occurred while committing xa-resource: xares= {}, branch= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), rex);\n\t\t\tupdateRequired = false;\n\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t} finally {\n\t\t\tif (updateRequired) {\n\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR */\n\tpublic synchronized void rollback(Xid xid) throws XAException {\n\t\tif (archive.isCommitted() && archive.isRolledback()) {\n\t\t\tthrow new XAException(XAException.XA_HEURMIX);\n\t\t} else if (archive.isRolledback()) {\n\t\t\treturn;\n\t\t} else if (archive.isReadonly()) {\n\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t} else if (archive.isCommitted()) {\n\t\t\tthrow new XAException(XAException.XA_HEURCOM);\n\t\t}\n\n\t\tTransactionLogger transactionLogger = this.beanFactory.getTransactionLogger();\n\n\t\tboolean updateRequired = true;\n\t\ttry {\n\t\t\tarchive.rollback(archive.getXid());\n\t\t\tarchive.setRolledback(true);\n\t\t\tarchive.setCompleted(true);\n\n\t\t\tlogger.info(\"{}> rollback: xares= {}, branch= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()));\n\t\t} catch (XAException xaex) {\n\t\t\tlogger.error(\"{}> Error occurred while rolling back xa-resource: xares= {}, branch= {}, code= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), xaex.errorCode, xaex);\n\n\t\t\t// * @exception XAException An error has occurred. Possible XAExceptions are\n\t\t\t// * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR, XAER_RMFAIL,\n\t\t\t// * XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t// * <p>If the transaction branch is already marked rollback-only the\n\t\t\t// * resource manager may throw one of the XA_RB* exceptions. Upon return,\n\t\t\t// * the resource manager has rolled back the branch's work and has released\n\t\t\t// * all held resources.\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\t// Due to some failure, the work done on behalf of the specified transaction branch\n\t\t\t\t// may have been heuristically completed. A resource manager may return this\n\t\t\t\t// value only if it has successfully prepared xid.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified transaction\n\t\t\t\t// branch was partially committed and partially rolled back. A resource manager\n\t\t\t\t// may return this value only if it has successfully prepared xid.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified transaction\n\t\t\t\t// branch was committed. A resource manager may return this value only if it has\n\t\t\t\t// successfully prepared xid.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setCommitted(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tthrow xaex;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\t// Due to a heuristic decision, the work done on behalf of the specified transaction\n\t\t\t\t// branch was rolled back. A resource manager may return this value only if it has\n\t\t\t\t// successfully prepared xid.\n\t\t\t\tarchive.setHeuristic(true);\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t// An error occurred that makes the resource manager unavailable.\n\n\t\t\t\tupdateRequired = false;\n\t\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\t// The specified XID is not known by the resource manager.\n\t\t\t\tif (archive.isReadonly()) {\n\t\t\t\t\tarchive.setReadonly(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t\t\t} else if (archive.getVote() == XAResourceArchive.DEFAULT_VOTE) {\n\t\t\t\t\tarchive.setRolledback(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tbreak; // rolled back\n\t\t\t\t} else if (archive.getVote() == XAResource.XA_RDONLY) {\n\t\t\t\t\tarchive.setReadonly(true);\n\t\t\t\t\tarchive.setCompleted(true);\n\t\t\t\t\tthrow new XAException(XAException.XA_RDONLY);\n\t\t\t\t} else if (archive.getVote() == XAResource.XA_OK) {\n\t\t\t\t\tupdateRequired = false;\n\t\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t\t} else {\n\t\t\t\t\tupdateRequired = false;\n\t\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t\t}\n\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t// The routine was invoked in an improper context.\n\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\t// Invalid arguments were specified.\n\n\t\t\t\tupdateRequired = false;\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t// An error occurred in rolling back the transaction branch. The resource manager is\n\t\t\t\t// free to forget about the branch when returning this error so long as all accessing\n\t\t\t\t// threads of control have been notified of the branch’s state.\n\t\t\tdefault: // XA_RB*\n\t\t\t\t// The resource manager has rolled back the transaction branch’s work and has\n\t\t\t\t// released all held resources. These values are typically returned when the\n\t\t\t\t// branch was already marked rollback-only.\n\t\t\t\tarchive.setRolledback(true);\n\t\t\t\tarchive.setCompleted(true);\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"{}> Error occurred while rolling back xa-resource: xares= {}, branch= {}\",\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getGlobalTransactionId()), archive,\n\t\t\t\t\tByteUtils.byteArrayToString(archive.getXid().getBranchQualifier()), rex);\n\t\t\tupdateRequired = false;\n\t\t\tthrow new XAException(XAException.XA_HEURHAZ);\n\t\t} finally {\n\t\t\tif (updateRequired) {\n\t\t\t\ttransactionLogger.updateParticipant(archive);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic boolean setTransactionTimeout(int seconds) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic void start(Xid xid, int flags) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic void end(Xid xid, int flags) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic boolean isSameRM(XAResource xares) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic Xid[] recover(int flag) throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t}\n\n\tpublic void forget(Xid xid) throws XAException {\n\t\tif (this.archive == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tXid currentXid = archive.getXid();\n\t\tif (archive.isHeuristic()) {\n\t\t\ttry {\n\t\t\t\tXid branchXid = archive.getXid();\n\t\t\t\tarchive.forget(branchXid);\n\t\t\t} catch (XAException xae) {\n\t\t\t\t// Possible exception values are XAER_RMERR, XAER_RMFAIL\n\t\t\t\t// , XAER_NOTA, XAER_INVAL, or XAER_PROTO.\n\t\t\t\tswitch (xae.errorCode) {\n\t\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_RMFAIL:\n\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\tcase XAException.XAER_INVAL:\n\t\t\t\tcase XAException.XAER_PROTO:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tlogger.error(\"{}> forget: xares= {}, branch={}, error= {}\",\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getGlobalTransactionId()), archive,\n\t\t\t\t\t\t\tByteUtils.byteArrayToString(currentXid.getBranchQualifier()), xae.errorCode);\n\t\t\t\t}\n\t\t\t}\n\t\t} // end-if\n\t}\n\n\tpublic List<XAResourceArchive> getResourceArchives() {\n\t\treturn new List<XAResourceArchive>() {\n\n\t\t\tpublic int size() {\n\t\t\t\treturn archive == null ? 0 : 1;\n\t\t\t}\n\n\t\t\tpublic boolean isEmpty() {\n\t\t\t\treturn archive == null ? true : false;\n\t\t\t}\n\n\t\t\tpublic boolean contains(Object o) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic Iterator<XAResourceArchive> iterator() {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic Object[] toArray() {\n\t\t\t\treturn archive == null ? new Object[0] : new Object[] { archive };\n\t\t\t}\n\n\t\t\tpublic <T> T[] toArray(T[] a) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic boolean add(XAResourceArchive e) {\n\t\t\t\tif (XATerminatorOptd.this.archive != null && e != null) {\n\t\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t\t} else if (e != null) {\n\t\t\t\t\tXATerminatorOptd.this.archive = e;\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic boolean remove(Object o) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic boolean containsAll(Collection<?> c) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic boolean addAll(Collection<? extends XAResourceArchive> c) {\n\t\t\t\tif (c == null || c.size() > 1) {\n\t\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t\t} else if (XATerminatorOptd.this.archive != null && c.isEmpty() == false) {\n\t\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t\t} else if (c.isEmpty() == false) {\n\t\t\t\t\tObject[] array = c.toArray();\n\t\t\t\t\tXATerminatorOptd.this.archive = (XAResourceArchive) array[0];\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tpublic boolean addAll(int index, Collection<? extends XAResourceArchive> c) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic boolean removeAll(Collection<?> c) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic boolean retainAll(Collection<?> c) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic void clear() {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic XAResourceArchive get(int index) {\n\t\t\t\tif (index > 0 || index < 0) {\n\t\t\t\t\tthrow new IndexOutOfBoundsException(String.format(\"index: %s, size: %s\", index, this.size()));\n\t\t\t\t} else if (archive == null) {\n\t\t\t\t\tthrow new IndexOutOfBoundsException(String.format(\"index: %s, size: 0\", index));\n\t\t\t\t}\n\t\t\t\treturn archive;\n\t\t\t}\n\n\t\t\tpublic XAResourceArchive set(int index, XAResourceArchive element) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic void add(int index, XAResourceArchive element) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic XAResourceArchive remove(int index) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic int indexOf(Object o) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic int lastIndexOf(Object o) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic ListIterator<XAResourceArchive> listIterator() {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic ListIterator<XAResourceArchive> listIterator(int index) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\n\t\t\tpublic List<XAResourceArchive> subList(int fromIndex, int toIndex) {\n\t\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory beanFactory) {\n\t\tthis.beanFactory = beanFactory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/strategy/CommonTransactionStrategy.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.strategy;\n\nimport javax.transaction.HeuristicCommitException;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.bytejta.TransactionStrategy;\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\nimport org.bytesoft.transaction.resource.XATerminator;\n\npublic class CommonTransactionStrategy implements TransactionStrategy {\n\tprivate final XATerminator nativeTerminator;\n\tprivate final XATerminator remoteTerminator;\n\n\tpublic CommonTransactionStrategy(XATerminator nativeTerminator, XATerminator remoteTerminator) {\n\t\tif (nativeTerminator == null || nativeTerminator.getResourceArchives().isEmpty()) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (remoteTerminator == null || remoteTerminator.getResourceArchives().isEmpty()) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tthis.nativeTerminator = nativeTerminator;\n\t\tthis.remoteTerminator = remoteTerminator;\n\t}\n\n\tpublic int prepare(Xid xid) throws RollbackRequiredException, CommitRequiredException {\n\t\tint nativeVote = XAResource.XA_RDONLY;\n\t\ttry {\n\t\t\tnativeVote = this.nativeTerminator.prepare(xid);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t}\n\n\t\tint remoteVote = XAResource.XA_RDONLY;\n\t\ttry {\n\t\t\tremoteVote = this.remoteTerminator.prepare(xid);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t}\n\n\t\tif (XAResource.XA_OK == nativeVote || XAResource.XA_OK == remoteVote) {\n\t\t\treturn XAResource.XA_OK;\n\t\t} else {\n\t\t\treturn XAResource.XA_RDONLY;\n\t\t}\n\n\t}\n\n\tpublic void commit(Xid xid, boolean onePhaseCommit)\n\t\t\tthrows HeuristicMixedException, HeuristicRollbackException, IllegalStateException, SystemException {\n\t\tboolean committedExists = false;\n\t\tboolean rolledbackExists = false;\n\t\tboolean unFinishExists = false;\n\t\tboolean errorExists = false;\n\t\ttry {\n\t\t\tthis.nativeTerminator.commit(xid, onePhaseCommit);\n\t\t\tcommittedExists = true;\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tcommittedExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tunFinishExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\terrorExists = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\terrorExists = true;\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tunFinishExists = true;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.remoteTerminator.commit(xid, false);\n\t\t\tcommittedExists = true;\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tcommittedExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tunFinishExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\terrorExists = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\terrorExists = true;\n\t\t\t}\n\n\t\t} catch (RuntimeException ex) {\n\t\t\tunFinishExists = true;\n\t\t}\n\n\t\tif (committedExists && rolledbackExists) {\n\t\t\tthrow new HeuristicMixedException();\n\t\t} else if (unFinishExists) {\n\t\t\tthrow new SystemException(); // hazard\n\t\t} else if (errorExists) {\n\t\t\tthrow new SystemException();\n\t\t} else if (rolledbackExists) {\n\t\t\tthrow new HeuristicRollbackException();\n\t\t}\n\n\t}\n\n\tpublic void rollback(Xid xid)\n\t\t\tthrows HeuristicMixedException, HeuristicCommitException, IllegalStateException, SystemException {\n\n\t\tboolean committedExists = false;\n\t\tboolean rolledbackExists = false;\n\t\tboolean unFinishExists = false;\n\t\tboolean errorExists = false;\n\t\ttry {\n\t\t\tthis.nativeTerminator.rollback(xid);\n\t\t\trolledbackExists = true;\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tcommittedExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tunFinishExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\terrorExists = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\terrorExists = true;\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tunFinishExists = true;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.remoteTerminator.rollback(xid);\n\t\t\trolledbackExists = true;\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tcommittedExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tunFinishExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\terrorExists = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\terrorExists = true;\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tunFinishExists = true;\n\t\t}\n\n\t\tif (committedExists && rolledbackExists) {\n\t\t\tthrow new HeuristicMixedException();\n\t\t} else if (unFinishExists) {\n\t\t\tthrow new SystemException(); // hazard\n\t\t} else if (errorExists) {\n\t\t\tthrow new SystemException();\n\t\t} else if (committedExists) {\n\t\t\tthrow new HeuristicCommitException();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/strategy/LastResourceOptimizeStrategy.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.strategy;\n\nimport javax.transaction.HeuristicCommitException;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.bytejta.TransactionStrategy;\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\nimport org.bytesoft.transaction.resource.XATerminator;\n\npublic class LastResourceOptimizeStrategy implements TransactionStrategy {\n\tprivate final XATerminator terminatorOne;\n\tprivate final XATerminator terminatorTwo;\n\n\tpublic LastResourceOptimizeStrategy(XATerminator terminatorOne, XATerminator terminatorTwo) {\n\t\tif (terminatorOne == null || terminatorOne.getResourceArchives().size() != 1) {\n\t\t\tthrow new IllegalStateException();\n\t\t} else if (terminatorTwo == null || terminatorTwo.getResourceArchives().isEmpty()) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tthis.terminatorOne = terminatorOne;\n\t\tthis.terminatorTwo = terminatorTwo;\n\t}\n\n\tpublic int prepare(Xid xid) throws RollbackRequiredException, CommitRequiredException {\n\n\t\tint vote = XAResource.XA_RDONLY;\n\t\ttry {\n\t\t\tvote = this.terminatorTwo.prepare(xid);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t}\n\n\t\ttry {\n\t\t\tthis.terminatorOne.commit(xid, true);\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tthrow new CommitRequiredException();\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tthrow new RollbackRequiredException();\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tthrow new CommitRequiredException();\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tthrow new CommitRequiredException(); // TODO\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\treturn vote;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\tdefault:\n\t\t\t\tthrow new RollbackRequiredException();\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t}\n\n\t\tthrow new CommitRequiredException();\n\t}\n\n\tpublic void commit(Xid xid, boolean onePhaseCommit)\n\t\t\tthrows HeuristicMixedException, HeuristicRollbackException, IllegalStateException, SystemException {\n\t\ttry {\n\t\t\tthis.terminatorTwo.commit(xid, onePhaseCommit);\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tthrow new HeuristicRollbackException();\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tthrow new HeuristicMixedException();\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tthrow new SystemException();\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\tthrow new SystemException();\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\tthrow new SystemException();\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tthrow new SystemException();\n\t\t}\n\t}\n\n\tpublic void rollback(Xid xid)\n\t\t\tthrows HeuristicMixedException, HeuristicCommitException, IllegalStateException, SystemException {\n\n\t\tboolean committedExists = false;\n\t\tboolean rolledbackExists = false;\n\t\tboolean unFinishExists = false;\n\t\tboolean errorExists = false;\n\t\ttry {\n\t\t\tthis.terminatorOne.rollback(xid);\n\t\t\trolledbackExists = true;\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tcommittedExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tunFinishExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\terrorExists = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\terrorExists = true;\n\t\t\t}\n\n\t\t} catch (RuntimeException ex) {\n\t\t\tunFinishExists = true;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.terminatorTwo.rollback(xid);\n\t\t\trolledbackExists = true;\n\t\t} catch (XAException ex) {\n\t\t\t// error: XA_HEURHAZ, XA_HEURMIX, XA_HEURCOM, XA_HEURRB, XA_RDONLY, XAER_RMERR\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tcommittedExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tcommittedExists = true;\n\t\t\t\trolledbackExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURHAZ:\n\t\t\t\tunFinishExists = true;\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_RDONLY:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XAER_RMERR:\n\t\t\t\terrorExists = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// should never happen\n\t\t\t\terrorExists = true;\n\t\t\t}\n\t\t} catch (RuntimeException ex) {\n\t\t\tunFinishExists = true;\n\t\t}\n\n\t\tif (committedExists && rolledbackExists) {\n\t\t\tthrow new HeuristicMixedException();\n\t\t} else if (unFinishExists) {\n\t\t\tthrow new SystemException(); // hazard\n\t\t} else if (errorExists) {\n\t\t\tthrow new SystemException();\n\t\t} else if (committedExists) {\n\t\t\tthrow new HeuristicCommitException();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/strategy/SimpleTransactionStrategy.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.strategy;\n\nimport javax.transaction.HeuristicCommitException;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.bytejta.TransactionStrategy;\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\nimport org.bytesoft.transaction.resource.XATerminator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class SimpleTransactionStrategy implements TransactionStrategy {\n\tstatic final Logger logger = LoggerFactory.getLogger(SimpleTransactionStrategy.class);\n\n\tprivate final XATerminator terminator;\n\n\tpublic SimpleTransactionStrategy(XATerminator terminator) {\n\t\tif (terminator == null || terminator.getResourceArchives().isEmpty()) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tthis.terminator = terminator;\n\t}\n\n\tpublic int prepare(Xid xid) throws RollbackRequiredException, CommitRequiredException {\n\n\t\ttry {\n\t\t\treturn this.terminator.prepare(xid);\n\t\t} catch (XAException xaex) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t} catch (RuntimeException xaex) {\n\t\t\tthrow new RollbackRequiredException();\n\t\t}\n\n\t}\n\n\tpublic void commit(Xid xid, boolean onePhaseCommit)\n\t\t\tthrows HeuristicMixedException, HeuristicRollbackException, IllegalStateException, SystemException {\n\t\ttry {\n\t\t\tthis.terminator.commit(xid, onePhaseCommit);\n\t\t} catch (XAException xaex) {\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tthrow new HeuristicMixedException();\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tthrow new HeuristicRollbackException();\n\t\t\tdefault:\n\t\t\t\tlogger.error(\"Unknown state in committing transaction phase.\", xaex);\n\t\t\t\tthrow new SystemException();\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Unknown state in committing transaction phase.\", rex);\n\t\t\tthrow new SystemException();\n\t\t}\n\t}\n\n\tpublic void rollback(Xid xid)\n\t\t\tthrows HeuristicMixedException, HeuristicCommitException, IllegalStateException, SystemException {\n\t\ttry {\n\t\t\tthis.terminator.rollback(xid);\n\t\t} catch (XAException xaex) {\n\t\t\tswitch (xaex.errorCode) {\n\t\t\tcase XAException.XA_HEURRB:\n\t\t\t\tbreak;\n\t\t\tcase XAException.XA_HEURMIX:\n\t\t\t\tthrow new HeuristicMixedException();\n\t\t\tcase XAException.XA_HEURCOM:\n\t\t\t\tthrow new HeuristicCommitException();\n\t\t\tdefault:\n\t\t\t\tlogger.error(\"Unknown state in rollingback transaction phase.\", xaex);\n\t\t\t\tthrow new SystemException();\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Unknown state in rollingback transaction phase.\", rex);\n\t\t\tthrow new SystemException();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/strategy/VacantTransactionStrategy.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.strategy;\n\nimport javax.transaction.HeuristicCommitException;\nimport javax.transaction.HeuristicMixedException;\nimport javax.transaction.HeuristicRollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.bytejta.TransactionStrategy;\nimport org.bytesoft.transaction.CommitRequiredException;\nimport org.bytesoft.transaction.RollbackRequiredException;\n\npublic class VacantTransactionStrategy implements TransactionStrategy {\n\n\tpublic int prepare(Xid xid) throws RollbackRequiredException, CommitRequiredException {\n\t\treturn XAResource.XA_RDONLY;\n\t}\n\n\tpublic void commit(Xid xid, boolean onePhaseCommit)\n\t\t\tthrows HeuristicMixedException, HeuristicRollbackException, IllegalStateException, SystemException {\n\t}\n\n\tpublic void rollback(Xid xid)\n\t\t\tthrows HeuristicMixedException, HeuristicCommitException, IllegalStateException, SystemException {\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/jdbc/DataSourceHolder.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\nimport javax.sql.DataSource;\n\npublic interface DataSourceHolder {\n\n\tpublic DataSource getDataSource();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/jdbc/LocalXACompatible.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\npublic interface LocalXACompatible {\n\n\tpublic boolean compatibleLoggingLRO();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/jdbc/LocalXAConnection.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Set;\n\nimport javax.sql.ConnectionEvent;\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.StatementEventListener;\nimport javax.sql.XAConnection;\n\nimport org.bytesoft.bytejta.supports.resource.LocalXAResourceDescriptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class LocalXAConnection implements XAConnection {\n\tstatic final Logger logger = LoggerFactory.getLogger(LocalXAConnection.class);\n\n\tprivate String resourceId;\n\n\tprivate final Connection connection;\n\tprivate final LocalXAResource xaResource = new LocalXAResource(this);\n\tprivate boolean underlyingConCloseRequired = false;\n\tprivate boolean physicalConnectionReleased = false;\n\tprivate int physicalConnectionSharingCount = 0;\n\n\tprivate final Set<ConnectionEventListener> listeners = new HashSet<ConnectionEventListener>();\n\n\tpublic LocalXAConnection(Connection connection) {\n\t\tthis.connection = connection;\n\t}\n\n\tprotected Connection getPhysicalConnection() {\n\t\treturn this.connection;\n\t}\n\n\tpublic LogicalConnection getConnection() throws SQLException {\n\t\tif (this.physicalConnectionReleased) {\n\t\t\tthrow new SQLException(\"LocalXAConnection has already been closed!\");\n\t\t}\n\n\t\tLogicalConnection logicalConnection = new LogicalConnection(this, this.connection);\n\n\t\tthis.physicalConnectionSharingCount++;\n\t\tthis.underlyingConCloseRequired = false;\n\n\t\treturn logicalConnection;\n\t}\n\n\tpublic void closeLogicalConnection() throws SQLException {\n\t\tthis.physicalConnectionSharingCount--;\n\n\t\tif (this.physicalConnectionSharingCount == 0) {\n\t\t\tthis.underlyingConCloseRequired = true;\n\t\t}\n\n\t}\n\n\tprivate void releaseConnection() {\n\t\tif (this.physicalConnectionReleased == false) {\n\t\t\ttry {\n\t\t\t\tthis.connection.close();\n\t\t\t\tthis.fireConnectionClosed();\n\t\t\t} catch (SQLException ex) {\n\t\t\t\tlogger.debug(\"Error occurred while closing connection!\", ex);\n\n\t\t\t\tthis.fireConnectionErrorOccurred();\n\t\t\t} catch (RuntimeException ex) {\n\t\t\t\tlogger.debug(\"Error occurred while closing connection!\", ex);\n\n\t\t\t\tthis.fireConnectionErrorOccurred();\n\t\t\t} finally {\n\t\t\t\tthis.physicalConnectionReleased = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void commitLocalTransaction() throws SQLException {\n\t\ttry {\n\t\t\tthis.connection.commit();\n\t\t} catch (SQLException ex) {\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t}\n\t}\n\n\tpublic void rollbackLocalTransaction() throws SQLException {\n\t\ttry {\n\t\t\tthis.connection.rollback();\n\t\t} catch (SQLException ex) {\n\t\t\tthrow ex;\n\t\t} catch (RuntimeException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t}\n\t}\n\n\tpublic void closeQuietly() {\n\t\ttry {\n\t\t\tthis.close();\n\t\t} catch (Exception ex) {\n\t\t\tlogger.warn(\"Error occurred while closing physical connection.\", ex);\n\t\t}\n\t}\n\n\tpublic void close() throws SQLException {\n\t\tif (this.underlyingConCloseRequired == false) {\n\t\t\tlogger.warn(\"Illegal state: there is at least one connection that is not closed!\");\n\t\t}\n\n\t\tthis.releaseConnection();\n\t}\n\n\tprivate void fireConnectionClosed() {\n\t\tIterator<ConnectionEventListener> itr = this.listeners.iterator();\n\t\twhile (itr.hasNext()) {\n\t\t\tConnectionEventListener listener = itr.next();\n\t\t\ttry {\n\t\t\t\tlistener.connectionClosed(new ConnectionEvent(this));\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void fireConnectionErrorOccurred() {\n\t\tIterator<ConnectionEventListener> itr = this.listeners.iterator();\n\t\twhile (itr.hasNext()) {\n\t\t\tConnectionEventListener listener = itr.next();\n\t\t\ttry {\n\t\t\t\tlistener.connectionErrorOccurred(new ConnectionEvent(this));\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void addConnectionEventListener(ConnectionEventListener paramConnectionEventListener) {\n\t\tthis.listeners.add(paramConnectionEventListener);\n\t}\n\n\tpublic void removeConnectionEventListener(ConnectionEventListener paramConnectionEventListener) {\n\t\tthis.listeners.remove(paramConnectionEventListener);\n\t}\n\n\tpublic void addStatementEventListener(StatementEventListener paramStatementEventListener) {\n\t}\n\n\tpublic void removeStatementEventListener(StatementEventListener paramStatementEventListener) {\n\t}\n\n\tpublic LocalXAResourceDescriptor getXAResource(boolean loggingRequired) throws SQLException {\n\t\tLocalXAResourceDescriptor descriptor = new LocalXAResourceDescriptor();\n\t\tdescriptor.setIdentifier(this.resourceId);\n\t\tdescriptor.setDelegate(this.xaResource);\n\t\tdescriptor.setLoggingRequired(loggingRequired);\n\t\treturn descriptor;\n\t}\n\n\tpublic LocalXAResourceDescriptor getXAResource() throws SQLException {\n\t\treturn this.getXAResource(true);\n\t}\n\n\tpublic String getResourceId() {\n\t\treturn resourceId;\n\t}\n\n\tpublic void setResourceId(String resourceId) {\n\t\tthis.resourceId = resourceId;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/jdbc/LocalXAResource.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class LocalXAResource implements XAResource {\n\tstatic final Logger logger = LoggerFactory.getLogger(LocalXAResource.class);\n\n\tprivate LocalXAConnection managedConnection;\n\tprivate Xid currentXid;\n\tprivate Xid suspendXid;\n\tprivate boolean suspendAutoCommit;\n\tprivate boolean originalAutoCommit;\n\n\tpublic LocalXAResource() {\n\t}\n\n\tpublic LocalXAResource(LocalXAConnection managedConnection) {\n\t\tthis.managedConnection = managedConnection;\n\t}\n\n\tpublic void recoverable(Xid xid) throws XAException {\n\t\tbyte[] globalTransactionId = xid.getGlobalTransactionId();\n\t\tbyte[] branchQualifier = xid.getBranchQualifier();\n\n\t\tString gxid = ByteUtils.byteArrayToString(globalTransactionId);\n\t\tString bxid = null;\n\t\tif (branchQualifier == null || branchQualifier.length == 0) {\n\t\t\tbxid = gxid;\n\t\t} else {\n\t\t\tbxid = ByteUtils.byteArrayToString(branchQualifier);\n\t\t}\n\n\t\tString identifier = this.getIdentifier(globalTransactionId, branchQualifier);\n\n\t\tConnection connection = this.managedConnection.getPhysicalConnection();\n\n\t\tPreparedStatement stmt = null;\n\t\tResultSet rs = null;\n\t\ttry {\n\t\t\tStringBuilder sql = new StringBuilder();\n\t\t\tsql.append(\"select xid, gxid, bxid from bytejta where xid = ? gxid = ? and bxid = ? \");\n\t\t\tstmt = connection.prepareStatement(sql.toString());\n\t\t\tstmt.setString(1, identifier);\n\t\t\tstmt.setString(2, gxid);\n\t\t\tstmt.setString(3, bxid);\n\t\t\trs = stmt.executeQuery();\n\t\t\tif (rs.next() == false) {\n\t\t\t\tthrow new XAException(XAException.XAER_NOTA);\n\t\t\t}\n\t\t} catch (SQLException ex) {\n\t\t\ttry {\n\t\t\t\tthis.isTableExists(connection);\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} finally {\n\t\t\tthis.closeQuietly(rs);\n\t\t\tthis.closeQuietly(stmt);\n\t\t}\n\t}\n\n\tpublic synchronized void start(Xid xid, int flags) throws XAException {\n\t\tif (xid == null) {\n\t\t\tthrow new XAException(XAException.XAER_INVAL);\n\t\t} else if (flags == XAResource.TMRESUME && this.suspendXid != null) {\n\t\t\tif (this.suspendXid.equals(xid)) {\n\t\t\t\tthis.suspendXid = null;\n\t\t\t\tthis.currentXid = xid;\n\t\t\t\tthis.originalAutoCommit = this.suspendAutoCommit;\n\t\t\t\tthis.suspendAutoCommit = true;\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t\t}\n\t\t} else if (flags == XAResource.TMJOIN) {\n\t\t\tif (this.currentXid == null) {\n\t\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t\t}\n\t\t} else if (flags != XAResource.TMNOFLAGS) {\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t} else if (this.currentXid != null) {\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t} else {\n\t\t\tConnection connection = this.managedConnection.getPhysicalConnection();\n\n\t\t\ttry {\n\t\t\t\toriginalAutoCommit = connection.getAutoCommit();\n\t\t\t} catch (Exception ignored) {\n\t\t\t\toriginalAutoCommit = true;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconnection.setAutoCommit(false);\n\t\t\t} catch (Exception ex) {\n\t\t\t\tXAException xae = new XAException(XAException.XAER_RMERR);\n\t\t\t\txae.initCause(ex);\n\t\t\t\tthrow xae;\n\t\t\t}\n\n\t\t\tthis.currentXid = xid;\n\t\t}\n\t}\n\n\tpublic synchronized void end(Xid xid, int flags) throws XAException {\n\t\tif (xid == null) {\n\t\t\tthrow new XAException(XAException.XAER_INVAL);\n\t\t} else if (this.currentXid == null) {\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t} else if (!this.currentXid.equals(xid)) {\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t} else if (flags == XAResource.TMSUSPEND) {\n\t\t\tthis.suspendXid = xid;\n\t\t\tthis.suspendAutoCommit = this.originalAutoCommit;\n\t\t\tthis.currentXid = null;\n\t\t\tthis.originalAutoCommit = true;\n\t\t} else if (flags == XAResource.TMSUCCESS) {\n\t\t\t// delay the logging operation to the commit phase.\n\t\t\t// this.createTransactionLogIfNecessary(xid);\n\t\t} else if (flags == XAResource.TMFAIL) {\n\t\t\tlogger.debug(\"Error occurred while ending local-xa-resource.\");\n\t\t} else {\n\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t}\n\t}\n\n\tpublic synchronized int prepare(Xid xid) {\n\t\tConnection connection = this.managedConnection.getPhysicalConnection();\n\t\ttry {\n\t\t\tif (connection.isReadOnly()) {\n\t\t\t\tconnection.setAutoCommit(originalAutoCommit);\n\t\t\t\treturn XAResource.XA_RDONLY;\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tlogger.debug(\"Error occurred while preparing local-xa-resource: {}\", ex.getMessage());\n\t\t}\n\t\treturn XAResource.XA_OK;\n\t}\n\n\tpublic synchronized void commit(Xid xid, boolean loggingRequired) throws XAException {\n\t\ttry {\n\t\t\tif (xid == null) {\n\t\t\t\tthrow new XAException(XAException.XAER_INVAL);\n\t\t\t} else if (this.currentXid == null) {\n\t\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t\t} else if (!this.currentXid.equals(xid)) {\n\t\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t\t}\n\n\t\t\tif (loggingRequired) {\n\t\t\t\tthis.createTransactionLogIfNecessary(xid);\n\t\t\t} // end-if (loggingRequired)\n\n\t\t\tthis.managedConnection.commitLocalTransaction();\n\t\t} catch (XAException xae) {\n\t\t\tthrow xae;\n\t\t} catch (Exception ex) {\n\t\t\tXAException xae = new XAException(XAException.XAER_RMERR);\n\t\t\txae.initCause(ex);\n\t\t\tthrow xae;\n\t\t} finally {\n\t\t\tthis.releasePhysicalConnection();\n\t\t}\n\t}\n\n\tpublic synchronized void rollback(Xid xid) throws XAException {\n\t\ttry {\n\t\t\tif (xid == null) {\n\t\t\t\tthrow new XAException(XAException.XAER_INVAL);\n\t\t\t} else if (this.currentXid == null) {\n\t\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t\t} else if (!this.currentXid.equals(xid)) {\n\t\t\t\tthrow new XAException(XAException.XAER_PROTO);\n\t\t\t}\n\n\t\t\tthis.managedConnection.rollbackLocalTransaction();\n\t\t} catch (XAException xae) {\n\t\t\tthrow xae;\n\t\t} catch (Exception ex) {\n\t\t\tXAException xae = new XAException(XAException.XAER_RMERR);\n\t\t\txae.initCause(ex);\n\t\t\tthrow xae;\n\t\t} finally {\n\t\t\tthis.releasePhysicalConnection();\n\t\t}\n\t}\n\n\tprivate void createTransactionLogIfNecessary(Xid xid) throws XAException {\n\t\tbyte[] globalTransactionId = xid.getGlobalTransactionId();\n\t\tbyte[] branchQualifier = xid.getBranchQualifier();\n\n\t\tString gxid = ByteUtils.byteArrayToString(globalTransactionId);\n\t\tString bxid = null;\n\t\tif (branchQualifier == null || branchQualifier.length == 0) {\n\t\t\tbxid = gxid;\n\t\t} else {\n\t\t\tbxid = ByteUtils.byteArrayToString(branchQualifier);\n\t\t}\n\n\t\tString identifier = this.getIdentifier(globalTransactionId, branchQualifier);\n\n\t\tConnection connection = this.managedConnection.getPhysicalConnection();\n\n\t\tPreparedStatement stmt = null;\n\t\ttry {\n\t\t\tstmt = connection.prepareStatement(\"insert into bytejta(xid, gxid, bxid, ctime) values(?, ?, ?, ?)\");\n\t\t\tstmt.setString(1, identifier);\n\t\t\tstmt.setString(2, gxid);\n\t\t\tstmt.setString(3, bxid);\n\t\t\tstmt.setLong(4, System.currentTimeMillis());\n\t\t\tint value = stmt.executeUpdate();\n\t\t\tif (value == 0) {\n\t\t\t\tthrow new IllegalStateException(\"The operation failed and the data was not written to the database!\");\n\t\t\t}\n\t\t} catch (SQLException ex) {\n\t\t\tboolean tableExists = false;\n\t\t\ttry {\n\t\t\t\ttableExists = this.isTableExists(connection);\n\t\t\t} catch (Exception sqlEx) {\n\t\t\t\tlogger.error(\"Error occurred while ending local-xa-resource: {}\", ex.getMessage());\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\n\t\t\tif (tableExists) {\n\t\t\t\tlogger.error(\"Error occurred while ending local-xa-resource: {}\", ex.getMessage());\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t} else {\n\t\t\t\tlogger.debug(\"Error occurred while ending local-xa-resource: {}\", ex.getMessage());\n\t\t\t}\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred while ending local-xa-resource: {}\", rex.getMessage());\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} finally {\n\t\t\tthis.closeQuietly(stmt);\n\t\t}\n\t}\n\n\tprivate void releasePhysicalConnection() {\n\t\tConnection connection = this.managedConnection.getPhysicalConnection();\n\t\ttry {\n\t\t\tconnection.setAutoCommit(originalAutoCommit);\n\t\t} catch (Exception ex) {\n\t\t\tlogger.warn(\"Error occurred while configuring attr 'autoCommit' of physical connection.\", ex);\n\t\t} finally {\n\t\t\t// LocalXAConnection is only used for wrapping,\n\t\t\t// once the transaction completed it can be closed immediately.\n\t\t\tthis.managedConnection.closeQuietly();\n\t\t\tthis.forgetQuietly(this.currentXid);\n\t\t}\n\t}\n\n\tpublic boolean isSameRM(XAResource xares) {\n\t\tif (this == xares) {\n\t\t\treturn true;\n\t\t} else if (LocalXAResource.class.isInstance(xares) == false) {\n\t\t\treturn false;\n\t\t}\n\n\t\tLocalXAResource that = (LocalXAResource) xares;\n\t\tConnection thisConn = this.managedConnection.getPhysicalConnection();\n\t\tConnection thatConn = that.managedConnection.getPhysicalConnection();\n\t\treturn thisConn == thatConn;\n\t}\n\n\tpublic void forgetQuietly(Xid xid) {\n\t\ttry {\n\t\t\tthis.forget(xid);\n\t\t} catch (Exception ex) {\n\t\t\tlogger.warn(\"Error occurred while forgeting local-xa-resource.\", xid);\n\t\t}\n\t}\n\n\tpublic synchronized void forget(Xid xid) throws XAException {\n\t\tif (xid == null || this.currentXid == null) {\n\t\t\tlogger.warn(\"Error occurred while forgeting local-xa-resource: invalid xid.\");\n\t\t} else {\n\t\t\tthis.currentXid = null;\n\t\t\tthis.originalAutoCommit = true;\n\t\t\tthis.managedConnection = null;\n\t\t}\n\t}\n\n\tpublic Xid[] recover(int flags) throws XAException {\n\t\treturn new Xid[0];\n\t}\n\n\tprotected boolean isTableExists(Connection conn) throws SQLException {\n\n\t\tString catalog = null;\n\t\ttry {\n\t\t\tcatalog = conn.getCatalog();\n\t\t} catch (Throwable throwable) {\n\t\t\tlogger.debug(\"Error occurred while getting catalog of java.sql.Connection!\");\n\t\t}\n\t\tString schema = null;\n\t\ttry {\n\t\t\tschema = conn.getSchema();\n\t\t} catch (Throwable throwable) {\n\t\t\tlogger.debug(\"Error occurred while getting schema of java.sql.Connection!\");\n\t\t}\n\n\t\tResultSet rs = null;\n\t\ttry {\n\t\t\tDatabaseMetaData metadata = conn.getMetaData();\n\t\t\trs = metadata.getTables(catalog, schema, \"bytejta\", null);\n\t\t\treturn rs.next();\n\t\t} finally {\n\t\t\tthis.closeQuietly(rs);\n\t\t}\n\t}\n\n\tprotected void closeQuietly(ResultSet closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(\"Error occurred while closing resource {}.\", closeable);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void closeQuietly(Statement closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(\"Error occurred while closing resource {}.\", closeable);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void closeQuietly(Connection closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(\"Error occurred while closing resource {}.\", closeable);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected String getIdentifier(byte[] globalByteArray, byte[] branchByteArray) {\n\t\tif (branchByteArray == null || branchByteArray.length != XidFactory.BRANCH_QUALIFIER_LENGTH) {\n\t\t\tlogger.warn(\"Invalid branchByteArray: the length of branchQulifier not equals to 16!\");\n\t\t\treturn ByteUtils.byteArrayToString(globalByteArray);\n\t\t}\n\n\t\tbyte[] prefixByteArray = new byte[5];\n\t\tSystem.arraycopy(branchByteArray, 0, prefixByteArray, 0, 5);\n\n\t\tbyte[] gvalueByteArray = new byte[4];\n\t\tSystem.arraycopy(globalByteArray, 0, gvalueByteArray, 0, 4);\n\t\tint global = ByteUtils.byteArrayToInt(gvalueByteArray);\n\n\t\tint gday = (global << 8) >>> 27;\n\t\tint ghour = (global << 13) >>> 27;\n\t\tint gminute = (global << 18) >>> 26;\n\t\tint gsecond = (global << 24) >>> 26;\n\t\tint gmillis = ((global << 30) >>> 22) | (globalByteArray[4] - Byte.MIN_VALUE);\n\n\t\tint datime = 0;\n\t\tdatime = datime | (gday << 27);\n\t\tdatime = datime | (ghour << 22);\n\t\tdatime = datime | (gminute << 16);\n\t\tdatime = datime | (gsecond << 10);\n\t\tdatime = datime | gmillis;\n\t\tbyte[] datimeByteArray = ByteUtils.intToByteArray(datime);\n\n\t\tbyte[] randomByteArray = new byte[4];\n\t\tSystem.arraycopy(branchByteArray, 12, randomByteArray, 0, 4);\n\n\t\tbyte[] resultByteArray = new byte[16];\n\t\tSystem.arraycopy(prefixByteArray, 0, resultByteArray, 0, 5);\n\t\tSystem.arraycopy(datimeByteArray, 1, resultByteArray, 5, 3);\n\t\tSystem.arraycopy(branchByteArray, 5, resultByteArray, 8, 6);\n\t\tSystem.arraycopy(randomByteArray, 2, resultByteArray, 14, 2);\n\t\treturn ByteUtils.byteArrayToString(resultByteArray);\n\t}\n\n\tpublic int getTransactionTimeout() {\n\t\treturn 0;\n\t}\n\n\tpublic boolean setTransactionTimeout(int transactionTimeout) {\n\t\treturn false;\n\t}\n\n\tpublic LocalXAConnection getManagedConnection() {\n\t\treturn managedConnection;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/jdbc/LogicalConnection.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.CallableStatement;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.NClob;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLClientInfoException;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Savepoint;\nimport java.sql.Statement;\nimport java.sql.Struct;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class LogicalConnection implements Connection {\n\tstatic final Logger logger = LoggerFactory.getLogger(LogicalConnection.class);\n\n\tprivate boolean connectionClosed;\n\tprivate final LocalXAConnection managedConnection;\n\tprivate final Connection delegateConnection;\n\n\tpublic LogicalConnection(LocalXAConnection managedConnection, Connection connection) {\n\t\tthis.managedConnection = managedConnection;\n\t\tthis.delegateConnection = connection;\n\t}\n\n\tpublic <T> T unwrap(Class<T> iface) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.unwrap(iface);\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.isWrapperFor(iface);\n\t}\n\n\tpublic Statement createStatement() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createStatement();\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareStatement(sql);\n\t}\n\n\tpublic CallableStatement prepareCall(String sql) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareCall(sql);\n\t}\n\n\tpublic String nativeSQL(String sql) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.nativeSQL(sql);\n\t}\n\n\tpublic void setAutoCommit(boolean autoCommit) throws SQLException {\n\t\tthrow new SQLException(\"Illegal operation!\");\n\t}\n\n\tpublic boolean getAutoCommit() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getAutoCommit();\n\t}\n\n\tpublic void commit() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tthrow new SQLException(\"Illegal operation!\");\n\t}\n\n\tpublic void rollback() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tthrow new SQLException(\"Illegal operation!\");\n\t}\n\n\tpublic synchronized void close() throws SQLException {\n\t\tif (this.connectionClosed) {\n\t\t\tlogger.debug(\"Current connection has already been closed.\");\n\t\t} else {\n\t\t\tthis.connectionClosed = true;\n\t\t\tmanagedConnection.closeLogicalConnection();\n\t\t}\n\t}\n\n\tpublic boolean isClosed() throws SQLException {\n\t\treturn this.connectionClosed;\n\t}\n\n\tpublic DatabaseMetaData getMetaData() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getMetaData();\n\t}\n\n\tpublic void setReadOnly(boolean readOnly) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setReadOnly(readOnly);\n\t}\n\n\tpublic boolean isReadOnly() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.isReadOnly();\n\t}\n\n\tpublic void setCatalog(String catalog) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setCatalog(catalog);\n\t}\n\n\tpublic String getCatalog() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getCatalog();\n\t}\n\n\tpublic void setTransactionIsolation(int level) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setTransactionIsolation(level);\n\t}\n\n\tpublic int getTransactionIsolation() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getTransactionIsolation();\n\t}\n\n\tpublic SQLWarning getWarnings() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getWarnings();\n\t}\n\n\tpublic void clearWarnings() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.clearWarnings();\n\t}\n\n\tpublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createStatement(resultSetType, resultSetConcurrency);\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareStatement(sql, resultSetType, resultSetConcurrency);\n\t}\n\n\tpublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareCall(sql, resultSetType, resultSetConcurrency);\n\t}\n\n\tpublic Map<String, Class<?>> getTypeMap() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getTypeMap();\n\t}\n\n\tpublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setTypeMap(map);\n\t}\n\n\tpublic void setHoldability(int holdability) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setHoldability(holdability);\n\t}\n\n\tpublic int getHoldability() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getHoldability();\n\t}\n\n\tpublic Savepoint setSavepoint() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.setSavepoint();\n\t}\n\n\tpublic Savepoint setSavepoint(String name) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.setSavepoint(name);\n\t}\n\n\tpublic void rollback(Savepoint savepoint) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.rollback(savepoint);\n\t}\n\n\tpublic void releaseSavepoint(Savepoint savepoint) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.releaseSavepoint(savepoint);\n\t}\n\n\tpublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n\t\t\tthrows SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n\t\t\tthrows SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n\t}\n\n\tpublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n\t\t\tthrows SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareStatement(sql, autoGeneratedKeys);\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareStatement(sql, columnIndexes);\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.prepareStatement(sql, columnNames);\n\t}\n\n\tpublic Clob createClob() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createClob();\n\t}\n\n\tpublic Blob createBlob() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createBlob();\n\t}\n\n\tpublic NClob createNClob() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createNClob();\n\t}\n\n\tpublic SQLXML createSQLXML() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createSQLXML();\n\t}\n\n\tpublic boolean isValid(int timeout) throws SQLException {\n\t\treturn delegateConnection.isValid(timeout);\n\t}\n\n\tpublic void setClientInfo(String name, String value) throws SQLClientInfoException {\n\t\ttry {\n\t\t\tthis.validateConnectionStatus();\n\t\t} catch (SQLException ex) {\n\t\t\tthrow new SQLClientInfoException(null, ex);\n\t\t}\n\t\tdelegateConnection.setClientInfo(name, value);\n\t}\n\n\tpublic void setClientInfo(Properties properties) throws SQLClientInfoException {\n\t\ttry {\n\t\t\tthis.validateConnectionStatus();\n\t\t} catch (SQLException ex) {\n\t\t\tthrow new SQLClientInfoException(null, ex);\n\t\t}\n\t\tdelegateConnection.setClientInfo(properties);\n\t}\n\n\tpublic String getClientInfo(String name) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getClientInfo(name);\n\t}\n\n\tpublic Properties getClientInfo() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getClientInfo();\n\t}\n\n\tpublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createArrayOf(typeName, elements);\n\t}\n\n\tpublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.createStruct(typeName, attributes);\n\t}\n\n\tpublic void setSchema(String schema) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setSchema(schema);\n\t}\n\n\tpublic String getSchema() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getSchema();\n\t}\n\n\tpublic void abort(Executor executor) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.abort(executor);\n\t}\n\n\tpublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\tdelegateConnection.setNetworkTimeout(executor, milliseconds);\n\t}\n\n\tpublic int getNetworkTimeout() throws SQLException {\n\t\tthis.validateConnectionStatus();\n\t\treturn delegateConnection.getNetworkTimeout();\n\t}\n\n\tprivate void validateConnectionStatus() throws SQLException {\n\t\tif (this.connectionClosed) {\n\t\t\tthrow new SQLException(\"Connection is closed\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/jdbc/RecoveredResource.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.sql.DataSource;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class RecoveredResource extends LocalXAResource implements XAResource {\n\tstatic final Logger logger = LoggerFactory.getLogger(RecoveredResource.class);\n\n\tprivate DataSource dataSource;\n\n\tpublic void recoverable(Xid xid) throws XAException {\n\t\tbyte[] globalTransactionId = xid.getGlobalTransactionId();\n\t\tbyte[] branchQualifier = xid.getBranchQualifier();\n\n\t\tString identifier = this.getIdentifier(globalTransactionId, branchQualifier);\n\n\t\tConnection conn = null;\n\t\tPreparedStatement stmt = null;\n\t\tResultSet rs = null;\n\t\ttry {\n\t\t\tconn = this.dataSource.getConnection();\n\t\t\tstmt = conn.prepareStatement(\"select gxid, bxid from bytejta where xid = ?\");\n\t\t\tstmt.setString(1, identifier);\n\t\t\trs = stmt.executeQuery();\n\t\t\tif (rs.next() == false) {\n\t\t\t\tthrow new XAException(XAException.XAER_NOTA);\n\t\t\t}\n\t\t} catch (SQLException ex) {\n\t\t\ttry {\n\t\t\t\tthis.isTableExists(conn);\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} finally {\n\t\t\tthis.closeQuietly(rs);\n\t\t\tthis.closeQuietly(stmt);\n\t\t\tthis.closeQuietly(conn);\n\t\t}\n\t}\n\n\tpublic Xid[] recover(int flags) throws XAException {\n\t\tList<Xid> xidList = new ArrayList<Xid>();\n\n\t\tConnection conn = null;\n\t\tPreparedStatement stmt = null;\n\t\tResultSet rs = null;\n\t\ttry {\n\t\t\tconn = this.dataSource.getConnection();\n\t\t\tstmt = conn.prepareStatement(\"select gxid, bxid from bytejta\");\n\t\t\trs = stmt.executeQuery();\n\t\t\twhile (rs.next()) {\n\t\t\t\tString gxid = rs.getString(1);\n\t\t\t\tString bxid = rs.getString(2);\n\t\t\t\tbyte[] globalTransactionId = ByteUtils.stringToByteArray(gxid);\n\t\t\t\tbyte[] branchQualifier = ByteUtils.stringToByteArray(bxid);\n\t\t\t\tTransactionXid xid = null;\n\t\t\t\tif (StringUtils.equals(gxid, bxid)) {\n\t\t\t\t\txid = new TransactionXid(XidFactory.JTA_FORMAT_ID, globalTransactionId);\n\t\t\t\t} else {\n\t\t\t\t\txid = new TransactionXid(XidFactory.JTA_FORMAT_ID, globalTransactionId, branchQualifier);\n\t\t\t\t}\n\t\t\t\txidList.add(xid);\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tboolean tableExists = false;\n\t\t\ttry {\n\t\t\t\ttableExists = this.isTableExists(conn);\n\t\t\t} catch (Exception sqlEx) {\n\t\t\t\tlogger.warn(\"Error occurred while recovering local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\n\t\t\tif (tableExists) {\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.closeQuietly(rs);\n\t\t\tthis.closeQuietly(stmt);\n\t\t\tthis.closeQuietly(conn);\n\t\t}\n\n\t\tXid[] xidArray = new Xid[xidList.size()];\n\t\txidList.toArray(xidArray);\n\n\t\treturn xidArray;\n\t}\n\n\tpublic void forgetQuietly(Xid xid) {\n\t\ttry {\n\t\t\tthis.forget(xid);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.warn(\"Error occurred while forgeting local-xa-resource.\", xid);\n\t\t}\n\t}\n\n\tpublic synchronized void forget(Xid[] xids) throws XAException {\n\t\tif (xids == null || xids.length == 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tString[] xidArray = new String[xids.length];\n\n\t\tfor (int i = 0; i < xids.length; i++) {\n\t\t\tXid xid = xids[i];\n\n\t\t\tbyte[] globalTransactionId = xid.getGlobalTransactionId();\n\t\t\tbyte[] branchQualifier = xid.getBranchQualifier();\n\t\t\txidArray[i] = this.getIdentifier(globalTransactionId, branchQualifier);\n\t\t}\n\n\t\tConnection conn = null;\n\t\tPreparedStatement stmt = null;\n\t\tBoolean autoCommit = null;\n\t\ttry {\n\t\t\tconn = this.dataSource.getConnection();\n\t\t\tautoCommit = conn.getAutoCommit();\n\t\t\tconn.setAutoCommit(false);\n\t\t\tstmt = conn.prepareStatement(\"delete from bytejta where xid = ?\");\n\t\t\tfor (int i = 0; i < xids.length; i++) {\n\t\t\t\tstmt.setString(1, xidArray[i]);\n\t\t\t\tstmt.addBatch();\n\t\t\t}\n\t\t\tstmt.executeBatch();\n\t\t\tconn.commit();\n\t\t} catch (Exception ex) {\n\t\t\ttry {\n\t\t\t\tconn.rollback();\n\t\t\t} catch (Exception sqlEx) {\n\t\t\t\tlogger.error(\"Error occurred while rolling back local resources.\", sqlEx);\n\t\t\t}\n\n\t\t\tboolean tableExists = false;\n\t\t\ttry {\n\t\t\t\ttableExists = this.isTableExists(conn);\n\t\t\t} catch (Exception sqlEx) {\n\t\t\t\tlogger.warn(\"Error occurred while forgeting local resources.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\n\t\t\tif (tableExists) {\n\t\t\t\tlogger.error(\"Error occurred while forgetting resources.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.setAutoCommitIfNecessary(conn, autoCommit);\n\t\t\tthis.closeQuietly(stmt);\n\t\t\tthis.closeQuietly(conn);\n\t\t}\n\t}\n\n\tpublic synchronized void forget(Xid xid) throws XAException {\n\t\tif (xid == null) {\n\t\t\tlogger.warn(\"Error occurred while forgeting local-xa-resource: invalid xid.\");\n\t\t\treturn;\n\t\t}\n\n\t\tbyte[] globalTransactionId = xid.getGlobalTransactionId();\n\t\tbyte[] branchQualifier = xid.getBranchQualifier();\n\n\t\tString identifier = this.getIdentifier(globalTransactionId, branchQualifier);\n\n\t\tConnection conn = null;\n\t\tPreparedStatement stmt = null;\n\t\tBoolean autoCommit = null;\n\t\ttry {\n\t\t\tconn = this.dataSource.getConnection();\n\t\t\tautoCommit = conn.getAutoCommit();\n\t\t\tconn.setAutoCommit(false);\n\t\t\tstmt = conn.prepareStatement(\"delete from bytejta where xid = ?\");\n\t\t\tstmt.setString(1, identifier);\n\t\t\tstmt.executeUpdate();\n\t\t\tconn.commit();\n\t\t} catch (Exception ex) {\n\t\t\ttry {\n\t\t\t\tconn.rollback();\n\t\t\t} catch (Exception sqlEx) {\n\t\t\t\tlogger.error(\"Error occurred while rolling back local resources.\", sqlEx);\n\t\t\t}\n\n\t\t\tboolean tableExists = false;\n\t\t\ttry {\n\t\t\t\ttableExists = this.isTableExists(conn);\n\t\t\t} catch (Exception sqlEx) {\n\t\t\t\tlogger.warn(\"Error occurred while forgeting local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\n\t\t\tif (tableExists) {\n\t\t\t\tlogger.warn(\"Error occurred while forgeting local-xa-resource.\", ex);\n\t\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.setAutoCommitIfNecessary(conn, autoCommit);\n\t\t\tthis.closeQuietly(stmt);\n\t\t\tthis.closeQuietly(conn);\n\t\t}\n\t}\n\n\tprivate void setAutoCommitIfNecessary(Connection conn, Boolean autoCommit) {\n\t\tif (autoCommit != null) {\n\t\t\ttry {\n\t\t\t\tconn.setAutoCommit(autoCommit);\n\t\t\t} catch (SQLException sqlEx) {\n\t\t\t\tlogger.error(\"Error occurred while configuring attribute 'autoCommit'.\", sqlEx);\n\t\t\t}\n\t\t} // end-if (autoCommit != null)\n\t}\n\n\tpublic DataSource getDataSource() {\n\t\treturn dataSource;\n\t}\n\n\tpublic void setDataSource(DataSource dataSource) {\n\t\tthis.dataSource = dataSource;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/resource/CommonResourceDescriptor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class CommonResourceDescriptor implements XAResourceDescriptor {\n\tstatic Logger logger = LoggerFactory.getLogger(CommonResourceDescriptor.class);\n\n\tprivate XAResource delegate;\n\tprivate String identifier;\n\n\tprivate transient Xid recoverXid;\n\tprivate transient Object managed;\n\t// private transient boolean recved;\n\n\tpublic boolean isTransactionCommitted(Xid xid) throws IllegalStateException {\n\t\tthrow new IllegalStateException();\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"common-resource[id= %s]\", this.identifier);\n\t}\n\n\tpublic void setTransactionTimeoutQuietly(int timeout) {\n\t\ttry {\n\t\t\tthis.delegate.setTransactionTimeout(timeout);\n\t\t} catch (Exception ex) {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tpublic void commit(Xid arg0, boolean arg1) throws XAException {\n\t\tdelegate.commit(arg0, arg1);\n\t}\n\n\tpublic void end(Xid arg0, int arg1) throws XAException {\n\t\tdelegate.end(arg0, arg1);\n\t}\n\n\tpublic void forget(Xid arg0) throws XAException {\n\t\ttry {\n\t\t\tdelegate.forget(arg0);\n\t\t} finally {\n\t\t\tthis.closeIfNecessary();\n\t\t}\n\t}\n\n\tprivate void closeIfNecessary() {\n\t\tif (this.recoverXid != null && this.managed != null) {\n\t\t\tif (javax.sql.XAConnection.class.isInstance(this.managed)) {\n\t\t\t\tthis.closeQuietly((javax.sql.XAConnection) this.managed);\n\t\t\t} else if (javax.jms.XAConnection.class.isInstance(this.managed)) {\n\t\t\t\tthis.closeQuietly((javax.jms.XAConnection) this.managed);\n\t\t\t} else if (javax.resource.spi.ManagedConnection.class.isInstance(this.managed)) {\n\t\t\t\tthis.closeQuietly((javax.resource.spi.ManagedConnection) this.managed);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void closeQuietly(javax.jms.XAConnection closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void closeQuietly(javax.sql.XAConnection closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void closeQuietly(javax.resource.spi.ManagedConnection closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.cleanup();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcloseable.destroy();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\treturn delegate.getTransactionTimeout();\n\t}\n\n\tpublic boolean isSameRM(XAResource arg0) throws XAException {\n\t\treturn delegate.isSameRM(arg0);\n\t}\n\n\tpublic int prepare(Xid arg0) throws XAException {\n\t\treturn delegate.prepare(arg0);\n\t}\n\n\tpublic Xid[] recover(int arg0) throws XAException {\n\t\tXid[] xidArray = delegate.recover(arg0);\n\t\t// for (int i = 0; this.recoverXid != null && i < xidArray.length; i++) {\n\t\t// Xid xid = xidArray[i];\n\t\t// boolean formatIdEquals = xid.getFormatId() == this.recoverXid.getFormatId();\n\t\t// boolean globalTransactionIdEquals = Arrays.equals(xid.getGlobalTransactionId(),\n\t\t// this.recoverXid.getGlobalTransactionId());\n\t\t// boolean branchQualifierEquals = Arrays.equals(xid.getBranchQualifier(), this.recoverXid.getBranchQualifier());\n\t\t// if (formatIdEquals && globalTransactionIdEquals && branchQualifierEquals) {\n\t\t// this.recved = true;\n\t\t// }\n\t\t// }\n\t\treturn xidArray;\n\t}\n\n\tpublic void rollback(Xid arg0) throws XAException {\n\t\tdelegate.rollback(arg0);\n\t}\n\n\tpublic boolean setTransactionTimeout(int arg0) throws XAException {\n\t\treturn delegate.setTransactionTimeout(arg0);\n\t}\n\n\tpublic void start(Xid arg0, int arg1) throws XAException {\n\t\tdelegate.start(arg0, arg1);\n\t}\n\n\tpublic XAResource getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(XAResource delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic Xid getRecoverXid() {\n\t\treturn recoverXid;\n\t}\n\n\tpublic void setRecoverXid(Xid recoverXid) {\n\t\tthis.recoverXid = recoverXid;\n\t}\n\n\tpublic Object getManaged() {\n\t\treturn managed;\n\t}\n\n\tpublic void setManaged(Object managed) {\n\t\tthis.managed = managed;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/resource/LocalXAResourceDescriptor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.jdbc.LocalXAResource;\nimport org.bytesoft.bytejta.supports.jdbc.RecoveredResource;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\n\npublic class LocalXAResourceDescriptor implements XAResourceDescriptor {\n\n\tprivate String identifier;\n\tprivate LocalXAResource delegate;\n\tprivate boolean loggingRequired;\n\n\tpublic boolean isTransactionCommitted(Xid xid) throws IllegalStateException {\n\t\ttry {\n\t\t\tif (RecoveredResource.class.isInstance(this.delegate)) {\n\t\t\t\t((RecoveredResource) this.delegate).recoverable(xid);\n\t\t\t} else {\n\t\t\t\t((LocalXAResource) this.delegate).recoverable(xid);\n\t\t\t}\n\t\t\treturn true;\n\t\t} catch (XAException ex) {\n\t\t\tswitch (ex.errorCode) {\n\t\t\tcase XAException.XAER_NOTA:\n\t\t\t\treturn false;\n\t\t\tdefault:\n\t\t\t\tthrow new IllegalStateException(ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"local-xa-resource[%s]\", this.identifier);\n\t}\n\n\tpublic void setTransactionTimeoutQuietly(int timeout) {\n\t\ttry {\n\t\t\tthis.delegate.setTransactionTimeout(timeout);\n\t\t} catch (Exception ex) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tpublic void commit(Xid arg0, boolean arg1) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.commit(arg0, this.loggingRequired); // onePhaseCommit is unnecessary.\n\t}\n\n\tpublic void end(Xid arg0, int arg1) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.end(arg0, arg1);\n\t}\n\n\tpublic void forget(Xid arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.forget(arg0);\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn delegate.getTransactionTimeout();\n\t}\n\n\tpublic boolean isSameRM(XAResource xares) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (LocalXAResourceDescriptor.class.isInstance(xares)) {\n\t\t\tLocalXAResourceDescriptor that = (LocalXAResourceDescriptor) xares;\n\t\t\tboolean identifierEquals = StringUtils.equals(this.identifier, that.identifier);\n\t\t\tboolean xaResourceEquals = this.delegate.isSameRM(that.delegate); // this.delegate != null\n\t\t\treturn identifierEquals && xaResourceEquals;\n\t\t} else {\n\t\t\treturn delegate.isSameRM(xares);\n\t\t}\n\n\t}\n\n\tpublic int prepare(Xid arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn XAResource.XA_RDONLY;\n\t\t}\n\t\treturn delegate.prepare(arg0);\n\t}\n\n\tpublic Xid[] recover(int arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn new Xid[0];\n\t\t}\n\t\treturn delegate.recover(arg0);\n\t}\n\n\tpublic void rollback(Xid arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.rollback(arg0);\n\t}\n\n\tpublic boolean setTransactionTimeout(int arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn delegate.setTransactionTimeout(arg0);\n\t}\n\n\tpublic void start(Xid arg0, int arg1) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.start(arg0, arg1);\n\t}\n\n\tpublic boolean isLoggingRequired() {\n\t\treturn loggingRequired;\n\t}\n\n\tpublic void setLoggingRequired(boolean loggingRequired) {\n\t\tthis.loggingRequired = loggingRequired;\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic XAResource getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(LocalXAResource delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/resource/RemoteResourceDescriptor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\n\npublic class RemoteResourceDescriptor implements XAResourceDescriptor {\n\tpublic static final int X_SAME_CLUSTER = 501;\n\n\tprivate RemoteCoordinator delegate;\n\tprivate String identifier;\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic String getIdentifier() {\n\t\tif (StringUtils.isNotBlank(this.identifier)) {\n\t\t\treturn this.identifier;\n\t\t} else if (this.delegate == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tthis.identifier = this.delegate.getIdentifier();\n\t\treturn this.identifier;\n\t}\n\n\tpublic RemoteAddr getRemoteAddr() {\n\t\treturn this.delegate == null ? null : this.delegate.getRemoteAddr();\n\t}\n\n\tpublic RemoteNode getRemoteNode() {\n\t\treturn this.delegate == null ? null : this.delegate.getRemoteNode();\n\t}\n\n\tpublic RemoteSvc getRemoteSvc() {\n\t\treturn this.delegate == null ? null : CommonUtils.getRemoteSvc(this.delegate.getIdentifier());\n\t}\n\n\tpublic boolean isTransactionCommitted(Xid xid) throws IllegalStateException {\n\t\tthrow new IllegalStateException();\n\t}\n\n\tpublic String toString() {\n\t\treturn String.valueOf(this.delegate);\n\t}\n\n\tpublic void setTransactionTimeoutQuietly(int timeout) {\n\t}\n\n\tpublic void commit(Xid arg0, boolean arg1) throws XAException {\n\t\tdelegate.commit(arg0, arg1);\n\t}\n\n\tpublic void end(Xid arg0, int arg1) throws XAException {\n\t\t// delegate.end(arg0, arg1);\n\t}\n\n\tpublic void forget(Xid arg0) throws XAException {\n\t\tdelegate.forget(arg0);\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\tthrow new XAException(XAException.XAER_RMERR);\n\t}\n\n\tpublic boolean isSameRM(XAResource xares) throws XAException {\n\t\tif (xares == null) {\n\t\t\treturn false;\n\t\t} else if (RemoteResourceDescriptor.class.isInstance(xares) == false) {\n\t\t\treturn false;\n\t\t}\n\t\tRemoteResourceDescriptor that = (RemoteResourceDescriptor) xares;\n\t\tString thisKey = this.getIdentifier();\n\t\tString thatKey = that.getIdentifier();\n\n\t\tif (StringUtils.equalsIgnoreCase(thisKey, thatKey)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (CommonUtils.applicationEquals(thisKey, thatKey)) {\n\t\t\tthrow new XAException(X_SAME_CLUSTER);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic int prepare(Xid arg0) throws XAException {\n\t\treturn delegate.prepare(arg0);\n\t}\n\n\tpublic Xid[] recover(int arg0) throws XAException {\n\t\treturn delegate.recover(arg0);\n\t}\n\n\tpublic void rollback(Xid arg0) throws XAException {\n\t\tdelegate.rollback(arg0);\n\t}\n\n\tpublic boolean setTransactionTimeout(int arg0) throws XAException {\n\t\treturn true;\n\t}\n\n\tpublic void start(Xid arg0, int arg1) throws XAException {\n\t\tdelegate.start(arg0, arg1);\n\t}\n\n\tpublic RemoteCoordinator getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(RemoteCoordinator delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/supports/resource/UnidentifiedResourceDescriptor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\n\npublic class UnidentifiedResourceDescriptor implements XAResourceDescriptor {\n\n\tprivate String identifier;\n\tprivate XAResource delegate;\n\n\tpublic boolean isTransactionCommitted(Xid xid) throws IllegalStateException {\n\t\tthrow new IllegalStateException();\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"unknown-resource[%s]\", this.delegate);\n\t}\n\n\tpublic void setTransactionTimeoutQuietly(int timeout) {\n\t\ttry {\n\t\t\tthis.delegate.setTransactionTimeout(timeout);\n\t\t} catch (Exception ex) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tpublic void commit(Xid arg0, boolean arg1) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.commit(arg0, arg1);\n\t}\n\n\tpublic void end(Xid arg0, int arg1) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.end(arg0, arg1);\n\t}\n\n\tpublic void forget(Xid arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.forget(arg0);\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn delegate.getTransactionTimeout();\n\t}\n\n\tpublic boolean isSameRM(XAResource arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn delegate.isSameRM(arg0);\n\t}\n\n\tpublic int prepare(Xid arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn XAResource.XA_RDONLY;\n\t\t}\n\t\treturn delegate.prepare(arg0);\n\t}\n\n\tpublic Xid[] recover(int arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn new Xid[0];\n\t\t}\n\t\treturn delegate.recover(arg0);\n\t}\n\n\tpublic void rollback(Xid arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.rollback(arg0);\n\t}\n\n\tpublic boolean setTransactionTimeout(int arg0) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn delegate.setTransactionTimeout(arg0);\n\t}\n\n\tpublic void start(Xid arg0, int arg1) throws XAException {\n\t\tif (this.delegate == null) {\n\t\t\treturn;\n\t\t}\n\t\tdelegate.start(arg0, arg1);\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic XAResource getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(XAResource delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/work/TransactionWork.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.work;\n\nimport javax.resource.spi.work.Work;\n\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionRecovery;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.supports.TransactionTimer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionWork implements Work, TransactionBeanFactoryAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionWork.class);\n\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\n\tstatic final long SECOND_MILLIS = 1000L;\n\tprivate long stopTimeMillis = -1;\n\tprivate long delayOfStoping = SECOND_MILLIS * 15;\n\tprivate long recoveryInterval = SECOND_MILLIS * 60;\n\n\tpublic void run() {\n\n\t\tTransactionTimer transactionTimer = beanFactory.getTransactionTimer();\n\t\tTransactionRecovery transactionRecovery = beanFactory.getTransactionRecovery();\n\t\ttry {\n\t\t\ttransactionRecovery.startRecovery();\n\t\t\ttransactionRecovery.timingRecover();\n\t\t} catch (SecurityException rex) {\n\t\t\tlogger.debug(\"Only the master node can perform the recovery operation!\");\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"TransactionRecovery init failed!\", rex);\n\t\t}\n\n\t\tlong nextExecutionTime = 0;\n\t\tlong nextRecoveryTime = System.currentTimeMillis() + this.recoveryInterval;\n\t\twhile (this.currentActive()) {\n\n\t\t\tlong current = System.currentTimeMillis();\n\t\t\tif (current >= nextExecutionTime) {\n\t\t\t\tnextExecutionTime = current + SECOND_MILLIS;\n\t\t\t\ttry {\n\t\t\t\t\ttransactionTimer.timingExecution();\n\t\t\t\t} catch (RuntimeException rex) {\n\t\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (current >= nextRecoveryTime) {\n\t\t\t\tnextRecoveryTime = current + this.recoveryInterval;\n\n\t\t\t\tthis.fireGlobalRecovery();\n\t\t\t\tthis.fireBranchRecovery();\n\t\t\t}\n\n\t\t\tthis.waitForMillis(100L);\n\n\t\t} // end-while (this.currentActive())\n\t}\n\n\tprivate void fireGlobalRecovery() {\n\t\tTransactionRecovery transactionRecovery = beanFactory.getTransactionRecovery();\n\t\ttry {\n\t\t\ttransactionRecovery.timingRecover();\n\t\t} catch (SecurityException rex) {\n\t\t\tlogger.debug(\"Only the master node can perform the global recovery operation!\");\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t}\n\t}\n\n\tprivate void fireBranchRecovery() {\n\t\tTransactionRecovery transactionRecovery = beanFactory.getTransactionRecovery();\n\t\ttry {\n\t\t\ttransactionRecovery.branchRecover();\n\t\t} catch (SecurityException rex) {\n\t\t\tlogger.debug(\"Only the branch node can perform the branch recovery operation!\");\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t}\n\t}\n\n\tprivate void waitForMillis(long millis) {\n\t\ttry {\n\t\t\tThread.sleep(millis);\n\t\t} catch (Exception ignore) {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tpublic void release() {\n\t\tthis.stopTimeMillis = System.currentTimeMillis() + this.delayOfStoping;\n\t}\n\n\tprotected boolean currentActive() {\n\t\treturn this.stopTimeMillis <= 0 || System.currentTimeMillis() < this.stopTimeMillis;\n\t}\n\n\tpublic long getDelayOfStoping() {\n\t\treturn delayOfStoping;\n\t}\n\n\tpublic void setDelayOfStoping(long delayOfStoping) {\n\t\tthis.delayOfStoping = delayOfStoping;\n\t}\n\n\tpublic long getRecoveryInterval() {\n\t\treturn recoveryInterval;\n\t}\n\n\tpublic void setRecoveryInterval(long recoveryInterval) {\n\t\tthis.recoveryInterval = recoveryInterval;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn this.beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/bytejta/xa/XidFactoryImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.xa;\n\nimport java.net.NetworkInterface;\nimport java.util.Calendar;\nimport java.util.Enumeration;\nimport java.util.Random;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class XidFactoryImpl implements XidFactory {\n\tstatic final Logger logger = LoggerFactory.getLogger(XidFactoryImpl.class);\n\n\tstatic final int SIZE_OF_MAC = 6;\n\tstatic final Random random = new Random();\n\tstatic final byte[] hardwareAddress = new byte[SIZE_OF_MAC];\n\tstatic final AtomicInteger atomic = new AtomicInteger();\n\n\tstatic {\n\t\tbyte[] sourceByteArray = getHardwareAddress();\n\t\tSystem.arraycopy(sourceByteArray, 0, hardwareAddress, 0, SIZE_OF_MAC);\n\t}\n\n\tprivate static byte[] getHardwareAddress() {\n\t\tEnumeration<NetworkInterface> enumeration = null;\n\t\ttry {\n\t\t\tenumeration = NetworkInterface.getNetworkInterfaces();\n\t\t} catch (Exception ex) {\n\t\t\tlogger.debug(ex.getMessage(), ex);\n\t\t}\n\n\t\tbyte[] byteArray = null;\n\t\twhile (byteArray == null && enumeration != null && enumeration.hasMoreElements()) {\n\t\t\tNetworkInterface element = enumeration.nextElement();\n\n\t\t\ttry {\n\t\t\t\tif (element.isUp() == false) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (element.isPointToPoint() || element.isVirtual()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (element.isLoopback()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tbyte[] hardwareAddr = element.getHardwareAddress();\n\t\t\t\tif (hardwareAddr == null || hardwareAddr.length != SIZE_OF_MAC) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tbyteArray = new byte[SIZE_OF_MAC];\n\t\t\t\tSystem.arraycopy(hardwareAddr, 0, byteArray, 0, SIZE_OF_MAC);\n\t\t\t} catch (Exception rex) {\n\t\t\t\tlogger.debug(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\n\t\treturn byteArray != null ? byteArray : new byte[SIZE_OF_MAC];\n\t}\n\n\tpublic TransactionXid createGlobalXid() {\n\t\tbyte[] unique = this.generateUniqueKey();\n\t\tif (unique == null || unique.length != GLOBAL_TRANSACTION_LENGTH) {\n\t\t\tthrow new IllegalStateException(\"The length of globalTransactionId not equals to 16.\");\n\t\t}\n\n\t\tbyte[] global = new byte[GLOBAL_TRANSACTION_LENGTH];\n\t\tSystem.arraycopy(unique, 0, global, 0, global.length);\n\n\t\treturn new TransactionXid(XidFactory.JTA_FORMAT_ID, global);\n\t}\n\n\tpublic TransactionXid createGlobalXid(byte[] globalTransactionId) {\n\t\tif (globalTransactionId == null) {\n\t\t\tthrow new IllegalArgumentException(\"The globalTransactionId cannot be null.\");\n\t\t} else if (globalTransactionId.length > TransactionXid.MAXGTRIDSIZE) {\n\t\t\tthrow new IllegalArgumentException(\"The length of globalTransactionId cannot exceed 64 bytes.\");\n\t\t}\n\t\tbyte[] global = new byte[globalTransactionId.length];\n\t\tSystem.arraycopy(globalTransactionId, 0, global, 0, global.length);\n\t\treturn new TransactionXid(XidFactory.JTA_FORMAT_ID, global);\n\t}\n\n\tpublic TransactionXid createBranchXid(TransactionXid globalXid) {\n\t\tif (globalXid == null) {\n\t\t\tthrow new IllegalArgumentException(\"Xid cannot be null.\");\n\t\t} else if (globalXid.getGlobalTransactionId() == null) {\n\t\t\tthrow new IllegalArgumentException(\"The globalTransactionId cannot be null.\");\n\t\t} else if (globalXid.getGlobalTransactionId().length > TransactionXid.MAXGTRIDSIZE) {\n\t\t\tthrow new IllegalArgumentException(\"The length of globalTransactionId cannot exceed 64 bytes.\");\n\t\t}\n\n\t\tbyte[] global = new byte[globalXid.getGlobalTransactionId().length];\n\t\tSystem.arraycopy(globalXid.getGlobalTransactionId(), 0, global, 0, global.length);\n\n\t\tbyte[] unique = this.generateUniqueKey();\n\t\tif (unique == null || unique.length != BRANCH_QUALIFIER_LENGTH) {\n\t\t\tthrow new IllegalStateException(\"The length of branchQulifier not equals to 16.\");\n\t\t}\n\n\t\tbyte[] branch = new byte[BRANCH_QUALIFIER_LENGTH];\n\t\tSystem.arraycopy(unique, 0, branch, 0, branch.length);\n\n\t\treturn new TransactionXid(XidFactory.JTA_FORMAT_ID, global, branch);\n\t}\n\n\tpublic TransactionXid createBranchXid(TransactionXid globalXid, byte[] branchQualifier) {\n\t\tif (globalXid == null) {\n\t\t\tthrow new IllegalArgumentException(\"Xid cannot be null.\");\n\t\t} else if (globalXid.getGlobalTransactionId() == null) {\n\t\t\tthrow new IllegalArgumentException(\"The globalTransactionId cannot be null.\");\n\t\t} else if (globalXid.getGlobalTransactionId().length > TransactionXid.MAXGTRIDSIZE) {\n\t\t\tthrow new IllegalArgumentException(\"The length of globalTransactionId cannot exceed 64 bytes.\");\n\t\t}\n\n\t\tif (branchQualifier == null) {\n\t\t\tthrow new IllegalArgumentException(\"The branchQulifier cannot be null.\");\n\t\t} else if (branchQualifier.length > TransactionXid.MAXBQUALSIZE) {\n\t\t\tthrow new IllegalArgumentException(\"The length of branchQulifier cannot exceed 64 bytes.\");\n\t\t}\n\n\t\tbyte[] global = new byte[globalXid.getGlobalTransactionId().length];\n\t\tSystem.arraycopy(globalXid.getGlobalTransactionId(), 0, global, 0, global.length);\n\n\t\treturn new TransactionXid(XidFactory.JTA_FORMAT_ID, global, branchQualifier);\n\t}\n\n\tpublic byte[] generateUniqueKey() {\n\t\tbyte[] byteArray = new byte[16];\n\n\t\tCalendar calendar = Calendar.getInstance();\n\t\tcalendar.setTimeInMillis(System.currentTimeMillis());\n\t\tint year = calendar.get(Calendar.YEAR) - 2014;\n\t\tint month = calendar.get(Calendar.MONTH) + 1;\n\t\tint day = calendar.get(Calendar.DAY_OF_MONTH);\n\t\tint hour = calendar.get(Calendar.HOUR_OF_DAY);\n\t\tint minute = calendar.get(Calendar.MINUTE);\n\t\tint second = calendar.get(Calendar.SECOND);\n\t\tint millis = calendar.get(Calendar.MILLISECOND);\n\n\t\tint value = (year << 29) >>> 1;\n\t\tvalue = value | (month << 24);\n\t\tvalue = value | (day << 19);\n\t\tvalue = value | (hour << 14);\n\t\tvalue = value | (minute << 8);\n\t\tvalue = value | (second << 2);\n\t\tvalue = value | (millis >>> 8);\n\n\t\tbyte[] valueByteArray = ByteUtils.intToByteArray(value);\n\n\t\tbyte[] timeByteArray = new byte[5];\n\t\tSystem.arraycopy(valueByteArray, 0, timeByteArray, 0, 4);\n\t\ttimeByteArray[4] = (byte) (((millis << 24) >>> 24) + Byte.MIN_VALUE);\n\n\t\tbyte increment = (byte) atomic.incrementAndGet();\n\n\t\tbyte[] randomByteArray = new byte[4];\n\t\trandom.nextBytes(randomByteArray);\n\n\t\tSystem.arraycopy(timeByteArray, 0, byteArray, 0, timeByteArray.length);\n\t\tSystem.arraycopy(hardwareAddress, 0, byteArray, timeByteArray.length, SIZE_OF_MAC);\n\n\t\tbyteArray[SIZE_OF_MAC + 5] = increment;\n\t\tSystem.arraycopy(randomByteArray, 0, byteArray, SIZE_OF_MAC + 5 + 1, randomByteArray.length);\n\n\t\treturn byteArray;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/common/utils/ByteUtils.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.common.utils;\n\npublic class ByteUtils {\n\tpublic static short byteArrayToShort(final byte[] buf) {\n\t\treturn byteArrayToShort(buf, 0);\n\t}\n\n\tpublic static int byteArrayToInt(final byte[] buf) {\n\t\treturn byteArrayToInt(buf, 0);\n\t}\n\n\tpublic static long byteArrayToLong(final byte[] buf) {\n\t\treturn byteArrayToLong(buf, 0);\n\t}\n\n\tpublic static long byteArrayToLong(final byte[] buf, final int start) {\n\t\tif (start < 0 || start + 7 >= buf.length) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t\tlong value = ((long) buf[start] & 0xff) << 56;\n\t\tvalue |= ((long) buf[start + 1] & 0xff) << 48;\n\t\tvalue |= ((long) buf[start + 2] & 0xff) << 40;\n\t\tvalue |= ((long) buf[start + 3] & 0xff) << 32;\n\t\tvalue |= ((long) buf[start + 4] & 0xff) << 24;\n\t\tvalue |= ((long) buf[start + 5] & 0xff) << 16;\n\t\tvalue |= ((long) buf[start + 6] & 0xff) << 8;\n\t\tvalue |= ((long) buf[start + 7] & 0xff);\n\t\treturn value;\n\t}\n\n\tpublic static byte[] longToByteArray(final long value) {\n\t\tfinal byte[] result = new byte[8];\n\t\tresult[7] = (byte) (value & 0xff);\n\t\tresult[6] = (byte) (value >> 8 & 0xff);\n\t\tresult[5] = (byte) (value >> 16 & 0xff);\n\t\tresult[4] = (byte) (value >> 24 & 0xff);\n\t\tresult[3] = (byte) (value >> 32 & 0xff);\n\t\tresult[2] = (byte) (value >> 40 & 0xff);\n\t\tresult[1] = (byte) (value >> 48 & 0xff);\n\t\tresult[0] = (byte) (value >> 56 & 0xff);\n\t\treturn result;\n\t}\n\n\tpublic static int byteArrayToInt(final byte[] buf, final int start) {\n\t\tif (start < 0 || start + 3 >= buf.length) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\t\tint value = (buf[start] & 0xff) << 24;\n\t\tvalue |= (buf[start + 1] & 0xff) << 16;\n\t\tvalue |= (buf[start + 2] & 0xff) << 8;\n\t\tvalue |= (buf[start + 3] & 0xff);\n\t\treturn value;\n\t}\n\n\tpublic static byte[] intToByteArray(final int value) {\n\t\tfinal byte[] result = new byte[4];\n\t\tresult[3] = (byte) (value & 0xff);\n\t\tresult[2] = (byte) (value >> 8 & 0xff);\n\t\tresult[1] = (byte) (value >> 16 & 0xff);\n\t\tresult[0] = (byte) (value >> 24 & 0xff);\n\t\treturn result;\n\t}\n\n\tpublic static short byteArrayToShort(final byte[] buf, final int start) {\n\t\tif (start < 0 || start + 1 >= buf.length) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\t\tint value = (buf[start] & 0xff) << 8;\n\t\tvalue = value | (buf[start + 1] & 0xff);\n\t\treturn (short) value;\n\t}\n\n\tpublic static byte[] shortToByteArray(final short value) {\n\t\tfinal byte[] result = new byte[2];\n\t\tresult[1] = (byte) (value & 0xff);\n\t\tresult[0] = (byte) (value >> 8 & 0xff);\n\t\treturn result;\n\t}\n\n\tpublic static String byteArrayToString(final byte[] bytes, final int startIndex, final int len) {\n\t\tStringBuilder ber = new StringBuilder();\n\t\tfor (int i = startIndex, j = 0; j < len; i++, j++) {\n\t\t\tbyte b = bytes[i];\n\t\t\tber.append(CHARS[(b & 0xf0) >> 4]);\n\t\t\tber.append(CHARS[(b & 0x0f)]);\n\t\t}\n\t\treturn ber.toString();\n\t}\n\n\tpublic static String byteArrayToString(final byte[] bytes) {\n\t\treturn byteArrayToString(bytes, 0, bytes.length);\n\t}\n\n\tpublic static byte[] stringToByteArray(String str) {\n\t\tif (str == null) {\n\t\t\treturn new byte[0];\n\t\t} else if (str.length() % 2 == 1) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\t\tchar[] array = str.toCharArray();\n\t\tbyte[] bytes = new byte[array.length / 2];\n\n\t\tfor (int i = 0; i < array.length; i = i + 2) {\n\t\t\tint index1 = indexOf(array[i]);\n\t\t\tint index2 = indexOf(array[i + 1]);\n\t\t\tint tempval = index1 << 4;\n\t\t\tint byteval = tempval | index2;\n\t\t\tbytes[i / 2] = (byte) byteval;\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tprivate static int indexOf(char chr) {\n\t\tif (chr >= DIGIT_START && chr <= DIGIT_END) {\n\t\t\treturn chr - DIGIT_START;\n\t\t} else if (chr >= LETTER_START && chr <= LETTER_END) {\n\t\t\treturn chr - LETTER_START + 10;\n\t\t} else if (chr >= UPPER_LETTER_START && chr <= UPPER_LETTER_END) {\n\t\t\treturn chr - UPPER_LETTER_START + 10;\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\t}\n\n\tstatic final char DIGIT_START = '0';\n\tstatic final char DIGIT_END = '9';\n\tstatic final char LETTER_START = 'a';\n\tstatic final char LETTER_END = 'f';\n\tstatic final char UPPER_LETTER_START = 'A';\n\tstatic final char UPPER_LETTER_END = 'F';\n\tstatic final char[] CHARS = new char[] {\n\t\t\t//\n\t\t\t'0', '1', '2', '3', '4', '5', '6', '7',//\n\t\t\t'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' //\n\t};\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/common/utils/CommonUtils.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.common.utils;\n\nimport java.io.Closeable;\nimport java.net.Inet4Address;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.net.SocketException;\nimport java.net.UnknownHostException;\nimport java.util.Comparator;\nimport java.util.Enumeration;\nimport java.util.Iterator;\nimport java.util.Set;\nimport java.util.TreeSet;\n\nimport org.apache.commons.io.IOUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class CommonUtils {\n\tstatic final Logger logger = LoggerFactory.getLogger(CommonUtils.class);\n\n\tpublic static RemoteAddr getRemoteAddr(String identifier) {\n\t\tif (StringUtils.isBlank(identifier)) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tString[] values = identifier.split(\"\\\\s*:\\\\s*\");\n\t\t\tif (values.length != 3) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tRemoteAddr remoteAddr = new RemoteAddr();\n\t\t\tremoteAddr.setServerHost(values[0]);\n\t\t\tremoteAddr.setServerPort(Integer.parseInt(values[2]));\n\t\t\treturn remoteAddr;\n\t\t}\n\t}\n\n\tpublic static RemoteNode getRemoteNode(String identifier) {\n\t\tif (StringUtils.isBlank(identifier)) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tString[] values = identifier.split(\"\\\\s*:\\\\s*\");\n\t\t\tif (values.length != 3) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tRemoteNode remoteNode = new RemoteNode();\n\t\t\tremoteNode.setServerHost(values[0]);\n\t\t\tremoteNode.setServiceKey(values[1]);\n\t\t\tremoteNode.setServerPort(Integer.parseInt(values[2]));\n\t\t\treturn remoteNode;\n\t\t}\n\t}\n\n\tpublic static RemoteSvc getRemoteSvc(RemoteNode remoteNode) {\n\t\tRemoteSvc remoteSvc = new RemoteSvc();\n\t\tremoteSvc.setServerHost(remoteNode.getServerHost());\n\t\tremoteSvc.setServiceKey(remoteNode.getServiceKey());\n\t\tremoteSvc.setServerPort(remoteNode.getServerPort());\n\t\treturn remoteSvc;\n\t}\n\n\tpublic static RemoteSvc getRemoteSvc(String identifier) {\n\t\tRemoteNode remoteNode = getRemoteNode(identifier);\n\t\treturn getRemoteSvc(remoteNode);\n\t}\n\n\tpublic static String getApplication(String identifier) {\n\t\tif (StringUtils.isBlank(identifier)) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tString[] values = identifier.split(\"\\\\s*:\\\\s*\");\n\t\t\treturn values.length == 3 ? values[1] : null;\n\t\t}\n\t}\n\n\tpublic static String getInstanceKey(String identifier) {\n\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(identifier);\n\t\tif (remoteNode == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn String.format(\"%s:%s\", remoteNode.getServerHost(), remoteNode.getServerPort());\n\t\t}\n\t}\n\n\tpublic static boolean applicationEquals(String source, String target) {\n\t\tString sourceApplication = CommonUtils.getApplication(source);\n\t\tString targetApplication = CommonUtils.getApplication(target);\n\t\tif (StringUtils.isBlank(sourceApplication) || StringUtils.isBlank(targetApplication)) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn StringUtils.equalsIgnoreCase(sourceApplication, targetApplication);\n\t\t}\n\t}\n\n\tpublic static boolean instanceKeyEquals(String source, String target) {\n\t\tRemoteAddr sourceAddr = CommonUtils.getRemoteAddr(source);\n\t\tRemoteAddr targetAddr = CommonUtils.getRemoteAddr(target);\n\t\tif (sourceAddr == null || targetAddr == null) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tString sourceHost = sourceAddr.getServerHost();\n\t\t\tString targetHost = targetAddr.getServerHost();\n\t\t\tint sourcePort = sourceAddr.getServerPort();\n\t\t\tint targetPort = targetAddr.getServerPort();\n\t\t\treturn StringUtils.equalsIgnoreCase(sourceHost, targetHost) && sourcePort == targetPort;\n\t\t}\n\t}\n\n\tpublic static boolean equals(Object o1, Object o2) {\n\t\treturn java.util.Objects.equals(o1, o2);\n\t}\n\n\tpublic static void closeQuietly(Closeable closeable) {\n\t\tIOUtils.closeQuietly(closeable);\n\t}\n\n\tpublic static String getInetAddress() {\n\t\tEnumeration<NetworkInterface> interfaces = null;\n\t\ttry {\n\t\t\tinterfaces = NetworkInterface.getNetworkInterfaces();\n\t\t} catch (SocketException ignored) {\n\t\t\treturn CommonUtils.getLocalHostAddress();\n\t\t}\n\n\t\tfinal Set<InetAddress> virtualist = new TreeSet<InetAddress>(new InetAddrComparator());\n\t\tfinal Set<InetAddress> candidates = new TreeSet<InetAddress>(new InetAddrComparator());\n\t\twhile (interfaces != null && interfaces.hasMoreElements()) {\n\t\t\tNetworkInterface network = interfaces.nextElement();\n\t\t\ttry {\n\t\t\t\tif (network.isUp() == false || network.isLoopback() || network.isPointToPoint()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} catch (SocketException ignored) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tEnumeration<InetAddress> addresses = network.getInetAddresses();\n\t\t\twhile (addresses.hasMoreElements()) {\n\t\t\t\tInetAddress address = addresses.nextElement();\n\t\t\t\tif (Inet4Address.class.isInstance(address) == false) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (address.isAnyLocalAddress() || address.isMulticastAddress()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t(network.isVirtual() ? virtualist : candidates).add(address);\n\t\t\t}\n\t\t}\n\n\t\tIterator<InetAddress> itr = candidates.iterator();\n\t\tIterator<InetAddress> vtr = virtualist.iterator();\n\t\tif (itr.hasNext()) {\n\t\t\treturn itr.next().getHostAddress();\n\t\t} else if (vtr.hasNext()) {\n\t\t\treturn vtr.next().getHostAddress();\n\t\t}\n\n\t\treturn CommonUtils.getLocalHostAddress();\n\t}\n\n\tprivate static class InetAddrComparator implements Comparator<InetAddress> {\n\t\tpublic int compare(InetAddress o1, InetAddress o2) {\n\t\t\tboolean linkLocalAddr1 = o1.isLinkLocalAddress();\n\t\t\tboolean siteLocalAddr1 = o1.isSiteLocalAddress();\n\t\t\tboolean linkLocalAddr2 = o2.isLinkLocalAddress();\n\t\t\tboolean siteLocalAddr2 = o2.isSiteLocalAddress();\n\t\t\tboolean linkLocalEquals = linkLocalAddr1 == linkLocalAddr2;\n\t\t\tboolean siteLocalEquals = siteLocalAddr1 == siteLocalAddr2;\n\t\t\tif (linkLocalEquals && siteLocalEquals) {\n\t\t\t\treturn -1;\n\t\t\t} else if (linkLocalEquals == false && siteLocalEquals == false) {\n\t\t\t\treturn linkLocalAddr1 ? -1 : 1;\n\t\t\t} else if (siteLocalEquals) {\n\t\t\t\treturn linkLocalAddr1 ? -1 : 1;\n\t\t\t} else if (linkLocalEquals) {\n\t\t\t\treturn siteLocalAddr1 ? -1 : 1;\n\t\t\t} else {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static String getInetAddress(String host) {\n\t\ttry {\n\t\t\tInetAddress inetAddr = InetAddress.getByName(host);\n\t\t\treturn inetAddr.getHostAddress();\n\t\t} catch (UnknownHostException ex) {\n\t\t\tlogger.error(\"Error occurred while getting ip address: host= {}.\", host, ex);\n\t\t\treturn host;\n\t\t}\n\t}\n\n\tpublic static String getLocalHostAddress() {\n\t\ttry {\n\t\t\tInetAddress inetAddr = InetAddress.getLocalHost();\n\t\t\treturn inetAddr.getHostAddress();\n\t\t} catch (Exception ex) {\n\t\t\tlogger.error(\"Error occurred while getting ip address.\", ex);\n\t\t\treturn \"127.0.0.1\";\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/common/utils/SerializeUtils.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.common.utils;\n\nimport java.io.BufferedInputStream;\nimport java.io.BufferedOutputStream;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.io.Serializable;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.objenesis.strategy.SerializingInstantiatorStrategy;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.esotericsoftware.kryo.Kryo;\nimport com.esotericsoftware.kryo.Kryo.DefaultInstantiatorStrategy;\nimport com.esotericsoftware.kryo.io.Input;\nimport com.esotericsoftware.kryo.io.Output;\nimport com.esotericsoftware.kryo.pool.KryoCallback;\nimport com.esotericsoftware.kryo.pool.KryoFactory;\nimport com.esotericsoftware.kryo.pool.KryoPool;\n\npublic class SerializeUtils {\n\tstatic final Logger logger = LoggerFactory.getLogger(SerializeUtils.class);\n\n\tstatic final String SERIALIZER_NAME_DEFAULT = \"default\";\n\tstatic final String SERIALIZER_NAME_KRYO = \"kryo\";\n\tstatic final String SERIALIZER_NAME_HESSIAN = \"hessian\";\n\n\tstatic final int SERIALIZER_DEFAULT = 0x0;\n\tstatic final int SERIALIZER_KRYO = 0x1;\n\tstatic final int SERIALIZER_HESSIAN = 0x2;\n\n\tstatic int PREFERRED_SERIALIZER = SERIALIZER_KRYO;\n\tstatic {\n\t\tString serializer = StringUtils.trimToNull(System.getProperty(\"bytejta.serializer.preferred\"));\n\t\tif (StringUtils.isNotBlank(serializer) && StringUtils.equalsIgnoreCase(SERIALIZER_NAME_KRYO, serializer)) {\n\t\t\tPREFERRED_SERIALIZER = SERIALIZER_KRYO;\n\t\t} else if (StringUtils.isNotBlank(serializer) && StringUtils.equalsIgnoreCase(SERIALIZER_NAME_HESSIAN, serializer)) {\n\t\t\tPREFERRED_SERIALIZER = SERIALIZER_HESSIAN;\n\t\t} else if (StringUtils.isNotBlank(serializer)) {\n\t\t\tPREFERRED_SERIALIZER = SERIALIZER_DEFAULT;\n\t\t}\n\t}\n\n\tstatic KryoPool kryoPool = new KryoPool.Builder(new KryoFactory() {\n\t\tpublic Kryo create() {\n\t\t\tKryo kryo = new Kryo();\n\t\t\tkryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new SerializingInstantiatorStrategy()));\n\t\t\treturn kryo;\n\t\t}\n\t}).softReferences().build();\n\n\tpublic static byte[] serializeObject(Serializable obj, int serializerType) throws IOException {\n\t\tint serializer = SERIALIZER_DEFAULT;\n\t\tbyte[] dataArray = null;\n\t\tif (serializerType == SERIALIZER_KRYO) {\n\t\t\tdataArray = kryoSerialize(obj);\n\t\t\tserializer = SERIALIZER_KRYO;\n\t\t} else if (serializerType == SERIALIZER_HESSIAN) {\n\t\t\tdataArray = hessianSerialize(obj);\n\t\t\tserializer = SERIALIZER_HESSIAN;\n\t\t} else {\n\t\t\tdataArray = javaSerialize(obj);\n\t\t\tserializer = SERIALIZER_DEFAULT;\n\t\t}\n\n\t\tbyte[] byteArray = new byte[dataArray.length + 1];\n\t\tbyteArray[0] = (byte) serializer;\n\t\tSystem.arraycopy(dataArray, 0, byteArray, 1, dataArray.length);\n\n\t\treturn byteArray;\n\t}\n\n\tpublic static byte[] serializeObject(Serializable obj) throws IOException {\n\t\tif (PREFERRED_SERIALIZER == SERIALIZER_DEFAULT) {\n\t\t\treturn serializeObject(obj, PREFERRED_SERIALIZER);\n\t\t} else {\n\t\t\ttry {\n\t\t\t\treturn serializeObject(obj, PREFERRED_SERIALIZER);\n\t\t\t} catch (Exception ex) {\n\t\t\t\treturn serializeObject(obj, SERIALIZER_DEFAULT);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static Serializable deserializeObject(byte[] bytes) throws IOException {\n\t\tif (bytes.length == 0) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t\tbyte[] byteArray = new byte[bytes.length - 1];\n\t\tint serializer = bytes[0];\n\n\t\tif (serializer == SERIALIZER_KRYO) {\n\t\t\tSystem.arraycopy(bytes, 1, byteArray, 0, byteArray.length);\n\t\t\treturn kryoDeserialize(byteArray);\n\t\t} else if (serializer == SERIALIZER_HESSIAN) {\n\t\t\tSystem.arraycopy(bytes, 1, byteArray, 0, byteArray.length);\n\t\t\treturn hessianDeserialize(byteArray);\n\t\t} else if (serializer == SERIALIZER_DEFAULT) {\n\t\t\tSystem.arraycopy(bytes, 1, byteArray, 0, byteArray.length);\n\t\t\treturn javaDeserialize(byteArray);\n\t\t} else {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\t}\n\n\tpublic static byte[] javaSerialize(final Serializable obj) throws IOException {\n\t\tByteArrayOutputStream baos = new ByteArrayOutputStream();\n\t\tObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(baos));\n\t\ttry {\n\t\t\toos.writeObject(obj);\n\t\t} finally {\n\t\t\tCommonUtils.closeQuietly(oos);\n\t\t}\n\t\treturn baos.toByteArray();\n\t}\n\n\tpublic static Serializable javaDeserialize(byte[] byteArray) throws IOException {\n\t\tObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(byteArray)));\n\t\ttry {\n\t\t\treturn (Serializable) ois.readObject();\n\t\t} catch (ClassNotFoundException ex) {\n\t\t\tthrow new IllegalStateException(ex);\n\t\t} finally {\n\t\t\tCommonUtils.closeQuietly(ois);\n\t\t}\n\t}\n\n\tpublic static byte[] kryoSerialize(final Serializable obj) throws IOException {\n\t\tByteArrayOutputStream baos = new ByteArrayOutputStream();\n\t\tfinal Output output = new Output(baos);\n\n\t\ttry {\n\t\t\tkryoPool.run(new KryoCallback<Object>() {\n\t\t\t\tpublic Object execute(Kryo kryo) {\n\t\t\t\t\tkryo.writeClassAndObject(output, obj);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t});\n\t\t} finally {\n\t\t\tCommonUtils.closeQuietly(output);\n\t\t}\n\n\t\treturn baos.toByteArray();\n\t}\n\n\tpublic static Serializable kryoDeserialize(byte[] byteArray) throws IOException {\n\t\tfinal Input input = new Input(new ByteArrayInputStream(byteArray));\n\n\t\ttry {\n\t\t\treturn kryoPool.run(new KryoCallback<Serializable>() {\n\t\t\t\tpublic Serializable execute(Kryo kryo) {\n\t\t\t\t\treturn (Serializable) kryo.readClassAndObject(input);\n\t\t\t\t}\n\t\t\t});\n\t\t} finally {\n\t\t\tCommonUtils.closeQuietly(input);\n\t\t}\n\t}\n\n\tpublic static byte[] hessianSerialize(Serializable obj) throws IOException {\n\t\tByteArrayOutputStream baos = new ByteArrayOutputStream();\n\t\tHessianOutput ho = new HessianOutput(baos);\n\t\ttry {\n\t\t\tho.writeObject(obj);\n\t\t\treturn baos.toByteArray();\n\t\t} finally {\n\t\t\tCommonUtils.closeQuietly(baos);\n\t\t}\n\n\t}\n\n\tpublic static Serializable hessianDeserialize(byte[] bytes) throws IOException {\n\t\tByteArrayInputStream bais = new ByteArrayInputStream(bytes);\n\t\tHessianInput hi = new HessianInput(bais);\n\t\ttry {\n\t\t\tObject result = hi.readObject();\n\t\t\treturn (Serializable) result;\n\t\t} finally {\n\t\t\tCommonUtils.closeQuietly(bais);\n\t\t}\n\t}\n\n\tpublic static String serializeClass(Class<?> clazz) {\n\t\tif (boolean.class.equals(clazz)) {\n\t\t\treturn \"Z\";\n\t\t} else if (byte.class.equals(clazz)) {\n\t\t\treturn \"B\";\n\t\t} else if (short.class.equals(clazz)) {\n\t\t\treturn \"S\";\n\t\t} else if (char.class.equals(clazz)) {\n\t\t\treturn \"C\";\n\t\t} else if (int.class.equals(clazz)) {\n\t\t\treturn \"I\";\n\t\t} else if (float.class.equals(clazz)) {\n\t\t\treturn \"F\";\n\t\t} else if (long.class.equals(clazz)) {\n\t\t\treturn \"J\";\n\t\t} else if (double.class.equals(clazz)) {\n\t\t\treturn \"D\";\n\t\t} else if (void.class.equals(clazz)) {\n\t\t\treturn \"V\";\n\t\t} else if (clazz.isArray()) {\n\t\t\treturn clazz.getName();\n\t\t} else {\n\t\t\treturn String.format(\"L%s;\", clazz.getName().replaceAll(\"\\\\.\", \"/\"));\n\t\t}\n\t}\n\n\tpublic static Class<?> deserializeClass(String classDesc) {\n\t\tString clazz = StringUtils.trimToEmpty(classDesc);\n\t\tif (StringUtils.isBlank(clazz)) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\n\t\tif (clazz.length() > 1) {\n\t\t\tString clazzName = clazz.replaceAll(\"\\\\/\", \".\");\n\t\t\tClassLoader cl = Thread.currentThread().getContextClassLoader();\n\t\t\ttry {\n\t\t\t\treturn cl.loadClass(clazzName);\n\t\t\t} catch (ClassNotFoundException ex) {\n\t\t\t\tthrow new IllegalStateException(ex.getMessage());\n\t\t\t}\n\t\t}\n\n\t\tfinal char character = clazz.charAt(0);\n\t\treturn SerializeUtils.deserializeClass(character);\n\t}\n\n\tpublic static Class<?> deserializeClass(final char character) {\n\t\tswitch (character) {\n\t\tcase 'Z':\n\t\t\treturn boolean.class;\n\t\tcase 'B':\n\t\t\treturn byte.class;\n\t\tcase 'S':\n\t\t\treturn short.class;\n\t\tcase 'C':\n\t\t\treturn char.class;\n\t\tcase 'I':\n\t\t\treturn int.class;\n\t\tcase 'J':\n\t\t\treturn long.class;\n\t\tcase 'F':\n\t\t\treturn float.class;\n\t\tcase 'D':\n\t\t\treturn double.class;\n\t\tdefault:\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic static String serializeMethod(Method method) {\n\t\tStringBuilder ber = new StringBuilder();\n\t\tber.append(method.getName()).append(\"(\");\n\t\tClass<?>[] parameterTypes = method.getParameterTypes();\n\t\tfor (int i = 0; i < parameterTypes.length; i++) {\n\t\t\tClass<?> parameterType = parameterTypes[i];\n\t\t\tString clazzName = SerializeUtils.serializeClass(parameterType);\n\t\t\tber.append(clazzName);\n\t\t}\n\n\t\tber.append(\")\").append(SerializeUtils.serializeClass(method.getReturnType()));\n\n\t\treturn ber.toString();\n\t}\n\n\tpublic static Method deserializeMethod(Class<?> interfaceClass, String methodDesc) throws Exception {\n\t\tint startIdx = methodDesc.indexOf(\"(\");\n\t\tString methodName = methodDesc.substring(0, startIdx);\n\t\tint endIndex = methodDesc.indexOf(\")\");\n\t\tString value = methodDesc.substring(startIdx + 1, endIndex);\n\t\tchar[] values = value.toCharArray();\n\n\t\tList<Class<?>> paramTypeList = new ArrayList<Class<?>>();\n\t\tboolean flags = false;\n\t\tStringBuilder clazzDesc = new StringBuilder();\n\t\tfor (int i = 0; i < values.length; i++) {\n\t\t\tchar character = values[i];\n\t\t\tif (character == ';') {\n\t\t\t\tflags = false;\n\t\t\t\tString paramTypeNameDesc = clazzDesc.toString();\n\t\t\t\tclazzDesc.delete(0, clazzDesc.length());\n\t\t\t\tClass<?> paramType = SerializeUtils.deserializeClass(paramTypeNameDesc);\n\t\t\t\tparamTypeList.add(paramType);\n\t\t\t\tcontinue;\n\t\t\t} else if (flags) {\n\t\t\t\tclazzDesc.append(character);\n\t\t\t\tcontinue;\n\t\t\t} else if (character == 'L') {\n\t\t\t\tflags = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tClass<?> paramType = SerializeUtils.deserializeClass(character);\n\t\t\tparamTypeList.add(paramType);\n\t\t}\n\n\t\tClass<?>[] parameterTypes = new Class<?>[paramTypeList.size()];\n\t\tparamTypeList.toArray(parameterTypes);\n\n\t\treturn interfaceClass.getDeclaredMethod(methodName, parameterTypes);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/CommitRequiredException.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport javax.transaction.SystemException;\n\npublic class CommitRequiredException extends SystemException {\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic CommitRequiredException() {\n\t\tsuper();\n\t}\n\n\tpublic CommitRequiredException(String s) {\n\t\tsuper(s);\n\t}\n\n\tpublic CommitRequiredException(int errcode) {\n\t\tsuper(errcode);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/RemoteSystemException.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport java.rmi.RemoteException;\n\nimport javax.transaction.SystemException;\n\npublic class RemoteSystemException extends SystemException {\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic RemoteSystemException() {\n\t\tsuper();\n\t}\n\n\tpublic RemoteSystemException(String s) {\n\t\tsuper(s);\n\t}\n\n\tpublic RemoteSystemException(int errcode) {\n\t\tsuper(errcode);\n\t}\n\n\tpublic Throwable initCause(Throwable cause) {\n\t\tif (RemoteException.class.isInstance(cause) == false) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\t\treturn super.initCause(cause);\n\t}\n\n\tpublic RemoteException getRemoteException() {\n\t\tThrowable thrown = super.getCause();\n\t\treturn RemoteException.class.cast(thrown);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/RollbackRequiredException.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport javax.transaction.SystemException;\n\npublic class RollbackRequiredException extends SystemException {\n\tprivate static final long serialVersionUID = 1L;\n\n\tpublic RollbackRequiredException() {\n\t\tsuper();\n\t}\n\n\tpublic RollbackRequiredException(String s) {\n\t\tsuper(s);\n\t}\n\n\tpublic RollbackRequiredException(int errcode) {\n\t\tsuper(errcode);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/Transaction.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<liuyangming@gmail.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.transaction;\r\n\r\nimport javax.transaction.HeuristicMixedException;\r\nimport javax.transaction.HeuristicRollbackException;\r\nimport javax.transaction.RollbackException;\r\nimport javax.transaction.SystemException;\r\n\r\nimport org.bytesoft.transaction.archive.TransactionArchive;\r\nimport org.bytesoft.transaction.remote.RemoteSvc;\r\nimport org.bytesoft.transaction.supports.TransactionExtra;\r\nimport org.bytesoft.transaction.supports.TransactionListener;\r\nimport org.bytesoft.transaction.supports.TransactionResourceListener;\r\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\r\n\r\npublic interface Transaction extends javax.transaction.Transaction, TransactionExtra {\r\n\r\n\tpublic void fireBeforeTransactionCompletion() throws RollbackRequiredException, SystemException;\r\n\r\n\tpublic void fireBeforeTransactionCompletionQuietly();\r\n\r\n\tpublic void fireAfterTransactionCompletion();\r\n\r\n\tpublic boolean isLocalTransaction();\r\n\r\n\tpublic boolean isMarkedRollbackOnly();\r\n\r\n\tpublic void setRollbackOnlyQuietly();\r\n\r\n\tpublic int getTransactionStatus();\r\n\r\n\tpublic void setTransactionStatus(int status);\r\n\r\n\tpublic void resume() throws SystemException;\r\n\r\n\tpublic void suspend() throws SystemException;\r\n\r\n\tpublic boolean isTiming();\r\n\r\n\tpublic void setTransactionTimeout(int seconds);\r\n\r\n\tpublic void registerTransactionListener(TransactionListener listener);\r\n\r\n\tpublic void registerTransactionResourceListener(TransactionResourceListener listener);\r\n\r\n\tpublic TransactionExtra getTransactionalExtra();\r\n\r\n\tpublic void setTransactionalExtra(TransactionExtra transactionalExtra);\r\n\r\n\tpublic XAResourceDescriptor getResourceDescriptor(String beanName);\r\n\r\n\tpublic XAResourceDescriptor getRemoteCoordinator(RemoteSvc remoteSvc);\r\n\r\n\tpublic XAResourceDescriptor getRemoteCoordinator(String application);\r\n\r\n\tpublic TransactionContext getTransactionContext();\r\n\r\n\tpublic TransactionArchive getTransactionArchive();\r\n\r\n\tpublic int participantPrepare() throws RollbackRequiredException, CommitRequiredException;\r\n\r\n\tpublic void participantCommit(boolean opc) throws RollbackException, HeuristicMixedException, HeuristicRollbackException,\r\n\t\t\tSecurityException, IllegalStateException, CommitRequiredException, SystemException;\r\n\r\n\tpublic void participantRollback() throws IllegalStateException, RollbackRequiredException, SystemException;\r\n\r\n\tpublic void forget() throws SystemException;\r\n\r\n\tpublic void forgetQuietly();\r\n\r\n\tpublic void recover() throws SystemException;\r\n\r\n\tpublic void recoveryCommit() throws CommitRequiredException, SystemException;\r\n\r\n\tpublic void recoveryRollback() throws RollbackRequiredException, SystemException;\r\n\r\n\tpublic Exception getCreatedAt();\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionBeanFactory.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.transaction;\r\n\r\nimport org.bytesoft.transaction.logging.ArchiveDeserializer;\r\nimport org.bytesoft.transaction.logging.TransactionLogger;\r\nimport org.bytesoft.transaction.supports.TransactionTimer;\r\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\r\nimport org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;\r\nimport org.bytesoft.transaction.xa.XidFactory;\r\n\r\npublic interface TransactionBeanFactory {\r\n\r\n\tpublic TransactionLock getTransactionLock();\r\n\r\n\tpublic TransactionManager getTransactionManager();\r\n\r\n\tpublic XidFactory getXidFactory();\r\n\r\n\tpublic TransactionTimer getTransactionTimer();\r\n\r\n\tpublic TransactionRepository getTransactionRepository();\r\n\r\n\tpublic TransactionInterceptor getTransactionInterceptor();\r\n\r\n\tpublic TransactionRecovery getTransactionRecovery();\r\n\r\n\tpublic TransactionParticipant getNativeParticipant();\r\n\r\n\tpublic TransactionLogger getTransactionLogger();\r\n\r\n\tpublic ArchiveDeserializer getArchiveDeserializer();\r\n\r\n\tpublic XAResourceDeserializer getResourceDeserializer();\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionContext.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport java.io.Serializable;\n\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic class TransactionContext implements Serializable, Cloneable {\n\tprivate static final long serialVersionUID = 1L;\n\n\tprotected transient Object propagatedBy;\n\tprotected transient boolean propagated;\n\tprotected transient boolean coordinator;\n\tprotected transient boolean recoveried;\n\tprotected transient int recoveredTimes;\n\n\tprotected TransactionXid xid;\n\tprotected long createdTime;\n\tprotected long expiredTime;\n\tprotected boolean rollbackOnly;\n\tprotected long configFlags;\n\n\tpublic TransactionContext clone() {\n\t\tTransactionContext that = new TransactionContext();\n\t\tthat.xid = this.xid.clone();\n\t\tthat.createdTime = System.currentTimeMillis();\n\t\tthat.expiredTime = this.expiredTime;\n\t\tthat.rollbackOnly = this.rollbackOnly;\n\t\tthat.configFlags = this.configFlags;\n\t\treturn that;\n\t}\n\n\tpublic int getRecoveredTimes() {\n\t\treturn recoveredTimes;\n\t}\n\n\tpublic void setRecoveredTimes(int recoveredTimes) {\n\t\tthis.recoveredTimes = recoveredTimes;\n\t}\n\n\tpublic boolean isCoordinator() {\n\t\treturn coordinator;\n\t}\n\n\tpublic void setCoordinator(boolean coordinator) {\n\t\tthis.coordinator = coordinator;\n\t}\n\n\tpublic boolean isRecoveried() {\n\t\treturn recoveried;\n\t}\n\n\tpublic void setRecoveried(boolean recoveried) {\n\t\tthis.recoveried = recoveried;\n\t}\n\n\tpublic TransactionXid getXid() {\n\t\treturn xid;\n\t}\n\n\tpublic void setXid(TransactionXid xid) {\n\t\tthis.xid = xid;\n\t}\n\n\tpublic long getCreatedTime() {\n\t\treturn createdTime;\n\t}\n\n\tpublic void setCreatedTime(long createdTime) {\n\t\tthis.createdTime = createdTime;\n\t}\n\n\tpublic long getExpiredTime() {\n\t\treturn expiredTime;\n\t}\n\n\tpublic void setExpiredTime(long expiredTime) {\n\t\tthis.expiredTime = expiredTime;\n\t}\n\n\tpublic long getConfigFlags() {\n\t\treturn configFlags;\n\t}\n\n\tpublic void setConfigFlags(long configFlags) {\n\t\tthis.configFlags = configFlags;\n\t}\n\n\tpublic boolean isPropagated() {\n\t\treturn propagated;\n\t}\n\n\tpublic void setPropagated(boolean propagated) {\n\t\tthis.propagated = propagated;\n\t}\n\n\tpublic Object getPropagatedBy() {\n\t\treturn propagatedBy;\n\t}\n\n\tpublic void setPropagatedBy(Object propagatedBy) {\n\t\tthis.propagatedBy = propagatedBy;\n\t}\n\n\tpublic boolean isRollbackOnly() {\n\t\treturn rollbackOnly;\n\t}\n\n\tpublic void setRollbackOnly(boolean rollbackOnly) {\n\t\tthis.rollbackOnly = rollbackOnly;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionException.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\npublic class TransactionException extends RuntimeException {\n\tprivate static final long serialVersionUID = 1L;\n\n\t/* XAException.errorCode */\n\tpublic int errorCode;\n\n\tpublic TransactionException(int errcode) {\n\t\tsuper();\n\t\terrorCode = errcode;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionLock.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic interface TransactionLock {\n\n\tpublic boolean lockTransaction(TransactionXid transactionXid, String identifier);\n\n\tpublic void unlockTransaction(TransactionXid transactionXid, String identifier);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionManager.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<liuyangming@gmail.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.transaction;\r\n\r\nimport javax.transaction.SystemException;\r\n\r\npublic interface TransactionManager extends javax.transaction.TransactionManager {\r\n\r\n\tpublic int getTimeoutSeconds();\r\n\r\n\tpublic void setTimeoutSeconds(int timeoutSeconds);\r\n\r\n\tpublic void associateThread(Transaction transaction);\r\n\r\n\tpublic Transaction desociateThread();\r\n\r\n\tpublic Transaction getTransaction(Thread thread);\r\n\r\n\tpublic Transaction getTransactionQuietly();\r\n\r\n\tpublic Transaction getTransaction() throws SystemException;\r\n\r\n\tpublic Transaction suspend() throws SystemException;\r\n\r\n\tpublic void setRollbackOnlyQuietly();\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionParticipant.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\npublic interface TransactionParticipant extends XAResource {\n\n\tpublic Transaction end(TransactionContext transactionContext, int flags) throws XAException;\n\n\tpublic void forgetQuietly(Xid xid);\n\n\tpublic Transaction start(TransactionContext transactionContext, int flags) throws XAException;\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionRecovery.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction;\n\nimport org.bytesoft.transaction.archive.TransactionArchive;\n\npublic interface TransactionRecovery {\n\n\tpublic Transaction reconstruct(TransactionArchive archive);\n\n\tpublic void timingRecover();\n\n\tpublic void startRecovery();\n\n\tpublic void branchRecover();\n\n\tpublic boolean isInitialized();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/TransactionRepository.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.transaction;\r\n\r\nimport java.util.List;\r\n\r\nimport org.bytesoft.transaction.xa.TransactionXid;\r\n\r\npublic interface TransactionRepository {\r\n\r\n\t// active-transaction & error-transaction\r\n\tpublic void putTransaction(TransactionXid xid, Transaction transaction);\r\n\r\n\tpublic Transaction getTransaction(TransactionXid xid);\r\n\r\n\tpublic Transaction removeTransaction(TransactionXid xid);\r\n\r\n\t// error-transaction\r\n\tpublic void putErrorTransaction(TransactionXid xid, Transaction transaction);\r\n\r\n\tpublic Transaction getErrorTransaction(TransactionXid xid);\r\n\r\n\tpublic Transaction removeErrorTransaction(TransactionXid xid);\r\n\r\n\tpublic List<Transaction> getErrorTransactionList();\r\n\r\n\tpublic List<Transaction> getActiveTransactionList();\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/adapter/ResourceAdapterImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.adapter;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.resource.ResourceException;\nimport javax.resource.spi.ActivationSpec;\nimport javax.resource.spi.BootstrapContext;\nimport javax.resource.spi.ResourceAdapter;\nimport javax.resource.spi.ResourceAdapterInternalException;\nimport javax.resource.spi.endpoint.MessageEndpointFactory;\nimport javax.resource.spi.work.Work;\nimport javax.resource.spi.work.WorkException;\nimport javax.resource.spi.work.WorkManager;\nimport javax.transaction.xa.XAResource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class ResourceAdapterImpl implements ResourceAdapter {\n\tstatic final Logger logger = LoggerFactory.getLogger(ResourceAdapterImpl.class);\n\n\tprivate List<Work> workList = new ArrayList<Work>();;\n\tprivate WorkManager workManager;\n\n\tpublic void start(BootstrapContext ctx) throws ResourceAdapterInternalException {\n\t\tthis.workManager = ctx.getWorkManager();\n\t\tfor (int i = 0; this.workList != null && i < this.workList.size(); i++) {\n\t\t\tWork work = this.workList.get(i);\n\t\t\ttry {\n\t\t\t\tthis.workManager.startWork(work);\n\t\t\t} catch (WorkException ex) {\n\t\t\t\tthis.stop();\n\t\t\t\tthrow new ResourceAdapterInternalException(ex);\n\t\t\t} catch (RuntimeException ex) {\n\t\t\t\tthis.stop();\n\t\t\t\tthrow new ResourceAdapterInternalException(ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void stop() {\n\t\tfor (int i = 0; this.workList != null && i < this.workList.size(); i++) {\n\t\t\tWork work = this.workList.get(i);\n\t\t\ttry {\n\t\t\t\twork.release();\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.debug(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void endpointActivation(MessageEndpointFactory endpointFactory, ActivationSpec spec) throws ResourceException {\n\t}\n\n\tpublic void endpointDeactivation(MessageEndpointFactory endpointFactory, ActivationSpec spec) {\n\t}\n\n\tpublic XAResource[] getXAResources(ActivationSpec[] specs) throws ResourceException {\n\t\treturn new XAResource[0];\n\t}\n\n\tpublic List<Work> getWorkList() {\n\t\treturn workList;\n\t}\n\n\tpublic void setWorkList(List<Work> workList) {\n\t\tthis.workList = workList;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/archive/TransactionArchive.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.archive;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.transaction.xa.Xid;\n\npublic class TransactionArchive {\n\tprivate transient String endpoint;\n\tprivate Xid xid;\n\tprivate int status;\n\tprivate int vote;\n\tprivate boolean coordinator;\n\tprivate Object propagatedBy;\n\tprivate final List<XAResourceArchive> nativeResources = new ArrayList<XAResourceArchive>();\n\tprivate final List<XAResourceArchive> remoteResources = new ArrayList<XAResourceArchive>();\n\n\tprivate int transactionStrategyType;\n\tprivate XAResourceArchive optimizedResource;\n\n\tprivate int recoveredTimes;\n\tprivate long recoveredAt;\n\n\tpublic int getRecoveredTimes() {\n\t\treturn recoveredTimes;\n\t}\n\n\tpublic void setRecoveredTimes(int recoveredTimes) {\n\t\tthis.recoveredTimes = recoveredTimes;\n\t}\n\n\tpublic long getRecoveredAt() {\n\t\treturn recoveredAt;\n\t}\n\n\tpublic void setRecoveredAt(long recoveredAt) {\n\t\tthis.recoveredAt = recoveredAt;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn endpoint;\n\t}\n\n\tpublic void setEndpoint(String endpoint) {\n\t\tthis.endpoint = endpoint;\n\t}\n\n\tpublic Xid getXid() {\n\t\treturn xid;\n\t}\n\n\tpublic void setXid(Xid xid) {\n\t\tthis.xid = xid;\n\t}\n\n\tpublic int getStatus() {\n\t\treturn status;\n\t}\n\n\tpublic void setStatus(int status) {\n\t\tthis.status = status;\n\t}\n\n\tpublic int getVote() {\n\t\treturn vote;\n\t}\n\n\tpublic void setVote(int vote) {\n\t\tthis.vote = vote;\n\t}\n\n\tpublic boolean isCoordinator() {\n\t\treturn coordinator;\n\t}\n\n\tpublic void setCoordinator(boolean coordinator) {\n\t\tthis.coordinator = coordinator;\n\t}\n\n\tpublic Object getPropagatedBy() {\n\t\treturn propagatedBy;\n\t}\n\n\tpublic void setPropagatedBy(Object propagatedBy) {\n\t\tthis.propagatedBy = propagatedBy;\n\t}\n\n\tpublic List<XAResourceArchive> getNativeResources() {\n\t\treturn nativeResources;\n\t}\n\n\tpublic List<XAResourceArchive> getRemoteResources() {\n\t\treturn remoteResources;\n\t}\n\n\tpublic XAResourceArchive getOptimizedResource() {\n\t\treturn optimizedResource;\n\t}\n\n\tpublic void setOptimizedResource(XAResourceArchive optimizedResource) {\n\t\tthis.optimizedResource = optimizedResource;\n\t}\n\n\tpublic int getTransactionStrategyType() {\n\t\treturn transactionStrategyType;\n\t}\n\n\tpublic void setTransactionStrategyType(int transactionStrategyType) {\n\t\tthis.transactionStrategyType = transactionStrategyType;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/archive/XAResourceArchive.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.archive;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class XAResourceArchive implements XAResource {\n\tstatic final Logger logger = LoggerFactory.getLogger(XAResourceArchive.class);\n\tpublic static final int DEFAULT_VOTE = -1;\n\n\tprivate boolean suspended;\n\tprivate boolean delisted;\n\tprivate boolean completed;\n\tprivate boolean readonly;\n\tprivate boolean committed;\n\tprivate boolean rolledback;\n\tprivate boolean heuristic;\n\tprivate boolean identified;\n\n\tprivate transient boolean recovered;\n\n\tprivate Xid xid;\n\tprivate int vote = DEFAULT_VOTE;\n\tprivate XAResourceDescriptor descriptor;\n\tprivate XAResourceDescriptor stickiness;\n\n\tpublic void commit(Xid ignore, boolean onePhase) throws XAException {\n\t\tif (this.readonly) {\n\t\t\t// ignore\n\t\t} else if (this.committed) {\n\t\t\t// ignore\n\t\t} else if (this.rolledback) {\n\t\t\tthrow new XAException(XAException.XA_HEURRB);\n\t\t} else {\n\t\t\tdescriptor.commit(xid, onePhase);\n\t\t}\n\t}\n\n\tpublic void end(Xid ignore, int flags) throws XAException {\n\t\tdescriptor.end(xid, flags);\n\t}\n\n\tpublic void forget(Xid ignore) throws XAException {\n\t\tdescriptor.forget(xid);\n\t}\n\n\tpublic void forgetQuietly(Xid ignore) {\n\t\ttry {\n\t\t\tdescriptor.forget(xid);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.warn(\"Error occurred while forgeting xa-resource.\", xid);\n\t\t}\n\t}\n\n\tpublic int getTransactionTimeout() throws XAException {\n\t\treturn descriptor.getTransactionTimeout();\n\t}\n\n\tpublic boolean isSameRM(XAResource xares) throws XAException {\n\t\tif (XAResourceArchive.class.isInstance(xares)) {\n\t\t\tXAResourceArchive archive = (XAResourceArchive) xares;\n\t\t\treturn descriptor.isSameRM(archive.getDescriptor());\n\t\t} else {\n\t\t\treturn descriptor.isSameRM(xares);\n\t\t}\n\t}\n\n\tpublic int prepare(Xid ignore) throws XAException {\n\t\tif (this.vote == -1) {\n\t\t\tthis.vote = this.descriptor.prepare(this.xid);\n\t\t\tthis.readonly = this.vote == XAResource.XA_RDONLY;\n\t\t}\n\t\treturn this.vote;\n\n\t}\n\n\tpublic Xid[] recover(int flag) throws XAException {\n\t\treturn descriptor.recover(flag);\n\t}\n\n\tpublic void rollback(Xid ignore) throws XAException {\n\n\t\tif (this.readonly) {\n\t\t\t// ignore\n\t\t} else if (this.committed) {\n\t\t\tthrow new XAException(XAException.XA_HEURCOM);\n\t\t} else if (this.rolledback) {\n\t\t\t// ignore\n\t\t} else {\n\t\t\tdescriptor.rollback(xid);\n\t\t}\n\n\t}\n\n\tpublic boolean setTransactionTimeout(int seconds) throws XAException {\n\t\treturn descriptor.setTransactionTimeout(seconds);\n\t}\n\n\tpublic void start(Xid ignore, int flags) throws XAException {\n\t\tdescriptor.start(xid, flags);\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"xa-res-archive[descriptor: %s]\", this.descriptor);\n\t}\n\n\tpublic XAResourceDescriptor getStickiness() {\n\t\treturn stickiness;\n\t}\n\n\tpublic void setStickiness(XAResourceDescriptor stickiness) {\n\t\tthis.stickiness = stickiness;\n\t}\n\n\tpublic XAResourceDescriptor getDescriptor() {\n\t\treturn descriptor;\n\t}\n\n\tpublic void setDescriptor(XAResourceDescriptor descriptor) {\n\t\tthis.descriptor = descriptor;\n\t}\n\n\tpublic boolean isSuspended() {\n\t\treturn suspended;\n\t}\n\n\tpublic void setSuspended(boolean suspended) {\n\t\tthis.suspended = suspended;\n\t}\n\n\tpublic boolean isDelisted() {\n\t\treturn delisted;\n\t}\n\n\tpublic void setDelisted(boolean delisted) {\n\t\tthis.delisted = delisted;\n\t}\n\n\tpublic Xid getXid() {\n\t\treturn xid;\n\t}\n\n\tpublic void setXid(Xid xid) {\n\t\tthis.xid = xid;\n\t}\n\n\tpublic int getVote() {\n\t\treturn vote;\n\t}\n\n\tpublic void setVote(int vote) {\n\t\tthis.vote = vote;\n\t}\n\n\tpublic boolean isCompleted() {\n\t\treturn completed;\n\t}\n\n\tpublic void setCompleted(boolean completed) {\n\t\tthis.completed = completed;\n\t}\n\n\tpublic boolean isCommitted() {\n\t\treturn committed;\n\t}\n\n\tpublic void setCommitted(boolean committed) {\n\t\tthis.committed = committed;\n\t}\n\n\tpublic boolean isRolledback() {\n\t\treturn rolledback;\n\t}\n\n\tpublic void setRolledback(boolean rolledback) {\n\t\tthis.rolledback = rolledback;\n\t}\n\n\tpublic boolean isReadonly() {\n\t\treturn readonly;\n\t}\n\n\tpublic void setReadonly(boolean readonly) {\n\t\tthis.readonly = readonly;\n\t}\n\n\tpublic boolean isHeuristic() {\n\t\treturn heuristic;\n\t}\n\n\tpublic void setHeuristic(boolean heuristic) {\n\t\tthis.heuristic = heuristic;\n\t}\n\n\tpublic boolean isRecovered() {\n\t\treturn recovered;\n\t}\n\n\tpublic void setRecovered(boolean recovered) {\n\t\tthis.recovered = recovered;\n\t}\n\n\tpublic boolean isIdentified() {\n\t\treturn identified;\n\t}\n\n\tpublic void setIdentified(boolean identified) {\n\t\tthis.identified = identified;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/aware/TransactionBeanFactoryAware.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.transaction.aware;\r\n\r\nimport org.bytesoft.transaction.TransactionBeanFactory;\r\n\r\npublic interface TransactionBeanFactoryAware {\r\n\tpublic static final String BEAN_FACTORY_FIELD_NAME = \"beanFactory\";\r\n\r\n\tpublic TransactionBeanFactory getBeanFactory();\r\n\r\n\tpublic void setBeanFactory(TransactionBeanFactory tbf);\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/aware/TransactionDebuggable.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.aware;\n\npublic interface TransactionDebuggable {\n\n\tpublic boolean isDebuggingEnabled();\n\n\tpublic void setDebuggingEnabled(boolean debuggingEnabled);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/aware/TransactionEndpointAware.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.aware;\n\npublic interface TransactionEndpointAware {\n\tpublic static final String ENDPOINT_FIELD_NAME = \"endpoint\";\n\n\tpublic String getEndpoint();\n\n\tpublic void setEndpoint(String identifier);\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/cmd/CommandDispatcher.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.cmd;\n\nimport java.util.concurrent.Callable;\n\npublic interface CommandDispatcher {\n\n\tpublic Object dispatch(Callable<Object> callable) throws Exception;\n\n\tpublic void dispatch(Runnable runnable) throws Exception;\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/internal/SynchronizationImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.internal;\n\nimport javax.transaction.Synchronization;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n\npublic class SynchronizationImpl implements Synchronization {\n\tstatic final Logger logger = LoggerFactory.getLogger(SynchronizationImpl.class);\n\n\tprivate Synchronization delegate;\n\tprivate boolean beforeRequired;\n\tprivate boolean finishRequired;\n\n\tpublic SynchronizationImpl(Synchronization sync) {\n\t\tif (sync == null) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t} else {\n\t\t\tthis.delegate = sync;\n\t\t\tthis.beforeRequired = true;\n\t\t\tthis.finishRequired = true;\n\t\t}\n\t}\n\n\tpublic void beforeCompletion() {\n\t\tif (this.beforeRequired) {\n\t\t\ttry {\n\t\t\t\tthis.delegate.beforeCompletion();\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\t// ignore\n\t\t\t} finally {\n\t\t\t\tthis.beforeRequired = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void afterCompletion(int status) {\n\t\tif (this.finishRequired) {\n\t\t\ttry {\n\t\t\t\tthis.delegate.afterCompletion(status);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\t// ignore\n\t\t\t} finally {\n\t\t\t\tthis.finishRequired = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"[%s] delegate: %s\", this.getClass().getSimpleName(), this.delegate);\n\t}\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/internal/SynchronizationList.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.internal;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.transaction.Synchronization;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class SynchronizationList implements Synchronization {\n\tprivate static final Logger logger = LoggerFactory.getLogger(SynchronizationList.class);\n\tprivate final List<Synchronization> synchronizations = new ArrayList<Synchronization>();\n\n\tprivate boolean beforeCompletionInvoked;\n\tprivate boolean finishCompletionInvoked;\n\n\tpublic void registerSynchronizationQuietly(Synchronization sync) {\n\t\tSynchronizationImpl synchronization = new SynchronizationImpl(sync);\n\t\tthis.synchronizations.add(synchronization);\n\t}\n\n\tpublic synchronized void beforeCompletion() {\n\t\tif (this.beforeCompletionInvoked == false) {\n\t\t\tint length = this.synchronizations.size();\n\t\t\tfor (int i = 0; i < length; i++) {\n\t\t\t\tSynchronization synchronization = this.synchronizations.get(i);\n\t\t\t\ttry {\n\t\t\t\t\tsynchronization.beforeCompletion();\n\t\t\t\t} catch (RuntimeException error) {\n\t\t\t\t\tlogger.error(error.getMessage(), error);\n\t\t\t\t}\n\t\t\t} // end-for\n\n\t\t\tthis.beforeCompletionInvoked = true;\n\t\t} // end-if (this.beforeCompletionInvoked == false)\n\t}\n\n\tpublic synchronized void afterCompletion(int status) {\n\t\tif (this.finishCompletionInvoked == false) {\n\t\t\tint length = this.synchronizations.size();\n\t\t\tfor (int i = 0; i < length; i++) {\n\t\t\t\tSynchronization synchronization = this.synchronizations.get(i);\n\t\t\t\ttry {\n\t\t\t\t\tsynchronization.afterCompletion(status);\n\t\t\t\t} catch (RuntimeException error) {\n\t\t\t\t\tlogger.error(error.getMessage(), error);\n\t\t\t\t}\n\t\t\t} // end-for\n\n\t\t\tthis.finishCompletionInvoked = true;\n\t\t} // end-if (this.finishCompletionInvoked == false)\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/internal/TransactionListenerList.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.internal;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.bytesoft.transaction.supports.TransactionListener;\nimport org.bytesoft.transaction.supports.TransactionListenerAdapter;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionListenerList extends TransactionListenerAdapter {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionListenerList.class);\n\n\tprivate final List<TransactionListener> listeners = new ArrayList<TransactionListener>();\n\n\tpublic void registerTransactionListener(TransactionListener listener) {\n\t\tthis.listeners.add(listener);\n\t}\n\n\tpublic void onPrepareStart(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onPrepareStart(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onPrepareSuccess(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onPrepareSuccess(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onPrepareFailure(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onPrepareFailure(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onCommitStart(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onCommitStart(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onCommitSuccess(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onCommitSuccess(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onCommitFailure(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onCommitFailure(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onCommitHeuristicMixed(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onCommitHeuristicMixed(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onCommitHeuristicRolledback(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onCommitHeuristicRolledback(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onRollbackStart(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onRollbackStart(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onRollbackSuccess(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onRollbackSuccess(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onRollbackFailure(TransactionXid xid) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onRollbackFailure(xid);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/internal/TransactionResourceListenerList.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.internal;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.transaction.supports.TransactionResourceListener;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionResourceListenerList implements TransactionResourceListener {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionResourceListenerList.class);\n\n\tprivate final List<TransactionResourceListener> listeners = new ArrayList<TransactionResourceListener>();\n\n\tpublic void registerTransactionResourceListener(TransactionResourceListener listener) {\n\t\tthis.listeners.add(listener);\n\t}\n\n\tpublic void onEnlistResource(Xid xid, XAResource xares) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionResourceListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onEnlistResource(xid, xares);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void onDelistResource(Xid xid, XAResource xares) {\n\t\tfor (int i = 0; i < this.listeners.size(); i++) {\n\t\t\ttry {\n\t\t\t\tTransactionResourceListener listener = this.listeners.get(i);\n\t\t\t\tlistener.onDelistResource(xid, xares);\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tlogger.error(rex.getMessage(), rex);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/ArchiveDeserializer.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging;\n\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic interface ArchiveDeserializer {\n\n\tpublic byte[] serialize(TransactionXid xid, Object archive);\n\n\tpublic Object deserialize(TransactionXid xid, byte[] array);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/LoggingFlushable.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging;\n\npublic interface LoggingFlushable {\n\n\tpublic void flushImmediately();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/TransactionLogger.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging;\n\nimport org.bytesoft.transaction.archive.TransactionArchive;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.recovery.TransactionRecoveryCallback;\n\npublic interface TransactionLogger {\n\n\t/* transaction */\n\tpublic void createTransaction(TransactionArchive archive);\n\n\tpublic void updateTransaction(TransactionArchive archive);\n\n\tpublic void deleteTransaction(TransactionArchive archive);\n\n\t/* resource */\n\tpublic void createResource(XAResourceArchive archive);\n\n\tpublic void updateResource(XAResourceArchive archive);\n\n\tpublic void deleteResource(XAResourceArchive archive);\n\n\t/* participant */\n\tpublic void createParticipant(XAResourceArchive archive);\n\n\tpublic void updateParticipant(XAResourceArchive archive);\n\n\tpublic void deleteParticipant(XAResourceArchive archive);\n\n\t/* recovery */\n\tpublic void recover(TransactionRecoveryCallback callback);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/store/VirtualLoggingKey.java",
    "content": "package org.bytesoft.transaction.logging.store;\n\nimport java.util.Arrays;\n\nimport javax.transaction.xa.Xid;\n\npublic class VirtualLoggingKey implements Xid {\n\tpublic static final int FORMAT_ID = 9257;\n\n\tprivate byte[] globalTransactionId = new byte[0];\n\tprivate byte[] branchQualifier = new byte[0];\n\n\tpublic int hashCode() {\n\t\tint hash = 11;\n\t\thash += 13 * this.getFormatId();\n\t\thash += 17 * Arrays.hashCode(branchQualifier);\n\t\thash += 19 * Arrays.hashCode(globalTransactionId);\n\t\treturn hash;\n\t}\n\n\tpublic boolean equals(Object obj) {\n\t\tif (obj == null) {\n\t\t\treturn false;\n\t\t} else if (VirtualLoggingKey.class.isInstance(obj) == false) {\n\t\t\treturn false;\n\t\t}\n\t\tVirtualLoggingKey that = (VirtualLoggingKey) obj;\n\t\tif (this.getFormatId() != that.getFormatId()) {\n\t\t\treturn false;\n\t\t} else if (Arrays.equals(branchQualifier, that.branchQualifier) == false) {\n\t\t\treturn false;\n\t\t} else if (Arrays.equals(globalTransactionId, that.globalTransactionId) == false) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic int getFormatId() {\n\t\treturn FORMAT_ID;\n\t}\n\n\tpublic byte[] getGlobalTransactionId() {\n\t\treturn globalTransactionId;\n\t}\n\n\tpublic void setGlobalTransactionId(byte[] globalTransactionId) {\n\t\tthis.globalTransactionId = globalTransactionId;\n\t}\n\n\tpublic byte[] getBranchQualifier() {\n\t\treturn branchQualifier;\n\t}\n\n\tpublic void setBranchQualifier(byte[] branchQualifier) {\n\t\tthis.branchQualifier = branchQualifier;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/store/VirtualLoggingListener.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging.store;\n\npublic interface VirtualLoggingListener {\n\n\tpublic void recvOperation(VirtualLoggingRecord action);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/store/VirtualLoggingRecord.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging.store;\n\nimport javax.transaction.xa.Xid;\n\npublic class VirtualLoggingRecord {\n\n\tprivate Xid identifier;\n\tprivate int operator;\n\tprivate byte[] value;\n\tprivate byte[] content;\n\n\tpublic int getOperator() {\n\t\treturn operator;\n\t}\n\n\tpublic void setOperator(int operator) {\n\t\tthis.operator = operator;\n\t}\n\n\tpublic Xid getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(Xid identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic byte[] getValue() {\n\t\treturn value;\n\t}\n\n\tpublic void setValue(byte[] value) {\n\t\tthis.value = value;\n\t}\n\n\tpublic byte[] getContent() {\n\t\treturn content;\n\t}\n\n\tpublic void setContent(byte[] content) {\n\t\tthis.content = content;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/store/VirtualLoggingSystem.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging.store;\n\nimport javax.transaction.xa.Xid;\n\npublic interface VirtualLoggingSystem {\n\tpublic static final int OPERATOR_CREATE = 1;\n\tpublic static final int OPERATOR_MOFIFY = 2;\n\tpublic static final int OPERATOR_DELETE = 3;\n\n\tpublic void create(Xid xid, byte[] byteArray);\n\n\tpublic void delete(Xid xid);\n\n\tpublic void modify(Xid xid, byte[] byteArray);\n\n\tpublic void traversal(VirtualLoggingListener listener);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/logging/store/VirtualLoggingTrigger.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.logging.store;\n\npublic interface VirtualLoggingTrigger {\n\n\tpublic void fireSwapImmediately();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/recovery/TransactionRecoveryCallback.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.recovery;\n\nimport org.bytesoft.transaction.archive.TransactionArchive;\n\npublic interface TransactionRecoveryCallback {\n\n\tpublic void recover(TransactionArchive archive);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/recovery/TransactionRecoveryListener.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.recovery;\n\nimport org.bytesoft.transaction.Transaction;\n\npublic interface TransactionRecoveryListener {\n\n\tpublic void onRecovery(Transaction transaction);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/remote/RemoteAddr.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.remote;\n\nimport java.io.Serializable;\n\nimport org.apache.commons.lang3.StringUtils;\n\npublic class RemoteAddr implements Serializable {\n\tprivate static final long serialVersionUID = 1L;\n\n\tprotected String serverHost;\n\tprotected int serverPort;\n\n\tpublic int hashCode() {\n\t\tint hash = 7;\n\t\thash += 11 * (this.serverHost == null ? 0 : this.serverHost.hashCode());\n\t\thash += 13 * this.serverPort;\n\t\treturn hash;\n\t}\n\n\tpublic boolean equals(Object obj) {\n\t\tif (obj == null) {\n\t\t\treturn false;\n\t\t} else if (RemoteAddr.class.isInstance(obj) == false) {\n\t\t\treturn false;\n\t\t}\n\t\tRemoteAddr that = (RemoteAddr) obj;\n\t\tboolean hostEquals = StringUtils.equals(this.serverHost, that.serverHost);\n\t\tboolean portEquals = this.serverPort == that.serverPort;\n\t\treturn hostEquals && portEquals;\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"<remote-addr| %s:%s>\", this.serverHost, this.serverPort);\n\t}\n\n\tpublic String getServerHost() {\n\t\treturn serverHost;\n\t}\n\n\tpublic void setServerHost(String serverHost) {\n\t\tthis.serverHost = serverHost;\n\t}\n\n\tpublic int getServerPort() {\n\t\treturn serverPort;\n\t}\n\n\tpublic void setServerPort(int serverPort) {\n\t\tthis.serverPort = serverPort;\n\t}\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/remote/RemoteCoordinator.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.transaction.remote;\r\n\r\nimport org.bytesoft.transaction.TransactionParticipant;\r\n\r\npublic interface RemoteCoordinator extends TransactionParticipant {\r\n\r\n\tpublic String getIdentifier();\r\n\r\n\tpublic RemoteAddr getRemoteAddr();\r\n\r\n\tpublic RemoteNode getRemoteNode();\r\n\r\n\tpublic String getApplication();\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/remote/RemoteNode.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.remote;\n\nimport org.apache.commons.lang3.StringUtils;\n\npublic class RemoteNode extends RemoteAddr {\n\tprivate static final long serialVersionUID = 1L;\n\n\tprotected String serviceKey;\n\n\tpublic int hashCode() {\n\t\tint hash = 7;\n\t\thash += 11 * (this.serverHost == null ? 0 : this.serverHost.hashCode());\n\t\thash += 13 * this.serverPort;\n\t\thash += 17 * (this.serviceKey == null ? 0 : this.serviceKey.hashCode());\n\t\treturn hash;\n\t}\n\n\tpublic boolean equals(Object obj) {\n\t\tif (obj == null) {\n\t\t\treturn false;\n\t\t} else if (RemoteNode.class.isInstance(obj) == false) {\n\t\t\treturn false;\n\t\t}\n\t\tRemoteNode that = (RemoteNode) obj;\n\t\tboolean hostEquals = StringUtils.equals(this.serverHost, that.serverHost);\n\t\tboolean portEquals = this.serverPort == that.serverPort;\n\t\tboolean servEquals = StringUtils.equals(this.serviceKey, that.serviceKey);\n\t\treturn hostEquals && portEquals && servEquals;\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"<remote-node| %s:%s:%s>\", this.serverHost, this.serviceKey, this.serverPort);\n\t}\n\n\tpublic String getServiceKey() {\n\t\treturn serviceKey;\n\t}\n\n\tpublic void setServiceKey(String serviceKey) {\n\t\tthis.serviceKey = serviceKey;\n\t}\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/remote/RemoteSvc.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.remote;\n\nimport org.apache.commons.lang3.StringUtils;\n\npublic class RemoteSvc extends RemoteAddr {\n\tprivate static final long serialVersionUID = 1L;\n\n\tprotected String serviceKey;\n\n\tpublic int hashCode() {\n\t\tint hash = 19;\n\t\thash += 23 * (this.serviceKey == null ? 0 : this.serviceKey.hashCode());\n\t\treturn hash;\n\t}\n\n\tpublic boolean equals(Object obj) {\n\t\tif (obj == null) {\n\t\t\treturn false;\n\t\t} else if (RemoteSvc.class.isInstance(obj) == false) {\n\t\t\treturn false;\n\t\t}\n\t\tRemoteSvc that = (RemoteSvc) obj;\n\t\treturn StringUtils.equals(this.serviceKey, that.serviceKey);\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"<remote-svc| serviceKey= %s>\", this.serviceKey);\n\t}\n\n\tpublic String getServiceKey() {\n\t\treturn serviceKey;\n\t}\n\n\tpublic void setServiceKey(String serviceKey) {\n\t\tthis.serviceKey = serviceKey;\n\t}\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/resource/XATerminator.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.resource;\n\nimport java.util.List;\n\nimport org.bytesoft.transaction.archive.XAResourceArchive;\n\npublic interface XATerminator extends javax.transaction.xa.XAResource {\n\n\tpublic List<XAResourceArchive> getResourceArchives();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionExtra.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic interface TransactionExtra {\n\n\tpublic TransactionXid getTransactionXid();\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionListener.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic interface TransactionListener {\n\n\tpublic void onPrepareStart(TransactionXid xid);\n\n\tpublic void onPrepareSuccess(TransactionXid xid);\n\n\tpublic void onPrepareFailure(TransactionXid xid);\n\n\tpublic void onCommitStart(TransactionXid xid);\n\n\tpublic void onCommitSuccess(TransactionXid xid);\n\n\tpublic void onCommitFailure(TransactionXid xid);\n\n\tpublic void onCommitHeuristicMixed(TransactionXid xid);\n\n\tpublic void onCommitHeuristicRolledback(TransactionXid xid);\n\n\tpublic void onRollbackStart(TransactionXid xid);\n\n\tpublic void onRollbackSuccess(TransactionXid xid);\n\n\tpublic void onRollbackFailure(TransactionXid xid);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionListenerAdapter.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport org.bytesoft.transaction.xa.TransactionXid;\n\npublic class TransactionListenerAdapter implements TransactionListener {\n\n\tpublic void onPrepareStart(TransactionXid xid) {\n\t}\n\n\tpublic void onPrepareSuccess(TransactionXid xid) {\n\t}\n\n\tpublic void onPrepareFailure(TransactionXid xid) {\n\t}\n\n\tpublic void onCommitStart(TransactionXid xid) {\n\t}\n\n\tpublic void onCommitSuccess(TransactionXid xid) {\n\t}\n\n\tpublic void onCommitFailure(TransactionXid xid) {\n\t}\n\n\tpublic void onCommitHeuristicMixed(TransactionXid xid) {\n\t}\n\n\tpublic void onCommitHeuristicRolledback(TransactionXid xid) {\n\t}\n\n\tpublic void onRollbackStart(TransactionXid xid) {\n\t}\n\n\tpublic void onRollbackSuccess(TransactionXid xid) {\n\t}\n\n\tpublic void onRollbackFailure(TransactionXid xid) {\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionResourceListener.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\npublic interface TransactionResourceListener {\n\n\tpublic void onEnlistResource(Xid xid, XAResource xares);\n\n\tpublic void onDelistResource(Xid xid, XAResource xares);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionResourceListenerAdapter.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\npublic class TransactionResourceListenerAdapter implements TransactionResourceListener {\n\n\tpublic void onEnlistResource(Xid xid, XAResource xares) {\n\t}\n\n\tpublic void onDelistResource(Xid xid, XAResource xares) {\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionStatistic.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport org.bytesoft.bytejta.TransactionImpl;\n\npublic interface TransactionStatistic {\n\tpublic static final long FLAGS_ACTIVE = 0x1;\n\tpublic static final long FLAGS_PREPARING = 0x2;\n\tpublic static final long FLAGS_PREPARED = 0x4;\n\tpublic static final long FLAGS_COMMITTING = 0x8;\n\tpublic static final long FLAGS_COMMITTED = 0x10;\n\tpublic static final long FLAGS_ROLLINGBACK = 0x20;\n\tpublic static final long FLAGS_ROLEDBACK = 0x40;\n\tpublic static final long FLAGS_ERROR = 0x80;\n\tpublic static final long FLAGS_ERROR_TOTAL = 0x100;\n\n\tpublic void fireBeginTransaction(TransactionImpl transaction);\n\n\tpublic void firePreparingTransaction(TransactionImpl transaction);\n\n\tpublic void firePreparedTransaction(TransactionImpl transaction);\n\n\tpublic void fireCommittingTransaction(TransactionImpl transaction);\n\n\tpublic void fireCommittedTransaction(TransactionImpl transaction);\n\n\tpublic void fireRollingBackTransaction(TransactionImpl transaction);\n\n\tpublic void fireRolledbackTransaction(TransactionImpl transaction);\n\n\tpublic void fireCompleteFailure(TransactionImpl transaction);\n\n\tpublic void fireCleanupTransaction(TransactionImpl transaction);\n\n\tpublic void fireRecoverTransaction(TransactionImpl transaction);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/TransactionTimer.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports;\n\nimport org.bytesoft.transaction.Transaction;\n\npublic interface TransactionTimer {\n\n\tpublic void timingExecution();\n\n\tpublic void stopTiming(Transaction tx);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/resource/XAResourceDescriptor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports.resource;\n\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\npublic interface XAResourceDescriptor extends XAResource {\n\n\tpublic void setIdentifier(String identifier);\n\n\tpublic String getIdentifier();\n\n\tpublic XAResource getDelegate();\n\n\tpublic void setTransactionTimeoutQuietly(int timeout);\n\n\tpublic boolean isTransactionCommitted(Xid xid) throws IllegalStateException;\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/rpc/TransactionInterceptor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports.rpc;\n\npublic interface TransactionInterceptor {\n\n\tpublic void beforeSendRequest(TransactionRequest request) throws IllegalStateException;\n\n\tpublic void beforeSendResponse(TransactionResponse response) throws IllegalStateException;\n\n\tpublic void afterReceiveRequest(TransactionRequest request) throws IllegalStateException;\n\n\tpublic void afterReceiveResponse(TransactionResponse response) throws IllegalStateException;\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/rpc/TransactionRequest.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports.rpc;\n\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\n\npublic interface TransactionRequest {\n\n\tpublic RemoteCoordinator getTargetTransactionCoordinator();\n\n\tpublic TransactionContext getTransactionContext();\n\n\tpublic void setTransactionContext(TransactionContext transactionContext);\n\n\tpublic Object getHeader(String name);\n\n\tpublic void setHeader(String name, Object value);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/rpc/TransactionResponse.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports.rpc;\n\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\n\npublic interface TransactionResponse {\n\n\tpublic boolean isParticipantStickyRequired();\n\n\tpublic boolean isParticipantRollbackOnly();\n\n\tpublic RemoteCoordinator getSourceTransactionCoordinator();\n\n\tpublic TransactionContext getTransactionContext();\n\n\tpublic void setTransactionContext(TransactionContext transactionContext);\n\n\tpublic Object getHeader(String name);\n\n\tpublic void setHeader(String name, Object value);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/supports/serialize/XAResourceDeserializer.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.supports.serialize;\n\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\n\npublic interface XAResourceDeserializer {\n\n\tpublic XAResourceDescriptor deserialize(String identifier);\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/work/SimpleWork.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.work;\n\nimport javax.resource.spi.work.Work;\nimport javax.resource.spi.work.WorkEvent;\nimport javax.resource.spi.work.WorkListener;\n\npublic class SimpleWork implements Runnable {\n\n\tprivate Object source;\n\tprivate Work work;\n\tprivate WorkListener workListener;\n\n\tpublic void run() {\n\t\tthis.workListener.workStarted(new WorkEvent(this.source, WorkEvent.WORK_STARTED, this.work, null));\n\t\tthis.work.run();\n\t\tthis.workListener.workCompleted(new WorkEvent(this.source, WorkEvent.WORK_COMPLETED, this.work, null));\n\t}\n\n\tpublic void setSource(Object source) {\n\t\tthis.source = source;\n\t}\n\n\tpublic void setWork(Work work) {\n\t\tthis.work = work;\n\t}\n\n\tpublic void setWorkListener(WorkListener workListener) {\n\t\tthis.workListener = workListener;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/work/SimpleWorkListener.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.work;\n\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport javax.resource.spi.work.WorkEvent;\nimport javax.resource.spi.work.WorkListener;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class SimpleWorkListener implements WorkListener {\n\tstatic final Logger logger = LoggerFactory.getLogger(SimpleWorkListener.class);\n\n\tprivate long acceptedTime = -1;\n\tprivate long startedTime = -1;\n\n\tprivate final WorkListener delegate;\n\tprivate final Lock lock = new ReentrantLock();\n\tprivate final Condition condition = this.lock.newCondition();\n\n\tpublic SimpleWorkListener(WorkListener workListener) {\n\t\tthis.delegate = workListener;\n\t}\n\n\tpublic long waitForStart() {\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\twhile (this.acceptedTime < 0 || this.startedTime < 0) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.condition.await();\n\t\t\t\t} catch (InterruptedException ex) {\n\t\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this.startedTime - this.acceptedTime;\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic void signalStarted() {\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\tthis.condition.signalAll();\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic void workAccepted(WorkEvent event) {\n\t\tif (this.delegate != null) {\n\t\t\tdelegate.workAccepted(event);\n\t\t}\n\t\tthis.acceptedTime = System.currentTimeMillis();\n\t}\n\n\tpublic void workCompleted(WorkEvent event) {\n\t\tif (this.delegate != null) {\n\t\t\tdelegate.workCompleted(event);\n\t\t}\n\t}\n\n\tpublic void workRejected(WorkEvent event) {\n\t\tif (this.delegate != null) {\n\t\t\tdelegate.workRejected(event);\n\t\t}\n\t}\n\n\tpublic void workStarted(WorkEvent event) {\n\t\tif (this.delegate != null) {\n\t\t\tdelegate.workStarted(event);\n\t\t}\n\t\tthis.startedTime = System.currentTimeMillis();\n\t\tthis.signalStarted();\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/work/SimpleWorkManager.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.work;\n\nimport java.util.concurrent.CancellationException;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.resource.spi.work.ExecutionContext;\nimport javax.resource.spi.work.Work;\nimport javax.resource.spi.work.WorkEvent;\nimport javax.resource.spi.work.WorkException;\nimport javax.resource.spi.work.WorkListener;\nimport javax.resource.spi.work.WorkManager;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class SimpleWorkManager implements WorkManager {\n\tstatic final Logger logger = LoggerFactory.getLogger(SimpleWorkManager.class);\n\n\tprivate final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,\n\t\t\tnew LinkedBlockingQueue<Runnable>());\n\t// private final ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(1);\n\n\tpublic void doWork(Work work) throws WorkException {\n\t\tthis.doWork(work, 1800 * 1000L, null, null);\n\t}\n\n\tpublic void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)\n\t\t\tthrows WorkException {\n\t\tSimpleWorkListener wrappedListener = new SimpleWorkListener(workListener);\n\t\twrappedListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));\n\t\tSimpleWork task = new SimpleWork();\n\t\ttask.setWork(work);\n\t\ttask.setWorkListener(wrappedListener);\n\t\tFuture<?> future = this.executor.submit(task);\n\t\ttry {\n\t\t\tfuture.get();\n\t\t} catch (CancellationException ex) {\n\t\t\twrappedListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, new WorkException(ex)));\n\t\t} catch (InterruptedException ex) {\n\t\t\twrappedListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, work, new WorkException(ex)));\n\t\t} catch (ExecutionException ex) {\n\t\t\twrappedListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, work, new WorkException(ex)));\n\t\t}\n\t}\n\n\tpublic long startWork(Work work) throws WorkException {\n\t\treturn this.startWork(work, 1800 * 1000L, null, null);\n\t}\n\n\tpublic long startWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)\n\t\t\tthrows WorkException {\n\t\tSimpleWorkListener wrappedListener = new SimpleWorkListener(workListener);\n\t\twrappedListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));\n\t\tSimpleWork task = new SimpleWork();\n\t\ttask.setSource(this);\n\t\ttask.setWork(work);\n\t\ttask.setWorkListener(wrappedListener);\n\t\tthis.executor.submit(task);\n\t\treturn wrappedListener.waitForStart();\n\t}\n\n\tpublic void scheduleWork(Work work) throws WorkException {\n\t\tthrow new WorkException(\"not supported yet!\");\n\t}\n\n\tpublic void scheduleWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)\n\t\t\tthrows WorkException {\n\t\t// SimpleWorkListener wrappedListener = new SimpleWorkListener(workListener);\n\t\t// wrappedListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));\n\t\t// SimpleWork task = new SimpleWork();\n\t\t// task.setSource(this);\n\t\t// task.setWork(work);\n\t\t// task.setWorkListener(wrappedListener);\n\t\t// // ScheduledFuture<?> future =\n\t\t// this.scheduled.scheduleAtFixedRate(task, 0, 1000, TimeUnit.MILLISECONDS);\n\t\tthrow new WorkException(\"not supported yet!\");\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/xa/TransactionXid.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.xa;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\n\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.common.utils.ByteUtils;\n\npublic class TransactionXid implements Xid, Cloneable, Serializable {\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate int formatId;\n\tprivate byte[] globalTransactionId;\n\tprivate byte[] branchQualifier;\n\n\tpublic TransactionXid() {\n\t}\n\n\tpublic TransactionXid(int formatId, byte[] global) {\n\t\tthis(formatId, global, new byte[0]);\n\t}\n\n\tpublic TransactionXid(int formatId, byte[] global, byte[] branch) {\n\t\tif (global == null) {\n\t\t\tthrow new IllegalArgumentException(\"globalTransactionId cannot be null.\");\n\t\t} else if (global.length > MAXGTRIDSIZE) {\n\t\t\tthrow new IllegalArgumentException(\"length of globalTransactionId cannot exceed 64 bytes.\");\n\t\t}\n\n\t\tif (branch == null) {\n\t\t\tthrow new IllegalArgumentException(\"branchQualifier cannot be null.\");\n\t\t} else if (branch.length > MAXBQUALSIZE) {\n\t\t\tthrow new IllegalArgumentException(\"length of branchQualifier cannot exceed 64 bytes.\");\n\t\t}\n\n\t\tthis.globalTransactionId = new byte[global.length];\n\t\tthis.branchQualifier = new byte[branch.length];\n\n\t\tSystem.arraycopy(global, 0, this.globalTransactionId, 0, global.length);\n\t\tSystem.arraycopy(branch, 0, this.branchQualifier, 0, branch.length);\n\n\t\tthis.formatId = formatId;\n\t\tthis.globalTransactionId = global;\n\t\tthis.branchQualifier = branch;\n\t}\n\n\tpublic TransactionXid clone() {\n\t\tTransactionXid that = new TransactionXid();\n\t\tthat.setFormatId(this.formatId);\n\t\tbyte[] global = new byte[this.globalTransactionId.length];\n\t\tbyte[] branch = new byte[this.branchQualifier.length];\n\n\t\tSystem.arraycopy(this.globalTransactionId, 0, global, 0, this.globalTransactionId.length);\n\t\tSystem.arraycopy(this.branchQualifier, 0, branch, 0, this.branchQualifier.length);\n\n\t\tthat.setGlobalTransactionId(global);\n\t\tthat.setBranchQualifier(branch);\n\n\t\treturn that;\n\t}\n\n\tpublic int getFormatId() {\n\t\treturn this.formatId;\n\t}\n\n\tpublic int hashCode() {\n\t\tint hash = 23;\n\t\thash += 29 * this.getFormatId();\n\t\thash += 31 * Arrays.hashCode(branchQualifier);\n\t\thash += 37 * Arrays.hashCode(globalTransactionId);\n\t\treturn hash;\n\t}\n\n\tpublic boolean equals(Object obj) {\n\t\tif (this == obj) {\n\t\t\treturn true;\n\t\t} else if (obj == null) {\n\t\t\treturn false;\n\t\t} else if (getClass() != obj.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tTransactionXid other = (TransactionXid) obj;\n\t\tif (this.formatId != other.formatId) {\n\t\t\treturn false;\n\t\t} else if (Arrays.equals(branchQualifier, other.branchQualifier) == false) {\n\t\t\treturn false;\n\t\t} else if (Arrays.equals(globalTransactionId, other.globalTransactionId) == false) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic String toString() {\n\t\tString global = this.globalTransactionId == null ? null : ByteUtils.byteArrayToString(this.globalTransactionId);\n\t\tString branch = this.branchQualifier == null ? null : ByteUtils.byteArrayToString(this.branchQualifier);\n\t\treturn String.format(\"%s-%s-%s\", this.getFormatId(), global, branch);\n\t}\n\n\tpublic byte[] getGlobalTransactionId() {\n\t\treturn globalTransactionId;\n\t}\n\n\tpublic void setGlobalTransactionId(byte[] globalTransactionId) {\n\t\tthis.globalTransactionId = globalTransactionId;\n\t}\n\n\tpublic byte[] getBranchQualifier() {\n\t\treturn branchQualifier;\n\t}\n\n\tpublic void setBranchQualifier(byte[] branchQualifier) {\n\t\tthis.branchQualifier = branchQualifier;\n\t}\n\n\tpublic void setFormatId(int formatId) {\n\t\tthis.formatId = formatId;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-core/src/main/java/org/bytesoft/transaction/xa/XidFactory.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.transaction.xa;\n\npublic interface XidFactory {\n\tpublic static final int JTA_FORMAT_ID = 1207;\n\tpublic static final int TCC_FORMAT_ID = 8127;\n\n\tpublic static final int GLOBAL_TRANSACTION_LENGTH = 16;\n\tpublic static final int BRANCH_QUALIFIER_LENGTH = 16;\n\n\tpublic TransactionXid createGlobalXid();\n\n\tpublic TransactionXid createGlobalXid(byte[] globalTransactionId);\n\n\tpublic TransactionXid createBranchXid(TransactionXid globalXid);\n\n\tpublic TransactionXid createBranchXid(TransactionXid globalXid, byte[] branchQualifier);\n}\n"
  },
  {
    "path": "bytejta-supports/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.bytesoft</groupId>\n\t\t<artifactId>bytejta-parent</artifactId>\n\t\t<version>0.5.0-BETA9</version>\n\t</parent>\n\n\t<artifactId>bytejta-supports</artifactId>\n\t<packaging>jar</packaging>\n\n\t<name>bytejta-supports</name>\n\t<description>The bytejta-supports project is the module of ByteJTA for integrating with third-party open source project.</description>\n\t<url>http://www.bytesoft.org</url>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t<artifactId>bytejta-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-tx</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-jdbc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-aop</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>aopalliance</groupId>\n\t\t\t<artifactId>aopalliance</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>cglib</groupId>\n\t\t\t<artifactId>cglib</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>asm</groupId>\n\t\t\t\t\t<artifactId>asm</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.ow2.asm</groupId>\n\t\t\t<artifactId>asm</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.aspectj</groupId>\n\t\t\t<artifactId>aspectjweaver</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t<artifactId>zookeeper</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.curator</groupId>\n\t\t\t<artifactId>curator-recipes</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-autoconfigure</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-dbcp2</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.hibernate</groupId>\n\t\t\t<artifactId>hibernate-core</artifactId>\n\t\t</dependency>\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/boot/jdbc/DataSourceCciBuilder.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.boot.jdbc;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Proxy;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.sql.DataSource;\nimport javax.sql.XADataSource;\n\nimport org.apache.commons.dbcp2.managed.BasicManagedDataSource;\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.resource.ManagedConnectionFactoryHandler;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.BeanNameAware;\nimport org.springframework.boot.context.properties.bind.Bindable;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertyName;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertySource;\nimport org.springframework.boot.context.properties.source.MapConfigurationPropertySource;\n\npublic class DataSourceCciBuilder<T extends DataSource> {\n\tstatic final Logger logger = LoggerFactory.getLogger(DataSourceCciBuilder.class);\n\n\tprivate XADataSource xaDataSourceInstance;\n\tprivate final Map<String, String> properties = new HashMap<String, String>();\n\n\tprivate DataSourceCciBuilder(XADataSource xaDataSourceInstance) {\n\t\tif (xaDataSourceInstance == null) {\n\t\t\tthrow new IllegalArgumentException(\"the xaDataSourceInstance cannot be null!\");\n\t\t}\n\t\tthis.xaDataSourceInstance = xaDataSourceInstance;\n\t}\n\n\t@SuppressWarnings(\"rawtypes\")\n\tpublic static DataSourceCciBuilder<?> create(XADataSource xaDataSourceInstance) {\n\t\treturn new DataSourceCciBuilder(xaDataSourceInstance);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic DataSource build() {\n\t\tthis.validateXADataSourceInstance();\n\n\t\tBasicManagedDataSource dataSource = BeanUtils.instantiateClass(BasicManagedDataSource.class);\n\t\tthis.bind(dataSource);\n\n\t\tdataSource.setXaDataSourceInstance(this.xaDataSourceInstance);\n\n\t\treturn (T) dataSource;\n\t}\n\n\tprivate void validateXADataSourceInstance() {\n\t\tInvocationHandler handler = Proxy.isProxyClass(this.xaDataSourceInstance.getClass())\n\t\t\t\t? Proxy.getInvocationHandler(this.xaDataSourceInstance) : null;\n\t\tManagedConnectionFactoryHandler mcfh = //\n\t\t\t\t(handler == null || ManagedConnectionFactoryHandler.class.isInstance(handler) == false) ? null\n\t\t\t\t\t\t: (ManagedConnectionFactoryHandler) handler;\n\t\tif (BeanNameAware.class.isInstance(this.xaDataSourceInstance) == false\n\t\t\t\t&& (mcfh == null || StringUtils.isBlank(mcfh.getIdentifier()))) {\n\t\t\tthrow new IllegalStateException(\"XADataSource is not properly configured!\");\n\t\t}\n\t}\n\n\tprivate void bind(DataSource dataSource) {\n\t\tConfigurationPropertySource source = new MapConfigurationPropertySource(this.properties);\n\t\tConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();\n\t\tBinder binder = new Binder(source.withAliases(aliases));\n\t\tbinder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(dataSource));\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/boot/jdbc/DataSourceSpiBuilder.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.boot.jdbc;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.sql.XADataSource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.boot.context.properties.bind.Bindable;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertyName;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertySource;\nimport org.springframework.boot.context.properties.source.MapConfigurationPropertySource;\nimport org.springframework.util.ClassUtils;\n\npublic class DataSourceSpiBuilder<T extends XADataSource> {\n\tprivate static final String[] XA_DATA_SOURCE_TYPE_NAMES = new String[] { \"com.mysql.jdbc.jdbc2.optional.MysqlXADataSource\",\n\t\t\t\"org.postgresql.xa.PGXADataSource\", \"oracle.jdbc.xa.client.OracleXADataSource\" };\n\tstatic final Logger logger = LoggerFactory.getLogger(DataSourceSpiBuilder.class);\n\n\tprivate Class<? extends XADataSource> type;\n\tprivate final Map<String, String> properties = new HashMap<String, String>();\n\tprivate ClassLoader classLoader;\n\n\tprivate DataSourceSpiBuilder(ClassLoader classLoader) {\n\t\tthis.classLoader = classLoader;\n\t}\n\n\t@SuppressWarnings(\"rawtypes\")\n\tpublic static DataSourceSpiBuilder<?> create() {\n\t\treturn new DataSourceSpiBuilder(null);\n\t}\n\n\t@SuppressWarnings(\"rawtypes\")\n\tpublic static DataSourceSpiBuilder<?> create(ClassLoader classLoader) {\n\t\treturn new DataSourceSpiBuilder(classLoader);\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tpublic XADataSource build() {\n\t\tClass<? extends XADataSource> type = this.getType();\n\t\tXADataSource xaDataSourceInstance = BeanUtils.instantiate(type);\n\t\tthis.bind(xaDataSourceInstance);\n\t\treturn xaDataSourceInstance;\n\t}\n\n\tprivate void bind(XADataSource result) {\n\t\tConfigurationPropertySource source = new MapConfigurationPropertySource(this.properties);\n\t\tConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();\n\t\taliases.addAliases(\"url\", \"jdbc-url\");\n\t\taliases.addAliases(\"username\", \"user\");\n\t\tBinder binder = new Binder(source.withAliases(aliases));\n\t\tbinder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(result));\n\t}\n\n\tpublic DataSourceSpiBuilder<?> type(Class<? extends XADataSource> type) {\n\t\tthis.type = type;\n\t\treturn this;\n\t}\n\n\tpublic DataSourceSpiBuilder<?> url(String url) {\n\t\tthis.properties.put(\"url\", url);\n\t\treturn this;\n\t}\n\n\tpublic DataSourceSpiBuilder<?> username(String username) {\n\t\tthis.properties.put(\"username\", username);\n\t\treturn this;\n\t}\n\n\tpublic DataSourceSpiBuilder<?> password(String password) {\n\t\tthis.properties.put(\"password\", password);\n\t\treturn this;\n\t}\n\n\tprivate Class<? extends XADataSource> getType() {\n\t\tClass<? extends XADataSource> type = (this.type != null) ? this.type : findType(this.classLoader);\n\t\tif (type != null) {\n\t\t\treturn type;\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\"No supported XADataSource type found\");\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static Class<? extends XADataSource> findType(ClassLoader classLoader) {\n\t\tfor (String name : XA_DATA_SOURCE_TYPE_NAMES) {\n\t\t\ttry {\n\t\t\t\treturn (Class<? extends XADataSource>) ClassUtils.forName(name, classLoader);\n\t\t\t} catch (Exception error) {\n\t\t\t\tlogger.debug(\"Error occurred while loading class: {}!\", name, error);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/internal/RemoteCoordinatorRegistry.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.bytejta.supports.internal;\r\n\r\nimport java.util.Arrays;\r\nimport java.util.Map;\r\nimport java.util.concurrent.ConcurrentHashMap;\r\n\r\nimport org.apache.commons.lang3.StringUtils;\r\nimport org.bytesoft.common.utils.CommonUtils;\r\nimport org.bytesoft.transaction.remote.RemoteAddr;\r\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\r\nimport org.bytesoft.transaction.remote.RemoteNode;\r\n\r\npublic class RemoteCoordinatorRegistry {\r\n\tstatic final RemoteCoordinatorRegistry instance = new RemoteCoordinatorRegistry();\r\n\r\n\t/* host:port -> participant(url= host: port) */\r\n\tprivate final Map<RemoteAddr, RemoteCoordinator> physicalMap = new ConcurrentHashMap<RemoteAddr, RemoteCoordinator>();\r\n\t/* host:port -> host:application:port */\r\n\tprivate final Map<RemoteAddr, RemoteNode> mappings = new ConcurrentHashMap<RemoteAddr, RemoteNode>();\r\n\t/* application -> participant */\r\n\tprivate final Map<String, RemoteCoordinator> clusterMap = new ConcurrentHashMap<String, RemoteCoordinator>();\r\n\r\n\t/* invocation -> host:application:port */\r\n\tprivate final Map<InvocationDef, RemoteNode> invocationMap = new ConcurrentHashMap<InvocationDef, RemoteNode>();\r\n\r\n\tpublic void putInvocationDef(InvocationDef invocationDef, RemoteNode remoteNode) {\r\n\t\tthis.invocationMap.put(invocationDef, remoteNode);\r\n\t}\r\n\r\n\tpublic RemoteNode getRemoteNodeByInvocationDef(InvocationDef invocationDef) {\r\n\t\treturn this.invocationMap.get(invocationDef);\r\n\t}\r\n\r\n\tpublic boolean containsInvocationDef(InvocationDef invocationDef) {\r\n\t\treturn this.invocationMap.containsKey(invocationDef);\r\n\t}\r\n\r\n\tpublic void removetInvocationDef(InvocationDef invocationDef) {\r\n\t\tthis.invocationMap.remove(invocationDef);\r\n\t}\r\n\r\n\tpublic void putPhysicalInstance(RemoteAddr remoteAddr, RemoteCoordinator participant) {\r\n\t\tthis.physicalMap.put(remoteAddr, participant);\r\n\t}\r\n\r\n\tpublic RemoteCoordinator getPhysicalInstance(RemoteAddr remoteAddr) {\r\n\t\treturn this.physicalMap.get(remoteAddr);\r\n\t}\r\n\r\n\tpublic boolean containsPhysicalInstance(RemoteAddr remoteAddr) {\r\n\t\treturn this.physicalMap.containsKey(remoteAddr);\r\n\t}\r\n\r\n\tpublic void removePhysicalInstance(RemoteAddr remoteAddr) {\r\n\t\tthis.physicalMap.remove(remoteAddr);\r\n\t}\r\n\r\n\tpublic void putRemoteNode(RemoteAddr remoteAddr, RemoteNode remoteNode) {\r\n\t\tthis.mappings.put(remoteAddr, remoteNode);\r\n\t}\r\n\r\n\tpublic RemoteNode getRemoteNode(RemoteAddr remoteAddr) {\r\n\t\treturn this.mappings.get(remoteAddr);\r\n\t}\r\n\r\n\tpublic boolean containsRemoteNode(RemoteAddr remoteAddr) {\r\n\t\treturn this.mappings.containsKey(remoteAddr);\r\n\t}\r\n\r\n\tpublic void removeRemoteNode(RemoteAddr remoteAddr) {\r\n\t\tthis.mappings.remove(remoteAddr);\r\n\t}\r\n\r\n\tpublic void putParticipant(String application, RemoteCoordinator participant) {\r\n\t\tthis.clusterMap.put(application, participant);\r\n\t}\r\n\r\n\tpublic boolean containsParticipant(String application) {\r\n\t\treturn this.clusterMap.containsKey(application);\r\n\t}\r\n\r\n\tpublic RemoteCoordinator getParticipant(String application) {\r\n\t\treturn this.clusterMap.get(application);\r\n\t}\r\n\r\n\tpublic void removeParticipant(String application) {\r\n\t\tthis.clusterMap.remove(application);\r\n\t}\r\n\r\n\tprivate RemoteCoordinatorRegistry() {\r\n\t\tif (instance != null) {\r\n\t\t\tthrow new IllegalStateException();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic static RemoteCoordinatorRegistry getInstance() {\r\n\t\treturn instance;\r\n\t}\r\n\r\n\tpublic static class InvocationDef {\r\n\t\tprivate Class<?> interfaceClass;\r\n\t\tprivate String methodName;\r\n\t\tprivate Class<?>[] parameterTypes;\r\n\r\n\t\tpublic int hashCode() {\r\n\t\t\tint hash = 3;\r\n\t\t\thash += 5 * this.interfaceClass.hashCode();\r\n\t\t\thash += 7 * this.methodName.hashCode();\r\n\t\t\thash += 11 * Arrays.hashCode(this.parameterTypes);\r\n\t\t\treturn hash;\r\n\t\t}\r\n\r\n\t\tpublic boolean equals(Object obj) {\r\n\t\t\tif (obj == null) {\r\n\t\t\t\treturn false;\r\n\t\t\t} else if (InvocationDef.class.isInstance(obj) == false) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tInvocationDef that = (InvocationDef) obj;\r\n\t\t\tboolean clazzEquals = CommonUtils.equals(this.interfaceClass, that.interfaceClass);\r\n\t\t\tboolean methodEquals = StringUtils.equals(this.methodName, that.methodName);\r\n\t\t\tboolean typesEquals = Arrays.equals(this.parameterTypes, that.parameterTypes);\r\n\t\t\treturn clazzEquals && methodEquals && typesEquals;\r\n\t\t}\r\n\r\n\t\tpublic Class<?> getInterfaceClass() {\r\n\t\t\treturn interfaceClass;\r\n\t\t}\r\n\r\n\t\tpublic void setInterfaceClass(Class<?> interfaceClass) {\r\n\t\t\tthis.interfaceClass = interfaceClass;\r\n\t\t}\r\n\r\n\t\tpublic String getMethodName() {\r\n\t\t\treturn methodName;\r\n\t\t}\r\n\r\n\t\tpublic void setMethodName(String methodName) {\r\n\t\t\tthis.methodName = methodName;\r\n\t\t}\r\n\r\n\t\tpublic Class<?>[] getParameterTypes() {\r\n\t\t\treturn parameterTypes;\r\n\t\t}\r\n\r\n\t\tpublic void setParameterTypes(Class<?>[] parameterTypes) {\r\n\t\t\tthis.parameterTypes = parameterTypes;\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/internal/TransactionCommandDispatcher.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.internal;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport javax.resource.spi.work.Work;\nimport javax.resource.spi.work.WorkManager;\n\nimport org.apache.curator.framework.CuratorFramework;\nimport org.apache.curator.framework.recipes.leader.LeaderSelector;\nimport org.apache.curator.framework.recipes.leader.LeaderSelectorListener;\nimport org.apache.curator.framework.state.ConnectionState;\nimport org.apache.zookeeper.CreateMode;\nimport org.apache.zookeeper.KeeperException.NodeExistsException;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.bytesoft.transaction.cmd.CommandDispatcher;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.SmartInitializingSingleton;\n\npublic class TransactionCommandDispatcher\n\t\timplements SmartInitializingSingleton, TransactionEndpointAware, LeaderSelectorListener, CommandDispatcher {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionCommandDispatcher.class);\n\n\t@javax.annotation.Resource\n\tprivate CuratorFramework curatorFramework;\n\n\tprivate Lock stateLock = new ReentrantLock();\n\tprivate Condition stateCondition = this.stateLock.newCondition();\n\tprivate volatile Boolean stateDisallowed;\n\tprivate volatile boolean permsDisallowed;\n\n\tprivate String endpoint;\n\n\tprivate LeaderSelector leadSelector;\n\n\t@javax.annotation.Resource\n\tprivate WorkManager workManager;\n\n\tprivate String workDirectory = \"/org/bytesoft/bytejta\";\n\n\tpublic void dispatch(Runnable runnable) throws Exception {\n\t\tif (this.hasLeadership() == false) {\n\t\t\tthrow new SecurityException(\"Current node is not the master!\");\n\t\t}\n\n\t\tthis.checkExecutionPermission();\n\n\t\tWorkImpl work = new WorkImpl(runnable);\n\t\tthis.workManager.startWork(work);\n\t}\n\n\tpublic Object dispatch(Callable<Object> callable) throws Exception {\n\t\tif (this.hasLeadership() == false) {\n\t\t\tthrow new SecurityException(\"Current node is not the master!\");\n\t\t}\n\n\t\tthis.checkExecutionPermission();\n\n\t\tWorkImpl work = new WorkImpl(callable);\n\t\tthis.workManager.startWork(work);\n\t\treturn work.waitForResultIfNecessary();\n\t}\n\n\tprivate void checkExecutionPermission() {\n\t\tif (this.stateDisallowed != null && this.stateDisallowed) {\n\t\t\tthrow new SecurityException(\"Current state is no longer connected!\");\n\t\t} else if (this.permsDisallowed) {\n\t\t\tthrow new SecurityException(\"Current node is no longer the master!\");\n\t\t}\n\t}\n\n\tpublic void takeLeadership(CuratorFramework client) throws Exception {\n\t\ttry {\n\t\t\tthis.stateLock.lock();\n\t\t\tthis.permsDisallowed = false;\n\t\t\tif (this.stateDisallowed != null && this.stateDisallowed) {\n\t\t\t\tlogger.warn(\"Wrong state! Re-elect the master node.\");\n\t\t\t} else {\n\t\t\t\tthis.stateCondition.awaitUninterruptibly();\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.permsDisallowed = true;\n\t\t\tthis.stateLock.unlock();\n\t\t}\n\t}\n\n\tpublic boolean hasLeadership() {\n\t\tif (this.leadSelector == null) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn this.leadSelector.hasLeadership();\n\t\t}\n\t}\n\n\tpublic void stateChanged(CuratorFramework client, ConnectionState newState) {\n\t\ttry {\n\t\t\tthis.stateLock.lock();\n\t\t\tthis.stateDisallowed = ConnectionState.CONNECTED.equals(newState) == false\n\t\t\t\t\t&& ConnectionState.RECONNECTED.equals(newState) == false;\n\n\t\t\tif (this.stateDisallowed) {\n\t\t\t\tthis.stateCondition.signalAll();\n\t\t\t} // end-if (this.stateDisallowed)\n\t\t} finally {\n\t\t\tthis.stateLock.unlock();\n\t\t}\n\t}\n\n\tpublic void afterSingletonsInstantiated() {\n\t\tString basePath = String.format(\"%s/%s\", this.workDirectory, this.getApplication());\n\t\ttry {\n\t\t\tthis.createPersistentPathIfNecessary(basePath);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new IllegalStateException(ex);\n\t\t}\n\n\t\tString masterPath = String.format(\"%s/master\", basePath);\n\t\tthis.leadSelector = new LeaderSelector(this.curatorFramework, masterPath, this);\n\t\tthis.leadSelector.autoRequeue();\n\t\tthis.leadSelector.start();\n\t}\n\n\tprivate void createPersistentPathIfNecessary(String path) throws Exception {\n\t\ttry {\n\t\t\tthis.curatorFramework.create() //\n\t\t\t\t\t.creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path);\n\t\t} catch (NodeExistsException nex) {\n\t\t\tlogger.debug(\"Path exists(path= {})!\", path);\n\t\t}\n\t}\n\n\tpublic String getWorkDirectory() {\n\t\treturn workDirectory;\n\t}\n\n\tpublic void setWorkDirectory(String workDirectory) {\n\t\tthis.workDirectory = workDirectory;\n\t}\n\n\tclass WorkImpl implements Work {\n\t\tprivate final Lock lock = new ReentrantLock();\n\t\tprivate final Condition condition = this.lock.newCondition();\n\t\tprivate final Callable<Object> callable;\n\t\tprivate final Runnable runnable;\n\t\tprivate Object result;\n\t\tprivate Boolean error;\n\n\t\tpublic WorkImpl(Callable<Object> callable) {\n\t\t\tthis.runnable = null;\n\t\t\tthis.callable = callable;\n\t\t}\n\n\t\tpublic WorkImpl(Runnable runnable) {\n\t\t\tthis.callable = null;\n\t\t\tthis.runnable = runnable;\n\t\t}\n\n\t\tpublic Object waitForResultIfNecessary() throws Exception {\n\t\t\tif (this.callable == null) {\n\t\t\t\treturn null;\n\t\t\t} else {\n\t\t\t\treturn this.waitForResult();\n\t\t\t}\n\t\t}\n\n\t\tpublic Object waitForResult() throws Exception {\n\t\t\ttry {\n\t\t\t\tthis.lock.lock();\n\t\t\t\tif (this.error == null) {\n\t\t\t\t\tthis.condition.awaitUninterruptibly();\n\t\t\t\t}\n\n\t\t\t\tif (this.error == false) {\n\t\t\t\t\treturn this.result;\n\t\t\t\t} else if (Exception.class.isInstance(this.result)) {\n\t\t\t\t\tthrow (Exception) this.result;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new RuntimeException((Throwable) this.result);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tthis.lock.unlock();\n\t\t\t}\n\t\t}\n\n\t\tpublic void run() {\n\t\t\tif (this.callable != null) {\n\t\t\t\tthis.executeCallable();\n\t\t\t} else if (this.runnable != null) {\n\t\t\t\tthis.executeRunnable();\n\t\t\t}\n\t\t}\n\n\t\tprivate void executeCallable() {\n\t\t\ttry {\n\t\t\t\tthis.lock.lock();\n\t\t\t\tcheckExecutionPermission();\n\t\t\t\tthis.result = this.callable.call();\n\t\t\t\tthis.error = false;\n\t\t\t\tthis.condition.signalAll();\n\t\t\t} catch (Exception error) {\n\t\t\t\tthis.result = error;\n\t\t\t\tthis.error = true;\n\t\t\t\tthis.condition.signalAll();\n\t\t\t} finally {\n\t\t\t\tthis.lock.unlock();\n\t\t\t}\n\t\t}\n\n\t\tprivate void executeRunnable() {\n\t\t\ttry {\n\t\t\t\tthis.runnable.run();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.error(\"Error occurred while executing task(task= {}).\", this.runnable);\n\t\t\t}\n\t\t}\n\n\t\tpublic void release() {\n\t\t}\n\n\t\tpublic Object getResult() {\n\t\t\treturn result;\n\t\t}\n\n\t\tpublic void setResult(Object result) {\n\t\t\tthis.result = result;\n\t\t}\n\n\t\tpublic Boolean getError() {\n\t\t\treturn error;\n\t\t}\n\n\t\tpublic void setError(Boolean error) {\n\t\t\tthis.error = error;\n\t\t}\n\n\t}\n\n\tpublic CuratorFramework getCuratorFramework() {\n\t\treturn curatorFramework;\n\t}\n\n\tpublic void setCuratorFramework(CuratorFramework curatorFramework) {\n\t\tthis.curatorFramework = curatorFramework;\n\t}\n\n\tprivate String getApplication() {\n\t\treturn CommonUtils.getApplication(this.endpoint);\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn this.endpoint;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.endpoint = identifier;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/jdbc/LocalXADataSource.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jdbc;\n\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.logging.Logger;\n\nimport javax.sql.DataSource;\nimport javax.sql.XADataSource;\nimport javax.transaction.RollbackException;\nimport javax.transaction.SystemException;\nimport javax.transaction.TransactionManager;\n\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.springframework.beans.factory.BeanNameAware;\n\npublic class LocalXADataSource /* extends TransactionListenerAdapter */\n\t\timplements XADataSource, DataSource, DataSourceHolder, BeanNameAware {\n\tprivate PrintWriter logWriter;\n\tprivate int loginTimeout;\n\n\tprivate DataSource dataSource;\n\tprivate String beanName;\n\t@javax.annotation.Resource\n\tprivate TransactionManager transactionManager;\n\n\tpublic Connection getConnection() throws SQLException {\n\t\ttry {\n\t\t\tTransaction transaction = (Transaction) this.transactionManager.getTransaction();\n\t\t\tif (transaction == null) {\n\t\t\t\treturn this.dataSource.getConnection();\n\t\t\t}\n\n\t\t\tXAResourceDescriptor descriptor = transaction.getResourceDescriptor(this.beanName);\n\t\t\tLocalXAResource resource = descriptor == null ? null : (LocalXAResource) descriptor.getDelegate();\n\t\t\tLocalXAConnection xacon = resource == null ? null : resource.getManagedConnection();\n\n\t\t\tif (xacon != null) {\n\t\t\t\treturn xacon.getConnection();\n\t\t\t}\n\n\t\t\tTransaction transactionExtra = (Transaction) transaction.getTransactionalExtra();\n\n\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\tTransactionContext extraContext = transactionExtra != null ? transactionExtra.getTransactionContext() : null;\n\n\t\t\tboolean transactionCompatibleLoggingLRO = LocalXACompatible.class.isInstance(transactionContext) //\n\t\t\t\t\t? ((LocalXACompatible) transactionContext).compatibleLoggingLRO() : false;\n\t\t\tboolean extraCompatibleLoggingLRO = extraContext != null && LocalXACompatible.class.isInstance(extraContext) //\n\t\t\t\t\t? ((LocalXACompatible) extraContext).compatibleLoggingLRO() : false;\n\n\t\t\tboolean loggingRequired = transactionCompatibleLoggingLRO || extraCompatibleLoggingLRO;\n\n\t\t\txacon = this.getXAConnection();\n\t\t\tLogicalConnection connection = xacon.getConnection();\n\t\t\tdescriptor = xacon.getXAResource(loggingRequired);\n\t\t\ttransaction.enlistResource(descriptor);\n\n\t\t\treturn connection;\n\t\t} catch (SystemException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t} catch (RollbackException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t} catch (RuntimeException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t}\n\n\t}\n\n\tpublic Connection getConnection(String username, String password) throws SQLException {\n\t\ttry {\n\t\t\tTransaction transaction = (Transaction) this.transactionManager.getTransaction();\n\t\t\tif (transaction == null) {\n\t\t\t\treturn this.dataSource.getConnection(username, password);\n\t\t\t}\n\n\t\t\tXAResourceDescriptor descriptor = transaction.getResourceDescriptor(this.beanName);\n\t\t\tLocalXAResource resource = descriptor == null ? null : (LocalXAResource) descriptor.getDelegate();\n\t\t\tLocalXAConnection xacon = resource == null ? null : resource.getManagedConnection();\n\n\t\t\tif (xacon != null) {\n\t\t\t\treturn xacon.getConnection();\n\t\t\t}\n\n\t\t\tTransaction transactionExtra = (Transaction) transaction.getTransactionalExtra();\n\n\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\tTransactionContext extraContext = transactionExtra != null ? transactionExtra.getTransactionContext() : null;\n\n\t\t\tboolean transactionCompatibleLoggingLRO = LocalXACompatible.class.isInstance(transactionContext) //\n\t\t\t\t\t? ((LocalXACompatible) transactionContext).compatibleLoggingLRO() : false;\n\t\t\tboolean extraCompatibleLoggingLRO = extraContext != null && LocalXACompatible.class.isInstance(extraContext) //\n\t\t\t\t\t? ((LocalXACompatible) extraContext).compatibleLoggingLRO() : false;\n\n\t\t\tboolean loggingRequired = transactionCompatibleLoggingLRO || extraCompatibleLoggingLRO;\n\n\t\t\txacon = this.getXAConnection(username, password);\n\t\t\tLogicalConnection connection = xacon.getConnection();\n\t\t\tdescriptor = xacon.getXAResource(loggingRequired);\n\t\t\ttransaction.enlistResource(descriptor);\n\n\t\t\treturn connection;\n\t\t} catch (SystemException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t} catch (RollbackException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t} catch (RuntimeException ex) {\n\t\t\tthrow new SQLException(ex);\n\t\t}\n\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) {\n\t\tif (iface == null) {\n\t\t\treturn false;\n\t\t} else if (iface.isInstance(this)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic <T> T unwrap(Class<T> iface) {\n\t\tif (iface == null) {\n\t\t\treturn null;\n\t\t} else if (iface.isInstance(this)) {\n\t\t\treturn (T) this;\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic LocalXAConnection getXAConnection() throws SQLException {\n\t\tConnection connection = this.dataSource.getConnection();\n\t\tLocalXAConnection xacon = new LocalXAConnection(connection);\n\t\txacon.setResourceId(this.beanName);\n\t\treturn xacon;\n\t}\n\n\tpublic LocalXAConnection getXAConnection(String user, String passwd) throws SQLException {\n\t\tConnection connection = this.dataSource.getConnection(user, passwd);\n\t\tLocalXAConnection xacon = new LocalXAConnection(connection);\n\t\txacon.setResourceId(this.beanName);\n\t\treturn xacon;\n\t}\n\n\tpublic Logger getParentLogger() throws SQLFeatureNotSupportedException {\n\t\tthrow new SQLFeatureNotSupportedException();\n\t}\n\n\tpublic void setBeanName(String name) {\n\t\tthis.beanName = name;\n\t}\n\n\tpublic PrintWriter getLogWriter() {\n\t\treturn logWriter;\n\t}\n\n\tpublic void setLogWriter(PrintWriter logWriter) {\n\t\tthis.logWriter = logWriter;\n\t}\n\n\tpublic int getLoginTimeout() {\n\t\treturn loginTimeout;\n\t}\n\n\tpublic void setLoginTimeout(int loginTimeout) {\n\t\tthis.loginTimeout = loginTimeout;\n\t}\n\n\tpublic DataSource getDataSource() {\n\t\treturn dataSource;\n\t}\n\n\tpublic void setDataSource(DataSource dataSource) {\n\t\tif (LocalXADataSource.class.isInstance(dataSource)) {\n\t\t\tLocalXADataSource that = (LocalXADataSource) dataSource;\n\t\t\tthis.dataSource = that.dataSource;\n\t\t} else {\n\t\t\tthis.dataSource = dataSource;\n\t\t}\n\t}\n\n\tpublic TransactionManager getTransactionManager() {\n\t\treturn transactionManager;\n\t}\n\n\tpublic void setTransactionManager(TransactionManager transactionManager) {\n\t\tthis.transactionManager = transactionManager;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/jpa/hibernate/HibernateJtaPlatform.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.jpa.hibernate;\n\nimport org.bytesoft.bytejta.TransactionBeanFactoryImpl;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;\n\npublic class HibernateJtaPlatform extends AbstractJtaPlatform {\n\tprivate static final long serialVersionUID = 1L;\n\n\tprotected javax.transaction.TransactionManager locateTransactionManager() {\n\t\tTransactionBeanFactory beanFactory = TransactionBeanFactoryImpl.getInstance();\n\t\treturn beanFactory == null ? null : beanFactory.getTransactionManager();\n\t}\n\n\tprotected javax.transaction.UserTransaction locateUserTransaction() {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/ManagedConnectionFactoryHandler.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\n\nimport javax.jms.XAConnectionFactory;\nimport javax.resource.spi.ManagedConnection;\nimport javax.resource.spi.ManagedConnectionFactory;\nimport javax.sql.XADataSource;\n\npublic class ManagedConnectionFactoryHandler implements InvocationHandler {\n\n\tprivate final Object delegate;\n\tprivate String identifier;\n\n\tpublic ManagedConnectionFactoryHandler(Object xads) {\n\t\tthis.delegate = xads;\n\t}\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tClass<?> declaringClass = method.getDeclaringClass();\n\t\tClass<?> returningClass = method.getReturnType();\n\n\t\tObject resultObject = null;\n\t\ttry {\n\t\t\tresultObject = method.invoke(this.delegate, args);\n\t\t} catch (InvocationTargetException ex) {\n\t\t\tthrow ex.getTargetException();\n\t\t} catch (IllegalAccessException ex) {\n\t\t\tthrow new RuntimeException(ex);\n\t\t}\n\n\t\tClass<?> clazz = resultObject.getClass();\n\t\tClassLoader cl = clazz.getClassLoader();\n\n\t\tboolean containsReturningClass = false;\n\t\tClass<?>[] interfaces = clazz.getInterfaces();\n\t\tfor (int i = 0; i < interfaces.length; i++) {\n\t\t\tClass<?> interfaceClass = interfaces[i];\n\t\t\tif (interfaceClass.equals(returningClass)) {\n\t\t\t\tcontainsReturningClass = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} // end-for (int i = 0; i < interfaces.length; i++)\n\n\t\tif (XADataSource.class.equals(declaringClass) && javax.sql.XAConnection.class.equals(returningClass)) {\n\t\t\tManagedConnectionHandler interceptor = new ManagedConnectionHandler(resultObject);\n\t\t\tinterceptor.setIdentifier(this.identifier);\n\n\t\t\tObject finalObject = null;\n\t\t\tif (containsReturningClass) {\n\t\t\t\tfinalObject = Proxy.newProxyInstance(cl, interfaces, interceptor);\n\t\t\t} else {\n\t\t\t\tClass<?>[] interfaceArray = new Class<?>[interfaces.length + 1];\n\t\t\t\tSystem.arraycopy(interfaces, 0, interfaceArray, 0, interfaces.length);\n\t\t\t\tinterfaceArray[interfaces.length] = javax.sql.XAConnection.class;\n\t\t\t\tfinalObject = Proxy.newProxyInstance(cl, interfaceArray, interceptor);\n\t\t\t}\n\t\t\treturn (javax.sql.XAConnection) finalObject;\n\t\t} else if (XAConnectionFactory.class.equals(declaringClass) && javax.jms.XAConnection.class.equals(returningClass)) {\n\t\t\tManagedConnectionHandler interceptor = new ManagedConnectionHandler(resultObject);\n\t\t\tinterceptor.setIdentifier(this.identifier);\n\n\t\t\tObject finalObject = null;\n\t\t\tif (containsReturningClass) {\n\t\t\t\tfinalObject = Proxy.newProxyInstance(cl, interfaces, interceptor);\n\t\t\t} else {\n\t\t\t\tClass<?>[] interfaceArray = new Class<?>[interfaces.length + 1];\n\t\t\t\tSystem.arraycopy(interfaces, 0, interfaceArray, 0, interfaces.length);\n\t\t\t\tinterfaceArray[interfaces.length] = javax.jms.XAConnection.class;\n\t\t\t\tfinalObject = Proxy.newProxyInstance(cl, interfaceArray, interceptor);\n\t\t\t}\n\t\t\treturn (javax.jms.XAConnection) finalObject;\n\t\t} else if (ManagedConnectionFactory.class.equals(declaringClass) && ManagedConnection.class.equals(returningClass)) {\n\t\t\tManagedConnectionHandler interceptor = new ManagedConnectionHandler(resultObject);\n\t\t\tinterceptor.setIdentifier(this.identifier);\n\n\t\t\tObject finalObject = null;\n\t\t\tif (containsReturningClass) {\n\t\t\t\tfinalObject = Proxy.newProxyInstance(cl, interfaces, interceptor);\n\t\t\t} else {\n\t\t\t\tClass<?>[] interfaceArray = new Class<?>[interfaces.length + 1];\n\t\t\t\tSystem.arraycopy(interfaces, 0, interfaceArray, 0, interfaces.length);\n\t\t\t\tinterfaceArray[interfaces.length] = ManagedConnection.class;\n\t\t\t\tfinalObject = Proxy.newProxyInstance(cl, interfaceArray, interceptor);\n\t\t\t}\n\n\t\t\treturn (ManagedConnection) finalObject;\n\t\t} else {\n\t\t\treturn resultObject;\n\t\t}\n\t}\n\n\tpublic Object getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/ManagedConnectionHandler.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\n\nimport javax.jms.XASession;\nimport javax.resource.spi.ManagedConnection;\nimport javax.transaction.xa.XAResource;\n\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\n\npublic class ManagedConnectionHandler implements InvocationHandler {\n\n\tprivate final Object delegate;\n\tprivate String identifier;\n\n\tpublic ManagedConnectionHandler(Object managed) {\n\t\tthis.delegate = managed;\n\t}\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tClass<?> declaringClass = method.getDeclaringClass();\n\t\tClass<?> returningClass = method.getReturnType();\n\n\t\tObject resultObject = null;\n\t\ttry {\n\t\t\tresultObject = method.invoke(this.delegate, args);\n\t\t} catch (InvocationTargetException ex) {\n\t\t\tthrow ex.getTargetException();\n\t\t} catch (IllegalAccessException ex) {\n\t\t\tthrow new RuntimeException(ex);\n\t\t}\n\n\t\tif (resultObject != null && XAResourceDescriptor.class.isInstance(resultObject)) {\n\t\t\treturn resultObject;\n\t\t}\n\n\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\tdescriptor.setIdentifier(this.identifier);\n\t\tif (javax.sql.XAConnection.class.equals(declaringClass) && XAResource.class.equals(returningClass)) {\n\t\t\tdescriptor.setDelegate((XAResource) resultObject);\n\t\t} else if (javax.jms.XAConnection.class.equals(declaringClass) && XAResource.class.equals(returningClass)) {\n\t\t\tdescriptor.setDelegate((XAResource) resultObject);\n\t\t} else if (javax.jms.XAConnection.class.equals(declaringClass) && XASession.class.equals(returningClass)) {\n\t\t\tClass<?> clazz = resultObject.getClass();\n\t\t\tClassLoader cl = clazz.getClassLoader();\n\t\t\tClass<?>[] interfaces = clazz.getInterfaces();\n\t\t\tboolean containsReturningClass = false;\n\t\t\tfor (int i = 0; i < interfaces.length; i++) {\n\t\t\t\tClass<?> interfaceClass = interfaces[i];\n\t\t\t\tif (interfaceClass.equals(returningClass)) {\n\t\t\t\t\tcontainsReturningClass = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} // end-for (int i = 0; i < interfaces.length; i++)\n\n\t\t\tManagedXASessionHandler interceptor = new ManagedXASessionHandler(resultObject);\n\t\t\tinterceptor.setIdentifier(this.identifier);\n\n\t\t\tif (containsReturningClass) {\n\t\t\t\treturn Proxy.newProxyInstance(cl, interfaces, interceptor);\n\t\t\t} else {\n\t\t\t\tClass<?>[] interfaceArray = new Class<?>[interfaces.length + 1];\n\t\t\t\tSystem.arraycopy(interfaces, 0, interfaceArray, 0, interfaces.length);\n\t\t\t\tinterfaceArray[interfaces.length] = javax.jms.XASession.class;\n\t\t\t\treturn Proxy.newProxyInstance(cl, interfaceArray, interceptor);\n\t\t\t}\n\t\t} else if (ManagedConnection.class.equals(declaringClass) && XAResource.class.equals(returningClass)) {\n\t\t\tdescriptor.setDelegate((XAResource) resultObject);\n\t\t}\n\n\t\treturn descriptor.getDelegate() != null ? descriptor : resultObject;\n\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/ManagedXASessionHandler.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\nimport javax.transaction.xa.XAResource;\n\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\n\npublic class ManagedXASessionHandler implements InvocationHandler {\n\n\tprivate final Object delegate;\n\tprivate String identifier;\n\n\tpublic ManagedXASessionHandler(Object managed) {\n\t\tthis.delegate = managed;\n\t}\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tClass<?> declaringClass = method.getDeclaringClass();\n\t\tClass<?> returningClass = method.getReturnType();\n\n\t\tObject resultObject = null;\n\t\ttry {\n\t\t\tresultObject = method.invoke(this.delegate, args);\n\t\t} catch (InvocationTargetException ex) {\n\t\t\tthrow ex.getTargetException();\n\t\t} catch (IllegalAccessException ex) {\n\t\t\tthrow new RuntimeException(ex);\n\t\t}\n\n\t\tif (resultObject != null && XAResourceDescriptor.class.isInstance(resultObject)) {\n\t\t\treturn resultObject;\n\t\t}\n\n\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\tdescriptor.setIdentifier(this.identifier);\n\t\tif (javax.jms.XASession.class.equals(declaringClass) && XAResource.class.equals(returningClass)) {\n\t\t\tdescriptor.setDelegate((XAResource) resultObject);\n\t\t}\n\n\t\treturn descriptor.getDelegate() != null ? descriptor : resultObject;\n\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/CallableStatementImpl.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.CallableStatement;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.ParameterMetaData;\nimport java.sql.Ref;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLType;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\nimport java.util.Map;\n\npublic class CallableStatementImpl implements CallableStatement {\n\tprivate CallableStatement delegate;\n\tprivate ConnectionImpl connection;\n\n\tpublic <T> T unwrap(Class<T> iface) throws SQLException {\n\t\treturn delegate.unwrap(iface);\n\t}\n\n\tpublic ResultSet executeQuery(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeQuery(sql);\n\t}\n\n\tpublic ResultSet executeQuery() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeQuery();\n\t}\n\n\tpublic void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterIndex, sqlType);\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) throws SQLException {\n\t\treturn delegate.isWrapperFor(iface);\n\t}\n\n\tpublic int executeUpdate(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql);\n\t}\n\n\tpublic int executeUpdate() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate();\n\t}\n\n\tpublic void setNull(int parameterIndex, int sqlType) throws SQLException {\n\t\tdelegate.setNull(parameterIndex, sqlType);\n\t}\n\n\tpublic void close() throws SQLException {\n\t\tdelegate.close();\n\t}\n\n\tpublic void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterIndex, sqlType, scale);\n\t}\n\n\tpublic int getMaxFieldSize() throws SQLException {\n\t\treturn delegate.getMaxFieldSize();\n\t}\n\n\tpublic void setBoolean(int parameterIndex, boolean x) throws SQLException {\n\t\tdelegate.setBoolean(parameterIndex, x);\n\t}\n\n\tpublic void setByte(int parameterIndex, byte x) throws SQLException {\n\t\tdelegate.setByte(parameterIndex, x);\n\t}\n\n\tpublic void setMaxFieldSize(int max) throws SQLException {\n\t\tdelegate.setMaxFieldSize(max);\n\t}\n\n\tpublic boolean wasNull() throws SQLException {\n\t\treturn delegate.wasNull();\n\t}\n\n\tpublic void setShort(int parameterIndex, short x) throws SQLException {\n\t\tdelegate.setShort(parameterIndex, x);\n\t}\n\n\tpublic String getString(int parameterIndex) throws SQLException {\n\t\treturn delegate.getString(parameterIndex);\n\t}\n\n\tpublic int getMaxRows() throws SQLException {\n\t\treturn delegate.getMaxRows();\n\t}\n\n\tpublic void setInt(int parameterIndex, int x) throws SQLException {\n\t\tdelegate.setInt(parameterIndex, x);\n\t}\n\n\tpublic void setMaxRows(int max) throws SQLException {\n\t\tdelegate.setMaxRows(max);\n\t}\n\n\tpublic void setLong(int parameterIndex, long x) throws SQLException {\n\t\tdelegate.setLong(parameterIndex, x);\n\t}\n\n\tpublic boolean getBoolean(int parameterIndex) throws SQLException {\n\t\treturn delegate.getBoolean(parameterIndex);\n\t}\n\n\tpublic void setFloat(int parameterIndex, float x) throws SQLException {\n\t\tdelegate.setFloat(parameterIndex, x);\n\t}\n\n\tpublic void setEscapeProcessing(boolean enable) throws SQLException {\n\t\tdelegate.setEscapeProcessing(enable);\n\t}\n\n\tpublic byte getByte(int parameterIndex) throws SQLException {\n\t\treturn delegate.getByte(parameterIndex);\n\t}\n\n\tpublic void setDouble(int parameterIndex, double x) throws SQLException {\n\t\tdelegate.setDouble(parameterIndex, x);\n\t}\n\n\tpublic short getShort(int parameterIndex) throws SQLException {\n\t\treturn delegate.getShort(parameterIndex);\n\t}\n\n\tpublic int getQueryTimeout() throws SQLException {\n\t\treturn delegate.getQueryTimeout();\n\t}\n\n\tpublic void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {\n\t\tdelegate.setBigDecimal(parameterIndex, x);\n\t}\n\n\tpublic int getInt(int parameterIndex) throws SQLException {\n\t\treturn delegate.getInt(parameterIndex);\n\t}\n\n\tpublic void setQueryTimeout(int seconds) throws SQLException {\n\t\tdelegate.setQueryTimeout(seconds);\n\t}\n\n\tpublic void setString(int parameterIndex, String x) throws SQLException {\n\t\tdelegate.setString(parameterIndex, x);\n\t}\n\n\tpublic long getLong(int parameterIndex) throws SQLException {\n\t\treturn delegate.getLong(parameterIndex);\n\t}\n\n\tpublic void setBytes(int parameterIndex, byte[] x) throws SQLException {\n\t\tdelegate.setBytes(parameterIndex, x);\n\t}\n\n\tpublic float getFloat(int parameterIndex) throws SQLException {\n\t\treturn delegate.getFloat(parameterIndex);\n\t}\n\n\tpublic void cancel() throws SQLException {\n\t\tdelegate.cancel();\n\t}\n\n\tpublic double getDouble(int parameterIndex) throws SQLException {\n\t\treturn delegate.getDouble(parameterIndex);\n\t}\n\n\tpublic void setDate(int parameterIndex, Date x) throws SQLException {\n\t\tdelegate.setDate(parameterIndex, x);\n\t}\n\n\tpublic SQLWarning getWarnings() throws SQLException {\n\t\treturn delegate.getWarnings();\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tpublic BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {\n\t\treturn delegate.getBigDecimal(parameterIndex, scale);\n\t}\n\n\tpublic void setTime(int parameterIndex, Time x) throws SQLException {\n\t\tdelegate.setTime(parameterIndex, x);\n\t}\n\n\tpublic void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {\n\t\tdelegate.setTimestamp(parameterIndex, x);\n\t}\n\n\tpublic void clearWarnings() throws SQLException {\n\t\tdelegate.clearWarnings();\n\t}\n\n\tpublic byte[] getBytes(int parameterIndex) throws SQLException {\n\t\treturn delegate.getBytes(parameterIndex);\n\t}\n\n\tpublic void setCursorName(String name) throws SQLException {\n\t\tdelegate.setCursorName(name);\n\t}\n\n\tpublic void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterIndex, x, length);\n\t}\n\n\tpublic Date getDate(int parameterIndex) throws SQLException {\n\t\treturn delegate.getDate(parameterIndex);\n\t}\n\n\tpublic Time getTime(int parameterIndex) throws SQLException {\n\t\treturn delegate.getTime(parameterIndex);\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tpublic void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {\n\t\tdelegate.setUnicodeStream(parameterIndex, x, length);\n\t}\n\n\tpublic boolean execute(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql);\n\t}\n\n\tpublic Timestamp getTimestamp(int parameterIndex) throws SQLException {\n\t\treturn delegate.getTimestamp(parameterIndex);\n\t}\n\n\tpublic Object getObject(int parameterIndex) throws SQLException {\n\t\treturn delegate.getObject(parameterIndex);\n\t}\n\n\tpublic void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterIndex, x, length);\n\t}\n\n\tpublic ResultSet getResultSet() throws SQLException {\n\t\treturn delegate.getResultSet();\n\t}\n\n\tpublic BigDecimal getBigDecimal(int parameterIndex) throws SQLException {\n\t\treturn delegate.getBigDecimal(parameterIndex);\n\t}\n\n\tpublic int getUpdateCount() throws SQLException {\n\t\treturn delegate.getUpdateCount();\n\t}\n\n\tpublic void clearParameters() throws SQLException {\n\t\tdelegate.clearParameters();\n\t}\n\n\tpublic Object getObject(int parameterIndex, Map<String, Class<?>> map) throws SQLException {\n\t\treturn delegate.getObject(parameterIndex, map);\n\t}\n\n\tpublic boolean getMoreResults() throws SQLException {\n\t\treturn delegate.getMoreResults();\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType);\n\t}\n\n\tpublic void setFetchDirection(int direction) throws SQLException {\n\t\tdelegate.setFetchDirection(direction);\n\t}\n\n\tpublic Ref getRef(int parameterIndex) throws SQLException {\n\t\treturn delegate.getRef(parameterIndex);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x);\n\t}\n\n\tpublic int getFetchDirection() throws SQLException {\n\t\treturn delegate.getFetchDirection();\n\t}\n\n\tpublic Blob getBlob(int parameterIndex) throws SQLException {\n\t\treturn delegate.getBlob(parameterIndex);\n\t}\n\n\tpublic void setFetchSize(int rows) throws SQLException {\n\t\tdelegate.setFetchSize(rows);\n\t}\n\n\tpublic Clob getClob(int parameterIndex) throws SQLException {\n\t\treturn delegate.getClob(parameterIndex);\n\t}\n\n\tpublic int getFetchSize() throws SQLException {\n\t\treturn delegate.getFetchSize();\n\t}\n\n\tpublic boolean execute() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute();\n\t}\n\n\tpublic Array getArray(int parameterIndex) throws SQLException {\n\t\treturn delegate.getArray(parameterIndex);\n\t}\n\n\tpublic int getResultSetConcurrency() throws SQLException {\n\t\treturn delegate.getResultSetConcurrency();\n\t}\n\n\tpublic Date getDate(int parameterIndex, Calendar cal) throws SQLException {\n\t\treturn delegate.getDate(parameterIndex, cal);\n\t}\n\n\tpublic int getResultSetType() throws SQLException {\n\t\treturn delegate.getResultSetType();\n\t}\n\n\tpublic void addBatch(String sql) throws SQLException {\n\t\tdelegate.addBatch(sql);\n\t}\n\n\tpublic void addBatch() throws SQLException {\n\t\tdelegate.addBatch();\n\t}\n\n\tpublic void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterIndex, reader, length);\n\t}\n\n\tpublic Time getTime(int parameterIndex, Calendar cal) throws SQLException {\n\t\treturn delegate.getTime(parameterIndex, cal);\n\t}\n\n\tpublic void clearBatch() throws SQLException {\n\t\tdelegate.clearBatch();\n\t}\n\n\tpublic int[] executeBatch() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeBatch();\n\t}\n\n\tpublic Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {\n\t\treturn delegate.getTimestamp(parameterIndex, cal);\n\t}\n\n\tpublic void setRef(int parameterIndex, Ref x) throws SQLException {\n\t\tdelegate.setRef(parameterIndex, x);\n\t}\n\n\tpublic void setBlob(int parameterIndex, Blob x) throws SQLException {\n\t\tdelegate.setBlob(parameterIndex, x);\n\t}\n\n\tpublic void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterIndex, sqlType, typeName);\n\t}\n\n\tpublic void setClob(int parameterIndex, Clob x) throws SQLException {\n\t\tdelegate.setClob(parameterIndex, x);\n\t}\n\n\tpublic void setArray(int parameterIndex, Array x) throws SQLException {\n\t\tdelegate.setArray(parameterIndex, x);\n\t}\n\n\tpublic Connection getConnection() throws SQLException {\n\t\treturn connection;\n\t}\n\n\tpublic ResultSetMetaData getMetaData() throws SQLException {\n\t\treturn delegate.getMetaData();\n\t}\n\n\tpublic void registerOutParameter(String parameterName, int sqlType) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterName, sqlType);\n\t}\n\n\tpublic void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {\n\t\tdelegate.setDate(parameterIndex, x, cal);\n\t}\n\n\tpublic boolean getMoreResults(int current) throws SQLException {\n\t\treturn delegate.getMoreResults(current);\n\t}\n\n\tpublic void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterName, sqlType, scale);\n\t}\n\n\tpublic void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {\n\t\tdelegate.setTime(parameterIndex, x, cal);\n\t}\n\n\tpublic ResultSet getGeneratedKeys() throws SQLException {\n\t\treturn delegate.getGeneratedKeys();\n\t}\n\n\tpublic void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {\n\t\tdelegate.setTimestamp(parameterIndex, x, cal);\n\t}\n\n\tpublic void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterName, sqlType, typeName);\n\t}\n\n\tpublic int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, autoGeneratedKeys);\n\t}\n\n\tpublic void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {\n\t\tdelegate.setNull(parameterIndex, sqlType, typeName);\n\t}\n\n\tpublic URL getURL(int parameterIndex) throws SQLException {\n\t\treturn delegate.getURL(parameterIndex);\n\t}\n\n\tpublic int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, columnIndexes);\n\t}\n\n\tpublic void setURL(int parameterIndex, URL x) throws SQLException {\n\t\tdelegate.setURL(parameterIndex, x);\n\t}\n\n\tpublic void setURL(String parameterName, URL val) throws SQLException {\n\t\tdelegate.setURL(parameterName, val);\n\t}\n\n\tpublic ParameterMetaData getParameterMetaData() throws SQLException {\n\t\treturn delegate.getParameterMetaData();\n\t}\n\n\tpublic void setNull(String parameterName, int sqlType) throws SQLException {\n\t\tdelegate.setNull(parameterName, sqlType);\n\t}\n\n\tpublic void setRowId(int parameterIndex, RowId x) throws SQLException {\n\t\tdelegate.setRowId(parameterIndex, x);\n\t}\n\n\tpublic int executeUpdate(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, columnNames);\n\t}\n\n\tpublic void setBoolean(String parameterName, boolean x) throws SQLException {\n\t\tdelegate.setBoolean(parameterName, x);\n\t}\n\n\tpublic void setNString(int parameterIndex, String value) throws SQLException {\n\t\tdelegate.setNString(parameterIndex, value);\n\t}\n\n\tpublic void setByte(String parameterName, byte x) throws SQLException {\n\t\tdelegate.setByte(parameterName, x);\n\t}\n\n\tpublic void setShort(String parameterName, short x) throws SQLException {\n\t\tdelegate.setShort(parameterName, x);\n\t}\n\n\tpublic void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {\n\t\tdelegate.setNCharacterStream(parameterIndex, value, length);\n\t}\n\n\tpublic boolean execute(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, autoGeneratedKeys);\n\t}\n\n\tpublic void setInt(String parameterName, int x) throws SQLException {\n\t\tdelegate.setInt(parameterName, x);\n\t}\n\n\tpublic void setNClob(int parameterIndex, NClob value) throws SQLException {\n\t\tdelegate.setNClob(parameterIndex, value);\n\t}\n\n\tpublic void setLong(String parameterName, long x) throws SQLException {\n\t\tdelegate.setLong(parameterName, x);\n\t}\n\n\tpublic void setFloat(String parameterName, float x) throws SQLException {\n\t\tdelegate.setFloat(parameterName, x);\n\t}\n\n\tpublic void setClob(int parameterIndex, Reader reader, long length) throws SQLException {\n\t\tdelegate.setClob(parameterIndex, reader, length);\n\t}\n\n\tpublic void setDouble(String parameterName, double x) throws SQLException {\n\t\tdelegate.setDouble(parameterName, x);\n\t}\n\n\tpublic boolean execute(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, columnIndexes);\n\t}\n\n\tpublic void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {\n\t\tdelegate.setBigDecimal(parameterName, x);\n\t}\n\n\tpublic void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {\n\t\tdelegate.setBlob(parameterIndex, inputStream, length);\n\t}\n\n\tpublic void setString(String parameterName, String x) throws SQLException {\n\t\tdelegate.setString(parameterName, x);\n\t}\n\n\tpublic void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {\n\t\tdelegate.setNClob(parameterIndex, reader, length);\n\t}\n\n\tpublic void setBytes(String parameterName, byte[] x) throws SQLException {\n\t\tdelegate.setBytes(parameterName, x);\n\t}\n\n\tpublic void setDate(String parameterName, Date x) throws SQLException {\n\t\tdelegate.setDate(parameterName, x);\n\t}\n\n\tpublic boolean execute(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, columnNames);\n\t}\n\n\tpublic void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {\n\t\tdelegate.setSQLXML(parameterIndex, xmlObject);\n\t}\n\n\tpublic void setTime(String parameterName, Time x) throws SQLException {\n\t\tdelegate.setTime(parameterName, x);\n\t}\n\n\tpublic void setTimestamp(String parameterName, Timestamp x) throws SQLException {\n\t\tdelegate.setTimestamp(parameterName, x);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n\t}\n\n\tpublic void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterName, x, length);\n\t}\n\n\tpublic int getResultSetHoldability() throws SQLException {\n\t\treturn delegate.getResultSetHoldability();\n\t}\n\n\tpublic boolean isClosed() throws SQLException {\n\t\treturn delegate.isClosed();\n\t}\n\n\tpublic void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterName, x, length);\n\t}\n\n\tpublic void setPoolable(boolean poolable) throws SQLException {\n\t\tdelegate.setPoolable(poolable);\n\t}\n\n\tpublic void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterIndex, x, length);\n\t}\n\n\tpublic void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {\n\t\tdelegate.setObject(parameterName, x, targetSqlType, scale);\n\t}\n\n\tpublic boolean isPoolable() throws SQLException {\n\t\treturn delegate.isPoolable();\n\t}\n\n\tpublic void closeOnCompletion() throws SQLException {\n\t\tdelegate.closeOnCompletion();\n\t}\n\n\tpublic void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterIndex, x, length);\n\t}\n\n\tpublic boolean isCloseOnCompletion() throws SQLException {\n\t\treturn delegate.isCloseOnCompletion();\n\t}\n\n\tpublic void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {\n\t\tdelegate.setObject(parameterName, x, targetSqlType);\n\t}\n\n\tpublic void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterIndex, reader, length);\n\t}\n\n\tpublic long getLargeUpdateCount() throws SQLException {\n\t\treturn delegate.getLargeUpdateCount();\n\t}\n\n\tpublic void setObject(String parameterName, Object x) throws SQLException {\n\t\tdelegate.setObject(parameterName, x);\n\t}\n\n\tpublic void setLargeMaxRows(long max) throws SQLException {\n\t\tdelegate.setLargeMaxRows(max);\n\t}\n\n\tpublic void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterIndex, x);\n\t}\n\n\tpublic long getLargeMaxRows() throws SQLException {\n\t\treturn delegate.getLargeMaxRows();\n\t}\n\n\tpublic void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterIndex, x);\n\t}\n\n\tpublic long[] executeLargeBatch() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeBatch();\n\t}\n\n\tpublic void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterName, reader, length);\n\t}\n\n\tpublic void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterIndex, reader);\n\t}\n\n\tpublic void setDate(String parameterName, Date x, Calendar cal) throws SQLException {\n\t\tdelegate.setDate(parameterName, x, cal);\n\t}\n\n\tpublic void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {\n\t\tdelegate.setNCharacterStream(parameterIndex, value);\n\t}\n\n\tpublic void setTime(String parameterName, Time x, Calendar cal) throws SQLException {\n\t\tdelegate.setTime(parameterName, x, cal);\n\t}\n\n\tpublic long executeLargeUpdate(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql);\n\t}\n\n\tpublic void setClob(int parameterIndex, Reader reader) throws SQLException {\n\t\tdelegate.setClob(parameterIndex, reader);\n\t}\n\n\tpublic void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {\n\t\tdelegate.setTimestamp(parameterName, x, cal);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, autoGeneratedKeys);\n\t}\n\n\tpublic void setNull(String parameterName, int sqlType, String typeName) throws SQLException {\n\t\tdelegate.setNull(parameterName, sqlType, typeName);\n\t}\n\n\tpublic void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {\n\t\tdelegate.setBlob(parameterIndex, inputStream);\n\t}\n\n\tpublic void setNClob(int parameterIndex, Reader reader) throws SQLException {\n\t\tdelegate.setNClob(parameterIndex, reader);\n\t}\n\n\tpublic String getString(String parameterName) throws SQLException {\n\t\treturn delegate.getString(parameterName);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, columnIndexes);\n\t}\n\n\tpublic boolean getBoolean(String parameterName) throws SQLException {\n\t\treturn delegate.getBoolean(parameterName);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n\t}\n\n\tpublic byte getByte(String parameterName) throws SQLException {\n\t\treturn delegate.getByte(parameterName);\n\t}\n\n\tpublic short getShort(String parameterName) throws SQLException {\n\t\treturn delegate.getShort(parameterName);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, columnNames);\n\t}\n\n\tpublic int getInt(String parameterName) throws SQLException {\n\t\treturn delegate.getInt(parameterName);\n\t}\n\n\tpublic long getLong(String parameterName) throws SQLException {\n\t\treturn delegate.getLong(parameterName);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType);\n\t}\n\n\tpublic float getFloat(String parameterName) throws SQLException {\n\t\treturn delegate.getFloat(parameterName);\n\t}\n\n\tpublic long executeLargeUpdate() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate();\n\t}\n\n\tpublic double getDouble(String parameterName) throws SQLException {\n\t\treturn delegate.getDouble(parameterName);\n\t}\n\n\tpublic byte[] getBytes(String parameterName) throws SQLException {\n\t\treturn delegate.getBytes(parameterName);\n\t}\n\n\tpublic Date getDate(String parameterName) throws SQLException {\n\t\treturn delegate.getDate(parameterName);\n\t}\n\n\tpublic Time getTime(String parameterName) throws SQLException {\n\t\treturn delegate.getTime(parameterName);\n\t}\n\n\tpublic Timestamp getTimestamp(String parameterName) throws SQLException {\n\t\treturn delegate.getTimestamp(parameterName);\n\t}\n\n\tpublic Object getObject(String parameterName) throws SQLException {\n\t\treturn delegate.getObject(parameterName);\n\t}\n\n\tpublic BigDecimal getBigDecimal(String parameterName) throws SQLException {\n\t\treturn delegate.getBigDecimal(parameterName);\n\t}\n\n\tpublic Object getObject(String parameterName, Map<String, Class<?>> map) throws SQLException {\n\t\treturn delegate.getObject(parameterName, map);\n\t}\n\n\tpublic Ref getRef(String parameterName) throws SQLException {\n\t\treturn delegate.getRef(parameterName);\n\t}\n\n\tpublic Blob getBlob(String parameterName) throws SQLException {\n\t\treturn delegate.getBlob(parameterName);\n\t}\n\n\tpublic Clob getClob(String parameterName) throws SQLException {\n\t\treturn delegate.getClob(parameterName);\n\t}\n\n\tpublic Array getArray(String parameterName) throws SQLException {\n\t\treturn delegate.getArray(parameterName);\n\t}\n\n\tpublic Date getDate(String parameterName, Calendar cal) throws SQLException {\n\t\treturn delegate.getDate(parameterName, cal);\n\t}\n\n\tpublic Time getTime(String parameterName, Calendar cal) throws SQLException {\n\t\treturn delegate.getTime(parameterName, cal);\n\t}\n\n\tpublic Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {\n\t\treturn delegate.getTimestamp(parameterName, cal);\n\t}\n\n\tpublic URL getURL(String parameterName) throws SQLException {\n\t\treturn delegate.getURL(parameterName);\n\t}\n\n\tpublic RowId getRowId(int parameterIndex) throws SQLException {\n\t\treturn delegate.getRowId(parameterIndex);\n\t}\n\n\tpublic RowId getRowId(String parameterName) throws SQLException {\n\t\treturn delegate.getRowId(parameterName);\n\t}\n\n\tpublic void setRowId(String parameterName, RowId x) throws SQLException {\n\t\tdelegate.setRowId(parameterName, x);\n\t}\n\n\tpublic void setNString(String parameterName, String value) throws SQLException {\n\t\tdelegate.setNString(parameterName, value);\n\t}\n\n\tpublic void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {\n\t\tdelegate.setNCharacterStream(parameterName, value, length);\n\t}\n\n\tpublic void setNClob(String parameterName, NClob value) throws SQLException {\n\t\tdelegate.setNClob(parameterName, value);\n\t}\n\n\tpublic void setClob(String parameterName, Reader reader, long length) throws SQLException {\n\t\tdelegate.setClob(parameterName, reader, length);\n\t}\n\n\tpublic void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {\n\t\tdelegate.setBlob(parameterName, inputStream, length);\n\t}\n\n\tpublic void setNClob(String parameterName, Reader reader, long length) throws SQLException {\n\t\tdelegate.setNClob(parameterName, reader, length);\n\t}\n\n\tpublic NClob getNClob(int parameterIndex) throws SQLException {\n\t\treturn delegate.getNClob(parameterIndex);\n\t}\n\n\tpublic NClob getNClob(String parameterName) throws SQLException {\n\t\treturn delegate.getNClob(parameterName);\n\t}\n\n\tpublic void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {\n\t\tdelegate.setSQLXML(parameterName, xmlObject);\n\t}\n\n\tpublic SQLXML getSQLXML(int parameterIndex) throws SQLException {\n\t\treturn delegate.getSQLXML(parameterIndex);\n\t}\n\n\tpublic SQLXML getSQLXML(String parameterName) throws SQLException {\n\t\treturn delegate.getSQLXML(parameterName);\n\t}\n\n\tpublic String getNString(int parameterIndex) throws SQLException {\n\t\treturn delegate.getNString(parameterIndex);\n\t}\n\n\tpublic String getNString(String parameterName) throws SQLException {\n\t\treturn delegate.getNString(parameterName);\n\t}\n\n\tpublic Reader getNCharacterStream(int parameterIndex) throws SQLException {\n\t\treturn delegate.getNCharacterStream(parameterIndex);\n\t}\n\n\tpublic Reader getNCharacterStream(String parameterName) throws SQLException {\n\t\treturn delegate.getNCharacterStream(parameterName);\n\t}\n\n\tpublic Reader getCharacterStream(int parameterIndex) throws SQLException {\n\t\treturn delegate.getCharacterStream(parameterIndex);\n\t}\n\n\tpublic Reader getCharacterStream(String parameterName) throws SQLException {\n\t\treturn delegate.getCharacterStream(parameterName);\n\t}\n\n\tpublic void setBlob(String parameterName, Blob x) throws SQLException {\n\t\tdelegate.setBlob(parameterName, x);\n\t}\n\n\tpublic void setClob(String parameterName, Clob x) throws SQLException {\n\t\tdelegate.setClob(parameterName, x);\n\t}\n\n\tpublic void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterName, x, length);\n\t}\n\n\tpublic void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterName, x, length);\n\t}\n\n\tpublic void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterName, reader, length);\n\t}\n\n\tpublic void setAsciiStream(String parameterName, InputStream x) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterName, x);\n\t}\n\n\tpublic void setBinaryStream(String parameterName, InputStream x) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterName, x);\n\t}\n\n\tpublic void setCharacterStream(String parameterName, Reader reader) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterName, reader);\n\t}\n\n\tpublic void setNCharacterStream(String parameterName, Reader value) throws SQLException {\n\t\tdelegate.setNCharacterStream(parameterName, value);\n\t}\n\n\tpublic void setClob(String parameterName, Reader reader) throws SQLException {\n\t\tdelegate.setClob(parameterName, reader);\n\t}\n\n\tpublic void setBlob(String parameterName, InputStream inputStream) throws SQLException {\n\t\tdelegate.setBlob(parameterName, inputStream);\n\t}\n\n\tpublic void setNClob(String parameterName, Reader reader) throws SQLException {\n\t\tdelegate.setNClob(parameterName, reader);\n\t}\n\n\tpublic <T> T getObject(int parameterIndex, Class<T> type) throws SQLException {\n\t\treturn delegate.getObject(parameterIndex, type);\n\t}\n\n\tpublic <T> T getObject(String parameterName, Class<T> type) throws SQLException {\n\t\treturn delegate.getObject(parameterName, type);\n\t}\n\n\tpublic void setObject(String parameterName, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {\n\t\tdelegate.setObject(parameterName, x, targetSqlType, scaleOrLength);\n\t}\n\n\tpublic void setObject(String parameterName, Object x, SQLType targetSqlType) throws SQLException {\n\t\tdelegate.setObject(parameterName, x, targetSqlType);\n\t}\n\n\tpublic void registerOutParameter(int parameterIndex, SQLType sqlType) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterIndex, sqlType);\n\t}\n\n\tpublic void registerOutParameter(int parameterIndex, SQLType sqlType, int scale) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterIndex, sqlType, scale);\n\t}\n\n\tpublic void registerOutParameter(int parameterIndex, SQLType sqlType, String typeName) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterIndex, sqlType, typeName);\n\t}\n\n\tpublic void registerOutParameter(String parameterName, SQLType sqlType) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterName, sqlType);\n\t}\n\n\tpublic void registerOutParameter(String parameterName, SQLType sqlType, int scale) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterName, sqlType, scale);\n\t}\n\n\tpublic void registerOutParameter(String parameterName, SQLType sqlType, String typeName) throws SQLException {\n\t\tdelegate.registerOutParameter(parameterName, sqlType, typeName);\n\t}\n\n\tpublic void setConnection(ConnectionImpl connection) {\n\t\tthis.connection = connection;\n\t}\n\n\tpublic CallableStatement getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(CallableStatement delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/ConnectionImpl.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.CallableStatement;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.NClob;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLClientInfoException;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Savepoint;\nimport java.sql.Statement;\nimport java.sql.Struct;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\nimport javax.transaction.Status;\n\nimport org.bytesoft.bytejta.TransactionBeanFactoryImpl;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionManager;\n\npublic class ConnectionImpl implements Connection {\n\tprivate Connection delegate;\n\tprivate XAConnectionImpl managedConnection;\n\tprivate boolean closed;\n\n\tpublic <T> T unwrap(Class<T> iface) throws SQLException {\n\t\treturn delegate.unwrap(iface);\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) throws SQLException {\n\t\treturn delegate.isWrapperFor(iface);\n\t}\n\n\tpublic Statement createStatement() throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tStatementImpl statement = new StatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.createStatement());\n\t\treturn statement;\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tPreparedStatementImpl statement = new PreparedStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareStatement(sql));\n\t\treturn statement;\n\t}\n\n\tpublic CallableStatement prepareCall(String sql) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tCallableStatementImpl statement = new CallableStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareCall(sql));\n\t\treturn statement;\n\t}\n\n\tpublic String nativeSQL(String sql) throws SQLException {\n\t\treturn delegate.nativeSQL(sql);\n\t}\n\n\tpublic void setAutoCommit(boolean autoCommit) throws SQLException {\n\t\tdelegate.setAutoCommit(autoCommit);\n\t}\n\n\tpublic boolean getAutoCommit() throws SQLException {\n\t\treturn delegate.getAutoCommit();\n\t}\n\n\tpublic void commit() throws SQLException {\n\t\tdelegate.commit();\n\t}\n\n\tpublic void rollback() throws SQLException {\n\t\tdelegate.rollback();\n\t}\n\n\tpublic void close() throws SQLException {\n\t\tthis.closed = true;\n\t\tdelegate.close();\n\t}\n\n\tpublic boolean isClosed() throws SQLException {\n\t\treturn this.closed ? true : delegate.isClosed();\n\t}\n\n\tpublic DatabaseMetaData getMetaData() throws SQLException {\n\t\tDatabaseMetaDataImpl metadata = new DatabaseMetaDataImpl();\n\t\tDatabaseMetaData delegateMetadata = delegate.getMetaData();\n\t\tmetadata.setDelegate(delegateMetadata);\n\t\treturn metadata;\n\t}\n\n\tpublic void setReadOnly(boolean readOnly) throws SQLException {\n\t\tdelegate.setReadOnly(readOnly);\n\t}\n\n\tpublic boolean isReadOnly() throws SQLException {\n\t\treturn delegate.isReadOnly();\n\t}\n\n\tpublic void setCatalog(String catalog) throws SQLException {\n\t\tdelegate.setCatalog(catalog);\n\t}\n\n\tpublic String getCatalog() throws SQLException {\n\t\treturn delegate.getCatalog();\n\t}\n\n\tpublic void setTransactionIsolation(int level) throws SQLException {\n\t\tdelegate.setTransactionIsolation(level);\n\t}\n\n\tpublic int getTransactionIsolation() throws SQLException {\n\t\treturn delegate.getTransactionIsolation();\n\t}\n\n\tpublic SQLWarning getWarnings() throws SQLException {\n\t\treturn delegate.getWarnings();\n\t}\n\n\tpublic void clearWarnings() throws SQLException {\n\t\tdelegate.clearWarnings();\n\t}\n\n\tpublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tStatementImpl statement = new StatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.createStatement(resultSetType, resultSetConcurrency));\n\t\treturn statement;\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tPreparedStatementImpl statement = new PreparedStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareStatement(sql, resultSetType, resultSetConcurrency));\n\t\treturn statement;\n\t}\n\n\tpublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tCallableStatementImpl statement = new CallableStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareCall(sql, resultSetType, resultSetConcurrency));\n\t\treturn statement;\n\t}\n\n\tpublic Map<String, Class<?>> getTypeMap() throws SQLException {\n\t\treturn delegate.getTypeMap();\n\t}\n\n\tpublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n\t\tdelegate.setTypeMap(map);\n\t}\n\n\tpublic void setHoldability(int holdability) throws SQLException {\n\t\tdelegate.setHoldability(holdability);\n\t}\n\n\tpublic int getHoldability() throws SQLException {\n\t\treturn delegate.getHoldability();\n\t}\n\n\tpublic Savepoint setSavepoint() throws SQLException {\n\t\treturn delegate.setSavepoint();\n\t}\n\n\tpublic Savepoint setSavepoint(String name) throws SQLException {\n\t\treturn delegate.setSavepoint(name);\n\t}\n\n\tpublic void rollback(Savepoint savepoint) throws SQLException {\n\t\tdelegate.rollback(savepoint);\n\t}\n\n\tpublic void releaseSavepoint(Savepoint savepoint) throws SQLException {\n\t\tdelegate.releaseSavepoint(savepoint);\n\t}\n\n\tpublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n\t\t\tthrows SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tStatementImpl statement = new StatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability));\n\t\treturn statement;\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n\t\t\tthrows SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tPreparedStatementImpl statement = new PreparedStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability));\n\t\treturn statement;\n\t}\n\n\tpublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n\t\t\tthrows SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tCallableStatementImpl statement = new CallableStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability));\n\t\treturn statement;\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tPreparedStatementImpl statement = new PreparedStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareStatement(sql, autoGeneratedKeys));\n\t\treturn statement;\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tPreparedStatementImpl statement = new PreparedStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareStatement(sql, columnIndexes));\n\t\treturn statement;\n\t}\n\n\tpublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {\n\t\tthis.checkTransactionStatusIfNecessary();\n\n\t\tPreparedStatementImpl statement = new PreparedStatementImpl();\n\t\tstatement.setConnection(this);\n\t\tstatement.setDelegate(delegate.prepareStatement(sql, columnNames));\n\t\treturn statement;\n\t}\n\n\tpublic Clob createClob() throws SQLException {\n\t\treturn delegate.createClob();\n\t}\n\n\tpublic Blob createBlob() throws SQLException {\n\t\treturn delegate.createBlob();\n\t}\n\n\tpublic NClob createNClob() throws SQLException {\n\t\treturn delegate.createNClob();\n\t}\n\n\tpublic SQLXML createSQLXML() throws SQLException {\n\t\treturn delegate.createSQLXML();\n\t}\n\n\tpublic boolean isValid(int timeout) throws SQLException {\n\t\treturn this.closed ? false : delegate.isValid(timeout);\n\t}\n\n\tpublic void setClientInfo(String name, String value) throws SQLClientInfoException {\n\t\tdelegate.setClientInfo(name, value);\n\t}\n\n\tpublic void setClientInfo(Properties properties) throws SQLClientInfoException {\n\t\tdelegate.setClientInfo(properties);\n\t}\n\n\tpublic String getClientInfo(String name) throws SQLException {\n\t\treturn delegate.getClientInfo(name);\n\t}\n\n\tpublic Properties getClientInfo() throws SQLException {\n\t\treturn delegate.getClientInfo();\n\t}\n\n\tpublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {\n\t\treturn delegate.createArrayOf(typeName, elements);\n\t}\n\n\tpublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {\n\t\treturn delegate.createStruct(typeName, attributes);\n\t}\n\n\tpublic void setSchema(String schema) throws SQLException {\n\t\tdelegate.setSchema(schema);\n\t}\n\n\tpublic String getSchema() throws SQLException {\n\t\treturn delegate.getSchema();\n\t}\n\n\tpublic void abort(Executor executor) throws SQLException {\n\t\tdelegate.abort(executor);\n\t}\n\n\tpublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {\n\t\tdelegate.setNetworkTimeout(executor, milliseconds);\n\t}\n\n\tpublic int getNetworkTimeout() throws SQLException {\n\t\treturn delegate.getNetworkTimeout();\n\t}\n\n\tpublic void checkTransactionStatusIfNecessary() throws SQLException {\n\t\tTransactionBeanFactory beanFactory = TransactionBeanFactoryImpl.getInstance();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tif (transaction == null) {\n\t\t\treturn; // return quietly\n\t\t} // end-if (transaction == null)\n\n\t\tint transactionStatus = transaction.getTransactionStatus();\n\t\tif (Status.STATUS_ACTIVE != transactionStatus && Status.STATUS_MARKED_ROLLBACK != transactionStatus) {\n\t\t\tthrow new SQLException(\"Operation is disabled during the inactive phase of the transaction!\");\n\t\t} else if (transaction.isTiming() == false) {\n\t\t\tthrow new SQLException(\"Operation is disabled during the inactive phase of the transaction!\");\n\t\t}\n\t}\n\n\tpublic XAConnectionImpl getManagedConnection() {\n\t\treturn managedConnection;\n\t}\n\n\tpublic void setManagedConnection(XAConnectionImpl managedConnection) {\n\t\tthis.managedConnection = managedConnection;\n\t}\n\n\tpublic Connection getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(Connection delegate) {\n\t\tthis.delegate = delegate;\n\t}\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/DatabaseMetaDataImpl.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.ResultSet;\nimport java.sql.RowIdLifetime;\nimport java.sql.SQLException;\n\npublic class DatabaseMetaDataImpl implements DatabaseMetaData {\n\tprivate DatabaseMetaData delegate;\n\tprivate Connection connection;\n\n\tpublic <T> T unwrap(Class<T> iface) throws SQLException {\n\t\treturn delegate.unwrap(iface);\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) throws SQLException {\n\t\treturn delegate.isWrapperFor(iface);\n\t}\n\n\tpublic boolean allProceduresAreCallable() throws SQLException {\n\t\treturn delegate.allProceduresAreCallable();\n\t}\n\n\tpublic boolean allTablesAreSelectable() throws SQLException {\n\t\treturn delegate.allTablesAreSelectable();\n\t}\n\n\tpublic String getURL() throws SQLException {\n\t\treturn delegate.getURL();\n\t}\n\n\tpublic String getUserName() throws SQLException {\n\t\treturn delegate.getUserName();\n\t}\n\n\tpublic boolean isReadOnly() throws SQLException {\n\t\treturn delegate.isReadOnly();\n\t}\n\n\tpublic boolean nullsAreSortedHigh() throws SQLException {\n\t\treturn delegate.nullsAreSortedHigh();\n\t}\n\n\tpublic boolean nullsAreSortedLow() throws SQLException {\n\t\treturn delegate.nullsAreSortedLow();\n\t}\n\n\tpublic boolean nullsAreSortedAtStart() throws SQLException {\n\t\treturn delegate.nullsAreSortedAtStart();\n\t}\n\n\tpublic boolean nullsAreSortedAtEnd() throws SQLException {\n\t\treturn delegate.nullsAreSortedAtEnd();\n\t}\n\n\tpublic String getDatabaseProductName() throws SQLException {\n\t\treturn delegate.getDatabaseProductName();\n\t}\n\n\tpublic String getDatabaseProductVersion() throws SQLException {\n\t\treturn delegate.getDatabaseProductVersion();\n\t}\n\n\tpublic String getDriverName() throws SQLException {\n\t\treturn delegate.getDriverName();\n\t}\n\n\tpublic String getDriverVersion() throws SQLException {\n\t\treturn delegate.getDriverVersion();\n\t}\n\n\tpublic int getDriverMajorVersion() {\n\t\treturn delegate.getDriverMajorVersion();\n\t}\n\n\tpublic int getDriverMinorVersion() {\n\t\treturn delegate.getDriverMinorVersion();\n\t}\n\n\tpublic boolean usesLocalFiles() throws SQLException {\n\t\treturn delegate.usesLocalFiles();\n\t}\n\n\tpublic boolean usesLocalFilePerTable() throws SQLException {\n\t\treturn delegate.usesLocalFilePerTable();\n\t}\n\n\tpublic boolean supportsMixedCaseIdentifiers() throws SQLException {\n\t\treturn delegate.supportsMixedCaseIdentifiers();\n\t}\n\n\tpublic boolean storesUpperCaseIdentifiers() throws SQLException {\n\t\treturn delegate.storesUpperCaseIdentifiers();\n\t}\n\n\tpublic boolean storesLowerCaseIdentifiers() throws SQLException {\n\t\treturn delegate.storesLowerCaseIdentifiers();\n\t}\n\n\tpublic boolean storesMixedCaseIdentifiers() throws SQLException {\n\t\treturn delegate.storesMixedCaseIdentifiers();\n\t}\n\n\tpublic boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {\n\t\treturn delegate.supportsMixedCaseQuotedIdentifiers();\n\t}\n\n\tpublic boolean storesUpperCaseQuotedIdentifiers() throws SQLException {\n\t\treturn delegate.storesUpperCaseQuotedIdentifiers();\n\t}\n\n\tpublic boolean storesLowerCaseQuotedIdentifiers() throws SQLException {\n\t\treturn delegate.storesLowerCaseQuotedIdentifiers();\n\t}\n\n\tpublic boolean storesMixedCaseQuotedIdentifiers() throws SQLException {\n\t\treturn delegate.storesMixedCaseQuotedIdentifiers();\n\t}\n\n\tpublic String getIdentifierQuoteString() throws SQLException {\n\t\treturn delegate.getIdentifierQuoteString();\n\t}\n\n\tpublic String getSQLKeywords() throws SQLException {\n\t\treturn delegate.getSQLKeywords();\n\t}\n\n\tpublic String getNumericFunctions() throws SQLException {\n\t\treturn delegate.getNumericFunctions();\n\t}\n\n\tpublic String getStringFunctions() throws SQLException {\n\t\treturn delegate.getStringFunctions();\n\t}\n\n\tpublic String getSystemFunctions() throws SQLException {\n\t\treturn delegate.getSystemFunctions();\n\t}\n\n\tpublic String getTimeDateFunctions() throws SQLException {\n\t\treturn delegate.getTimeDateFunctions();\n\t}\n\n\tpublic String getSearchStringEscape() throws SQLException {\n\t\treturn delegate.getSearchStringEscape();\n\t}\n\n\tpublic String getExtraNameCharacters() throws SQLException {\n\t\treturn delegate.getExtraNameCharacters();\n\t}\n\n\tpublic boolean supportsAlterTableWithAddColumn() throws SQLException {\n\t\treturn delegate.supportsAlterTableWithAddColumn();\n\t}\n\n\tpublic boolean supportsAlterTableWithDropColumn() throws SQLException {\n\t\treturn delegate.supportsAlterTableWithDropColumn();\n\t}\n\n\tpublic boolean supportsColumnAliasing() throws SQLException {\n\t\treturn delegate.supportsColumnAliasing();\n\t}\n\n\tpublic boolean nullPlusNonNullIsNull() throws SQLException {\n\t\treturn delegate.nullPlusNonNullIsNull();\n\t}\n\n\tpublic boolean supportsConvert() throws SQLException {\n\t\treturn delegate.supportsConvert();\n\t}\n\n\tpublic boolean supportsConvert(int fromType, int toType) throws SQLException {\n\t\treturn delegate.supportsConvert(fromType, toType);\n\t}\n\n\tpublic boolean supportsTableCorrelationNames() throws SQLException {\n\t\treturn delegate.supportsTableCorrelationNames();\n\t}\n\n\tpublic boolean supportsDifferentTableCorrelationNames() throws SQLException {\n\t\treturn delegate.supportsDifferentTableCorrelationNames();\n\t}\n\n\tpublic boolean supportsExpressionsInOrderBy() throws SQLException {\n\t\treturn delegate.supportsExpressionsInOrderBy();\n\t}\n\n\tpublic boolean supportsOrderByUnrelated() throws SQLException {\n\t\treturn delegate.supportsOrderByUnrelated();\n\t}\n\n\tpublic boolean supportsGroupBy() throws SQLException {\n\t\treturn delegate.supportsGroupBy();\n\t}\n\n\tpublic boolean supportsGroupByUnrelated() throws SQLException {\n\t\treturn delegate.supportsGroupByUnrelated();\n\t}\n\n\tpublic boolean supportsGroupByBeyondSelect() throws SQLException {\n\t\treturn delegate.supportsGroupByBeyondSelect();\n\t}\n\n\tpublic boolean supportsLikeEscapeClause() throws SQLException {\n\t\treturn delegate.supportsLikeEscapeClause();\n\t}\n\n\tpublic boolean supportsMultipleResultSets() throws SQLException {\n\t\treturn delegate.supportsMultipleResultSets();\n\t}\n\n\tpublic boolean supportsMultipleTransactions() throws SQLException {\n\t\treturn delegate.supportsMultipleTransactions();\n\t}\n\n\tpublic boolean supportsNonNullableColumns() throws SQLException {\n\t\treturn delegate.supportsNonNullableColumns();\n\t}\n\n\tpublic boolean supportsMinimumSQLGrammar() throws SQLException {\n\t\treturn delegate.supportsMinimumSQLGrammar();\n\t}\n\n\tpublic boolean supportsCoreSQLGrammar() throws SQLException {\n\t\treturn delegate.supportsCoreSQLGrammar();\n\t}\n\n\tpublic boolean supportsExtendedSQLGrammar() throws SQLException {\n\t\treturn delegate.supportsExtendedSQLGrammar();\n\t}\n\n\tpublic boolean supportsANSI92EntryLevelSQL() throws SQLException {\n\t\treturn delegate.supportsANSI92EntryLevelSQL();\n\t}\n\n\tpublic boolean supportsANSI92IntermediateSQL() throws SQLException {\n\t\treturn delegate.supportsANSI92IntermediateSQL();\n\t}\n\n\tpublic boolean supportsANSI92FullSQL() throws SQLException {\n\t\treturn delegate.supportsANSI92FullSQL();\n\t}\n\n\tpublic boolean supportsIntegrityEnhancementFacility() throws SQLException {\n\t\treturn delegate.supportsIntegrityEnhancementFacility();\n\t}\n\n\tpublic boolean supportsOuterJoins() throws SQLException {\n\t\treturn delegate.supportsOuterJoins();\n\t}\n\n\tpublic boolean supportsFullOuterJoins() throws SQLException {\n\t\treturn delegate.supportsFullOuterJoins();\n\t}\n\n\tpublic boolean supportsLimitedOuterJoins() throws SQLException {\n\t\treturn delegate.supportsLimitedOuterJoins();\n\t}\n\n\tpublic String getSchemaTerm() throws SQLException {\n\t\treturn delegate.getSchemaTerm();\n\t}\n\n\tpublic String getProcedureTerm() throws SQLException {\n\t\treturn delegate.getProcedureTerm();\n\t}\n\n\tpublic String getCatalogTerm() throws SQLException {\n\t\treturn delegate.getCatalogTerm();\n\t}\n\n\tpublic boolean isCatalogAtStart() throws SQLException {\n\t\treturn delegate.isCatalogAtStart();\n\t}\n\n\tpublic String getCatalogSeparator() throws SQLException {\n\t\treturn delegate.getCatalogSeparator();\n\t}\n\n\tpublic boolean supportsSchemasInDataManipulation() throws SQLException {\n\t\treturn delegate.supportsSchemasInDataManipulation();\n\t}\n\n\tpublic boolean supportsSchemasInProcedureCalls() throws SQLException {\n\t\treturn delegate.supportsSchemasInProcedureCalls();\n\t}\n\n\tpublic boolean supportsSchemasInTableDefinitions() throws SQLException {\n\t\treturn delegate.supportsSchemasInTableDefinitions();\n\t}\n\n\tpublic boolean supportsSchemasInIndexDefinitions() throws SQLException {\n\t\treturn delegate.supportsSchemasInIndexDefinitions();\n\t}\n\n\tpublic boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {\n\t\treturn delegate.supportsSchemasInPrivilegeDefinitions();\n\t}\n\n\tpublic boolean supportsCatalogsInDataManipulation() throws SQLException {\n\t\treturn delegate.supportsCatalogsInDataManipulation();\n\t}\n\n\tpublic boolean supportsCatalogsInProcedureCalls() throws SQLException {\n\t\treturn delegate.supportsCatalogsInProcedureCalls();\n\t}\n\n\tpublic boolean supportsCatalogsInTableDefinitions() throws SQLException {\n\t\treturn delegate.supportsCatalogsInTableDefinitions();\n\t}\n\n\tpublic boolean supportsCatalogsInIndexDefinitions() throws SQLException {\n\t\treturn delegate.supportsCatalogsInIndexDefinitions();\n\t}\n\n\tpublic boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {\n\t\treturn delegate.supportsCatalogsInPrivilegeDefinitions();\n\t}\n\n\tpublic boolean supportsPositionedDelete() throws SQLException {\n\t\treturn delegate.supportsPositionedDelete();\n\t}\n\n\tpublic boolean supportsPositionedUpdate() throws SQLException {\n\t\treturn delegate.supportsPositionedUpdate();\n\t}\n\n\tpublic boolean supportsSelectForUpdate() throws SQLException {\n\t\treturn delegate.supportsSelectForUpdate();\n\t}\n\n\tpublic boolean supportsStoredProcedures() throws SQLException {\n\t\treturn delegate.supportsStoredProcedures();\n\t}\n\n\tpublic boolean supportsSubqueriesInComparisons() throws SQLException {\n\t\treturn delegate.supportsSubqueriesInComparisons();\n\t}\n\n\tpublic boolean supportsSubqueriesInExists() throws SQLException {\n\t\treturn delegate.supportsSubqueriesInExists();\n\t}\n\n\tpublic boolean supportsSubqueriesInIns() throws SQLException {\n\t\treturn delegate.supportsSubqueriesInIns();\n\t}\n\n\tpublic boolean supportsSubqueriesInQuantifieds() throws SQLException {\n\t\treturn delegate.supportsSubqueriesInQuantifieds();\n\t}\n\n\tpublic boolean supportsCorrelatedSubqueries() throws SQLException {\n\t\treturn delegate.supportsCorrelatedSubqueries();\n\t}\n\n\tpublic boolean supportsUnion() throws SQLException {\n\t\treturn delegate.supportsUnion();\n\t}\n\n\tpublic boolean supportsUnionAll() throws SQLException {\n\t\treturn delegate.supportsUnionAll();\n\t}\n\n\tpublic boolean supportsOpenCursorsAcrossCommit() throws SQLException {\n\t\treturn delegate.supportsOpenCursorsAcrossCommit();\n\t}\n\n\tpublic boolean supportsOpenCursorsAcrossRollback() throws SQLException {\n\t\treturn delegate.supportsOpenCursorsAcrossRollback();\n\t}\n\n\tpublic boolean supportsOpenStatementsAcrossCommit() throws SQLException {\n\t\treturn delegate.supportsOpenStatementsAcrossCommit();\n\t}\n\n\tpublic boolean supportsOpenStatementsAcrossRollback() throws SQLException {\n\t\treturn delegate.supportsOpenStatementsAcrossRollback();\n\t}\n\n\tpublic int getMaxBinaryLiteralLength() throws SQLException {\n\t\treturn delegate.getMaxBinaryLiteralLength();\n\t}\n\n\tpublic int getMaxCharLiteralLength() throws SQLException {\n\t\treturn delegate.getMaxCharLiteralLength();\n\t}\n\n\tpublic int getMaxColumnNameLength() throws SQLException {\n\t\treturn delegate.getMaxColumnNameLength();\n\t}\n\n\tpublic int getMaxColumnsInGroupBy() throws SQLException {\n\t\treturn delegate.getMaxColumnsInGroupBy();\n\t}\n\n\tpublic int getMaxColumnsInIndex() throws SQLException {\n\t\treturn delegate.getMaxColumnsInIndex();\n\t}\n\n\tpublic int getMaxColumnsInOrderBy() throws SQLException {\n\t\treturn delegate.getMaxColumnsInOrderBy();\n\t}\n\n\tpublic int getMaxColumnsInSelect() throws SQLException {\n\t\treturn delegate.getMaxColumnsInSelect();\n\t}\n\n\tpublic int getMaxColumnsInTable() throws SQLException {\n\t\treturn delegate.getMaxColumnsInTable();\n\t}\n\n\tpublic int getMaxConnections() throws SQLException {\n\t\treturn delegate.getMaxConnections();\n\t}\n\n\tpublic int getMaxCursorNameLength() throws SQLException {\n\t\treturn delegate.getMaxCursorNameLength();\n\t}\n\n\tpublic int getMaxIndexLength() throws SQLException {\n\t\treturn delegate.getMaxIndexLength();\n\t}\n\n\tpublic int getMaxSchemaNameLength() throws SQLException {\n\t\treturn delegate.getMaxSchemaNameLength();\n\t}\n\n\tpublic int getMaxProcedureNameLength() throws SQLException {\n\t\treturn delegate.getMaxProcedureNameLength();\n\t}\n\n\tpublic int getMaxCatalogNameLength() throws SQLException {\n\t\treturn delegate.getMaxCatalogNameLength();\n\t}\n\n\tpublic int getMaxRowSize() throws SQLException {\n\t\treturn delegate.getMaxRowSize();\n\t}\n\n\tpublic boolean doesMaxRowSizeIncludeBlobs() throws SQLException {\n\t\treturn delegate.doesMaxRowSizeIncludeBlobs();\n\t}\n\n\tpublic int getMaxStatementLength() throws SQLException {\n\t\treturn delegate.getMaxStatementLength();\n\t}\n\n\tpublic int getMaxStatements() throws SQLException {\n\t\treturn delegate.getMaxStatements();\n\t}\n\n\tpublic int getMaxTableNameLength() throws SQLException {\n\t\treturn delegate.getMaxTableNameLength();\n\t}\n\n\tpublic int getMaxTablesInSelect() throws SQLException {\n\t\treturn delegate.getMaxTablesInSelect();\n\t}\n\n\tpublic int getMaxUserNameLength() throws SQLException {\n\t\treturn delegate.getMaxUserNameLength();\n\t}\n\n\tpublic int getDefaultTransactionIsolation() throws SQLException {\n\t\treturn delegate.getDefaultTransactionIsolation();\n\t}\n\n\tpublic boolean supportsTransactions() throws SQLException {\n\t\treturn delegate.supportsTransactions();\n\t}\n\n\tpublic boolean supportsTransactionIsolationLevel(int level) throws SQLException {\n\t\treturn delegate.supportsTransactionIsolationLevel(level);\n\t}\n\n\tpublic boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {\n\t\treturn delegate.supportsDataDefinitionAndDataManipulationTransactions();\n\t}\n\n\tpublic boolean supportsDataManipulationTransactionsOnly() throws SQLException {\n\t\treturn delegate.supportsDataManipulationTransactionsOnly();\n\t}\n\n\tpublic boolean dataDefinitionCausesTransactionCommit() throws SQLException {\n\t\treturn delegate.dataDefinitionCausesTransactionCommit();\n\t}\n\n\tpublic boolean dataDefinitionIgnoredInTransactions() throws SQLException {\n\t\treturn delegate.dataDefinitionIgnoredInTransactions();\n\t}\n\n\tpublic ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {\n\t\treturn delegate.getProcedures(catalog, schemaPattern, procedureNamePattern);\n\t}\n\n\tpublic ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,\n\t\t\tString columnNamePattern) throws SQLException {\n\t\treturn delegate.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern);\n\t}\n\n\tpublic ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getTables(catalog, schemaPattern, tableNamePattern, types);\n\t}\n\n\tpublic ResultSet getSchemas() throws SQLException {\n\t\treturn delegate.getSchemas();\n\t}\n\n\tpublic ResultSet getCatalogs() throws SQLException {\n\t\treturn delegate.getCatalogs();\n\t}\n\n\tpublic ResultSet getTableTypes() throws SQLException {\n\t\treturn delegate.getTableTypes();\n\t}\n\n\tpublic ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n\t}\n\n\tpublic ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getColumnPrivileges(catalog, schema, table, columnNamePattern);\n\t}\n\n\tpublic ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {\n\t\treturn delegate.getTablePrivileges(catalog, schemaPattern, tableNamePattern);\n\t}\n\n\tpublic ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getBestRowIdentifier(catalog, schema, table, scope, nullable);\n\t}\n\n\tpublic ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {\n\t\treturn delegate.getVersionColumns(catalog, schema, table);\n\t}\n\n\tpublic ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {\n\t\treturn delegate.getPrimaryKeys(catalog, schema, table);\n\t}\n\n\tpublic ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {\n\t\treturn delegate.getImportedKeys(catalog, schema, table);\n\t}\n\n\tpublic ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {\n\t\treturn delegate.getExportedKeys(catalog, schema, table);\n\t}\n\n\tpublic ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog,\n\t\t\tString foreignSchema, String foreignTable) throws SQLException {\n\t\treturn delegate.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema,\n\t\t\t\tforeignTable);\n\t}\n\n\tpublic ResultSet getTypeInfo() throws SQLException {\n\t\treturn delegate.getTypeInfo();\n\t}\n\n\tpublic ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getIndexInfo(catalog, schema, table, unique, approximate);\n\t}\n\n\tpublic boolean supportsResultSetType(int type) throws SQLException {\n\t\treturn delegate.supportsResultSetType(type);\n\t}\n\n\tpublic boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {\n\t\treturn delegate.supportsResultSetConcurrency(type, concurrency);\n\t}\n\n\tpublic boolean ownUpdatesAreVisible(int type) throws SQLException {\n\t\treturn delegate.ownUpdatesAreVisible(type);\n\t}\n\n\tpublic boolean ownDeletesAreVisible(int type) throws SQLException {\n\t\treturn delegate.ownDeletesAreVisible(type);\n\t}\n\n\tpublic boolean ownInsertsAreVisible(int type) throws SQLException {\n\t\treturn delegate.ownInsertsAreVisible(type);\n\t}\n\n\tpublic boolean othersUpdatesAreVisible(int type) throws SQLException {\n\t\treturn delegate.othersUpdatesAreVisible(type);\n\t}\n\n\tpublic boolean othersDeletesAreVisible(int type) throws SQLException {\n\t\treturn delegate.othersDeletesAreVisible(type);\n\t}\n\n\tpublic boolean othersInsertsAreVisible(int type) throws SQLException {\n\t\treturn delegate.othersInsertsAreVisible(type);\n\t}\n\n\tpublic boolean updatesAreDetected(int type) throws SQLException {\n\t\treturn delegate.updatesAreDetected(type);\n\t}\n\n\tpublic boolean deletesAreDetected(int type) throws SQLException {\n\t\treturn delegate.deletesAreDetected(type);\n\t}\n\n\tpublic boolean insertsAreDetected(int type) throws SQLException {\n\t\treturn delegate.insertsAreDetected(type);\n\t}\n\n\tpublic boolean supportsBatchUpdates() throws SQLException {\n\t\treturn delegate.supportsBatchUpdates();\n\t}\n\n\tpublic ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {\n\t\treturn delegate.getUDTs(catalog, schemaPattern, typeNamePattern, types);\n\t}\n\n\tpublic Connection getConnection() throws SQLException {\n\t\treturn connection;\n\t}\n\n\tpublic boolean supportsSavepoints() throws SQLException {\n\t\treturn delegate.supportsSavepoints();\n\t}\n\n\tpublic boolean supportsNamedParameters() throws SQLException {\n\t\treturn delegate.supportsNamedParameters();\n\t}\n\n\tpublic boolean supportsMultipleOpenResults() throws SQLException {\n\t\treturn delegate.supportsMultipleOpenResults();\n\t}\n\n\tpublic boolean supportsGetGeneratedKeys() throws SQLException {\n\t\treturn delegate.supportsGetGeneratedKeys();\n\t}\n\n\tpublic ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {\n\t\treturn delegate.getSuperTypes(catalog, schemaPattern, typeNamePattern);\n\t}\n\n\tpublic ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {\n\t\treturn delegate.getSuperTables(catalog, schemaPattern, tableNamePattern);\n\t}\n\n\tpublic ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern);\n\t}\n\n\tpublic boolean supportsResultSetHoldability(int holdability) throws SQLException {\n\t\treturn delegate.supportsResultSetHoldability(holdability);\n\t}\n\n\tpublic int getResultSetHoldability() throws SQLException {\n\t\treturn delegate.getResultSetHoldability();\n\t}\n\n\tpublic int getDatabaseMajorVersion() throws SQLException {\n\t\treturn delegate.getDatabaseMajorVersion();\n\t}\n\n\tpublic int getDatabaseMinorVersion() throws SQLException {\n\t\treturn delegate.getDatabaseMinorVersion();\n\t}\n\n\tpublic int getJDBCMajorVersion() throws SQLException {\n\t\treturn delegate.getJDBCMajorVersion();\n\t}\n\n\tpublic int getJDBCMinorVersion() throws SQLException {\n\t\treturn delegate.getJDBCMinorVersion();\n\t}\n\n\tpublic int getSQLStateType() throws SQLException {\n\t\treturn delegate.getSQLStateType();\n\t}\n\n\tpublic boolean locatorsUpdateCopy() throws SQLException {\n\t\treturn delegate.locatorsUpdateCopy();\n\t}\n\n\tpublic boolean supportsStatementPooling() throws SQLException {\n\t\treturn delegate.supportsStatementPooling();\n\t}\n\n\tpublic RowIdLifetime getRowIdLifetime() throws SQLException {\n\t\treturn delegate.getRowIdLifetime();\n\t}\n\n\tpublic ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {\n\t\treturn delegate.getSchemas(catalog, schemaPattern);\n\t}\n\n\tpublic boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {\n\t\treturn delegate.supportsStoredFunctionsUsingCallSyntax();\n\t}\n\n\tpublic boolean autoCommitFailureClosesAllResultSets() throws SQLException {\n\t\treturn delegate.autoCommitFailureClosesAllResultSets();\n\t}\n\n\tpublic ResultSet getClientInfoProperties() throws SQLException {\n\t\treturn delegate.getClientInfoProperties();\n\t}\n\n\tpublic ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {\n\t\treturn delegate.getFunctions(catalog, schemaPattern, functionNamePattern);\n\t}\n\n\tpublic ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern,\n\t\t\tString columnNamePattern) throws SQLException {\n\t\treturn delegate.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern);\n\t}\n\n\tpublic ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)\n\t\t\tthrows SQLException {\n\t\treturn delegate.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n\t}\n\n\tpublic boolean generatedKeyAlwaysReturned() throws SQLException {\n\t\treturn delegate.generatedKeyAlwaysReturned();\n\t}\n\n\tpublic long getMaxLogicalLobSize() throws SQLException {\n\t\treturn delegate.getMaxLogicalLobSize();\n\t}\n\n\tpublic boolean supportsRefCursors() throws SQLException {\n\t\treturn delegate.supportsRefCursors();\n\t}\n\n\tpublic void setConnection(Connection connection) {\n\t\tthis.connection = connection;\n\t}\n\n\tpublic DatabaseMetaData getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(DatabaseMetaData delegate) {\n\t\tthis.delegate = delegate;\n\t}\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/PreparedStatementImpl.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.ParameterMetaData;\nimport java.sql.PreparedStatement;\nimport java.sql.Ref;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLType;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\n\npublic class PreparedStatementImpl implements PreparedStatement {\n\tprivate PreparedStatement delegate;\n\tprivate ConnectionImpl connection;\n\n\tpublic <T> T unwrap(Class<T> iface) throws SQLException {\n\t\treturn delegate.unwrap(iface);\n\t}\n\n\tpublic ResultSet executeQuery(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeQuery(sql);\n\t}\n\n\tpublic ResultSet executeQuery() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeQuery();\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) throws SQLException {\n\t\treturn delegate.isWrapperFor(iface);\n\t}\n\n\tpublic int executeUpdate(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql);\n\t}\n\n\tpublic int executeUpdate() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate();\n\t}\n\n\tpublic void setNull(int parameterIndex, int sqlType) throws SQLException {\n\t\tdelegate.setNull(parameterIndex, sqlType);\n\t}\n\n\tpublic void close() throws SQLException {\n\t\tdelegate.close();\n\t}\n\n\tpublic int getMaxFieldSize() throws SQLException {\n\t\treturn delegate.getMaxFieldSize();\n\t}\n\n\tpublic void setBoolean(int parameterIndex, boolean x) throws SQLException {\n\t\tdelegate.setBoolean(parameterIndex, x);\n\t}\n\n\tpublic void setByte(int parameterIndex, byte x) throws SQLException {\n\t\tdelegate.setByte(parameterIndex, x);\n\t}\n\n\tpublic void setMaxFieldSize(int max) throws SQLException {\n\t\tdelegate.setMaxFieldSize(max);\n\t}\n\n\tpublic void setShort(int parameterIndex, short x) throws SQLException {\n\t\tdelegate.setShort(parameterIndex, x);\n\t}\n\n\tpublic int getMaxRows() throws SQLException {\n\t\treturn delegate.getMaxRows();\n\t}\n\n\tpublic void setInt(int parameterIndex, int x) throws SQLException {\n\t\tdelegate.setInt(parameterIndex, x);\n\t}\n\n\tpublic void setMaxRows(int max) throws SQLException {\n\t\tdelegate.setMaxRows(max);\n\t}\n\n\tpublic void setLong(int parameterIndex, long x) throws SQLException {\n\t\tdelegate.setLong(parameterIndex, x);\n\t}\n\n\tpublic void setFloat(int parameterIndex, float x) throws SQLException {\n\t\tdelegate.setFloat(parameterIndex, x);\n\t}\n\n\tpublic void setEscapeProcessing(boolean enable) throws SQLException {\n\t\tdelegate.setEscapeProcessing(enable);\n\t}\n\n\tpublic void setDouble(int parameterIndex, double x) throws SQLException {\n\t\tdelegate.setDouble(parameterIndex, x);\n\t}\n\n\tpublic int getQueryTimeout() throws SQLException {\n\t\treturn delegate.getQueryTimeout();\n\t}\n\n\tpublic void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {\n\t\tdelegate.setBigDecimal(parameterIndex, x);\n\t}\n\n\tpublic void setQueryTimeout(int seconds) throws SQLException {\n\t\tdelegate.setQueryTimeout(seconds);\n\t}\n\n\tpublic void setString(int parameterIndex, String x) throws SQLException {\n\t\tdelegate.setString(parameterIndex, x);\n\t}\n\n\tpublic void setBytes(int parameterIndex, byte[] x) throws SQLException {\n\t\tdelegate.setBytes(parameterIndex, x);\n\t}\n\n\tpublic void cancel() throws SQLException {\n\t\tdelegate.cancel();\n\t}\n\n\tpublic void setDate(int parameterIndex, Date x) throws SQLException {\n\t\tdelegate.setDate(parameterIndex, x);\n\t}\n\n\tpublic SQLWarning getWarnings() throws SQLException {\n\t\treturn delegate.getWarnings();\n\t}\n\n\tpublic void setTime(int parameterIndex, Time x) throws SQLException {\n\t\tdelegate.setTime(parameterIndex, x);\n\t}\n\n\tpublic void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {\n\t\tdelegate.setTimestamp(parameterIndex, x);\n\t}\n\n\tpublic void clearWarnings() throws SQLException {\n\t\tdelegate.clearWarnings();\n\t}\n\n\tpublic void setCursorName(String name) throws SQLException {\n\t\tdelegate.setCursorName(name);\n\t}\n\n\tpublic void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterIndex, x, length);\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tpublic void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {\n\t\tdelegate.setUnicodeStream(parameterIndex, x, length);\n\t}\n\n\tpublic boolean execute(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql);\n\t}\n\n\tpublic void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterIndex, x, length);\n\t}\n\n\tpublic ResultSet getResultSet() throws SQLException {\n\t\treturn delegate.getResultSet();\n\t}\n\n\tpublic int getUpdateCount() throws SQLException {\n\t\treturn delegate.getUpdateCount();\n\t}\n\n\tpublic void clearParameters() throws SQLException {\n\t\tdelegate.clearParameters();\n\t}\n\n\tpublic boolean getMoreResults() throws SQLException {\n\t\treturn delegate.getMoreResults();\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType);\n\t}\n\n\tpublic void setFetchDirection(int direction) throws SQLException {\n\t\tdelegate.setFetchDirection(direction);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x);\n\t}\n\n\tpublic int getFetchDirection() throws SQLException {\n\t\treturn delegate.getFetchDirection();\n\t}\n\n\tpublic void setFetchSize(int rows) throws SQLException {\n\t\tdelegate.setFetchSize(rows);\n\t}\n\n\tpublic int getFetchSize() throws SQLException {\n\t\treturn delegate.getFetchSize();\n\t}\n\n\tpublic boolean execute() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute();\n\t}\n\n\tpublic int getResultSetConcurrency() throws SQLException {\n\t\treturn delegate.getResultSetConcurrency();\n\t}\n\n\tpublic int getResultSetType() throws SQLException {\n\t\treturn delegate.getResultSetType();\n\t}\n\n\tpublic void addBatch(String sql) throws SQLException {\n\t\tdelegate.addBatch(sql);\n\t}\n\n\tpublic void addBatch() throws SQLException {\n\t\tdelegate.addBatch();\n\t}\n\n\tpublic void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterIndex, reader, length);\n\t}\n\n\tpublic void clearBatch() throws SQLException {\n\t\tdelegate.clearBatch();\n\t}\n\n\tpublic int[] executeBatch() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeBatch();\n\t}\n\n\tpublic void setRef(int parameterIndex, Ref x) throws SQLException {\n\t\tdelegate.setRef(parameterIndex, x);\n\t}\n\n\tpublic void setBlob(int parameterIndex, Blob x) throws SQLException {\n\t\tdelegate.setBlob(parameterIndex, x);\n\t}\n\n\tpublic void setClob(int parameterIndex, Clob x) throws SQLException {\n\t\tdelegate.setClob(parameterIndex, x);\n\t}\n\n\tpublic void setArray(int parameterIndex, Array x) throws SQLException {\n\t\tdelegate.setArray(parameterIndex, x);\n\t}\n\n\tpublic Connection getConnection() throws SQLException {\n\t\treturn connection;\n\t}\n\n\tpublic ResultSetMetaData getMetaData() throws SQLException {\n\t\treturn delegate.getMetaData();\n\t}\n\n\tpublic void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {\n\t\tdelegate.setDate(parameterIndex, x, cal);\n\t}\n\n\tpublic boolean getMoreResults(int current) throws SQLException {\n\t\treturn delegate.getMoreResults(current);\n\t}\n\n\tpublic void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {\n\t\tdelegate.setTime(parameterIndex, x, cal);\n\t}\n\n\tpublic ResultSet getGeneratedKeys() throws SQLException {\n\t\treturn delegate.getGeneratedKeys();\n\t}\n\n\tpublic void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {\n\t\tdelegate.setTimestamp(parameterIndex, x, cal);\n\t}\n\n\tpublic int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, autoGeneratedKeys);\n\t}\n\n\tpublic void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {\n\t\tdelegate.setNull(parameterIndex, sqlType, typeName);\n\t}\n\n\tpublic int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, columnIndexes);\n\t}\n\n\tpublic void setURL(int parameterIndex, URL x) throws SQLException {\n\t\tdelegate.setURL(parameterIndex, x);\n\t}\n\n\tpublic ParameterMetaData getParameterMetaData() throws SQLException {\n\t\treturn delegate.getParameterMetaData();\n\t}\n\n\tpublic void setRowId(int parameterIndex, RowId x) throws SQLException {\n\t\tdelegate.setRowId(parameterIndex, x);\n\t}\n\n\tpublic int executeUpdate(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, columnNames);\n\t}\n\n\tpublic void setNString(int parameterIndex, String value) throws SQLException {\n\t\tdelegate.setNString(parameterIndex, value);\n\t}\n\n\tpublic void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {\n\t\tdelegate.setNCharacterStream(parameterIndex, value, length);\n\t}\n\n\tpublic boolean execute(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, autoGeneratedKeys);\n\t}\n\n\tpublic void setNClob(int parameterIndex, NClob value) throws SQLException {\n\t\tdelegate.setNClob(parameterIndex, value);\n\t}\n\n\tpublic void setClob(int parameterIndex, Reader reader, long length) throws SQLException {\n\t\tdelegate.setClob(parameterIndex, reader, length);\n\t}\n\n\tpublic boolean execute(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, columnIndexes);\n\t}\n\n\tpublic void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {\n\t\tdelegate.setBlob(parameterIndex, inputStream, length);\n\t}\n\n\tpublic void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {\n\t\tdelegate.setNClob(parameterIndex, reader, length);\n\t}\n\n\tpublic boolean execute(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, columnNames);\n\t}\n\n\tpublic void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {\n\t\tdelegate.setSQLXML(parameterIndex, xmlObject);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n\t}\n\n\tpublic int getResultSetHoldability() throws SQLException {\n\t\treturn delegate.getResultSetHoldability();\n\t}\n\n\tpublic boolean isClosed() throws SQLException {\n\t\treturn delegate.isClosed();\n\t}\n\n\tpublic void setPoolable(boolean poolable) throws SQLException {\n\t\tdelegate.setPoolable(poolable);\n\t}\n\n\tpublic void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterIndex, x, length);\n\t}\n\n\tpublic boolean isPoolable() throws SQLException {\n\t\treturn delegate.isPoolable();\n\t}\n\n\tpublic void closeOnCompletion() throws SQLException {\n\t\tdelegate.closeOnCompletion();\n\t}\n\n\tpublic void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterIndex, x, length);\n\t}\n\n\tpublic boolean isCloseOnCompletion() throws SQLException {\n\t\treturn delegate.isCloseOnCompletion();\n\t}\n\n\tpublic void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterIndex, reader, length);\n\t}\n\n\tpublic void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {\n\t\tdelegate.setAsciiStream(parameterIndex, x);\n\t}\n\n\tpublic void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {\n\t\tdelegate.setBinaryStream(parameterIndex, x);\n\t}\n\n\tpublic void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {\n\t\tdelegate.setCharacterStream(parameterIndex, reader);\n\t}\n\n\tpublic void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {\n\t\tdelegate.setNCharacterStream(parameterIndex, value);\n\t}\n\n\tpublic void setClob(int parameterIndex, Reader reader) throws SQLException {\n\t\tdelegate.setClob(parameterIndex, reader);\n\t}\n\n\tpublic void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {\n\t\tdelegate.setBlob(parameterIndex, inputStream);\n\t}\n\n\tpublic void setNClob(int parameterIndex, Reader reader) throws SQLException {\n\t\tdelegate.setNClob(parameterIndex, reader);\n\t}\n\n\tpublic long getLargeUpdateCount() throws SQLException {\n\t\treturn delegate.getLargeUpdateCount();\n\t}\n\n\tpublic void setLargeMaxRows(long max) throws SQLException {\n\t\tdelegate.setLargeMaxRows(max);\n\t}\n\n\tpublic long getLargeMaxRows() throws SQLException {\n\t\treturn delegate.getLargeMaxRows();\n\t}\n\n\tpublic long[] executeLargeBatch() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeBatch();\n\t}\n\n\tpublic long executeLargeUpdate(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, autoGeneratedKeys);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, columnIndexes);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, columnNames);\n\t}\n\n\tpublic void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException {\n\t\tdelegate.setObject(parameterIndex, x, targetSqlType);\n\t}\n\n\tpublic long executeLargeUpdate() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate();\n\t}\n\n\tpublic void setConnection(ConnectionImpl connection) {\n\t\tthis.connection = connection;\n\t}\n\n\tpublic PreparedStatement getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(PreparedStatement delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/StatementImpl.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.Statement;\n\npublic class StatementImpl implements Statement {\n\tprivate Statement delegate;\n\tprivate ConnectionImpl connection;\n\n\tpublic <T> T unwrap(Class<T> iface) throws SQLException {\n\t\treturn delegate.unwrap(iface);\n\t}\n\n\tpublic ResultSet executeQuery(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeQuery(sql);\n\t}\n\n\tpublic boolean isWrapperFor(Class<?> iface) throws SQLException {\n\t\treturn delegate.isWrapperFor(iface);\n\t}\n\n\tpublic int executeUpdate(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql);\n\t}\n\n\tpublic void close() throws SQLException {\n\t\tdelegate.close();\n\t}\n\n\tpublic int getMaxFieldSize() throws SQLException {\n\t\treturn delegate.getMaxFieldSize();\n\t}\n\n\tpublic void setMaxFieldSize(int max) throws SQLException {\n\t\tdelegate.setMaxFieldSize(max);\n\t}\n\n\tpublic int getMaxRows() throws SQLException {\n\t\treturn delegate.getMaxRows();\n\t}\n\n\tpublic void setMaxRows(int max) throws SQLException {\n\t\tdelegate.setMaxRows(max);\n\t}\n\n\tpublic void setEscapeProcessing(boolean enable) throws SQLException {\n\t\tdelegate.setEscapeProcessing(enable);\n\t}\n\n\tpublic int getQueryTimeout() throws SQLException {\n\t\treturn delegate.getQueryTimeout();\n\t}\n\n\tpublic void setQueryTimeout(int seconds) throws SQLException {\n\t\tdelegate.setQueryTimeout(seconds);\n\t}\n\n\tpublic void cancel() throws SQLException {\n\t\tdelegate.cancel();\n\t}\n\n\tpublic SQLWarning getWarnings() throws SQLException {\n\t\treturn delegate.getWarnings();\n\t}\n\n\tpublic void clearWarnings() throws SQLException {\n\t\tdelegate.clearWarnings();\n\t}\n\n\tpublic void setCursorName(String name) throws SQLException {\n\t\tdelegate.setCursorName(name);\n\t}\n\n\tpublic boolean execute(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql);\n\t}\n\n\tpublic ResultSet getResultSet() throws SQLException {\n\t\treturn delegate.getResultSet();\n\t}\n\n\tpublic int getUpdateCount() throws SQLException {\n\t\treturn delegate.getUpdateCount();\n\t}\n\n\tpublic boolean getMoreResults() throws SQLException {\n\t\treturn delegate.getMoreResults();\n\t}\n\n\tpublic void setFetchDirection(int direction) throws SQLException {\n\t\tdelegate.setFetchDirection(direction);\n\t}\n\n\tpublic int getFetchDirection() throws SQLException {\n\t\treturn delegate.getFetchDirection();\n\t}\n\n\tpublic void setFetchSize(int rows) throws SQLException {\n\t\tdelegate.setFetchSize(rows);\n\t}\n\n\tpublic int getFetchSize() throws SQLException {\n\t\treturn delegate.getFetchSize();\n\t}\n\n\tpublic int getResultSetConcurrency() throws SQLException {\n\t\treturn delegate.getResultSetConcurrency();\n\t}\n\n\tpublic int getResultSetType() throws SQLException {\n\t\treturn delegate.getResultSetType();\n\t}\n\n\tpublic void addBatch(String sql) throws SQLException {\n\t\tdelegate.addBatch(sql);\n\t}\n\n\tpublic void clearBatch() throws SQLException {\n\t\tdelegate.clearBatch();\n\t}\n\n\tpublic int[] executeBatch() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeBatch();\n\t}\n\n\tpublic Connection getConnection() throws SQLException {\n\t\treturn connection;\n\t}\n\n\tpublic boolean getMoreResults(int current) throws SQLException {\n\t\treturn delegate.getMoreResults(current);\n\t}\n\n\tpublic ResultSet getGeneratedKeys() throws SQLException {\n\t\treturn delegate.getGeneratedKeys();\n\t}\n\n\tpublic int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, autoGeneratedKeys);\n\t}\n\n\tpublic int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, columnIndexes);\n\t}\n\n\tpublic int executeUpdate(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeUpdate(sql, columnNames);\n\t}\n\n\tpublic boolean execute(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, autoGeneratedKeys);\n\t}\n\n\tpublic boolean execute(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, columnIndexes);\n\t}\n\n\tpublic boolean execute(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.execute(sql, columnNames);\n\t}\n\n\tpublic int getResultSetHoldability() throws SQLException {\n\t\treturn delegate.getResultSetHoldability();\n\t}\n\n\tpublic boolean isClosed() throws SQLException {\n\t\treturn delegate.isClosed();\n\t}\n\n\tpublic void setPoolable(boolean poolable) throws SQLException {\n\t\tdelegate.setPoolable(poolable);\n\t}\n\n\tpublic boolean isPoolable() throws SQLException {\n\t\treturn delegate.isPoolable();\n\t}\n\n\tpublic void closeOnCompletion() throws SQLException {\n\t\tdelegate.closeOnCompletion();\n\t}\n\n\tpublic boolean isCloseOnCompletion() throws SQLException {\n\t\treturn delegate.isCloseOnCompletion();\n\t}\n\n\tpublic long getLargeUpdateCount() throws SQLException {\n\t\treturn delegate.getLargeUpdateCount();\n\t}\n\n\tpublic void setLargeMaxRows(long max) throws SQLException {\n\t\tdelegate.setLargeMaxRows(max);\n\t}\n\n\tpublic long getLargeMaxRows() throws SQLException {\n\t\treturn delegate.getLargeMaxRows();\n\t}\n\n\tpublic long[] executeLargeBatch() throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeBatch();\n\t}\n\n\tpublic long executeLargeUpdate(String sql) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, autoGeneratedKeys);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, columnIndexes);\n\t}\n\n\tpublic long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {\n\t\tthis.connection.checkTransactionStatusIfNecessary();\n\t\treturn delegate.executeLargeUpdate(sql, columnNames);\n\t}\n\n\tpublic void setConnection(ConnectionImpl connection) {\n\t\tthis.connection = connection;\n\t}\n\n\tpublic Statement getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(Statement delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/XAConnectionImpl.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Set;\n\nimport javax.sql.ConnectionEvent;\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.StatementEvent;\nimport javax.sql.StatementEventListener;\nimport javax.sql.XAConnection;\nimport javax.transaction.xa.XAResource;\n\nimport org.bytesoft.bytejta.supports.resource.CommonResourceDescriptor;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class XAConnectionImpl implements XAConnection, ConnectionEventListener, StatementEventListener {\n\tstatic final Logger logger = LoggerFactory.getLogger(XAConnectionImpl.class);\n\n\tprivate final Set<ConnectionEventListener> connectionEventListeners = new HashSet<ConnectionEventListener>();\n\tprivate final Set<StatementEventListener> statementEventListeners = new HashSet<StatementEventListener>();\n\n\tprivate String identifier;\n\tprivate XAConnection delegate;\n\tprivate boolean closed;\n\tprivate XAResource xaResource;\n\n\tpublic void statementClosed(StatementEvent event) {\n\t\tIterator<StatementEventListener> itr = this.statementEventListeners.iterator();\n\t\twhile (itr.hasNext()) {\n\t\t\tStatementEventListener listener = itr.next();\n\t\t\tSQLException sqlException = event.getSQLException();\n\t\t\tPreparedStatement statement = event.getStatement();\n\t\t\tStatementEvent statementEvent = new StatementEvent(this, statement, sqlException);\n\t\t\ttry {\n\t\t\t\tlistener.statementClosed(statementEvent);\n\t\t\t} catch (RuntimeException error) {\n\t\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\t}\n\t\t} // end-while (itr.hasNext())\n\t}\n\n\tpublic void statementErrorOccurred(StatementEvent event) {\n\t\tIterator<StatementEventListener> itr = this.statementEventListeners.iterator();\n\t\twhile (itr.hasNext()) {\n\t\t\tStatementEventListener listener = itr.next();\n\t\t\tSQLException sqlException = event.getSQLException();\n\t\t\tPreparedStatement statement = event.getStatement();\n\t\t\tStatementEvent statementEvent = new StatementEvent(this, statement, sqlException);\n\t\t\ttry {\n\t\t\t\tlistener.statementErrorOccurred(statementEvent);\n\t\t\t} catch (RuntimeException error) {\n\t\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\t}\n\t\t} // end-while (itr.hasNext())\n\t}\n\n\tpublic void connectionClosed(ConnectionEvent event) {\n\t\tIterator<ConnectionEventListener> itr = this.connectionEventListeners.iterator();\n\t\twhile (itr.hasNext()) {\n\t\t\tConnectionEventListener listener = itr.next();\n\t\t\tSQLException sqlException = event.getSQLException();\n\t\t\tConnectionEvent connectionEvent = new ConnectionEvent(this, sqlException);\n\t\t\ttry {\n\t\t\t\tlistener.connectionClosed(connectionEvent);\n\t\t\t} catch (RuntimeException error) {\n\t\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\t}\n\t\t} // end-while (itr.hasNext())\n\t}\n\n\tpublic void connectionErrorOccurred(ConnectionEvent event) {\n\t\tIterator<ConnectionEventListener> itr = this.connectionEventListeners.iterator();\n\t\twhile (itr.hasNext()) {\n\t\t\tConnectionEventListener listener = itr.next();\n\t\t\tSQLException sqlException = event.getSQLException();\n\t\t\tConnectionEvent connectionEvent = new ConnectionEvent(this, sqlException);\n\t\t\ttry {\n\t\t\t\tlistener.connectionErrorOccurred(connectionEvent);\n\t\t\t} catch (RuntimeException error) {\n\t\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\t}\n\t\t} // end-while (itr.hasNext())\n\t}\n\n\tpublic Connection getConnection() throws SQLException {\n\t\tConnection delegateConnection = this.delegate.getConnection();\n\n\t\tConnectionImpl connection = new ConnectionImpl();\n\t\tconnection.setManagedConnection(this);\n\t\tconnection.setDelegate(delegateConnection);\n\n\t\treturn connection;\n\t}\n\n\tpublic void addConnectionEventListener(ConnectionEventListener listener) {\n\t\tthis.connectionEventListeners.add(listener);\n\t}\n\n\tpublic void removeConnectionEventListener(ConnectionEventListener listener) {\n\t\tthis.connectionEventListeners.remove(listener);\n\t}\n\n\tpublic void addStatementEventListener(StatementEventListener listener) {\n\t\tthis.statementEventListeners.add(listener);\n\t}\n\n\tpublic void removeStatementEventListener(StatementEventListener listener) {\n\t\tthis.statementEventListeners.remove(listener);\n\t}\n\n\tpublic XAResource getXAResource() throws SQLException {\n\t\tif (this.xaResource == null) {\n\t\t\tthis.initXAResourceIfNecessary();\n\t\t} // end-if (this.xaResource == null)\n\n\t\treturn this.xaResource;\n\t}\n\n\tprivate synchronized void initXAResourceIfNecessary() throws SQLException {\n\t\tif (this.xaResource == null) {\n\t\t\tXAResource delegateResource = this.delegate.getXAResource();\n\t\t\tif (XAResourceDescriptor.class.isInstance(delegateResource)) {\n\t\t\t\tthis.xaResource = delegateResource;\n\t\t\t} else {\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(delegateResource);\n\t\t\t\tdescriptor.setIdentifier(this.identifier);\n\t\t\t\tthis.xaResource = descriptor;\n\t\t\t}\n\t\t} // end-if (this.xaResource == null)\n\t}\n\n\tpublic void close() throws SQLException {\n\t\tif (this.closed == false) {\n\t\t\tthis.delegate.close();\n\t\t\tthis.closed = true;\n\t\t} // end-if (this.closed == false)\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic XAConnection getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(XAConnection delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/jdbc/XADataSourceImpl.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.jdbc;\n\nimport java.io.PrintWriter;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.logging.Logger;\n\nimport javax.sql.XAConnection;\nimport javax.sql.XADataSource;\n\nimport org.springframework.beans.factory.BeanNameAware;\n\npublic class XADataSourceImpl implements XADataSource, BeanNameAware {\n\tprivate String identifier;\n\tprivate XADataSource xaDataSource;\n\n\tpublic PrintWriter getLogWriter() throws SQLException {\n\t\treturn this.xaDataSource.getLogWriter();\n\t}\n\n\tpublic void setLogWriter(PrintWriter out) throws SQLException {\n\t\tthis.xaDataSource.setLogWriter(out);\n\t}\n\n\tpublic void setLoginTimeout(int seconds) throws SQLException {\n\t\tthis.xaDataSource.setLoginTimeout(seconds);\n\t}\n\n\tpublic int getLoginTimeout() throws SQLException {\n\t\treturn this.xaDataSource.getLoginTimeout();\n\t}\n\n\tpublic Logger getParentLogger() throws SQLFeatureNotSupportedException {\n\t\treturn this.xaDataSource.getParentLogger();\n\t}\n\n\tpublic XAConnection getXAConnection() throws SQLException {\n\t\tXAConnection delegate = this.xaDataSource.getXAConnection();\n\n\t\tXAConnectionImpl managed = new XAConnectionImpl();\n\t\tmanaged.setIdentifier(this.identifier);\n\t\tmanaged.setDelegate(delegate);\n\n\t\tdelegate.addConnectionEventListener(managed);\n\t\tdelegate.addStatementEventListener(managed);\n\n\t\treturn managed;\n\t}\n\n\tpublic XAConnection getXAConnection(String user, String password) throws SQLException {\n\t\tXAConnection delegate = this.xaDataSource.getXAConnection(user, password);\n\n\t\tXAConnectionImpl managed = new XAConnectionImpl();\n\t\tmanaged.setIdentifier(this.identifier);\n\t\tmanaged.setDelegate(delegate);\n\n\t\tdelegate.addConnectionEventListener(managed);\n\t\tdelegate.addStatementEventListener(managed);\n\n\t\treturn managed;\n\t}\n\n\tpublic void setBeanName(String name) {\n\t\tthis.setIdentifier(name);\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic XADataSource getXaDataSource() {\n\t\treturn xaDataSource;\n\t}\n\n\tpublic void setXaDataSource(XADataSource xaDataSource) {\n\t\tthis.xaDataSource = xaDataSource;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/properties/ConnectorResourcePropertySource.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.properties;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.AbstractResource;\nimport org.springframework.core.io.support.EncodedResource;\n\npublic class ConnectorResourcePropertySource extends PropertySource<Object> {\n\tprivate final Map<String, String> aliases = new HashMap<String, String>();\n\n\tprivate boolean enabled;\n\n\tpublic ConnectorResourcePropertySource(String name, EncodedResource source) {\n\t\tthis(name, source, new HashMap<String, String>());\n\t}\n\n\tpublic ConnectorResourcePropertySource(String name, EncodedResource source, Map<String, String> aliases) {\n\t\tsuper(name, source);\n\t\tthis.aliases.putAll(aliases);\n\n\t\tEncodedResource encoded = (EncodedResource) this.getSource();\n\t\tAbstractResource resource = (AbstractResource) encoded.getResource();\n\t\tString path = resource.getFilename();\n\n\t\tif (StringUtils.isBlank(path)) {\n\t\t\treturn;\n\t\t}\n\n\t\tString[] values = path.split(\":\");\n\t\tif (values.length != 2) {\n\t\t\treturn;\n\t\t}\n\n\t\tString protocol = values[0];\n\t\tString resName = values[1];\n\t\tif (\"bytejta\".equalsIgnoreCase(protocol) == false) {\n\t\t\treturn;\n\t\t} else if (\"connector.config\".equalsIgnoreCase(resName) == false) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.enabled = true;\n\t}\n\n\tpublic Object getProperty(String name) {\n\t\tif (this.enabled == false) {\n\t\t\treturn null;\n\t\t} else if (StringUtils.isBlank(name)) {\n\t\t\treturn null;\n\t\t} else if (StringUtils.startsWith(name, \"spring.datasource.\") == false) {\n\t\t\treturn null;\n\t\t}\n\n\t\tint dotIndex = name.lastIndexOf(\".\");\n\t\tString prefix = name.substring(0, dotIndex);\n\t\tString suffix = name.substring(dotIndex + 1);\n\n\t\tString alias = this.aliases.get(suffix);\n\t\tif (StringUtils.isBlank(alias)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn String.format(\"${%s.%s}\", prefix, alias);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/resource/properties/ConnectorResourcePropertySourceFactory.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.resource.properties;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.support.EncodedResource;\nimport org.springframework.core.io.support.PropertySourceFactory;\n\npublic class ConnectorResourcePropertySourceFactory implements PropertySourceFactory {\n\tstatic final Map<String, String> aliases = new HashMap<String, String>();\n\tstatic {\n\t\taliases.put(\"user\", \"username\");\n\t\taliases.put(\"jdbcUrl\", \"url\");\n\t}\n\n\tpublic static Map<String, String> getAliases() {\n\t\treturn aliases;\n\t}\n\n\tpublic PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {\n\t\tif (name == null) {\n\t\t\tname = String.format(\"%s@%s\", ConnectorResourcePropertySource.class, System.identityHashCode(resource));\n\t\t} // end-if (name == null)\n\n\t\treturn new ConnectorResourcePropertySource(name, resource, aliases);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/rpc/TransactionInterceptorImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.rpc;\n\nimport javax.transaction.RollbackException;\nimport javax.transaction.Status;\nimport javax.transaction.SystemException;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\n\nimport org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.TransactionParticipant;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.bytesoft.transaction.supports.rpc.TransactionRequest;\nimport org.bytesoft.transaction.supports.rpc.TransactionResponse;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionInterceptorImpl implements TransactionInterceptor, TransactionBeanFactoryAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionInterceptorImpl.class);\n\n\t@javax.inject.Inject\n\tprotected TransactionBeanFactory beanFactory;\n\n\tpublic void beforeSendRequest(TransactionRequest request) throws IllegalStateException {\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tif (transaction == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (transaction.getTransactionStatus() == Status.STATUS_MARKED_ROLLBACK) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"Transaction has been marked as rollback only, can not propagate its context to remote branch.\");\n\t\t} // end-if (transaction.getTransactionStatus() == Status.STATUS_MARKED_ROLLBACK)\n\n\t\tTransactionContext srcTransactionContext = transaction.getTransactionContext();\n\t\tTransactionContext transactionContext = srcTransactionContext.clone();\n\t\trequest.setTransactionContext(transactionContext);\n\t\ttry {\n\t\t\tRemoteCoordinator resource = request.getTargetTransactionCoordinator();\n\n\t\t\tRemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();\n\t\t\tdescriptor.setDelegate(resource);\n\n\t\t\tboolean participantEnlisted = transaction.enlistResource(descriptor);\n\t\t\t((TransactionRequestImpl) request).setParticipantEnlistFlag(participantEnlisted);\n\t\t} catch (IllegalStateException ex) {\n\t\t\tlogger.error(\"TransactionInterceptorImpl.beforeSendRequest(TransactionRequest)\", ex);\n\t\t\tthrow ex;\n\t\t} catch (RollbackException ex) {\n\t\t\ttransaction.setRollbackOnlyQuietly();\n\t\t\tlogger.error(\"TransactionInterceptorImpl.beforeSendRequest(TransactionRequest)\", ex);\n\t\t\tthrow new IllegalStateException(ex);\n\t\t} catch (SystemException ex) {\n\t\t\tlogger.error(\"TransactionInterceptorImpl.beforeSendRequest(TransactionRequest)\", ex);\n\t\t\tthrow new IllegalStateException(ex);\n\t\t}\n\t}\n\n\tpublic void beforeSendResponse(TransactionResponse response) throws IllegalStateException {\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tif (transaction == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tTransactionParticipant coordinator = this.beanFactory.getNativeParticipant();\n\n\t\tTransactionContext srcTransactionContext = transaction.getTransactionContext();\n\t\tTransactionContext transactionContext = srcTransactionContext.clone();\n\t\ttransactionContext.setPropagatedBy(srcTransactionContext.getPropagatedBy());\n\n\t\tresponse.setTransactionContext(transactionContext);\n\t\t// response.setSourceTransactionCoordinator(coordinator);\n\t\ttry {\n\t\t\tcoordinator.end(transactionContext, XAResource.TMSUCCESS);\n\t\t} catch (XAException ex) {\n\t\t\tthrow new IllegalStateException(ex);\n\t\t}\n\n\t}\n\n\tpublic void afterReceiveRequest(TransactionRequest request) throws IllegalStateException {\n\t\tTransactionContext srcTransactionContext = request.getTransactionContext();\n\t\tif (srcTransactionContext == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tTransactionParticipant coordinator = this.beanFactory.getNativeParticipant();\n\n\t\tTransactionContext transactionContext = srcTransactionContext.clone();\n\t\ttransactionContext.setPropagatedBy(srcTransactionContext.getPropagatedBy());\n\t\ttry {\n\t\t\tcoordinator.start(transactionContext, XAResource.TMNOFLAGS);\n\t\t} catch (XAException ex) {\n\t\t\tthrow new IllegalStateException(ex);\n\t\t}\n\t}\n\n\tpublic void afterReceiveResponse(TransactionResponse response) throws IllegalStateException {\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tTransactionContext transactionContext = response.getTransactionContext();\n\t\tRemoteCoordinator resource = response.getSourceTransactionCoordinator();\n\n\t\tboolean participantEnlistFlag = ((TransactionResponseImpl) response).isParticipantEnlistFlag();\n\t\t// boolean participantDelistFlag = ((TransactionResponseImpl) response).isParticipantDelistFlag();\n\n\t\tif (transaction == null || transactionContext == null) {\n\t\t\treturn;\n\t\t} else if (participantEnlistFlag == false) {\n\t\t\treturn;\n\t\t} else if (resource == null) {\n\t\t\tlogger.error(\"TransactionInterceptorImpl.afterReceiveResponse(TransactionRequest): remote coordinator is null.\");\n\t\t\tthrow new IllegalStateException(\"remote coordinator is null.\");\n\t\t}\n\n\t\ttry {\n\t\t\tRemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();\n\t\t\tdescriptor.setDelegate(resource);\n\t\t\t// descriptor.setIdentifier(resource.getIdentifier());\n\n\t\t\ttransaction.delistResource(descriptor, XAResource.TMSUCCESS);\n\t\t\t// transaction.delistResource(descriptor, participantDelistFlag ? XAResource.TMFAIL : XAResource.TMSUCCESS);\n\t\t} catch (IllegalStateException ex) {\n\t\t\tlogger.error(\"TransactionInterceptorImpl.afterReceiveResponse(TransactionRequest)\", ex);\n\t\t\tthrow ex;\n\t\t} catch (SystemException ex) {\n\t\t\tlogger.error(\"TransactionInterceptorImpl.afterReceiveResponse(TransactionRequest)\", ex);\n\t\t\tthrow new IllegalStateException(ex);\n\t\t}\n\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn this.beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/rpc/TransactionRequestImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.rpc;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.supports.rpc.TransactionRequest;\n\npublic class TransactionRequestImpl implements TransactionRequest {\n\n\tprivate RemoteCoordinator participantCoordinator;\n\tprivate TransactionContext transactionContext;\n\n\tprivate transient boolean participantEnlistFlag;\n\n\tprivate final Map<String, Object> headers = new HashMap<String, Object>();\n\n\tpublic Object getHeader(String name) {\n\t\treturn this.headers.get(name);\n\t}\n\n\tpublic void setHeader(String name, Object value) {\n\t\tthis.headers.put(name, value);\n\t}\n\n\tpublic RemoteCoordinator getTargetTransactionCoordinator() {\n\t\treturn this.participantCoordinator;\n\t}\n\n\tpublic void setTargetTransactionCoordinator(RemoteCoordinator remoteCoordinator) {\n\t\tthis.participantCoordinator = remoteCoordinator;\n\t}\n\n\tpublic TransactionContext getTransactionContext() {\n\t\treturn this.transactionContext;\n\t}\n\n\tpublic void setTransactionContext(TransactionContext transactionContext) {\n\t\tthis.transactionContext = transactionContext;\n\t}\n\n\tpublic boolean isParticipantEnlistFlag() {\n\t\treturn participantEnlistFlag;\n\t}\n\n\tpublic void setParticipantEnlistFlag(boolean participantEnlistFlag) {\n\t\tthis.participantEnlistFlag = participantEnlistFlag;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/rpc/TransactionResponseImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.rpc;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.supports.rpc.TransactionResponse;\n\npublic class TransactionResponseImpl implements TransactionResponse {\n\n\tprivate boolean participantStickyRequired = true;\n\tprivate boolean participantRollbackOnly;\n\n\tprivate RemoteCoordinator participantCoordinator;\n\tprivate TransactionContext transactionContext;\n\n\tprivate transient boolean participantEnlistFlag;\n\tprivate transient boolean participantDelistFlag;\n\n\tprivate final Map<String, Object> headers = new HashMap<String, Object>();\n\n\tpublic Object getHeader(String name) {\n\t\treturn this.headers.get(name);\n\t}\n\n\tpublic void setHeader(String name, Object value) {\n\t\tthis.headers.put(name, value);\n\t}\n\n\tpublic RemoteCoordinator getSourceTransactionCoordinator() {\n\t\treturn this.participantCoordinator;\n\t}\n\n\tpublic void setSourceTransactionCoordinator(RemoteCoordinator remoteCoordinator) {\n\t\tthis.participantCoordinator = remoteCoordinator;\n\t}\n\n\tpublic TransactionContext getTransactionContext() {\n\t\treturn this.transactionContext;\n\t}\n\n\tpublic void setTransactionContext(TransactionContext transactionContext) {\n\t\tthis.transactionContext = transactionContext;\n\t}\n\n\tpublic boolean isParticipantRollbackOnly() {\n\t\treturn participantRollbackOnly;\n\t}\n\n\tpublic void setParticipantRollbackOnly(boolean participantRollbackOnly) {\n\t\tthis.participantRollbackOnly = participantRollbackOnly;\n\t}\n\n\tpublic boolean isParticipantStickyRequired() {\n\t\treturn participantStickyRequired;\n\t}\n\n\tpublic void setParticipantStickyRequired(boolean participantStickyRequired) {\n\t\tthis.participantStickyRequired = participantStickyRequired;\n\t}\n\n\tpublic boolean isParticipantDelistFlag() {\n\t\treturn participantDelistFlag;\n\t}\n\n\tpublic void setParticipantDelistFlag(boolean participantDelistFlag) {\n\t\tthis.participantDelistFlag = participantDelistFlag;\n\t}\n\n\tpublic boolean isParticipantEnlistFlag() {\n\t\treturn participantEnlistFlag;\n\t}\n\n\tpublic void setParticipantEnlistFlag(boolean participantEnlistFlag) {\n\t\tthis.participantEnlistFlag = participantEnlistFlag;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/serialize/XAResourceDeserializerImpl.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.serialize;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport javax.jms.XAConnectionFactory;\nimport javax.jms.XASession;\nimport javax.resource.spi.ManagedConnection;\nimport javax.resource.spi.ManagedConnectionFactory;\nimport javax.sql.XAConnection;\nimport javax.sql.XADataSource;\nimport javax.transaction.xa.XAResource;\n\nimport org.bytesoft.bytejta.supports.jdbc.DataSourceHolder;\nimport org.bytesoft.bytejta.supports.jdbc.RecoveredResource;\nimport org.bytesoft.bytejta.supports.resource.CommonResourceDescriptor;\nimport org.bytesoft.bytejta.supports.resource.LocalXAResourceDescriptor;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\npublic class XAResourceDeserializerImpl implements XAResourceDeserializer, ApplicationContextAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(XAResourceDeserializerImpl.class);\n\n\tprivate Map<String, XAResourceDescriptor> cachedResourceMap = new ConcurrentHashMap<String, XAResourceDescriptor>();\n\tprivate ApplicationContext applicationContext;\n\n\tpublic XAResourceDescriptor deserialize(String identifier) {\n\n\t\tXAResourceDescriptor cachedResource = this.cachedResourceMap.get(identifier);\n\t\tif (cachedResource != null) {\n\t\t\treturn cachedResource;\n\t\t}\n\n\t\ttry {\n\t\t\tObject bean = this.applicationContext.getBean(identifier);\n\t\t\tXAResourceDescriptor resolvedResource = this.deserializeResource(identifier, bean);\n\t\t\tif (resolvedResource == null) {\n\t\t\t\tlogger.error(\"can not find a matching xa-resource(beanId= {})!\", identifier);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthis.cachedResourceMap.put(identifier, resolvedResource);\n\t\t\treturn resolvedResource;\n\t\t} catch (BeansException bex) {\n\t\t\tlogger.error(\"can not find a matching xa-resource(beanId= {})!\", identifier);\n\t\t\treturn null;\n\t\t} catch (Exception ex) {\n\t\t\tlogger.error(\"can not find a matching xa-resource(beanId= {})!\", identifier, ex);\n\t\t\treturn null;\n\t\t}\n\n\t}\n\n\tprivate XAResourceDescriptor deserializeResource(String identifier, Object bean) throws Exception {\n\t\tif (DataSourceHolder.class.isInstance(bean)) {\n\t\t\tDataSourceHolder holder = (DataSourceHolder) bean;\n\t\t\tRecoveredResource xares = new RecoveredResource();\n\t\t\txares.setDataSource(holder.getDataSource());\n\n\t\t\tLocalXAResourceDescriptor descriptor = new LocalXAResourceDescriptor();\n\t\t\tdescriptor.setDelegate(xares);\n\t\t\tdescriptor.setIdentifier(identifier);\n\n\t\t\treturn descriptor;\n\t\t} else if (javax.sql.DataSource.class.isInstance(bean)) {\n\t\t\tjavax.sql.DataSource dataSource = (javax.sql.DataSource) bean;\n\t\t\tRecoveredResource xares = new RecoveredResource();\n\t\t\txares.setDataSource(dataSource);\n\n\t\t\tLocalXAResourceDescriptor descriptor = new LocalXAResourceDescriptor();\n\t\t\tdescriptor.setDelegate(xares);\n\t\t\tdescriptor.setIdentifier(identifier);\n\n\t\t\treturn descriptor;\n\t\t} else if (XADataSource.class.isInstance(bean)) {\n\t\t\tXADataSource xaDataSource = (XADataSource) bean;\n\t\t\tXAConnection xaConnection = xaDataSource.getXAConnection();\n\t\t\tjava.sql.Connection connection = null;\n\t\t\ttry {\n\t\t\t\tconnection = xaConnection.getConnection();\n\t\t\t\tXAResource xares = xaConnection.getXAResource();\n\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(xares);\n\t\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\t\tdescriptor.setManaged(xaConnection);\n\n\t\t\t\treturn descriptor;\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.warn(ex.getMessage(), ex);\n\n\t\t\t\tXAResource xares = xaConnection.getXAResource();\n\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(xares);\n\t\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\t\tdescriptor.setManaged(xaConnection);\n\n\t\t\t\treturn descriptor;\n\t\t\t} finally {\n\t\t\t\tthis.closeQuietly(connection);\n\t\t\t}\n\t\t} else if (XAConnectionFactory.class.isInstance(bean)) {\n\t\t\tXAConnectionFactory connectionFactory = (XAConnectionFactory) bean;\n\t\t\tjavax.jms.XAConnection xaConnection = connectionFactory.createXAConnection();\n\t\t\tXASession xaSession = xaConnection.createXASession();\n\t\t\tjavax.jms.Session session = null;\n\t\t\ttry {\n\t\t\t\tsession = xaSession.getSession();\n\t\t\t\tXAResource xares = xaSession.getXAResource();\n\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(xares);\n\t\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\t\tdescriptor.setManaged(xaConnection);\n\n\t\t\t\treturn descriptor;\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.warn(ex.getMessage(), ex);\n\n\t\t\t\tXAResource xares = xaSession.getXAResource();\n\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(xares);\n\t\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\t\tdescriptor.setManaged(xaConnection);\n\n\t\t\t\treturn descriptor;\n\t\t\t} finally {\n\t\t\t\tthis.closeQuietly(session);\n\t\t\t}\n\t\t} else if (ManagedConnectionFactory.class.isInstance(bean)) {\n\t\t\tManagedConnectionFactory connectionFactory = (ManagedConnectionFactory) bean;\n\t\t\tManagedConnection managedConnection = connectionFactory.createManagedConnection(null, null);\n\t\t\tjavax.resource.cci.Connection connection = null;\n\t\t\ttry {\n\t\t\t\tconnection = (javax.resource.cci.Connection) managedConnection.getConnection(null, null);\n\t\t\t\tXAResource xares = managedConnection.getXAResource();\n\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(xares);\n\t\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\t\tdescriptor.setManaged(managedConnection);\n\n\t\t\t\treturn descriptor;\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.warn(ex.getMessage(), ex);\n\n\t\t\t\tXAResource xares = managedConnection.getXAResource();\n\n\t\t\t\tCommonResourceDescriptor descriptor = new CommonResourceDescriptor();\n\t\t\t\tdescriptor.setDelegate(xares);\n\t\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\t\tdescriptor.setManaged(managedConnection);\n\n\t\t\t\treturn descriptor;\n\t\t\t} finally {\n\t\t\t\tthis.closeQuietly(connection);\n\t\t\t}\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\n\t}\n\n\tprotected void closeQuietly(javax.resource.cci.Connection closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void closeQuietly(java.sql.Connection closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void closeQuietly(javax.jms.Session closeable) {\n\t\tif (closeable != null) {\n\t\t\ttry {\n\t\t\t\tcloseable.close();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/spring/ManagedConnectionFactoryPostProcessor.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.spring;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Proxy;\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport javax.jms.XAConnectionFactory;\nimport javax.resource.spi.ManagedConnectionFactory;\nimport javax.sql.XADataSource;\nimport javax.transaction.TransactionManager;\n\nimport org.apache.commons.dbcp2.managed.BasicManagedDataSource;\nimport org.bytesoft.bytejta.TransactionBeanFactoryImpl;\nimport org.bytesoft.bytejta.supports.jdbc.LocalXADataSource;\nimport org.bytesoft.bytejta.supports.resource.ManagedConnectionFactoryHandler;\nimport org.bytesoft.bytejta.supports.resource.jdbc.XADataSourceImpl;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.SmartInitializingSingleton;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.core.Ordered;\n\npublic class ManagedConnectionFactoryPostProcessor\n\t\timplements BeanPostProcessor, Ordered, SmartInitializingSingleton, ApplicationContextAware {\n\tstatic String BEAN_TRANSACTION_MANAGER = \"transactionManager\";\n\n\tprivate ApplicationContext applicationContext;\n\n\tpublic void afterSingletonsInstantiated() {\n\t\tMap<String, LocalXADataSource> beanMap = this.applicationContext.getBeansOfType(LocalXADataSource.class);\n\t\tIterator<Map.Entry<String, LocalXADataSource>> iterator = beanMap == null ? null : beanMap.entrySet().iterator();\n\t\twhile (iterator != null && iterator.hasNext()) {\n\t\t\tMap.Entry<String, LocalXADataSource> entry = iterator.next();\n\t\t\tLocalXADataSource bean = entry.getValue();\n\t\t\tthis.initializeTransactionManagerIfNecessary(bean);\n\t\t}\n\t}\n\n\tprivate void initializeTransactionManagerIfNecessary(LocalXADataSource target) {\n\t\tif (target.getTransactionManager() == null) {\n\t\t\tTransactionManager transactionManager = //\n\t\t\t\t\t(TransactionManager) this.applicationContext.getBean(BEAN_TRANSACTION_MANAGER);\n\t\t\ttarget.setTransactionManager(transactionManager);\n\t\t} // end-if (target.getTransactionManager() == null)\n\t}\n\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\treturn this.wrapManagedConnectionFactoryIfNecessary(bean, beanName);\n\t}\n\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\treturn this.wrapManagedConnectionFactoryIfNecessary(bean, beanName);\n\t}\n\n\tprivate Object wrapManagedConnectionFactoryIfNecessary(Object bean, String beanName) throws BeansException {\n\t\tClass<?> clazz = bean.getClass();\n\t\tClassLoader cl = clazz.getClassLoader();\n\n\t\tClass<?>[] interfaces = clazz.getInterfaces();\n\n\t\tif (this.hasAlreadyBeenWrappedBySelf(bean)) /* managed-connection-factory has already been wrapped */ {\n\t\t\treturn bean;\n\t\t} else if (LocalXADataSource.class.isInstance(bean)) {\n\t\t\tLocalXADataSource target = (LocalXADataSource) bean;\n\t\t\tthis.initializeTransactionManagerIfNecessary(target);\n\t\t\treturn bean;\n\t\t} else if (BasicManagedDataSource.class.isInstance(bean)) /* spring boot auto configuration */ {\n\t\t\tBasicManagedDataSource managedDataSource = (BasicManagedDataSource) bean;\n\t\t\tTransactionBeanFactory beanFactory = TransactionBeanFactoryImpl.getInstance();\n\t\t\tmanagedDataSource.setTransactionManager(beanFactory.getTransactionManager());\n\t\t\treturn bean;\n\t\t} else if (XADataSource.class.isInstance(bean)) {\n\t\t\tXADataSource xaDataSource = (XADataSource) bean;\n\t\t\tXADataSourceImpl wrappedDataSource = new XADataSourceImpl();\n\t\t\twrappedDataSource.setIdentifier(beanName);\n\t\t\twrappedDataSource.setXaDataSource(xaDataSource);\n\t\t\treturn wrappedDataSource;\n\t\t} else if (XAConnectionFactory.class.isInstance(bean)) {\n\t\t\tManagedConnectionFactoryHandler interceptor = new ManagedConnectionFactoryHandler(bean);\n\t\t\tinterceptor.setIdentifier(beanName);\n\t\t\treturn Proxy.newProxyInstance(cl, interfaces, interceptor);\n\t\t} else if (ManagedConnectionFactory.class.isInstance(bean)) {\n\t\t\tManagedConnectionFactoryHandler interceptor = new ManagedConnectionFactoryHandler(bean);\n\t\t\tinterceptor.setIdentifier(beanName);\n\t\t\treturn Proxy.newProxyInstance(cl, interfaces, interceptor);\n\t\t} else {\n\t\t\treturn bean;\n\t\t}\n\t}\n\n\tprivate boolean hasAlreadyBeenWrappedBySelf(Object bean) {\n\t\tif (XADataSourceImpl.class.isInstance(bean)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (Proxy.isProxyClass(bean.getClass()) == false) {\n\t\t\treturn false;\n\t\t}\n\n\t\tInvocationHandler handler = Proxy.getInvocationHandler(bean);\n\t\treturn ManagedConnectionFactoryHandler.class.isInstance(handler);\n\t}\n\n\tpublic int getOrder() {\n\t\treturn Ordered.LOWEST_PRECEDENCE;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/spring/TransactionBeanFactoryAutoInjector.java",
    "content": "/**\r\n * Copyright 2014-2016 yangming.liu<liuyangming@gmail.com>.\r\n *\r\n * This copyrighted material is made available to anyone wishing to use, modify,\r\n * copy, or redistribute it subject to the terms and conditions of the GNU\r\n * Lesser General Public License, as published by the Free Software Foundation.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r\n * for more details.\r\n *\r\n * You should have received a copy of the GNU Lesser General Public License\r\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\r\n */\r\npackage org.bytesoft.bytejta.supports.spring;\r\n\r\nimport java.util.Iterator;\r\nimport java.util.Map;\r\n\r\nimport org.bytesoft.transaction.TransactionBeanFactory;\r\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\nimport org.springframework.beans.BeansException;\r\nimport org.springframework.beans.factory.SmartInitializingSingleton;\r\nimport org.springframework.beans.factory.config.BeanPostProcessor;\r\nimport org.springframework.context.ApplicationContext;\r\nimport org.springframework.context.ApplicationContextAware;\r\nimport org.springframework.core.Ordered;\r\n\r\n@org.springframework.core.annotation.Order(org.springframework.core.Ordered.HIGHEST_PRECEDENCE)\r\npublic class TransactionBeanFactoryAutoInjector\r\n\t\timplements BeanPostProcessor, Ordered, SmartInitializingSingleton, ApplicationContextAware {\r\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionBeanFactoryAutoInjector.class);\r\n\r\n\tprivate ApplicationContext applicationContext;\r\n\r\n\tpublic void afterSingletonsInstantiated() {\r\n\t\tMap<String, TransactionBeanFactoryAware> beanMap = //\r\n\t\t\t\tthis.applicationContext.getBeansOfType(TransactionBeanFactoryAware.class);\r\n\t\tIterator<Map.Entry<String, TransactionBeanFactoryAware>> iterator = //\r\n\t\t\t\t(beanMap == null) ? null : beanMap.entrySet().iterator();\r\n\t\twhile (iterator != null && iterator.hasNext()) {\r\n\t\t\tMap.Entry<String, TransactionBeanFactoryAware> entry = iterator.next();\r\n\t\t\tTransactionBeanFactoryAware bean = entry.getValue();\r\n\t\t\tthis.initializeTransactionBeanFactoryIfNecessary(bean);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\r\n\t\treturn bean;\r\n\t}\r\n\r\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\r\n\t\tif (TransactionBeanFactoryAware.class.isInstance(bean)) {\r\n\t\t\tthis.initializeTransactionBeanFactoryIfNecessary((TransactionBeanFactoryAware) bean);\r\n\t\t} // end-if (TransactionBeanFactoryAware.class.isInstance(bean))\r\n\r\n\t\treturn bean;\r\n\t}\r\n\r\n\tprivate void initializeTransactionBeanFactoryIfNecessary(TransactionBeanFactoryAware aware) {\r\n\t\tif (aware.getBeanFactory() == null) {\r\n\t\t\tTransactionBeanFactory beanFactory = //\r\n\t\t\t\t\tthis.applicationContext.getBean(TransactionBeanFactory.class);\r\n\t\t\taware.setBeanFactory(beanFactory);\r\n\t\t} // end-if (aware.getBeanFactory() == null)\r\n\t}\r\n\r\n\tpublic int getOrder() {\r\n\t\treturn Ordered.HIGHEST_PRECEDENCE;\r\n\t}\r\n\r\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\r\n\t\tthis.applicationContext = applicationContext;\r\n\t}\r\n\r\n}\r\n"
  },
  {
    "path": "bytejta-supports/src/main/java/org/bytesoft/bytejta/supports/spring/TransactionDebuggablePostProcessor.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.spring;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.transaction.aware.TransactionDebuggable;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.core.env.Environment;\n\npublic class TransactionDebuggablePostProcessor implements BeanPostProcessor, EnvironmentAware {\n\tstatic final String KEY_DEBUGGABLE = \"org.bytesoft.bytejta.debuggable\";\n\n\tprivate Environment environment;\n\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\tthis.setDebuggableIfNecessary(bean);\n\t\treturn bean;\n\t}\n\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tthis.setDebuggableIfNecessary(bean);\n\t\treturn bean;\n\t}\n\n\tprivate void setDebuggableIfNecessary(Object bean) {\n\t\tif (TransactionDebuggable.class.isInstance(bean)) {\n\t\t\tString debuggable = this.environment.getProperty(KEY_DEBUGGABLE);\n\t\t\tTransactionDebuggable target = (TransactionDebuggable) bean;\n\t\t\ttarget.setDebuggingEnabled(StringUtils.equalsIgnoreCase(Boolean.TRUE.toString(), debuggable));\n\t\t}\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports/src/main/resources/bytejta-supports-core.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns:context=\"http://www.springframework.org/schema/context\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n\txmlns:tx=\"http://www.springframework.org/schema/tx\"\n\txsi:schemaLocation=\"http://www.springframework.org/schema/beans    \n           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    \n           http://www.springframework.org/schema/context    \n           http://www.springframework.org/schema/context/spring-context-3.0.xsd    \n           http://www.springframework.org/schema/aop    \n           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    \n           http://www.springframework.org/schema/tx \n           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\">\n\n\t<description>The bytejta transaction manager module</description>\n\n\t<bean class=\"org.bytesoft.bytejta.supports.spring.TransactionBeanFactoryAutoInjector\" />\n\t<bean class=\"org.bytesoft.bytejta.supports.spring.ManagedConnectionFactoryPostProcessor\" />\n\n\t<bean id=\"bytejtaUserTransaction\" class=\"org.bytesoft.bytejta.UserTransactionImpl\" />\n\n\t<bean id=\"transactionManager\" class=\"org.bytesoft.bytejta.TransactionManagerImpl\" />\n\t<bean id=\"bytejtaTransactionCoordinator\" class=\"org.bytesoft.bytejta.TransactionCoordinator\" />\n\n\t<bean id=\"bytejtaTransactionRepository\" class=\"org.bytesoft.bytejta.TransactionRepositoryImpl\" />\n\t<bean id=\"bytejtaTransactionLogger\" class=\"org.bytesoft.bytejta.logging.SampleTransactionLogger\" />\n\t<bean id=\"bytejtaTransactionRecovery\" class=\"org.bytesoft.bytejta.TransactionRecoveryImpl\" />\n\t<bean id=\"bytejtaTransactionLock\" class=\"org.bytesoft.bytejta.VacantTransactionLock\" />\n\n\t<bean id=\"bytejtaXidFactory\" class=\"org.bytesoft.bytejta.xa.XidFactoryImpl\" />\n\t<bean id=\"bytejtaTransactionInterceptor\" class=\"org.bytesoft.bytejta.supports.rpc.TransactionInterceptorImpl\" />\n\n</beans>"
  },
  {
    "path": "bytejta-supports/src/main/resources/bytejta-supports-standalone.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns:context=\"http://www.springframework.org/schema/context\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n\txmlns:tx=\"http://www.springframework.org/schema/tx\"\n\txsi:schemaLocation=\"http://www.springframework.org/schema/beans    \n           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    \n           http://www.springframework.org/schema/context    \n           http://www.springframework.org/schema/context/spring-context-3.0.xsd    \n           http://www.springframework.org/schema/aop    \n           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    \n           http://www.springframework.org/schema/tx \n           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\">\n\n\t<import resource=\"classpath:bytejta-supports-core.xml\" />\n\t<import resource=\"classpath:bytejta-supports-task.xml\" />\n\n\t<!-- <bean class=\"org.bytesoft.bytejta.supports.dubbo.TransactionEndpointPostProcessor\" /> -->\n\t<!-- <bean class=\"org.bytesoft.bytejta.supports.dubbo.DubboConfigPostProcessor\" /> -->\n\t<!-- <bean class=\"org.bytesoft.bytejta.supports.dubbo.TransactionConfigPostProcessor\" /> -->\n\n\t<bean id=\"bytejtaXAResourceDeserializer\" class=\"org.bytesoft.bytejta.logging.deserializer.XAResourceArchiveDeserializer\" />\n\t<bean id=\"bytejtaTransactionDeserializer\" class=\"org.bytesoft.bytejta.logging.deserializer.TransactionArchiveDeserializer\">\n\t\t<property name=\"resourceArchiveDeserializer\" ref=\"bytejtaXAResourceDeserializer\" />\n\t</bean>\n\t<bean id=\"bytejtaArchiveDeserializer\" class=\"org.bytesoft.bytejta.logging.ArchiveDeserializerImpl\">\n\t\t<property name=\"transactionArchiveDeserializer\" ref=\"bytejtaTransactionDeserializer\" />\n\t\t<property name=\"xaResourceArchiveDeserializer\" ref=\"bytejtaXAResourceDeserializer\" />\n\t</bean>\n\n\t<bean id=\"bytejtaResourceDeserializer\" class=\"org.bytesoft.bytejta.supports.serialize.XAResourceDeserializerImpl\" />\n\n\t<bean id=\"bytejtaBeanFactory\" class=\"org.bytesoft.bytejta.TransactionBeanFactoryImpl\" factory-method=\"getInstance\">\n\t\t<property name=\"transactionManager\" ref=\"transactionManager\" />\n\t\t<property name=\"xidFactory\" ref=\"bytejtaXidFactory\" />\n\t\t<property name=\"transactionTimer\" ref=\"transactionManager\" />\n\t\t<property name=\"transactionLogger\" ref=\"bytejtaTransactionLogger\" />\n\t\t<property name=\"transactionRepository\" ref=\"bytejtaTransactionRepository\" />\n\t\t<property name=\"transactionInterceptor\" ref=\"bytejtaTransactionInterceptor\" />\n\t\t<property name=\"transactionRecovery\" ref=\"bytejtaTransactionRecovery\" />\n\t\t<property name=\"transactionCoordinator\" ref=\"bytejtaTransactionCoordinator\" />\n\t\t<property name=\"transactionLock\" ref=\"bytejtaTransactionLock\" />\n\t\t<property name=\"archiveDeserializer\" ref=\"bytejtaArchiveDeserializer\" />\n\t\t<property name=\"resourceDeserializer\" ref=\"bytejtaResourceDeserializer\" />\n\t</bean>\n\n\t<bean id=\"jtaTransactionManager\" class=\"org.springframework.transaction.jta.JtaTransactionManager\">\n\t\t<property name=\"userTransaction\" ref=\"bytejtaUserTransaction\" />\n\t\t<property name=\"transactionManager\" ref=\"transactionManager\" />\n\t</bean>\n\t<tx:annotation-driven transaction-manager=\"jtaTransactionManager\" />\n\n</beans>"
  },
  {
    "path": "bytejta-supports/src/main/resources/bytejta-supports-task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns:context=\"http://www.springframework.org/schema/context\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n\txmlns:tx=\"http://www.springframework.org/schema/tx\"\n\txsi:schemaLocation=\"http://www.springframework.org/schema/beans    \n           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    \n           http://www.springframework.org/schema/context    \n           http://www.springframework.org/schema/context/spring-context-3.0.xsd    \n           http://www.springframework.org/schema/aop    \n           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    \n           http://www.springframework.org/schema/tx \n           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\">\n\n\t<bean id=\"transactionWork\" class=\"org.bytesoft.bytejta.work.TransactionWork\" />\n\n\t<bean id=\"transactionWorkManager\" class=\"org.bytesoft.transaction.work.SimpleWorkManager\" />\n\t<bean id=\"transactionResourceAdapter\" class=\"org.bytesoft.transaction.adapter.ResourceAdapterImpl\">\n\t\t<property name=\"workList\">\n\t\t\t<list>\n\t\t\t\t<ref bean=\"transactionWork\" />\n\t\t\t</list>\n\t\t</property>\n\t</bean>\n\t<bean id=\"resourceAdapter\" class=\"org.springframework.jca.support.ResourceAdapterFactoryBean\">\n\t\t<property name=\"workManager\" ref=\"transactionWorkManager\" />\n\t\t<property name=\"resourceAdapter\" ref=\"transactionResourceAdapter\" />\n\t</bean>\n\n</beans>"
  },
  {
    "path": "bytejta-supports-dubbo/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.bytesoft</groupId>\n\t\t<artifactId>bytejta-parent</artifactId>\n\t\t<version>0.5.0-BETA9</version>\n\t</parent>\n\n\t<artifactId>bytejta-supports-dubbo</artifactId>\n\t<packaging>jar</packaging>\n\n\t<name>bytejta-supports-dubbo</name>\n\t<url>http://www.bytesoft.org</url>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t<artifactId>bytejta-supports</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t\t<artifactId>spring</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-autoconfigure</artifactId>\n\t\t</dependency>\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/DubboRemoteCoordinator.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionParticipant;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class DubboRemoteCoordinator implements InvocationHandler {\n\tpublic static final int KEY_PARTICIPANT_TYPE_GLOBAL = 0;\n\tpublic static final int KEY_PARTICIPANT_TYPE_SYSTEM = 1;\n\tpublic static final int KEY_PARTICIPANT_TYPE_EXACT = 2;\n\n\tstatic final Logger logger = LoggerFactory.getLogger(DubboRemoteCoordinator.class);\n\n\tprivate RemoteCoordinator remoteCoordinator;\n\tprivate int coordinatorType; // 0, global; 1, system; 2, direct\n\tprivate RemoteNode invocationContext;\n\tprivate RemoteCoordinator proxyCoordinator;\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tInvocationContextRegistry invocationRegistry = InvocationContextRegistry.getInstance();\n\t\ttry {\n\t\t\tinvocationRegistry.associateInvocationContext(this.invocationContext);\n\t\t\tClass<?> clazz = method.getDeclaringClass();\n\t\t\tString methodName = method.getName();\n\t\t\tClass<?> returnType = method.getReturnType();\n\t\t\tif (Object.class.equals(clazz)) {\n\t\t\t\treturn method.invoke(this, args);\n\t\t\t} else if (TransactionParticipant.class.equals(clazz)) {\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t} else if (RemoteCoordinator.class.equals(clazz)) {\n\t\t\t\tif (\"getIdentifier\".equals(methodName)) {\n\t\t\t\t\treturn this.getParticipantsIdentifier(proxy, method, args);\n\t\t\t\t} else if (\"getApplication\".equals(methodName)) {\n\t\t\t\t\treturn this.getParticipantsApplication(proxy, method, args);\n\t\t\t\t} else if (\"getRemoteAddr\".equals(methodName) && RemoteAddr.class.equals(returnType)) {\n\t\t\t\t\tString identifier = this.getParticipantsIdentifier(proxy, method, args);\n\t\t\t\t\treturn identifier == null ? null : CommonUtils.getRemoteAddr(identifier);\n\t\t\t\t} else if (\"getRemoteNode\".equals(methodName) && RemoteNode.class.equals(returnType)) {\n\t\t\t\t\tString identifier = this.getParticipantsIdentifier(proxy, method, args);\n\t\t\t\t\treturn identifier == null ? null : CommonUtils.getRemoteNode(identifier);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t\t}\n\t\t\t} else if (XAResource.class.equals(clazz)) {\n\t\t\t\tString serverHost = this.invocationContext == null ? null : this.invocationContext.getServerHost();\n\t\t\t\tint serverPort = this.invocationContext == null ? 0 : this.invocationContext.getServerPort();\n\t\t\t\tString remoteText = String.format(\"%s:%s:%s\", serverHost, null, serverPort);\n\t\t\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(remoteText);\n\t\t\t\tif (\"start\".equals(methodName)) {\n\t\t\t\t\tif (this.invocationContext == null) {\n\t\t\t\t\t\tthrow new IllegalAccessException();\n\t\t\t\t\t} else if (participantRegistry.getRemoteNode(remoteAddr) != null) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn this.invokeForGeneric(proxy, method, args);\n\t\t\t\t\t}\n\t\t\t\t} else if (\"prepare\".equals(methodName)) {\n\t\t\t\t\treturn this.invokeForGeneric(proxy, method, args);\n\t\t\t\t} else if (\"commit\".equals(methodName)) {\n\t\t\t\t\treturn this.invokeForGeneric(proxy, method, args);\n\t\t\t\t} else if (\"rollback\".equals(methodName)) {\n\t\t\t\t\treturn this.invokeForGeneric(proxy, method, args);\n\t\t\t\t} else if (\"recover\".equals(methodName)) {\n\t\t\t\t\treturn this.invokeForGeneric(proxy, method, args);\n\t\t\t\t} else if (\"forget\".equals(methodName)) {\n\t\t\t\t\treturn this.invokeForGeneric(proxy, method, args);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new IllegalAccessException();\n\t\t\t}\n\t\t} finally {\n\t\t\tinvocationRegistry.desociateInvocationContext();\n\t\t}\n\t}\n\n\tprivate String getParticipantsIdentifier(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tif (this.invocationContext == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tString serverHost = this.invocationContext == null ? null : this.invocationContext.getServerHost();\n\t\tString serviceKey = this.invocationContext == null ? null : this.invocationContext.getServiceKey();\n\t\tint serverPort = this.invocationContext == null ? 0 : this.invocationContext.getServerPort();\n\t\tif (StringUtils.isNotBlank(serviceKey) && StringUtils.equalsIgnoreCase(serviceKey, \"null\") == false) {\n\t\t\treturn String.format(\"%s:%s:%s\", serverHost, serviceKey, serverPort);\n\t\t} else {\n\t\t\tObject application = this.getParticipantsApplication(proxy, method, args);\n\t\t\treturn String.format(\"%s:%s:%s\", serverHost, application, serverPort);\n\t\t}\n\t}\n\n\tprivate Object getParticipantsApplication(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tif (this.invocationContext == null) {\n\t\t\treturn null;\n\t\t} else if (StringUtils.isNotBlank(this.invocationContext.getServiceKey())) {\n\t\t\treturn this.invocationContext.getServiceKey();\n\t\t}\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\n\t\tString serverHost = this.invocationContext.getServerHost();\n\t\tint serverPort = this.invocationContext.getServerPort();\n\t\tRemoteAddr remoteAddr = new RemoteAddr();\n\t\tremoteAddr.setServerHost(serverHost);\n\t\tremoteAddr.setServerPort(serverPort);\n\t\tRemoteNode remoteNode = participantRegistry.getRemoteNode(remoteAddr);\n\t\tif (remoteNode != null) {\n\t\t\tthis.invocationContext.setServiceKey(remoteNode.getServiceKey());\n\t\t\treturn this.invocationContext.getServiceKey();\n\t\t}\n\n\t\tObject result = this.invokeForSpecifiedDestination(proxy, method, args);\n\t\tString application = CommonUtils.getApplication(String.valueOf(result));\n\n\t\tif (StringUtils.isBlank(application) || StringUtils.equals(application, \"null\")) {\n\t\t\treturn null;\n\t\t}\n\n\t\tthis.invocationContext.setServiceKey(application);\n\n\t\tif (participantRegistry.containsRemoteNode(remoteAddr) == false) {\n\t\t\tRemoteNode targetNode = new RemoteNode();\n\t\t\ttargetNode.setServerHost(serverHost);\n\t\t\ttargetNode.setServiceKey(application);\n\t\t\ttargetNode.setServerPort(serverPort);\n\t\t\tparticipantRegistry.putRemoteNode(remoteAddr, targetNode);\n\t\t}\n\n\t\treturn application;\n\t}\n\n\tpublic Object invokeForGeneric(Object proxy, Method method, Object[] args) throws Throwable {\n\t\ttry {\n\t\t\treturn method.invoke(this.remoteCoordinator, args);\n\t\t} catch (IllegalArgumentException error) {\n\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} catch (InvocationTargetException error) {\n\t\t\tthrow error.getTargetException();\n\t\t} catch (IllegalAccessException error) {\n\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t}\n\t}\n\n\tpublic Object invokeForSpecifiedDestination(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tString serverHost = this.invocationContext.getServerHost();\n\t\tint serverPort = this.invocationContext.getServerPort();\n\t\tString address = String.format(\"%s:%s:%s\", serverHost, null, serverPort);\n\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(address);\n\n\t\tRemoteCoordinator participant = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\tif (participant == null) {\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t}\n\n\t\ttry {\n\t\t\treturn method.invoke(participant, args);\n\t\t} catch (IllegalArgumentException error) {\n\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t} catch (InvocationTargetException error) {\n\t\t\tthrow error.getTargetException();\n\t\t} catch (IllegalAccessException error) {\n\t\t\tlogger.warn(\"Error occurred!\", error);\n\t\t\tthrow new XAException(XAException.XAER_RMERR);\n\t\t}\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"<remote-resource| id= %s:%s:%s>\", this.invocationContext.getServerHost(),\n\t\t\t\tthis.invocationContext.getServiceKey(), this.invocationContext.getServerPort());\n\t}\n\n\tpublic RemoteNode getInvocationContext() {\n\t\treturn invocationContext;\n\t}\n\n\tpublic void setInvocationContext(RemoteNode invocationContext) {\n\t\tthis.invocationContext = invocationContext;\n\t}\n\n\tpublic int getCoordinatorType() {\n\t\treturn coordinatorType;\n\t}\n\n\tpublic void setCoordinatorType(int coordinatorType) {\n\t\tthis.coordinatorType = coordinatorType;\n\t}\n\n\tpublic RemoteCoordinator getProxyCoordinator() {\n\t\treturn proxyCoordinator;\n\t}\n\n\tpublic void setProxyCoordinator(RemoteCoordinator proxyCoordinator) {\n\t\tthis.proxyCoordinator = proxyCoordinator;\n\t}\n\n\tpublic RemoteCoordinator getRemoteCoordinator() {\n\t\treturn remoteCoordinator;\n\t}\n\n\tpublic void setRemoteCoordinator(RemoteCoordinator remoteCoordinator) {\n\t\tthis.remoteCoordinator = remoteCoordinator;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/InvocationContextRegistry.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.bytesoft.transaction.remote.RemoteNode;\n\npublic final class InvocationContextRegistry {\n\tprivate static final InvocationContextRegistry instance = new InvocationContextRegistry();\n\n\tprivate final Map<Thread, RemoteNode> contexts = new ConcurrentHashMap<Thread, RemoteNode>();\n\n\tprivate InvocationContextRegistry() {\n\t\tif (instance != null) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic static InvocationContextRegistry getInstance() {\n\t\treturn instance;\n\t}\n\n\tpublic void associateInvocationContext(RemoteNode context) {\n\t\tthis.contexts.put(Thread.currentThread(), context);\n\t}\n\n\tpublic RemoteNode desociateInvocationContext() {\n\t\treturn this.contexts.remove(Thread.currentThread());\n\t}\n\n\tpublic RemoteNode getInvocationContext() {\n\t\treturn this.contexts.get(Thread.currentThread());\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/TransactionBeanRegistry.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.NoSuchBeanDefinitionException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.core.env.Environment;\n\npublic class TransactionBeanRegistry implements TransactionBeanFactoryAware, ApplicationContextAware, EnvironmentAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionBeanRegistry.class);\n\n\tprivate static final TransactionBeanRegistry instance = new TransactionBeanRegistry();\n\n\tprivate RemoteCoordinator consumeCoordinator;\n\tprivate ApplicationContext applicationContext;\n\tprivate Environment environment;\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\n\tprivate Lock lock = new ReentrantLock();\n\tprivate Condition condition = this.lock.newCondition();\n\n\tprivate TransactionBeanRegistry() {\n\t\tif (instance != null) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic static TransactionBeanRegistry getInstance() {\n\t\treturn instance;\n\t}\n\n\tpublic RemoteCoordinator getConsumeCoordinator() {\n\t\tif (this.consumeCoordinator != null) {\n\t\t\treturn this.consumeCoordinator;\n\t\t} else {\n\t\t\treturn this.doGetConsumeCoordinator();\n\t\t}\n\t}\n\n\tprivate RemoteCoordinator doGetConsumeCoordinator() {\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\twhile (this.consumeCoordinator == null) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.condition.await(1, TimeUnit.SECONDS);\n\t\t\t\t} catch (InterruptedException ex) {\n\t\t\t\t\tlogger.debug(ex.getMessage());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ConsumeCoordinator is injected by the TransactionConfigPostProcessor, which has a slight delay.\n\t\t\treturn consumeCoordinator;\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic void setConsumeCoordinator(RemoteCoordinator consumeCoordinator) {\n\t\ttry {\n\t\t\tthis.lock.lock();\n\t\t\tif (this.consumeCoordinator == null) {\n\t\t\t\tthis.consumeCoordinator = consumeCoordinator;\n\t\t\t\tthis.condition.signalAll();\n\t\t\t} else {\n\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\"Field 'consumeCoordinator' has already been set, please check your app whether it imports ByteJTA repeatedly!\");\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.lock.unlock();\n\t\t}\n\t}\n\n\tpublic <T> T getBean(Class<T> requiredType) {\n\t\ttry {\n\t\t\treturn this.applicationContext.getBean(requiredType);\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\treturn null; // ignore\n\t\t}\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tpublic Environment getEnvironment() {\n\t\treturn environment;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/config/DubboSupportConfiguration.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.config;\n\nimport javax.transaction.UserTransaction;\n\nimport org.bytesoft.bytejta.supports.resource.properties.ConnectorResourcePropertySourceFactory;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.context.annotation.EnableAspectJAutoProxy;\nimport org.springframework.context.annotation.ImportResource;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.core.env.Environment;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\nimport org.springframework.transaction.annotation.TransactionManagementConfigurer;\nimport org.springframework.transaction.jta.JtaTransactionManager;\n\n@PropertySource(value = \"bytejta:connector.config\", factory = ConnectorResourcePropertySourceFactory.class)\n@ImportResource({ \"classpath:bytejta-supports-dubbo.xml\" })\n@EnableAspectJAutoProxy(proxyTargetClass = true)\n@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })\n@EnableTransactionManagement\npublic class DubboSupportConfiguration implements TransactionManagementConfigurer, ApplicationContextAware, EnvironmentAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(DubboSupportConfiguration.class);\n\n\tprivate Environment environment;\n\tprivate ApplicationContext applicationContext;\n\n\tpublic PlatformTransactionManager annotationDrivenTransactionManager() {\n\t\tJtaTransactionManager jtaTransactionManager = new JtaTransactionManager();\n\t\tjtaTransactionManager.setTransactionManager(this.applicationContext.getBean(TransactionManager.class));\n\t\tjtaTransactionManager.setUserTransaction(this.applicationContext.getBean(UserTransaction.class));\n\t\treturn jtaTransactionManager;\n\t}\n\n\tpublic Environment getEnvironment() {\n\t\treturn environment;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/ext/ILoadBalancer.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.ext;\n\nimport java.util.List;\n\nimport com.alibaba.dubbo.common.URL;\nimport com.alibaba.dubbo.common.extension.SPI;\nimport com.alibaba.dubbo.rpc.Invocation;\nimport com.alibaba.dubbo.rpc.Invoker;\nimport com.alibaba.dubbo.rpc.RpcException;\n\n@SPI\npublic interface ILoadBalancer {\n\n\tpublic <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/internal/TransactionBeanConfigValidator.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.internal;\n\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.FatalBeanException;\nimport org.springframework.beans.MutablePropertyValues;\nimport org.springframework.beans.PropertyValue;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.BeanFactoryPostProcessor;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\n\nimport com.alibaba.dubbo.config.ProtocolConfig;\nimport com.alibaba.dubbo.config.spring.ServiceBean;\nimport com.alibaba.dubbo.remoting.RemotingException;\n\npublic class TransactionBeanConfigValidator implements BeanPostProcessor, BeanFactoryPostProcessor {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionBeanConfigValidator.class);\n\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\treturn bean;\n\t}\n\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tif (ProtocolConfig.class.isInstance(bean)) {\n\t\t\tthis.validateProtocolConfig(beanName, (ProtocolConfig) bean);\n\t\t} else if (ServiceBean.class.isInstance(bean)) {\n\t\t\tthis.validateServiceBean(beanName, (ServiceBean<?>) bean);\n\t\t}\n\n\t\treturn bean;\n\t}\n\n\tprivate void validateProtocolConfig(String beanName, ProtocolConfig protocolConfig) throws BeansException {\n\t\tInteger port = protocolConfig.getPort();\n\t\tif (port == null) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\t\"The value of the attribute 'port' (<dubbo:protocol port='...' />) must be explicitly specified.\");\n\t\t} else if (port.intValue() <= 0) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\t\"The value of the attribute 'port' (<dubbo:protocol port='...' />) must be explicitly specified and not equal to -1.\");\n\t\t}\n\t}\n\n\tprivate void validateServiceBean(String beanName, ServiceBean<?> serviceBean) throws BeansException {\n\t\tInteger retries = serviceBean.getRetries();\n\t\tString loadbalance = serviceBean.getLoadbalance();\n\t\tString cluster = serviceBean.getCluster();\n\t\tString filter = serviceBean.getFilter();\n\t\tString group = serviceBean.getGroup();\n\n\t\tif (StringUtils.isBlank(group)) {\n\t\t\treturn;\n\t\t} else if (StringUtils.equalsIgnoreCase(\"x-bytejta\", group) == false\n\t\t\t\t&& StringUtils.lowerCase(group).startsWith(\"x-bytejta-\") == false) {\n\t\t\treturn;\n\t\t}\n\n\t\tString[] filterArray = filter == null ? new String[0] : filter.split(\"\\\\s*,\\\\s*\");\n\n\t\tif (retries != null && retries.intValue() >= 0) {\n\t\t\tthrow new FatalBeanException(String.format(\"The value of attr 'retries'(beanId= %s) should be '-1'.\", beanName));\n\t\t} else if (loadbalance == null || StringUtils.equals(\"bytejta\", loadbalance) == false) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\tString.format(\"The value of attr 'loadbalance'(beanId= %s) should be 'bytejta'.\", beanName));\n\t\t} else if (cluster == null || StringUtils.equals(\"failfast\", cluster) == false) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\tString.format(\"The value of attribute 'cluster' (beanId= %s) must be 'failfast'.\", beanName));\n\t\t} else if (filterArray.length == 0) {\n\t\t\tthrow new FatalBeanException(String.format(\"The value of attr 'filter'(beanId= %s) must be null.\", beanName));\n\t\t} else if (StringUtils.equalsIgnoreCase(filterArray[0], \"bytejta\") == false) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\tString.format(\"The first value of attr 'filter'(beanId= %s) should be 'bytejta'.\", beanName));\n\t\t}\n\t}\n\n\tprivate void validateReferenceConfig(String beanName, BeanDefinition beanDef) throws BeansException {\n\t\tMutablePropertyValues mpv = beanDef.getPropertyValues();\n\t\tPropertyValue group = mpv.getPropertyValue(\"group\");\n\t\tPropertyValue retries = mpv.getPropertyValue(\"retries\");\n\t\tPropertyValue loadbalance = mpv.getPropertyValue(\"loadbalance\");\n\t\tPropertyValue cluster = mpv.getPropertyValue(\"cluster\");\n\t\tPropertyValue filter = mpv.getPropertyValue(\"filter\");\n\n\t\tString filterValue = filter == null || filter.getValue() == null ? null : String.valueOf(filter.getValue());\n\t\tString[] filterArray = filter == null ? new String[0] : filterValue.split(\"\\\\s*,\\\\s*\");\n\n\t\tif (group == null || group.getValue() == null //\n\t\t\t\t|| (\"x-bytejta\".equals(group.getValue())\n\t\t\t\t\t\t|| String.valueOf(group.getValue()).startsWith(\"x-bytejta-\")) == false) {\n\t\t\tthrow new FatalBeanException(String.format(\n\t\t\t\t\t\"The value of attr 'group'(beanId= %s) should be 'x-bytejta' or starts with 'x-bytejta-'.\", beanName));\n\t\t} else if (retries == null || retries.getValue() == null || \"-1\".equals(retries.getValue()) == false) {\n\t\t\tthrow new FatalBeanException(String.format(\"The value of attr 'retries'(beanId= %s) should be '-1'.\", beanName));\n\t\t} else if (loadbalance == null || loadbalance.getValue() == null || \"bytejta\".equals(loadbalance.getValue()) == false) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\tString.format(\"The value of attr 'loadbalance'(beanId= %s) should be 'bytejta'.\", beanName));\n\t\t} else if (cluster == null || cluster.getValue() == null || \"failfast\".equals(cluster.getValue()) == false) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\tString.format(\"The value of attribute 'cluster' (beanId= %s) must be 'failfast'.\", beanName));\n\t\t} else if (filter == null || filter.getValue() == null || String.class.isInstance(filter.getValue()) == false) {\n\t\t\tthrow new FatalBeanException(String\n\t\t\t\t\t.format(\"The value of attr 'filter'(beanId= %s) must be java.lang.String and cannot be null.\", beanName));\n\t\t} else if (StringUtils.equalsIgnoreCase(filterArray[filterArray.length - 1], \"bytejta\") == false) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\tString.format(\"The last value of attr 'filter'(beanId= %s) should be 'bytejta'.\", beanName));\n\t\t}\n\n\t\tPropertyValue pv = mpv.getPropertyValue(\"interface\");\n\t\tString clazzName = String.valueOf(pv.getValue());\n\t\tClassLoader cl = Thread.currentThread().getContextClassLoader();\n\n\t\tClass<?> clazz = null;\n\t\ttry {\n\t\t\tclazz = cl.loadClass(clazzName);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new FatalBeanException(String.format(\"Cannot load class %s.\", clazzName));\n\t\t}\n\n\t\tMethod[] methodArray = clazz.getMethods();\n\t\tfor (int i = 0; i < methodArray.length; i++) {\n\t\t\tMethod method = methodArray[i];\n\t\t\tboolean declared = false;\n\t\t\tClass<?>[] exceptionTypeArray = method.getExceptionTypes();\n\t\t\tfor (int j = 0; j < exceptionTypeArray.length; j++) {\n\t\t\t\tClass<?> exceptionType = exceptionTypeArray[j];\n\t\t\t\tif (RemotingException.class.isAssignableFrom(exceptionType)) {\n\t\t\t\t\tdeclared = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (declared == false) {\n\t\t\t\tlogger.warn(\"The remote call method({}) should be declared to throw a remote exception: {}!\", method,\n\t\t\t\t\t\tRemotingException.class.getName());\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tpublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n\t\tClassLoader cl = Thread.currentThread().getContextClassLoader();\n\n\t\tMap<String, BeanDefinition> referenceMap = new HashMap<String, BeanDefinition>();\n\n\t\tMap<String, Class<?>> clazzMap = new HashMap<String, Class<?>>();\n\n\t\tString[] beanNameArray = beanFactory.getBeanDefinitionNames();\n\t\tfor (int i = 0; i < beanNameArray.length; i++) {\n\t\t\tString beanName = beanNameArray[i];\n\t\t\tBeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);\n\t\t\tString beanClassName = beanDef.getBeanClassName();\n\n\t\t\tif (StringUtils.equals(com.alibaba.dubbo.config.spring.ReferenceBean.class.getName(), beanClassName) == false) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tClass<?> beanClass = null;\n\t\t\ttry {\n\t\t\t\tbeanClass = cl.loadClass(beanClassName);\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(\"Cannot load class {}, beanId= {}!\", beanClassName, beanName, ex);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tclazzMap.put(beanClassName, beanClass);\n\t\t}\n\n\t\tfor (int i = 0; i < beanNameArray.length; i++) {\n\t\t\tString beanName = beanNameArray[i];\n\t\t\tBeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);\n\t\t\tString beanClassName = beanDef.getBeanClassName();\n\n\t\t\tClass<?> beanClass = clazzMap.get(beanClassName);\n\n\t\t\tif (com.alibaba.dubbo.config.spring.ReferenceBean.class.equals(beanClass)) {\n\t\t\t\tMutablePropertyValues mpv = beanDef.getPropertyValues();\n\t\t\t\tPropertyValue group = mpv.getPropertyValue(\"group\");\n\t\t\t\tif (group == null || group.getValue() == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tString groupValue = String.valueOf(group.getValue());\n\t\t\t\tif (StringUtils.equalsIgnoreCase(\"x-bytejta\", groupValue)) {\n\t\t\t\t\treferenceMap.put(beanName, beanDef);\n\t\t\t\t} else if (StringUtils.lowerCase(groupValue).startsWith(\"x-bytejta-\")) {\n\t\t\t\t\treferenceMap.put(beanName, beanDef);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (Iterator<Map.Entry<String, BeanDefinition>> itr = referenceMap.entrySet().iterator(); itr.hasNext();) {\n\t\t\tMap.Entry<String, BeanDefinition> entry = itr.next();\n\t\t\tthis.validateReferenceConfig(entry.getKey(), entry.getValue());\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/internal/TransactionEndpointAutoInjector.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.internal;\n\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.FatalBeanException;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.NoSuchBeanDefinitionException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\nimport com.alibaba.dubbo.common.utils.ConfigUtils;\n\npublic class TransactionEndpointAutoInjector implements InitializingBean, BeanPostProcessor, ApplicationContextAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionEndpointAutoInjector.class);\n\n\tprivate ApplicationContext applicationContext;\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tString host = CommonUtils.getInetAddress();\n\n\t\tString name = null;\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.ApplicationConfig applicationConfig = //\n\t\t\t\t\tthis.applicationContext.getBean(com.alibaba.dubbo.config.ApplicationConfig.class);\n\t\t\tname = String.valueOf(applicationConfig.getName());\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tString application = ConfigUtils.getProperty(\"dubbo.application.name\");\n\t\t\tif (StringUtils.isBlank(application)) {\n\t\t\t\tthrow new FatalBeanException(\"No configuration of class com.alibaba.dubbo.config.ApplicationConfig was found.\");\n\t\t\t}\n\n\t\t\tname = application;\n\t\t}\n\n\t\tString port = null;\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.ProtocolConfig protocolConfig = //\n\t\t\t\t\tthis.applicationContext.getBean(com.alibaba.dubbo.config.ProtocolConfig.class);\n\t\t\tif (protocolConfig.getPort() == null) {\n\t\t\t\tthrow new IllegalStateException();\n\t\t\t}\n\t\t\tport = String.valueOf(protocolConfig.getPort());\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tString serverPort = ConfigUtils.getProperty(\"dubbo.protocol.dubbo.port\");\n\t\t\tif (StringUtils.isBlank(serverPort)) {\n\t\t\t\tthrow new FatalBeanException(\"No configuration of class com.alibaba.dubbo.config.ProtocolConfig was found.\");\n\t\t\t}\n\n\t\t\tport = serverPort;\n\t\t} catch (IllegalStateException error) {\n\t\t\tString serverPort = ConfigUtils.getProperty(\"dubbo.protocol.dubbo.port\");\n\t\t\tif (StringUtils.isBlank(serverPort)) {\n\t\t\t\tthrow new FatalBeanException(\"No configuration of class com.alibaba.dubbo.config.ProtocolConfig was found.\");\n\t\t\t}\n\n\t\t\tport = serverPort;\n\t\t}\n\n\t\tif (StringUtils.isBlank(name)) {\n\t\t\tthrow new FatalBeanException(\"No configuration of class com.alibaba.dubbo.config.ApplicationConfig was found.\");\n\t\t}\n\n\t\tif (StringUtils.isBlank(port)) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\t\"The value of the attribute 'port' (<dubbo:protocol port='...' />) must be explicitly specified.\");\n\t\t} else if (Integer.valueOf(port) <= 0) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\t\"The value of the attribute 'port' (<dubbo:protocol port='...' />) can not equal to -1.\");\n\t\t}\n\n\t\tString identifier = String.format(\"%s:%s:%s\", host, name, port);\n\n\t\tMap<String, TransactionEndpointAware> beanMap = //\n\t\t\t\tthis.applicationContext.getBeansOfType(TransactionEndpointAware.class);\n\t\tfor (Iterator<Map.Entry<String, TransactionEndpointAware>> itr = beanMap.entrySet().iterator(); itr.hasNext();) {\n\t\t\tMap.Entry<String, TransactionEndpointAware> entry = itr.next();\n\t\t\tTransactionEndpointAware aware = entry.getValue();\n\t\t\taware.setEndpoint(identifier);\n\t\t} // end-for (Iterator<Map.Entry<String, TransactionEndpointAware>> itr = beanMap.entrySet().iterator(); itr.hasNext();)\n\t}\n\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\tif (TransactionEndpointAware.class.isInstance(bean)) {\n\t\t\tTransactionEndpointAware aware = (TransactionEndpointAware) bean;\n\t\t\tthis.initializeEndpointIfNecessary(aware);\n\t\t} // end-if (TransactionEndpointAware.class.isInstance(bean))\n\n\t\treturn bean;\n\t}\n\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tif (TransactionEndpointAware.class.isInstance(bean)) {\n\t\t\tTransactionEndpointAware aware = (TransactionEndpointAware) bean;\n\t\t\tthis.initializeEndpointIfNecessary(aware);\n\t\t} // end-if (TransactionEndpointAware.class.isInstance(bean))\n\n\t\treturn bean;\n\t}\n\n\tprivate void initializeEndpointIfNecessary(TransactionEndpointAware aware) {\n\t\tif (StringUtils.isBlank(aware.getEndpoint())) {\n\t\t\tString host = CommonUtils.getInetAddress();\n\n\t\t\tString name = null;\n\t\t\ttry {\n\t\t\t\tcom.alibaba.dubbo.config.ApplicationConfig applicationConfig = //\n\t\t\t\t\t\tthis.applicationContext.getBean(com.alibaba.dubbo.config.ApplicationConfig.class);\n\t\t\t\tname = String.valueOf(applicationConfig.getName());\n\t\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\t\tString application = ConfigUtils.getProperty(\"dubbo.application.name\");\n\t\t\t\tif (StringUtils.isBlank(application)) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tname = application;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tString port = null;\n\t\t\ttry {\n\t\t\t\tcom.alibaba.dubbo.config.ProtocolConfig protocolConfig = //\n\t\t\t\t\t\tthis.applicationContext.getBean(com.alibaba.dubbo.config.ProtocolConfig.class);\n\t\t\t\tport = String.valueOf(protocolConfig.getPort());\n\t\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\t\tString serverPort = ConfigUtils.getProperty(\"dubbo.protocol.dubbo.port\");\n\t\t\t\tif (StringUtils.isBlank(serverPort)) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tport = serverPort;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\taware.setEndpoint(String.format(\"%s:%s:%s\", host, name, port));\n\t\t}\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/internal/TransactionParticipantRegistrant.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.internal;\n\nimport org.bytesoft.bytejta.TransactionCoordinator;\nimport org.bytesoft.bytejta.supports.dubbo.TransactionBeanRegistry;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.FatalBeanException;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.BeanFactoryAware;\nimport org.springframework.beans.factory.NoSuchBeanDefinitionException;\nimport org.springframework.beans.factory.SmartInitializingSingleton;\nimport org.springframework.beans.factory.config.SingletonBeanRegistry;\n\nimport com.alibaba.dubbo.common.Constants;\nimport com.alibaba.dubbo.config.ReferenceConfig;\nimport com.alibaba.dubbo.config.ServiceConfig;\n\npublic class TransactionParticipantRegistrant\n\t\timplements SmartInitializingSingleton, TransactionEndpointAware, BeanFactoryAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionParticipantRegistrant.class);\n\n\tprivate BeanFactory beanFactory;\n\tprivate String endpoint;\n\n\tpublic void afterSingletonsInstantiated() {\n\t\tTransactionCoordinator transactionCoordinator = this.beanFactory.getBean(TransactionCoordinator.class);\n\t\tTransactionBeanRegistry beanRegistry = this.beanFactory.getBean(TransactionBeanRegistry.class);\n\n\t\tif (transactionCoordinator == null) {\n\t\t\tthrow new FatalBeanException(\"No configuration of class org.bytesoft.bytejta.TransactionCoordinator was found.\");\n\t\t} else if (beanRegistry == null) {\n\t\t\tthrow new FatalBeanException(\n\t\t\t\t\t\"No configuration of class org.bytesoft.bytejta.supports.dubbo.TransactionBeanRegistry was found.\");\n\t\t}\n\n\t\tthis.initializeForProvider(transactionCoordinator);\n\t\tthis.initializeForConsumer(beanRegistry);\n\t}\n\n\tpublic void initializeForProvider(RemoteCoordinator reference) throws BeansException {\n\t\tSingletonBeanRegistry registry = (SingletonBeanRegistry) this.beanFactory;\n\t\tServiceConfig<RemoteCoordinator> globalServiceConfig = new ServiceConfig<RemoteCoordinator>();\n\t\tglobalServiceConfig.setInterface(RemoteCoordinator.class);\n\t\tglobalServiceConfig.setRef(reference);\n\t\tglobalServiceConfig.setCluster(\"failfast\");\n\t\tglobalServiceConfig.setLoadbalance(\"bytejta\");\n\t\tglobalServiceConfig.setFilter(\"bytejta\");\n\t\tglobalServiceConfig.setGroup(\"org-bytesoft-bytejta\");\n\t\tglobalServiceConfig.setRetries(-1);\n\t\tglobalServiceConfig.setTimeout(15000);\n\n\t\tServiceConfig<RemoteCoordinator> applicationServiceConfig = new ServiceConfig<RemoteCoordinator>();\n\t\tapplicationServiceConfig.setInterface(RemoteCoordinator.class);\n\t\tapplicationServiceConfig.setRef(reference);\n\t\tapplicationServiceConfig.setCluster(\"failfast\");\n\t\tapplicationServiceConfig.setLoadbalance(\"bytejta\");\n\t\tapplicationServiceConfig.setFilter(\"bytejta\");\n\t\tapplicationServiceConfig.setGroup(CommonUtils.getApplication(this.endpoint));\n\t\tapplicationServiceConfig.setRetries(-1);\n\t\tapplicationServiceConfig.setTimeout(15000);\n\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.ApplicationConfig applicationConfig = //\n\t\t\t\t\tthis.beanFactory.getBean(com.alibaba.dubbo.config.ApplicationConfig.class);\n\t\t\tglobalServiceConfig.setApplication(applicationConfig);\n\t\t\tapplicationServiceConfig.setApplication(applicationConfig);\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tlogger.warn(\"No configuration of class com.alibaba.dubbo.config.ApplicationConfig was found.\");\n\t\t}\n\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.RegistryConfig registryConfig = //\n\t\t\t\t\tthis.beanFactory.getBean(com.alibaba.dubbo.config.RegistryConfig.class);\n\t\t\tif (registryConfig != null) {\n\t\t\t\tglobalServiceConfig.setRegistry(registryConfig);\n\t\t\t\tapplicationServiceConfig.setRegistry(registryConfig);\n\t\t\t}\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tlogger.warn(\"No configuration of class com.alibaba.dubbo.config.RegistryConfig was found.\");\n\t\t}\n\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.ProtocolConfig protocolConfig = //\n\t\t\t\t\tthis.beanFactory.getBean(com.alibaba.dubbo.config.ProtocolConfig.class);\n\t\t\tglobalServiceConfig.setProtocol(protocolConfig);\n\t\t\tapplicationServiceConfig.setProtocol(protocolConfig);\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tlogger.warn(\"No configuration of class com.alibaba.dubbo.config.ProtocolConfig was found.\");\n\t\t}\n\n\t\tglobalServiceConfig.export();\n\t\tapplicationServiceConfig.export();\n\n\t\tString globalSkeletonBeanId = String.format(\"skeleton@%s\", RemoteCoordinator.class.getName());\n\t\tregistry.registerSingleton(globalSkeletonBeanId, globalServiceConfig);\n\n\t\tString applicationSkeletonBeanId = //\n\t\t\t\tString.format(\"%s@%s\", CommonUtils.getApplication(this.endpoint), RemoteCoordinator.class.getName());\n\t\tregistry.registerSingleton(applicationSkeletonBeanId, applicationServiceConfig);\n\t}\n\n\tpublic void initializeForConsumer(TransactionBeanRegistry beanRegistry) throws BeansException {\n\t\tSingletonBeanRegistry registry = (SingletonBeanRegistry) this.beanFactory;\n\t\tReferenceConfig<RemoteCoordinator> referenceConfig = new ReferenceConfig<RemoteCoordinator>();\n\t\treferenceConfig.setInterface(RemoteCoordinator.class);\n\t\treferenceConfig.setTimeout(15000);\n\t\treferenceConfig.setCluster(\"failfast\");\n\t\treferenceConfig.setLoadbalance(\"bytejta\");\n\t\treferenceConfig.setFilter(\"bytejta\");\n\t\treferenceConfig.setGroup(\"org-bytesoft-bytejta\");\n\t\treferenceConfig.setCheck(false);\n\t\treferenceConfig.setRetries(-1);\n\t\treferenceConfig.setScope(Constants.SCOPE_REMOTE);\n\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.ApplicationConfig applicationConfig = //\n\t\t\t\t\tthis.beanFactory.getBean(com.alibaba.dubbo.config.ApplicationConfig.class);\n\t\t\treferenceConfig.setApplication(applicationConfig);\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tlogger.warn(\"No configuration of class com.alibaba.dubbo.config.ApplicationConfig was found.\");\n\t\t}\n\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.RegistryConfig registryConfig = //\n\t\t\t\t\tthis.beanFactory.getBean(com.alibaba.dubbo.config.RegistryConfig.class);\n\t\t\tif (registryConfig != null) {\n\t\t\t\treferenceConfig.setRegistry(registryConfig);\n\t\t\t}\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tlogger.warn(\"No configuration of class com.alibaba.dubbo.config.RegistryConfig was found.\");\n\t\t}\n\n\t\ttry {\n\t\t\tcom.alibaba.dubbo.config.ProtocolConfig protocolConfig = //\n\t\t\t\t\tthis.beanFactory.getBean(com.alibaba.dubbo.config.ProtocolConfig.class);\n\t\t\treferenceConfig.setProtocol(protocolConfig.getName());\n\t\t} catch (NoSuchBeanDefinitionException error) {\n\t\t\tlogger.warn(\"No configuration of class com.alibaba.dubbo.config.ProtocolConfig was found.\");\n\t\t}\n\n\t\tRemoteCoordinator globalCoordinator = referenceConfig.get();\n\t\tbeanRegistry.setConsumeCoordinator(globalCoordinator);\n\n\t\tString stubBeanId = String.format(\"stub@%s\", RemoteCoordinator.class.getName());\n\t\tregistry.registerSingleton(stubBeanId, globalCoordinator);\n\t}\n\n\tpublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {\n\t\tthis.beanFactory = beanFactory;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn this.endpoint;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.endpoint = identifier;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/serialize/XAResourceDeserializerImpl.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.serialize;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.dubbo.TransactionBeanRegistry;\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry;\nimport org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\nimport com.alibaba.dubbo.common.Constants;\nimport com.alibaba.dubbo.config.ApplicationConfig;\nimport com.alibaba.dubbo.config.ProtocolConfig;\nimport com.alibaba.dubbo.config.ReferenceConfig;\nimport com.alibaba.dubbo.config.RegistryConfig;\nimport com.alibaba.dubbo.rpc.RpcException;\n\npublic class XAResourceDeserializerImpl implements XAResourceDeserializer, ApplicationContextAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(XAResourceDeserializerImpl.class);\n\tstatic Pattern pattern = Pattern.compile(\"^[^:]+\\\\s*:\\\\s*[^:]+\\\\s*:\\\\s*\\\\d+$\");\n\n\tprivate XAResourceDeserializer resourceDeserializer;\n\tprivate ApplicationContext applicationContext;\n\n\tpublic XAResourceDescriptor deserialize(String identifier) {\n\t\tXAResourceDescriptor resourceDescriptor = this.resourceDeserializer.deserialize(identifier);\n\t\tif (resourceDescriptor != null) {\n\t\t\treturn resourceDescriptor;\n\t\t}\n\n\t\tMatcher matcher = pattern.matcher(identifier);\n\t\tif (matcher.find()) {\n\t\t\tRemoteCoordinatorRegistry registry = RemoteCoordinatorRegistry.getInstance();\n\t\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(identifier);\n\t\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(identifier);\n\n\t\t\tRemoteNode targetNode = registry.getRemoteNode(remoteAddr);\n\t\t\tif (targetNode == null && remoteAddr != null && remoteNode != null) {\n\t\t\t\tregistry.putRemoteNode(remoteAddr, remoteNode);\n\t\t\t}\n\n\t\t\tthis.initializePhysicalInstanceIfNecessary(remoteAddr);\n\n\t\t\tString application = CommonUtils.getApplication(identifier);\n\t\t\tthis.initializeRemoteParticipantIfNecessary(application);\n\n\t\t\tRemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();\n\t\t\tdescriptor.setIdentifier(identifier);\n\t\t\tdescriptor.setDelegate(registry.getPhysicalInstance(remoteAddr));\n\t\t\t// descriptor.setDelegate(registry.getParticipant(application));\n\n\t\t\treturn descriptor;\n\t\t} else {\n\t\t\tlogger.error(\"can not find a matching xa-resource(identifier= {})!\", identifier);\n\t\t\treturn null;\n\t\t}\n\n\t}\n\n\tprivate void initializePhysicalInstanceIfNecessary(RemoteAddr remoteAddr) throws RpcException {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tRemoteCoordinator physicalInst = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\tif (physicalInst == null) {\n\t\t\tString serverHost = remoteAddr.getServerHost();\n\t\t\tint serverPort = remoteAddr.getServerPort();\n\t\t\tfinal String target = String.format(\"%s:%s\", serverHost, serverPort).intern();\n\t\t\tsynchronized (target) {\n\t\t\t\tRemoteCoordinator participant = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\t\t\tif (participant == null) {\n\t\t\t\t\tthis.processInitPhysicalInstanceIfNecessary(remoteAddr);\n\t\t\t\t}\n\t\t\t} // end-synchronized (target)\n\t\t} // end-if (physicalInst == null)\n\t}\n\n\tprivate void processInitPhysicalInstanceIfNecessary(RemoteAddr remoteAddr) throws RpcException {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\n\t\tRemoteCoordinator participant = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\tif (participant == null) {\n\t\t\tApplicationConfig applicationConfig = beanRegistry.getBean(ApplicationConfig.class);\n\t\t\tRegistryConfig registryConfig = beanRegistry.getBean(RegistryConfig.class);\n\t\t\tProtocolConfig protocolConfig = beanRegistry.getBean(ProtocolConfig.class);\n\n\t\t\tReferenceConfig<RemoteCoordinator> referenceConfig = new ReferenceConfig<RemoteCoordinator>();\n\t\t\treferenceConfig.setInterface(RemoteCoordinator.class);\n\t\t\treferenceConfig.setTimeout(15000);\n\t\t\treferenceConfig.setCluster(\"failfast\");\n\t\t\treferenceConfig.setLoadbalance(\"bytejta\");\n\t\t\treferenceConfig.setFilter(\"bytejta\");\n\t\t\treferenceConfig.setGroup(\"org-bytesoft-bytejta\");\n\t\t\treferenceConfig.setCheck(false);\n\t\t\treferenceConfig.setRetries(-1);\n\t\t\treferenceConfig.setUrl(String.format(\"%s:%s\", remoteAddr.getServerHost(), remoteAddr.getServerPort()));\n\t\t\treferenceConfig.setScope(Constants.SCOPE_REMOTE);\n\n\t\t\treferenceConfig.setApplication(applicationConfig);\n\t\t\tif (registryConfig != null) {\n\t\t\t\treferenceConfig.setRegistry(registryConfig);\n\t\t\t}\n\t\t\tif (protocolConfig != null) {\n\t\t\t\treferenceConfig.setProtocol(protocolConfig.getName());\n\t\t\t} // end-if (protocolConfig != null)\n\n\t\t\tRemoteCoordinator reference = referenceConfig.get();\n\t\t\tif (reference == null) {\n\t\t\t\tthrow new RpcException(\"Cannot get the application name of the remote application.\");\n\t\t\t}\n\n\t\t\tparticipantRegistry.putPhysicalInstance(remoteAddr, reference);\n\t\t}\n\t}\n\n\tprivate void initializeRemoteParticipantIfNecessary(final String system) throws RpcException {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tfinal String application = StringUtils.trimToEmpty(system).intern();\n\t\tRemoteCoordinator remoteParticipant = participantRegistry.getParticipant(application);\n\t\tif (remoteParticipant == null) {\n\t\t\tsynchronized (application) {\n\t\t\t\tRemoteCoordinator participant = participantRegistry.getParticipant(application);\n\t\t\t\tif (participant == null) {\n\t\t\t\t\tthis.processInitRemoteParticipantIfNecessary(application);\n\t\t\t\t}\n\t\t\t} // end-synchronized (target)\n\t\t} // end-if (remoteParticipant == null)\n\t}\n\n\tprivate void processInitRemoteParticipantIfNecessary(String application) {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\n\t\tRemoteCoordinator participant = participantRegistry.getParticipant(application);\n\t\tif (participant == null) {\n\t\t\tApplicationConfig applicationConfig = beanRegistry.getBean(ApplicationConfig.class);\n\t\t\tRegistryConfig registryConfig = beanRegistry.getBean(RegistryConfig.class);\n\t\t\tProtocolConfig protocolConfig = beanRegistry.getBean(ProtocolConfig.class);\n\n\t\t\tReferenceConfig<RemoteCoordinator> referenceConfig = new ReferenceConfig<RemoteCoordinator>();\n\t\t\treferenceConfig.setInterface(RemoteCoordinator.class);\n\t\t\treferenceConfig.setTimeout(15000);\n\t\t\treferenceConfig.setCluster(\"failfast\");\n\t\t\treferenceConfig.setLoadbalance(\"bytejta\");\n\t\t\treferenceConfig.setFilter(\"bytejta\");\n\t\t\treferenceConfig.setGroup(application);\n\t\t\treferenceConfig.setCheck(false);\n\t\t\treferenceConfig.setRetries(-1);\n\t\t\treferenceConfig.setScope(Constants.SCOPE_REMOTE);\n\n\t\t\treferenceConfig.setApplication(applicationConfig);\n\t\t\tif (registryConfig != null) {\n\t\t\t\treferenceConfig.setRegistry(registryConfig);\n\t\t\t}\n\t\t\tif (protocolConfig != null) {\n\t\t\t\treferenceConfig.setProtocol(protocolConfig.getName());\n\t\t\t} // end-if (protocolConfig != null)\n\n\t\t\tRemoteCoordinator reference = referenceConfig.get();\n\t\t\tif (reference == null) {\n\t\t\t\tthrow new RpcException(\"Cannot get the application name of the remote application.\");\n\t\t\t}\n\n\t\t\tparticipantRegistry.putParticipant(application, reference);\n\t\t}\n\t}\n\n\tpublic XAResourceDeserializer getResourceDeserializer() {\n\t\treturn resourceDeserializer;\n\t}\n\n\tpublic void setResourceDeserializer(XAResourceDeserializer resourceDeserializer) {\n\t\tthis.resourceDeserializer = resourceDeserializer;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/spi/TransactionLoadBalance.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.spi;\n\nimport java.util.List;\n\nimport org.bytesoft.bytejta.TransactionImpl;\nimport org.bytesoft.bytejta.supports.dubbo.InvocationContextRegistry;\nimport org.bytesoft.bytejta.supports.dubbo.TransactionBeanRegistry;\nimport org.bytesoft.bytejta.supports.dubbo.ext.ILoadBalancer;\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.springframework.core.env.Environment;\n\nimport com.alibaba.dubbo.common.URL;\nimport com.alibaba.dubbo.common.extension.ExtensionLoader;\nimport com.alibaba.dubbo.rpc.Invocation;\nimport com.alibaba.dubbo.rpc.Invoker;\nimport com.alibaba.dubbo.rpc.RpcException;\nimport com.alibaba.dubbo.rpc.cluster.LoadBalance;\n\npublic final class TransactionLoadBalance implements LoadBalance {\n\tstatic final String CONSTANT_LOADBALANCE_KEY = \"org.bytesoft.bytejta.loadbalance\";\n\n\tprivate ILoadBalancer loadBalancer;\n\n\tprivate void fireInitializeIfNecessary() {\n\t\tif (this.loadBalancer == null) {\n\t\t\tthis.initializeIfNecessary();\n\t\t}\n\t}\n\n\tprivate synchronized void initializeIfNecessary() {\n\t\tif (this.loadBalancer == null) {\n\t\t\tEnvironment environment = TransactionBeanRegistry.getInstance().getEnvironment();\n\t\t\tString loadBalanceKey = environment.getProperty(CONSTANT_LOADBALANCE_KEY, \"default\");\n\t\t\tExtensionLoader<ILoadBalancer> extensionLoader = ExtensionLoader.getExtensionLoader(ILoadBalancer.class);\n\t\t\tthis.loadBalancer = extensionLoader.getExtension(loadBalanceKey);\n\t\t}\n\t}\n\n\tpublic <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {\n\t\tInvocationContextRegistry registry = InvocationContextRegistry.getInstance();\n\t\tRemoteNode invocationContext = registry.getInvocationContext();\n\t\tif (invocationContext == null) {\n\t\t\treturn this.selectConfigedInvoker(invokers, url, invocation);\n\t\t} else {\n\t\t\treturn this.selectSpecificInvoker(invokers, url, invocation, invocationContext);\n\t\t}\n\t}\n\n\tpublic <T> Invoker<T> selectConfigedInvoker(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {\n\t\tif (invokers == null || invokers.isEmpty()) {\n\t\t\tthrow new RpcException(\"No invoker is found!\");\n\t\t}\n\n\t\tTransactionBeanFactory beanFactory = TransactionBeanRegistry.getInstance().getBeanFactory();\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tTransactionImpl transaction = //\n\t\t\t\t(TransactionImpl) transactionManager.getTransactionQuietly();\n\t\tList<XAResourceArchive> participantList = transaction == null ? null : transaction.getRemoteParticipantList();\n\n\t\tRemoteAddr instanceAddr = null;\n\t\tfor (int i = 0; invokers != null && participantList != null && participantList.isEmpty() == false\n\t\t\t\t&& i < invokers.size(); i++) {\n\t\t\tInvoker<T> invoker = invokers.get(i);\n\t\t\tURL invokerUrl = invoker.getUrl();\n\t\t\tRemoteAddr invokerAddr = new RemoteAddr();\n\t\t\tinvokerAddr.setServerHost(invokerUrl.getHost());\n\t\t\tinvokerAddr.setServerPort(invokerUrl.getPort());\n\n\t\t\tRemoteNode remoteNode = participantRegistry.getRemoteNode(invokerAddr);\n\t\t\tif (remoteNode == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tXAResourceDescriptor participant = transaction.getRemoteCoordinator(remoteNode.getServiceKey());\n\t\t\tif (participant == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tString identifier = participant.getIdentifier();\n\t\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(identifier);\n\t\t\tif (invokerAddr.equals(remoteAddr) == false) {\n\t\t\t\tinstanceAddr = remoteAddr;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\treturn invoker;\n\t\t}\n\n\t\tif (instanceAddr != null) {\n\t\t\tthrow new RpcException(\n\t\t\t\t\tString.format(\"Invoker(%s:%s) is not found!\", instanceAddr.getServerHost(), instanceAddr.getServerPort()));\n\t\t}\n\n\t\tthis.fireInitializeIfNecessary();\n\n\t\tif (this.loadBalancer == null) {\n\t\t\tthrow new RpcException(\"No org.bytesoft.bytejta.supports.dubbo.ext.ILoadBalancer is found!\");\n\t\t} else {\n\t\t\treturn this.loadBalancer.select(invokers, url, invocation);\n\t\t}\n\n\t}\n\n\tpublic <T> Invoker<T> selectSpecificInvoker(List<Invoker<T>> invokers, URL url, Invocation invocation, RemoteNode context)\n\t\t\tthrows RpcException {\n\t\tRemoteAddr remoteAddr = new RemoteAddr();\n\t\tremoteAddr.setServerHost(context.getServerHost());\n\t\tremoteAddr.setServerPort(context.getServerPort());\n\t\tfor (int i = 0; invokers != null && i < invokers.size(); i++) {\n\t\t\tInvoker<T> invoker = invokers.get(i);\n\t\t\tURL targetUrl = invoker.getUrl();\n\t\t\tRemoteAddr targetAddr = new RemoteAddr();\n\t\t\ttargetAddr.setServerHost(targetUrl.getIp());\n\t\t\ttargetAddr.setServerPort(targetUrl.getPort());\n\t\t\tif (targetAddr.equals(remoteAddr)) {\n\t\t\t\treturn invoker;\n\t\t\t} // end-if (targetAddr.equals(remoteAddr))\n\t\t}\n\n\t\tthrow new RpcException(String.format(\"Invoker(%s:%s) is not found!\", context.getServerHost(), context.getServerPort()));\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/spi/TransactionLoadBalancer.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.spi;\n\nimport java.util.List;\nimport java.util.Random;\n\nimport org.bytesoft.bytejta.supports.dubbo.ext.ILoadBalancer;\n\nimport com.alibaba.dubbo.common.URL;\nimport com.alibaba.dubbo.rpc.Invocation;\nimport com.alibaba.dubbo.rpc.Invoker;\nimport com.alibaba.dubbo.rpc.RpcException;\n\npublic class TransactionLoadBalancer implements ILoadBalancer {\n\tstatic final Random random = new Random();\n\n\tpublic <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {\n\t\tif (invokers == null || invokers.isEmpty()) {\n\t\t\tthrow new RpcException(\"No invoker is found!\");\n\t\t}\n\n\t\tint lengthOfInvokerList = invokers == null ? 0 : invokers.size();\n\t\treturn invokers.get(random.nextInt(lengthOfInvokerList));\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/java/org/bytesoft/bytejta/supports/dubbo/spi/TransactionServiceFilter.java",
    "content": "/**\n * Copyright 2014-2016 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.dubbo.spi;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.Serializable;\nimport java.lang.reflect.Proxy;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.dubbo.DubboRemoteCoordinator;\nimport org.bytesoft.bytejta.supports.dubbo.TransactionBeanRegistry;\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry;\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry.InvocationDef;\nimport org.bytesoft.bytejta.supports.rpc.TransactionRequestImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionException;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.TransactionParticipant;\nimport org.bytesoft.transaction.TransactionRepository;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.transaction.annotation.Propagation;\n\nimport com.alibaba.com.caucho.hessian.io.HessianHandle;\nimport com.alibaba.dubbo.common.Constants;\nimport com.alibaba.dubbo.common.URL;\nimport com.alibaba.dubbo.config.ApplicationConfig;\nimport com.alibaba.dubbo.config.ProtocolConfig;\nimport com.alibaba.dubbo.config.ReferenceConfig;\nimport com.alibaba.dubbo.config.RegistryConfig;\nimport com.alibaba.dubbo.rpc.Filter;\nimport com.alibaba.dubbo.rpc.Invocation;\nimport com.alibaba.dubbo.rpc.Invoker;\nimport com.alibaba.dubbo.rpc.Result;\nimport com.alibaba.dubbo.rpc.RpcContext;\nimport com.alibaba.dubbo.rpc.RpcException;\nimport com.alibaba.dubbo.rpc.RpcResult;\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\n\npublic class TransactionServiceFilter implements Filter {\n\tstatic final String KEY_XA_RESOURCE_START = \"start\";\n\tstatic final String KEY_XA_GET_IDENTIFIER = \"getIdentifier\";\n\tstatic final String KEY_XA_GET_APPLICATION = \"getApplication\";\n\tstatic final String KEY_XA_GET_REMOTEADDR = \"getRemoteAddr\";\n\tstatic final String KEY_XA_GET_REMOTENODE = \"getRemoteNode\";\n\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionServiceFilter.class);\n\n\tpublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tif (RpcContext.getContext().isProviderSide()) {\n\t\t\treturn this.providerInvoke(invoker, invocation);\n\t\t} else {\n\t\t\treturn this.consumerInvoke(invoker, invocation);\n\t\t}\n\t}\n\n\tpublic Result providerInvoke(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tString interfaceClazz = RpcContext.getContext().getUrl().getServiceInterface();\n\n\t\tboolean participantFlag = TransactionParticipant.class.getName().equals(interfaceClazz);\n\t\tboolean xaResourceFlag = XAResource.class.getName().equals(interfaceClazz);\n\t\tboolean coordinatorFlag = RemoteCoordinator.class.getName().equals(interfaceClazz);\n\n\t\tif (participantFlag == false && xaResourceFlag == false && coordinatorFlag == false) {\n\t\t\treturn this.providerInvokeForSVC(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_RESOURCE_START)) {\n\t\t\treturn this.providerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_IDENTIFIER)) {\n\t\t\treturn this.providerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_APPLICATION)) {\n\t\t\treturn this.providerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_REMOTEADDR)) {\n\t\t\treturn this.providerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_REMOTENODE)) {\n\t\t\treturn this.providerInvokeForKey(invoker, invocation);\n\t\t} else {\n\t\t\treturn this.providerInvokeForJTA(invoker, invocation);\n\t\t}\n\t}\n\n\tpublic Result providerInvokeForKey(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tString instanceId = StringUtils.trimToEmpty(invocation.getAttachment(RemoteCoordinator.class.getName()));\n\n\t\tthis.registerRemoteParticipantIfNecessary(instanceId);\n\n\t\tRpcResult result = new RpcResult();\n\n\t\tInvocationResult wrapped = new InvocationResult();\n\t\twrapped.setVariable(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\n\t\tresult.setException(null);\n\t\tresult.setValue(wrapped);\n\n\t\treturn result;\n\t}\n\n\tpublic Result providerInvokeForJTA(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tXidFactory xidFactory = beanFactory.getXidFactory();\n\t\tTransactionRepository transactionRepository = beanFactory.getTransactionRepository();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tClass<?>[] parameterTypeArray = invocation.getParameterTypes();\n\t\tClass<?> parameterType = (parameterTypeArray == null || parameterTypeArray.length == 0) ? null : parameterTypeArray[0];\n\t\tif (parameterTypeArray == null || parameterTypeArray.length == 0) {\n\t\t\treturn this.wrapResultForProvider(invoker, invocation, null, false);\n\t\t} else if (Xid.class.equals(parameterType) == false) {\n\t\t\treturn this.wrapResultForProvider(invoker, invocation, null, false);\n\t\t}\n\n\t\tRpcResult result = new RpcResult();\n\n\t\tObject[] arguments = invocation.getArguments();\n\t\tXid xid = (Xid) arguments[0];\n\n\t\tTransactionXid globalXid = xidFactory.createGlobalXid(xid.getGlobalTransactionId());\n\t\tTransaction transaction = null;\n\t\ttry {\n\t\t\ttransaction = transactionRepository.getTransaction(globalXid);\n\t\t} catch (TransactionException tex) {\n\t\t\tInvocationResult wrapped = new InvocationResult();\n\t\t\twrapped.setError(new XAException(XAException.XAER_RMERR));\n\t\t\twrapped.setVariable(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\n\t\t\tresult.setException(null);\n\t\t\tresult.setValue(wrapped);\n\t\t\treturn result;\n\t\t}\n\n\t\tif (transaction == null) {\n\t\t\tInvocationResult wrapped = new InvocationResult();\n\t\t\twrapped.setError(new XAException(XAException.XAER_NOTA));\n\t\t\twrapped.setVariable(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\n\t\t\tresult.setException(null);\n\t\t\tresult.setValue(wrapped);\n\t\t} else {\n\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\tString propagatedBy = String.valueOf(transactionContext.getPropagatedBy());\n\n\t\t\tString remoteAddr = invocation.getAttachment(RemoteCoordinator.class.getName());\n\n\t\t\tif (StringUtils.equals(propagatedBy, remoteAddr)) {\n\t\t\t\treturn this.wrapResultForProvider(invoker, invocation, propagatedBy, false);\n\t\t\t}\n\n\t\t\tInvocationResult wrapped = new InvocationResult();\n\t\t\twrapped.setError(new XAException(XAException.XAER_PROTO));\n\n\t\t\twrapped.setVariable(Propagation.class.getName(), String.valueOf(transactionContext.getPropagatedBy()));\n\t\t\twrapped.setVariable(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\n\t\t\tresult.setException(null);\n\t\t\tresult.setValue(wrapped);\n\n\t\t\tlogger.warn(\"{}| branch should be invoked by its own coordinator(expect= {}, actual= {}).\" //\n\t\t\t\t\t, globalXid, propagatedBy, remoteAddr);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic Result providerInvokeForSVC(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\n\t\tString instanceId = invocation.getAttachment(RemoteCoordinator.class.getName());\n\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(instanceId);\n\n\t\tthis.registerRemoteParticipantIfNecessary(instanceId);\n\n\t\tthis.initializePhysicalInstanceIfNecessary(remoteAddr);\n\t\tRemoteCoordinator physical = participantRegistry.getPhysicalInstance(remoteAddr);\n\n\t\t// String application = CommonUtils.getApplication(instanceId);\n\t\t// RemoteCoordinator participant = //\n\t\t// StringUtils.isBlank(application) ? null : participantRegistry.getParticipant(application);\n\n\t\tTransactionRequestImpl request = new TransactionRequestImpl();\n\t\trequest.setTargetTransactionCoordinator(physical);\n\n\t\tTransactionResponseImpl response = new TransactionResponseImpl();\n\t\tresponse.setSourceTransactionCoordinator(physical);\n\n\t\tString propagatedBy = null;\n\t\tboolean failure = false;\n\t\ttry {\n\t\t\tthis.beforeProviderInvokeForSVC(invocation, request, response);\n\n\t\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\t\tTransactionContext transactionContext = transaction == null ? null : transaction.getTransactionContext();\n\t\t\tpropagatedBy = transactionContext == null ? null : String.valueOf(transactionContext.getPropagatedBy());\n\n\t\t\treturn this.wrapResultForProvider(invoker, invocation, propagatedBy, true);\n\t\t} catch (RpcException rex) {\n\t\t\tfailure = true;\n\n\t\t\treturn this.createErrorResultForProvider(rex, propagatedBy, true);\n\t\t} catch (Throwable rex) {\n\t\t\tfailure = true;\n\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\n\t\t\treturn this.createErrorResultForProvider(rex, propagatedBy, true);\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tthis.afterProviderInvokeForSVC(invocation, request, response);\n\t\t\t} catch (RpcException rex) {\n\t\t\t\tif (failure) {\n\t\t\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\t\t} else {\n\t\t\t\t\treturn this.createErrorResultForProvider(rex, propagatedBy, true);\n\t\t\t\t}\n\t\t\t} catch (Throwable rex) {\n\t\t\t\tif (failure) {\n\t\t\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\t\t} else {\n\t\t\t\t\treturn this.createErrorResultForProvider(rex, propagatedBy, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic Result wrapResultForProvider(Invoker<?> invoker, Invocation invocation, String propagatedBy,\n\t\t\tboolean attachRequired) {\n\n\t\ttry {\n\t\t\tRpcResult result = (RpcResult) invoker.invoke(invocation);\n\t\t\tif (result.hasException()) {\n\t\t\t\treturn this.createErrorResultForProvider(result.getException(), propagatedBy, attachRequired);\n\t\t\t} else {\n\t\t\t\treturn this.convertResultForProvider(result, propagatedBy, attachRequired);\n\t\t\t}\n\t\t} catch (Throwable rex) {\n\t\t\treturn this.createErrorResultForProvider(rex, propagatedBy, attachRequired);\n\t\t}\n\n\t}\n\n\tprivate Result convertResultForProvider(RpcResult result, String propagatedBy, boolean attachRequired) {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tObject value = result.getValue();\n\n\t\tInvocationResult wrapped = new InvocationResult();\n\t\twrapped.setValue(value);\n\t\tif (attachRequired) {\n\t\t\twrapped.setVariable(Propagation.class.getName(), propagatedBy);\n\t\t\twrapped.setVariable(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\t\t}\n\n\t\tresult.setException(null);\n\t\tresult.setValue(wrapped);\n\n\t\treturn result;\n\t}\n\n\tprivate Result createErrorResultForProvider(Throwable throwable, String propagatedBy, boolean attachRequired) {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tRpcResult result = new RpcResult();\n\n\t\tInvocationResult wrapped = new InvocationResult();\n\t\twrapped.setError(throwable);\n\t\tif (attachRequired) {\n\t\t\twrapped.setVariable(Propagation.class.getName(), propagatedBy);\n\t\t\twrapped.setVariable(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\t\t}\n\n\t\tresult.setException(null);\n\t\tresult.setValue(wrapped);\n\n\t\treturn result;\n\t}\n\n\tprivate void beforeProviderInvokeForSVC(Invocation invocation, TransactionRequestImpl request,\n\t\t\tTransactionResponseImpl response) {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tRpcException rpcError = null;\n\t\tString transactionContextContent = invocation.getAttachment(TransactionContext.class.getName());\n\t\tString propagatedBy = invocation.getAttachment(RemoteCoordinator.class.getName());\n\t\tif (StringUtils.isNotBlank(transactionContextContent)) {\n\t\t\tbyte[] requestByteArray = ByteUtils.stringToByteArray(transactionContextContent);\n\t\t\tByteArrayInputStream bais = new ByteArrayInputStream(requestByteArray);\n\t\t\tHessianInput input = new HessianInput(bais);\n\t\t\ttry {\n\t\t\t\tTransactionContext remoteTransactionContext = (TransactionContext) input.readObject();\n\t\t\t\tremoteTransactionContext.setPropagatedBy(propagatedBy);\n\t\t\t\trequest.setTransactionContext(remoteTransactionContext);\n\t\t\t} catch (IOException ex) {\n\t\t\t\tlogger.error(\"Error occurred in remote call!\", ex);\n\t\t\t\trpcError = new RpcException(\"Error occurred in remote call!\", ex);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\ttransactionInterceptor.afterReceiveRequest(request);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\tthrow new RpcException(\"Error occurred in remote call!\", rex);\n\t\t}\n\n\t\tif (rpcError != null) {\n\t\t\tthrow rpcError;\n\t\t}\n\n\t}\n\n\tprivate void afterProviderInvokeForSVC(Invocation invocation, TransactionRequestImpl request,\n\t\t\tTransactionResponseImpl response) {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tTransactionContext nativeTransactionContext = transaction == null ? null : transaction.getTransactionContext();\n\n\t\tresponse.setTransactionContext(nativeTransactionContext);\n\t\ttry {\n\t\t\ttransactionInterceptor.beforeSendResponse(response);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\tthrow new RpcException(\"Error occurred in remote call!\", rex);\n\t\t}\n\t}\n\n\tpublic Result consumerInvoke(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tString interfaceClazz = RpcContext.getContext().getUrl().getServiceInterface();\n\n\t\tboolean participantFlag = TransactionParticipant.class.getName().equals(interfaceClazz);\n\t\tboolean xaResourceFlag = XAResource.class.getName().equals(interfaceClazz);\n\t\tboolean coordinatorFlag = RemoteCoordinator.class.getName().equals(interfaceClazz);\n\n\t\tif (participantFlag == false && xaResourceFlag == false && coordinatorFlag == false) {\n\t\t\treturn this.consumerInvokeForSVC(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_RESOURCE_START)) {\n\t\t\treturn this.consumerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_IDENTIFIER)) {\n\t\t\treturn this.consumerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_APPLICATION)) {\n\t\t\treturn this.consumerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_REMOTEADDR)) {\n\t\t\treturn this.consumerInvokeForKey(invoker, invocation);\n\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_REMOTENODE)) {\n\t\t\treturn this.consumerInvokeForKey(invoker, invocation);\n\t\t} else {\n\t\t\treturn this.consumerInvokeForJTA(invoker, invocation);\n\t\t}\n\t}\n\n\tpublic Result consumerInvokeForKey(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tMap<String, String> attachments = invocation.getAttachments();\n\t\tattachments.put(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\n\t\tRpcResult result = (RpcResult) invoker.invoke(invocation);\n\n\t\tObject value = result.getValue();\n\t\tif (InvocationResult.class.isInstance(value)) {\n\t\t\tInvocationResult wrapped = (InvocationResult) value;\n\t\t\tresult.setValue(null);\n\t\t\tresult.setException(null);\n\n\t\t\tif (wrapped.isFailure()) {\n\t\t\t\tresult.setException(wrapped.getError());\n\t\t\t} else {\n\t\t\t\tresult.setValue(wrapped.getValue());\n\t\t\t}\n\n\t\t\tString instanceId = StringUtils.trimToEmpty(String.valueOf(wrapped.getVariable(RemoteCoordinator.class.getName())));\n\n\t\t\tthis.registerRemoteParticipantIfNecessary(instanceId);\n\n\t\t\tString interfaceClazz = RpcContext.getContext().getUrl().getServiceInterface();\n\t\t\tboolean participantFlag = TransactionParticipant.class.getName().equals(interfaceClazz);\n\t\t\tboolean xaResourceFlag = XAResource.class.getName().equals(interfaceClazz);\n\t\t\tboolean coordinatorFlag = RemoteCoordinator.class.getName().equals(interfaceClazz);\n\t\t\tboolean resultInitRequired = (participantFlag || xaResourceFlag || coordinatorFlag) && result.getValue() == null;\n\t\t\tif (resultInitRequired) {\n\t\t\t\tif (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_IDENTIFIER)) {\n\t\t\t\t\tresult.setValue(instanceId);\n\t\t\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_APPLICATION)) {\n\t\t\t\t\tresult.setValue(CommonUtils.getApplication(instanceId));\n\t\t\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_REMOTEADDR)) {\n\t\t\t\t\tresult.setValue(CommonUtils.getRemoteAddr(instanceId));\n\t\t\t\t} else if (StringUtils.equals(invocation.getMethodName(), KEY_XA_GET_REMOTENODE)) {\n\t\t\t\t\tresult.setValue(CommonUtils.getRemoteNode(instanceId));\n\t\t\t\t}\n\t\t\t} // end-if (resultInitRequired)\n\n\t\t} // end-if (InvocationResult.class.isInstance(value))\n\n\t\treturn result;\n\t}\n\n\tpublic Result consumerInvokeForJTA(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tMap<String, String> attachments = invocation.getAttachments();\n\t\tattachments.put(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\t\tRpcResult result = (RpcResult) invoker.invoke(invocation);\n\t\tObject value = result.getValue();\n\t\tif (InvocationResult.class.isInstance(value)) {\n\t\t\tInvocationResult wrapped = (InvocationResult) value;\n\t\t\tresult.setValue(null);\n\t\t\tresult.setException(null);\n\n\t\t\tif (wrapped.isFailure()) {\n\t\t\t\tresult.setException(wrapped.getError());\n\t\t\t} else {\n\t\t\t\tresult.setValue(wrapped.getValue());\n\t\t\t}\n\n\t\t} // end-if (InvocationResult.class.isInstance(value))\n\n\t\treturn result;\n\t}\n\n\tpublic Result consumerInvokeForSVC(Invoker<?> invoker, Invocation invocation) throws RpcException {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tTransactionContext nativeTransactionContext = transaction == null ? null : transaction.getTransactionContext();\n\n\t\tInvocationDef invocationDef = new InvocationDef();\n\t\tinvocationDef.setInterfaceClass(invoker.getInterface());\n\t\tinvocationDef.setMethodName(invocation.getMethodName());\n\t\tinvocationDef.setParameterTypes(invocation.getParameterTypes());\n\n\t\tRemoteCoordinator participant = this.getParticipantByRemoteAddr(invoker, invocationDef);\n\n\t\tTransactionRequestImpl request = new TransactionRequestImpl();\n\t\trequest.setTransactionContext(nativeTransactionContext);\n\t\trequest.setTargetTransactionCoordinator(participant);\n\n\t\tTransactionResponseImpl response = new TransactionResponseImpl();\n\t\tresponse.setSourceTransactionCoordinator(participant);\n\n\t\tRpcResult result = null;\n\t\tRpcException invokeError = null;\n\t\tThrowable serverError = null;\n\t\ttry {\n\t\t\tthis.beforeConsumerInvokeForSVC(invocation, request, response);\n\t\t\tresult = (RpcResult) invoker.invoke(invocation);\n\t\t\tObject value = result.getValue();\n\t\t\tif (InvocationResult.class.isInstance(value)) {\n\t\t\t\tInvocationResult wrapped = (InvocationResult) value;\n\t\t\t\tresult.setValue(null);\n\t\t\t\tresult.setException(null);\n\n\t\t\t\tif (wrapped.isFailure()) {\n\t\t\t\t\tresult.setException(wrapped.getError());\n\t\t\t\t\tserverError = wrapped.getError();\n\t\t\t\t} else {\n\t\t\t\t\tresult.setValue(wrapped.getValue());\n\t\t\t\t}\n\n\t\t\t\tString propagatedBy = (String) wrapped.getVariable(Propagation.class.getName());\n\t\t\t\tString instanceId = (String) wrapped.getVariable(RemoteCoordinator.class.getName());\n\n\t\t\t\tparticipantRegistry.putInvocationDef(invocationDef, CommonUtils.getRemoteNode(instanceId));\n\n\t\t\t\tString identifier = transactionCoordinator.getIdentifier();\n\t\t\t\tboolean participantDelistRequired = StringUtils.equals(propagatedBy, identifier) == false;\n\t\t\t\tresponse.setParticipantDelistFlag(participantDelistRequired);\n\t\t\t\tresponse.setParticipantEnlistFlag(request.isParticipantEnlistFlag());\n\t\t\t}\n\t\t} catch (RpcException rex) {\n\t\t\tinvokeError = rex;\n\t\t} catch (Throwable rex) {\n\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\tinvokeError = new RpcException(rex.getMessage());\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tthis.afterConsumerInvokeForSVC(invocation, request, response);\n\t\t\t} catch (RpcException rex) {\n\t\t\t\tif (invokeError == null) {\n\t\t\t\t\tthrow rex;\n\t\t\t\t} else {\n\t\t\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\t\t\tthrow invokeError;\n\t\t\t\t}\n\t\t\t} catch (RuntimeException rex) {\n\t\t\t\tif (invokeError == null) {\n\t\t\t\t\tthrow new RpcException(rex.getMessage());\n\t\t\t\t} else {\n\t\t\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\t\t\tthrow invokeError;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (serverError == null && invokeError == null) {\n\t\t\treturn result;\n\t\t} else if (serverError == null && invokeError != null) {\n\t\t\tthrow invokeError;\n\t\t} else if (RpcException.class.isInstance(serverError)) {\n\t\t\tthrow (RpcException) serverError;\n\t\t} else {\n\t\t\treturn result;\n\t\t}\n\n\t}\n\n\tprivate RemoteCoordinator getParticipantByRemoteAddr(Invoker<?> invoker, InvocationDef invocationDef) {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\n\t\tURL targetUrl = invoker.getUrl();\n\t\tString targetAddr = targetUrl.getIp();\n\t\tint targetPort = targetUrl.getPort();\n\n\t\tRemoteAddr remoteAddr = new RemoteAddr();\n\t\tremoteAddr.setServerHost(targetAddr);\n\t\tremoteAddr.setServerPort(targetPort);\n\n\t\tif (participantRegistry.containsPhysicalInstance(remoteAddr) == false) {\n\t\t\tthis.initializePhysicalInstanceIfNecessary(remoteAddr);\n\t\t} // end-if (participantRegistry.containsPhysicalInstance(remoteAddr) == false)\n\n\t\tRemoteNode invocationContext = new RemoteNode();\n\t\tinvocationContext.setServerHost(targetAddr);\n\t\tinvocationContext.setServerPort(targetPort);\n\n\t\tRemoteCoordinator remoteCoordinator = participantRegistry.getPhysicalInstance(remoteAddr);\n\n\t\tDubboRemoteCoordinator dubboCoordinator = new DubboRemoteCoordinator();\n\t\tdubboCoordinator.setInvocationContext(invocationContext);\n\t\tdubboCoordinator.setRemoteCoordinator(remoteCoordinator);\n\t\tdubboCoordinator.setCoordinatorType(DubboRemoteCoordinator.KEY_PARTICIPANT_TYPE_EXACT);\n\n\t\tRemoteCoordinator participant = (RemoteCoordinator) Proxy.newProxyInstance(\n\t\t\t\tDubboRemoteCoordinator.class.getClassLoader(), new Class[] { RemoteCoordinator.class }, dubboCoordinator);\n\t\tdubboCoordinator.setProxyCoordinator(participant);\n\n\t\treturn participant;\n\t}\n\n\tprivate void beforeConsumerInvokeForSVC(Invocation invocation, TransactionRequestImpl request,\n\t\t\tTransactionResponseImpl response) {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\t\tRemoteCoordinator transactionCoordinator = (RemoteCoordinator) beanFactory.getNativeParticipant();\n\n\t\tMap<String, String> attachments = invocation.getAttachments();\n\t\tattachments.put(RemoteCoordinator.class.getName(), transactionCoordinator.getIdentifier());\n\n\t\ttransactionInterceptor.beforeSendRequest(request);\n\t\tif (request.getTransactionContext() != null) {\n\t\t\tByteArrayOutputStream baos = new ByteArrayOutputStream();\n\t\t\tHessianOutput output = new HessianOutput(baos);\n\t\t\ttry {\n\t\t\t\toutput.writeObject(request.getTransactionContext());\n\t\t\t} catch (IOException ex) {\n\t\t\t\tlogger.error(\"Error occurred in remote call!\", ex);\n\t\t\t\tthrow new RpcException(\"Error occurred in remote call!\", ex);\n\t\t\t}\n\t\t\tString transactionContextContent = ByteUtils.byteArrayToString(baos.toByteArray());\n\t\t\tattachments.put(TransactionContext.class.getName(), transactionContextContent);\n\t\t}\n\n\t}\n\n\tprivate void afterConsumerInvokeForSVC(Invocation invocation, TransactionRequestImpl request,\n\t\t\tTransactionResponseImpl response) {\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tRpcException rpcError = null;\n\t\ttry {\n\t\t\tif (request.getTransactionContext() != null) {\n\t\t\t\tString transactionContextContent = invocation.getAttachment(TransactionContext.class.getName());\n\t\t\t\tbyte[] byteArray = ByteUtils.stringToByteArray(transactionContextContent);\n\t\t\t\tByteArrayInputStream bais = new ByteArrayInputStream(byteArray);\n\t\t\t\tHessianInput input = new HessianInput(bais);\n\t\t\t\tTransactionContext remoteTransactionContext = (TransactionContext) input.readObject();\n\t\t\t\tresponse.setTransactionContext(remoteTransactionContext);\n\t\t\t}\n\t\t} catch (IOException ex) {\n\t\t\tlogger.error(\"Error occurred in remote call!\", ex);\n\t\t\trpcError = new RpcException(\"Error occurred in remote call!\", ex);\n\t\t}\n\n\t\ttry {\n\t\t\ttransactionInterceptor.afterReceiveResponse(response);\n\t\t} catch (RuntimeException rex) {\n\t\t\tlogger.error(\"Error occurred in remote call!\", rex);\n\t\t\tthrow new RpcException(\"Error occurred in remote call!\", rex);\n\t\t}\n\n\t\tif (rpcError != null) {\n\t\t\tthrow rpcError;\n\t\t}\n\n\t}\n\n\tprivate void registerRemoteParticipantIfNecessary(String instanceId) {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\n\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(instanceId);\n\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(instanceId);\n\n\t\tif (StringUtils.isNotBlank(instanceId) && remoteAddr != null && remoteNode != null\n\t\t\t\t&& participantRegistry.containsRemoteNode(remoteAddr) == false) {\n\t\t\tparticipantRegistry.putRemoteNode(remoteAddr, remoteNode);\n\t\t}\n\t}\n\n\tprivate void initializePhysicalInstanceIfNecessary(RemoteAddr remoteAddr) throws RpcException {\n\t\tif (remoteAddr != null) {\n\t\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\t\tRemoteCoordinator physicalInst = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\t\tif (physicalInst == null) {\n\t\t\t\tString serverHost = remoteAddr.getServerHost();\n\t\t\t\tint serverPort = remoteAddr.getServerPort();\n\t\t\t\tfinal String target = String.format(\"%s:%s\", serverHost, serverPort).intern();\n\t\t\t\tsynchronized (target) {\n\t\t\t\t\tRemoteCoordinator participant = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\t\t\t\tif (participant == null) {\n\t\t\t\t\t\tthis.processInitPhysicalInstanceIfNecessary(remoteAddr);\n\t\t\t\t\t}\n\t\t\t\t} // end-synchronized (target)\n\t\t\t} // end-if (physicalInst == null)\n\t\t}\n\t}\n\n\tprivate void processInitPhysicalInstanceIfNecessary(RemoteAddr remoteAddr) throws RpcException {\n\t\tRemoteCoordinatorRegistry participantRegistry = RemoteCoordinatorRegistry.getInstance();\n\t\tTransactionBeanRegistry beanRegistry = TransactionBeanRegistry.getInstance();\n\n\t\tRemoteCoordinator participant = participantRegistry.getPhysicalInstance(remoteAddr);\n\t\tif (participant == null) {\n\t\t\tApplicationConfig applicationConfig = beanRegistry.getBean(ApplicationConfig.class);\n\t\t\tRegistryConfig registryConfig = beanRegistry.getBean(RegistryConfig.class);\n\t\t\tProtocolConfig protocolConfig = beanRegistry.getBean(ProtocolConfig.class);\n\n\t\t\tReferenceConfig<RemoteCoordinator> referenceConfig = new ReferenceConfig<RemoteCoordinator>();\n\t\t\treferenceConfig.setInterface(RemoteCoordinator.class);\n\t\t\treferenceConfig.setTimeout(15000);\n\t\t\treferenceConfig.setCluster(\"failfast\");\n\t\t\treferenceConfig.setLoadbalance(\"bytejta\");\n\t\t\treferenceConfig.setFilter(\"bytejta\");\n\t\t\treferenceConfig.setGroup(\"org-bytesoft-bytejta\");\n\t\t\treferenceConfig.setCheck(false);\n\t\t\treferenceConfig.setRetries(-1);\n\t\t\treferenceConfig.setUrl(String.format(\"%s:%s\", remoteAddr.getServerHost(), remoteAddr.getServerPort()));\n\t\t\treferenceConfig.setScope(Constants.SCOPE_REMOTE);\n\n\t\t\treferenceConfig.setApplication(applicationConfig);\n\t\t\tif (registryConfig != null) {\n\t\t\t\treferenceConfig.setRegistry(registryConfig);\n\t\t\t}\n\t\t\tif (protocolConfig != null) {\n\t\t\t\treferenceConfig.setProtocol(protocolConfig.getName());\n\t\t\t} // end-if (protocolConfig != null)\n\n\t\t\tRemoteCoordinator reference = referenceConfig.get();\n\t\t\tif (reference == null) {\n\t\t\t\tthrow new RpcException(\"Cannot get the application name of the remote application.\");\n\t\t\t}\n\n\t\t\tparticipantRegistry.putPhysicalInstance(remoteAddr, reference);\n\t\t}\n\t}\n\n\tstatic class InvocationResult implements HessianHandle, Serializable {\n\t\tprivate static final long serialVersionUID = 1L;\n\n\t\tprivate Throwable error;\n\t\tprivate Object value;\n\t\tprivate final Map<String, Serializable> variables = new HashMap<String, Serializable>();\n\n\t\tpublic boolean isFailure() {\n\t\t\treturn this.error != null;\n\t\t}\n\n\t\tpublic Object getValue() {\n\t\t\treturn value;\n\t\t}\n\n\t\tpublic void setValue(Object value) {\n\t\t\tthis.value = value;\n\t\t}\n\n\t\tpublic void setVariable(String key, Serializable value) {\n\t\t\tthis.variables.put(key, value);\n\t\t}\n\n\t\tpublic Serializable getVariable(String key) {\n\t\t\treturn this.variables.get(key);\n\t\t}\n\n\t\tpublic Throwable getError() {\n\t\t\treturn error;\n\t\t}\n\n\t\tpublic void setError(Throwable error) {\n\t\t\tthis.error = error;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter",
    "content": "bytejta=org.bytesoft.bytejta.supports.dubbo.spi.TransactionServiceFilter"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.LoadBalance",
    "content": "bytejta=org.bytesoft.bytejta.supports.dubbo.spi.TransactionLoadBalance"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/resources/META-INF/dubbo/org.bytesoft.bytejta.supports.dubbo.ext.ILoadBalancer",
    "content": "default=org.bytesoft.bytejta.supports.dubbo.spi.TransactionLoadBalancer"
  },
  {
    "path": "bytejta-supports-dubbo/src/main/resources/bytejta-supports-dubbo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns:context=\"http://www.springframework.org/schema/context\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n\txmlns:tx=\"http://www.springframework.org/schema/tx\"\n\txsi:schemaLocation=\"http://www.springframework.org/schema/beans    \n           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    \n           http://www.springframework.org/schema/context    \n           http://www.springframework.org/schema/context/spring-context-3.0.xsd    \n           http://www.springframework.org/schema/aop    \n           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    \n           http://www.springframework.org/schema/tx \n           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\">\n\n\t<import resource=\"classpath:bytejta-supports-core.xml\" />\n\t<import resource=\"classpath:bytejta-supports-task.xml\" />\n\n\t<bean class=\"org.bytesoft.bytejta.supports.dubbo.internal.TransactionBeanConfigValidator\" />\n\t<bean class=\"org.bytesoft.bytejta.supports.dubbo.internal.TransactionEndpointAutoInjector\" />\n\t<bean class=\"org.bytesoft.bytejta.supports.dubbo.internal.TransactionParticipantRegistrant\" />\n\n\t<bean class=\"org.bytesoft.bytejta.supports.spring.TransactionDebuggablePostProcessor\" />\n\n\t<bean class=\"org.bytesoft.bytejta.supports.dubbo.TransactionBeanRegistry\" factory-method=\"getInstance\" />\n\n\t<bean id=\"bytejtaXAResourceDeserializer\" class=\"org.bytesoft.bytejta.logging.deserializer.XAResourceArchiveDeserializer\" />\n\t<bean id=\"bytejtaTransactionDeserializer\" class=\"org.bytesoft.bytejta.logging.deserializer.TransactionArchiveDeserializer\">\n\t\t<property name=\"resourceArchiveDeserializer\" ref=\"bytejtaXAResourceDeserializer\" />\n\t</bean>\n\t<bean id=\"bytejtaArchiveDeserializer\" class=\"org.bytesoft.bytejta.logging.ArchiveDeserializerImpl\">\n\t\t<property name=\"transactionArchiveDeserializer\" ref=\"bytejtaTransactionDeserializer\" />\n\t\t<property name=\"xaResourceArchiveDeserializer\" ref=\"bytejtaXAResourceDeserializer\" />\n\t</bean>\n\n\t<bean id=\"commonResourceDeserializer\" class=\"org.bytesoft.bytejta.supports.serialize.XAResourceDeserializerImpl\" />\n\t<bean id=\"bytejtaResourceDeserializer\" class=\"org.bytesoft.bytejta.supports.dubbo.serialize.XAResourceDeserializerImpl\">\n\t\t<property name=\"resourceDeserializer\" ref=\"commonResourceDeserializer\" />\n\t</bean>\n\n\t<bean id=\"bytejtaBeanFactory\" class=\"org.bytesoft.bytejta.TransactionBeanFactoryImpl\" factory-method=\"getInstance\">\n\t\t<property name=\"transactionManager\" ref=\"transactionManager\" />\n\t\t<property name=\"xidFactory\" ref=\"bytejtaXidFactory\" />\n\t\t<property name=\"transactionTimer\" ref=\"transactionManager\" />\n\t\t<property name=\"transactionLogger\" ref=\"bytejtaTransactionLogger\" />\n\t\t<property name=\"transactionRepository\" ref=\"bytejtaTransactionRepository\" />\n\t\t<property name=\"transactionInterceptor\" ref=\"bytejtaTransactionInterceptor\" />\n\t\t<property name=\"transactionRecovery\" ref=\"bytejtaTransactionRecovery\" />\n\t\t<property name=\"transactionCoordinator\" ref=\"bytejtaTransactionCoordinator\" />\n\t\t<property name=\"transactionLock\" ref=\"bytejtaTransactionLock\" />\n\t\t<property name=\"archiveDeserializer\" ref=\"bytejtaArchiveDeserializer\" />\n\t\t<property name=\"resourceDeserializer\" ref=\"bytejtaResourceDeserializer\" />\n\t</bean>\n\n</beans>"
  },
  {
    "path": "bytejta-supports-springcloud/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.bytesoft</groupId>\n\t\t<artifactId>bytejta-parent</artifactId>\n\t\t<version>0.5.0-BETA9</version>\n\t</parent>\n\n\t<artifactId>bytejta-supports-springcloud</artifactId>\n\t<packaging>jar</packaging>\n\n\t<name>bytejta-supports-springcloud</name>\n\t<description>The bytejta-supports project is the module of ByteJTA for integrating with third-party open source project.</description>\n\t<url>http://www.bytesoft.org</url>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t<artifactId>bytejta-supports</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.servlet</groupId>\n\t\t\t<artifactId>javax.servlet-api</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-tx</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-jdbc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-aop</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-webmvc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-autoconfigure</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-buffer</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-codec</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-codec-http</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-common</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-handler</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-transport</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t<artifactId>netty-transport-native-epoll</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-netflix-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-openfeign-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-openfeign</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-commons</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-zookeeper-core</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-buffer</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-codec</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-codec-http</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-common</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-handler</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-transport</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.netty</groupId>\n\t\t\t<artifactId>netty-transport-native-epoll</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>aopalliance</groupId>\n\t\t\t<artifactId>aopalliance</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>cglib</groupId>\n\t\t\t<artifactId>cglib</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>asm</groupId>\n\t\t\t\t\t<artifactId>asm</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.ow2.asm</groupId>\n\t\t\t<artifactId>asm</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.aspectj</groupId>\n\t\t\t<artifactId>aspectjweaver</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-dbcp2</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/SpringCloudBeanRegistry.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud;\n\nimport java.lang.reflect.Proxy;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.loadbalancer.TransactionLoadBalancerInterceptor;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.core.env.Environment;\nimport org.springframework.web.client.RestTemplate;\n\npublic final class SpringCloudBeanRegistry implements TransactionBeanFactoryAware, EnvironmentAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(SpringCloudBeanRegistry.class);\n\tprivate static final SpringCloudBeanRegistry instance = new SpringCloudBeanRegistry();\n\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate RestTemplate restTemplate;\n\tprivate ThreadLocal<TransactionLoadBalancerInterceptor> interceptors = new ThreadLocal<TransactionLoadBalancerInterceptor>();\n\tprivate Environment environment;\n\n\tprivate SpringCloudBeanRegistry() {\n\t\tif (instance != null) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic static SpringCloudBeanRegistry getInstance() {\n\t\treturn instance;\n\t}\n\n\tpublic RemoteCoordinator getConsumeCoordinator(String identifier) {\n\t\tRemoteCoordinatorRegistry registry = RemoteCoordinatorRegistry.getInstance();\n\t\tif (StringUtils.isBlank(identifier)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(identifier);\n\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(identifier);\n\n\t\tRemoteNode targetNode = registry.getRemoteNode(remoteAddr);\n\t\tif (targetNode == null && remoteAddr != null //\n\t\t\t\t&& remoteNode != null && StringUtils.isNotBlank(remoteNode.getServiceKey())) {\n\t\t\tregistry.putRemoteNode(remoteAddr, remoteNode);\n\t\t}\n\n\t\t// String application = CommonUtils.getApplication(identifier);\n\t\t// RemoteCoordinator participant = registry.getParticipant(application);\n\t\t// if (participant != null) {\n\t\t// return participant;\n\t\t// }\n\n\t\tRemoteCoordinator physical = registry.getPhysicalInstance(remoteAddr);\n\t\tif (physical != null) {\n\t\t\treturn physical;\n\t\t}\n\n\t\tSpringCloudCoordinator handler = new SpringCloudCoordinator();\n\t\thandler.setIdentifier(identifier);\n\t\thandler.setEnvironment(this.environment);\n\n\t\tphysical = (RemoteCoordinator) Proxy.newProxyInstance(SpringCloudCoordinator.class.getClassLoader(),\n\t\t\t\tnew Class[] { RemoteCoordinator.class }, handler);\n\n\t\tregistry.putPhysicalInstance(remoteAddr, physical);\n\n\t\t// registry.putRemoteNode(remoteAddr, remoteNode);\n\t\t// registry.putParticipant(application, participant);\n\n\t\treturn physical;\n\t}\n\n\tpublic TransactionLoadBalancerInterceptor getLoadBalancerInterceptor() {\n\t\treturn this.interceptors.get();\n\t}\n\n\tpublic void setLoadBalancerInterceptor(TransactionLoadBalancerInterceptor interceptor) {\n\t\tthis.interceptors.set(interceptor);\n\t}\n\n\tpublic void removeLoadBalancerInterceptor() {\n\t\tthis.interceptors.remove();\n\t}\n\n\tpublic RestTemplate getRestTemplate() {\n\t\treturn restTemplate;\n\t}\n\n\tpublic void setRestTemplate(RestTemplate restTemplate) {\n\t\tthis.restTemplate = restTemplate;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n\tpublic Environment getEnvironment() {\n\t\treturn environment;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/SpringCloudCoordinator.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud;\n\nimport java.io.IOException;\nimport java.io.Serializable;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.common.utils.SerializeUtils;\nimport org.bytesoft.transaction.TransactionParticipant;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.xa.TransactionXid;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.env.Environment;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.client.HttpClientErrorException;\nimport org.springframework.web.client.HttpServerErrorException;\nimport org.springframework.web.client.RestTemplate;\n\npublic class SpringCloudCoordinator implements InvocationHandler {\n\tstatic final Logger logger = LoggerFactory.getLogger(SpringCloudCoordinator.class);\n\tstatic final String CONSTANT_CONTENT_PATH = \"org.bytesoft.bytejta.contextpath\";\n\n\tprivate String identifier;\n\tprivate Environment environment;\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tClass<?> clazz = method.getDeclaringClass();\n\t\tString methodName = method.getName();\n\t\tClass<?> returnType = method.getReturnType();\n\t\tif (Object.class.equals(clazz)) {\n\t\t\treturn method.invoke(this, args);\n\t\t} else if (TransactionParticipant.class.equals(clazz)) {\n\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t} else if (RemoteCoordinator.class.equals(clazz)) {\n\t\t\tif (\"getIdentifier\".equals(methodName)) {\n\t\t\t\treturn this.identifier;\n\t\t\t} else if (\"getApplication\".equals(methodName)) {\n\t\t\t\tint firstIndex = this.identifier.indexOf(\":\");\n\t\t\t\tint lastIndex = this.identifier.lastIndexOf(\":\");\n\t\t\t\treturn firstIndex <= 0 || lastIndex <= 0 || firstIndex > lastIndex //\n\t\t\t\t\t\t? null : this.identifier.subSequence(firstIndex + 1, lastIndex);\n\t\t\t} else if (\"getRemoteAddr\".equals(methodName) && RemoteAddr.class.equals(returnType)) {\n\t\t\t\treturn this.identifier == null ? null : CommonUtils.getRemoteAddr(this.identifier);\n\t\t\t} else if (\"getRemoteNode\".equals(methodName) && RemoteNode.class.equals(returnType)) {\n\t\t\t\treturn this.identifier == null ? null : CommonUtils.getRemoteNode(this.identifier);\n\t\t\t} else {\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\t\t} else if (XAResource.class.equals(clazz)) {\n\t\t\tif (\"start\".equals(methodName)) {\n\t\t\t\treturn null; // return immediately\n\t\t\t} else if (\"prepare\".equals(methodName)) {\n\t\t\t\treturn this.invokeHttpPostRequest(proxy, method, args);\n\t\t\t} else if (\"commit\".equals(methodName)) {\n\t\t\t\treturn this.invokeHttpPostRequest(proxy, method, args);\n\t\t\t} else if (\"rollback\".equals(methodName)) {\n\t\t\t\treturn this.invokeHttpPostRequest(proxy, method, args);\n\t\t\t} else if (\"recover\".equals(methodName)) {\n\t\t\t\treturn this.invokeTransactionRecover(proxy, method, args);\n\t\t\t} else if (\"forget\".equals(methodName)) {\n\t\t\t\treturn this.invokeHttpPostRequest(proxy, method, args);\n\t\t\t} else {\n\t\t\t\tthrow new XAException(XAException.XAER_RMFAIL);\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new IllegalAccessException();\n\t\t}\n\t}\n\n\tpublic Object invokeHttpPostRequest(Object proxy, Method method, Object[] args) throws Throwable {\n\n\t\tClass<?> returnType = method.getReturnType();\n\t\ttry {\n\t\t\tRestTemplate transactionRestTemplate = SpringCloudBeanRegistry.getInstance().getRestTemplate();\n\t\t\tRestTemplate restTemplate = transactionRestTemplate == null ? new RestTemplate() : transactionRestTemplate;\n\n\t\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(this.identifier);\n\t\t\tString contextPathKey = String.format(\"%s.%s\", CONSTANT_CONTENT_PATH, remoteNode.getServiceKey());\n\t\t\tString contextPath = StringUtils.isBlank(remoteNode.getServiceKey()) //\n\t\t\t\t\t? null : StringUtils.trimToEmpty(this.environment.getProperty(contextPathKey));\n\n\t\t\tStringBuilder ber = new StringBuilder();\n\t\t\tber.append(\"http://\").append(remoteNode.getServerHost()).append(\":\").append(remoteNode.getServerPort());\n\n\t\t\tif (StringUtils.isNotBlank(contextPath) || StringUtils.equals(contextPath, \"/\")) {\n\t\t\t\tber.append(contextPath.startsWith(\"/\") ? \"\" : \"/\").append(contextPath);\n\t\t\t} // end-if (StringUtils.isNotBlank(contextPath) || StringUtils.equals(contextPath, \"/\"))\n\n\t\t\tber.append(\"/org/bytesoft/bytejta/\");\n\t\t\tber.append(method.getName());\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tSerializable arg = (Serializable) args[i];\n\t\t\t\tber.append(\"/\").append(this.serialize(arg));\n\t\t\t}\n\n\t\t\tResponseEntity<?> response = restTemplate.postForEntity(ber.toString(), null, returnType, new Object[0]);\n\n\t\t\treturn response.getBody();\n\t\t} catch (HttpClientErrorException ex) {\n\t\t\tXAException xaEx = new XAException(XAException.XAER_RMFAIL);\n\t\t\txaEx.initCause(ex);\n\t\t\tthrow xaEx;\n\t\t} catch (HttpServerErrorException ex) {\n\t\t\t// int statusCode = ex.getRawStatusCode();\n\t\t\tHttpHeaders headers = ex.getResponseHeaders();\n\t\t\tString failureText = StringUtils.trimToNull(headers.getFirst(\"failure\"));\n\t\t\tString errorText = StringUtils.trimToNull(headers.getFirst(\"XA_XAER\"));\n\n\t\t\tBoolean failure = failureText == null ? null : Boolean.parseBoolean(failureText);\n\t\t\tInteger errorCode = null;\n\t\t\ttry {\n\t\t\t\terrorCode = errorText == null ? null : Integer.parseInt(errorText);\n\t\t\t} catch (Exception ignore) {\n\t\t\t\tlogger.debug(ignore.getMessage());\n\t\t\t}\n\n\t\t\tif (failure != null && errorCode != null) {\n\t\t\t\tXAException xaEx = new XAException(errorCode);\n\t\t\t\txaEx.initCause(ex);\n\t\t\t\tthrow xaEx;\n\t\t\t} else {\n\t\t\t\tXAException xaEx = new XAException(XAException.XAER_RMERR);\n\t\t\t\txaEx.initCause(ex);\n\t\t\t\tthrow xaEx;\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tXAException xaEx = new XAException(XAException.XAER_RMERR);\n\t\t\txaEx.initCause(ex);\n\t\t\tthrow xaEx;\n\t\t}\n\n\t}\n\n\tpublic Object invokeTransactionRecover(Object proxy, Method method, Object[] args) throws Throwable {\n\n\t\ttry {\n\t\t\tRestTemplate transactionRestTemplate = SpringCloudBeanRegistry.getInstance().getRestTemplate();\n\t\t\tRestTemplate restTemplate = transactionRestTemplate == null ? new RestTemplate() : transactionRestTemplate;\n\n\t\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(this.identifier);\n\t\t\tString contextPathKey = String.format(\"%s.%s\", CONSTANT_CONTENT_PATH, remoteNode.getServiceKey());\n\t\t\tString contextPath = StringUtils.isBlank(remoteNode.getServiceKey()) //\n\t\t\t\t\t? null : StringUtils.trimToEmpty(this.environment.getProperty(contextPathKey));\n\n\t\t\tStringBuilder ber = new StringBuilder();\n\t\t\tber.append(\"http://\").append(remoteNode.getServerHost()).append(\":\").append(remoteNode.getServerPort());\n\n\t\t\tif (StringUtils.isNotBlank(contextPath) || StringUtils.equals(contextPath, \"/\")) {\n\t\t\t\tber.append(contextPath.startsWith(\"/\") ? \"\" : \"/\").append(contextPath);\n\t\t\t} // end-if (StringUtils.isNotBlank(contextPath) || StringUtils.equals(contextPath, \"/\"))\n\n\t\t\tber.append(\"/org/bytesoft/bytejta/\");\n\t\t\tber.append(method.getName());\n\t\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\t\tSerializable arg = (Serializable) args[i];\n\t\t\t\tber.append(\"/\").append(this.serialize(arg));\n\t\t\t}\n\n\t\t\tResponseEntity<?> response = restTemplate.getForEntity(ber.toString(), TransactionXid[].class, new Object[0]);\n\n\t\t\treturn response.getBody();\n\t\t} catch (HttpClientErrorException ex) {\n\t\t\tXAException xaEx = new XAException(XAException.XAER_RMFAIL);\n\t\t\txaEx.initCause(ex);\n\t\t\tthrow xaEx;\n\t\t} catch (HttpServerErrorException ex) {\n\t\t\t// int statusCode = ex.getRawStatusCode();\n\t\t\tHttpHeaders headers = ex.getResponseHeaders();\n\t\t\tString failureText = StringUtils.trimToNull(headers.getFirst(\"failure\"));\n\t\t\tString errorText = StringUtils.trimToNull(headers.getFirst(\"XA_XAER\"));\n\n\t\t\tBoolean failure = failureText == null ? null : Boolean.parseBoolean(failureText);\n\t\t\tInteger errorCode = null;\n\t\t\ttry {\n\t\t\t\terrorCode = errorText == null ? null : Integer.parseInt(errorText);\n\t\t\t} catch (Exception ignore) {\n\t\t\t\tlogger.debug(ignore.getMessage());\n\t\t\t}\n\n\t\t\tif (failure != null && errorCode != null) {\n\t\t\t\tXAException xaEx = new XAException(errorCode);\n\t\t\t\txaEx.initCause(ex);\n\t\t\t\tthrow xaEx;\n\t\t\t} else {\n\t\t\t\tXAException xaEx = new XAException(XAException.XAER_RMERR);\n\t\t\t\txaEx.initCause(ex);\n\t\t\t\tthrow xaEx;\n\t\t\t}\n\t\t} catch (Exception ex) {\n\t\t\tXAException xaEx = new XAException(XAException.XAER_RMERR);\n\t\t\txaEx.initCause(ex);\n\t\t\tthrow xaEx;\n\t\t}\n\n\t}\n\n\tprivate String serialize(Serializable arg) throws IOException {\n\t\tif (Xid.class.isInstance(arg)) {\n\t\t\tXid xid = (Xid) arg;\n\t\t\tbyte[] globalTransactionId = xid.getGlobalTransactionId();\n\t\t\treturn ByteUtils.byteArrayToString(globalTransactionId);\n\t\t} else if (Integer.class.isInstance(arg) || Integer.TYPE.isInstance(arg)) {\n\t\t\treturn String.valueOf(arg);\n\t\t} else if (Boolean.class.isInstance(arg) || Boolean.TYPE.isInstance(arg)) {\n\t\t\treturn String.valueOf(arg);\n\t\t} else {\n\t\t\tbyte[] byteArray = SerializeUtils.serializeObject(arg);\n\t\t\treturn ByteUtils.byteArrayToString(byteArray);\n\t\t}\n\t}\n\n\tpublic String toString() {\n\t\treturn String.format(\"<remote-resource| id= %s>\", this.identifier);\n\t}\n\n\tpublic String getIdentifier() {\n\t\treturn identifier;\n\t}\n\n\tpublic void setIdentifier(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic Environment getEnvironment() {\n\t\treturn environment;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/SpringCloudEndpointPostProcessor.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.MutablePropertyValues;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.BeanFactoryPostProcessor;\nimport org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.core.env.Environment;\n\npublic class SpringCloudEndpointPostProcessor\n\t\timplements BeanFactoryPostProcessor, TransactionBeanFactoryAware, EnvironmentAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(SpringCloudEndpointPostProcessor.class);\n\n\t@javax.inject.Inject\n\tprivate TransactionBeanFactory beanFactory;\n\tprivate Environment environment;\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n\tpublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n\t\tClassLoader cl = Thread.currentThread().getContextClassLoader();\n\n\t\tList<BeanDefinition> beanDefList = new ArrayList<BeanDefinition>();\n\t\tString[] beanNameArray = beanFactory.getBeanDefinitionNames();\n\t\tfor (int i = 0; i < beanNameArray.length; i++) {\n\t\t\tString beanName = beanNameArray[i];\n\t\t\tBeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);\n\t\t\tString beanClassName = beanDef.getBeanClassName();\n\n\t\t\tClass<?> beanClass = null;\n\t\t\ttry {\n\t\t\t\tbeanClass = cl.loadClass(beanClassName);\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.debug(\"Cannot load class {}, beanId= {}!\", beanClassName, beanName, ex);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (TransactionEndpointAware.class.isAssignableFrom(beanClass)) {\n\t\t\t\tbeanDefList.add(beanDef);\n\t\t\t}\n\t\t}\n\n\t\tString host = CommonUtils.getInetAddress();\n\t\tString name = this.environment.getProperty(\"spring.application.name\");\n\t\tString port = this.environment.getProperty(\"server.port\");\n\t\tString identifier = String.format(\"%s:%s:%s\", host, name, port);\n\n\t\tfor (int i = 0; i < beanDefList.size(); i++) {\n\t\t\tBeanDefinition beanDef = beanDefList.get(i);\n\t\t\tMutablePropertyValues mpv = beanDef.getPropertyValues();\n\t\t\tmpv.addPropertyValue(TransactionEndpointAware.ENDPOINT_FIELD_NAME, identifier);\n\t\t}\n\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory beanFactory) {\n\t\tthis.beanFactory = beanFactory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/config/SpringCloudConfiguration.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.config;\n\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Set;\n\nimport javax.transaction.UserTransaction;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.resource.properties.ConnectorResourcePropertySourceFactory;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionClientRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionFeignBeanPostProcessor;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionFeignContract;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionFeignDecoder;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionFeignErrorDecoder;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionFeignInterceptor;\nimport org.bytesoft.bytejta.supports.springcloud.hystrix.TransactionHystrixBeanPostProcessor;\nimport org.bytesoft.bytejta.supports.springcloud.loadbalancer.TransactionLoadBalancerRuleImpl;\nimport org.bytesoft.bytejta.supports.springcloud.property.TransactionPropertySourceFactory;\nimport org.bytesoft.bytejta.supports.springcloud.web.TransactionHandlerInterceptor;\nimport org.bytesoft.bytejta.supports.springcloud.web.TransactionRequestInterceptor;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.MutablePropertyValues;\nimport org.springframework.beans.PropertyValue;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.NoSuchBeanDefinitionException;\nimport org.springframework.beans.factory.ObjectFactory;\nimport org.springframework.beans.factory.SmartInitializingSingleton;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.BeanFactoryPostProcessor;\nimport org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.autoconfigure.http.HttpMessageConverters;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;\nimport org.springframework.cloud.openfeign.support.ResponseEntityDecoder;\nimport org.springframework.cloud.openfeign.support.SpringDecoder;\nimport org.springframework.cloud.openfeign.support.SpringMvcContract;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.context.annotation.DependsOn;\nimport org.springframework.context.annotation.EnableAspectJAutoProxy;\nimport org.springframework.context.annotation.ImportResource;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.core.env.Environment;\nimport org.springframework.http.client.ClientHttpRequestFactory;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\nimport org.springframework.transaction.annotation.TransactionManagementConfigurer;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\nimport feign.codec.ErrorDecoder;\n\n@PropertySource(value = \"bytejta:loadbalancer.config\", factory = TransactionPropertySourceFactory.class)\n@PropertySource(value = \"bytejta:connector.config\", factory = ConnectorResourcePropertySourceFactory.class)\n@ImportResource({ \"classpath:bytejta-supports-springcloud.xml\" })\n@EnableAspectJAutoProxy(proxyTargetClass = true)\n@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })\n@EnableTransactionManagement\npublic class SpringCloudConfiguration implements WebMvcConfigurer, TransactionManagementConfigurer, BeanFactoryPostProcessor,\n\t\tInitializingBean, SmartInitializingSingleton, TransactionEndpointAware, EnvironmentAware, ApplicationContextAware {\n\tstatic final String CONSTANT_INCLUSIONS = \"org.bytesoft.bytejta.feign.inclusions\";\n\tstatic final String CONSTANT_EXCLUSIONS = \"org.bytesoft.bytejta.feign.exclusions\";\n\tstatic final String FEIGN_FACTORY_CLASS = \"org.springframework.cloud.openfeign.FeignClientFactoryBean\";\n\n\tprivate ApplicationContext applicationContext;\n\tprivate String identifier;\n\tprivate Environment environment;\n\tprivate transient final Set<String> transientClientSet = new HashSet<String>();\n\n\tpublic void afterSingletonsInstantiated() /* Check if the rule is set correctly */ {\n\t\tcom.netflix.loadbalancer.IRule loadBalancerRule = null;\n\t\ttry {\n\t\t\tloadBalancerRule = this.applicationContext.getBean(com.netflix.loadbalancer.IRule.class);\n\t\t} catch (NoSuchBeanDefinitionException ex) {\n\t\t\treturn; // return quietly\n\t\t}\n\n\t\tif (TransactionLoadBalancerRuleImpl.class.isInstance(loadBalancerRule)) {\n\t\t\treturn; // return quietly\n\t\t}\n\n\t\tthrow new IllegalStateException(\"TransactionLoadBalancerRuleImpl is disabled!\");\n\t}\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tString host = CommonUtils.getInetAddress();\n\t\tString name = this.environment.getProperty(\"spring.application.name\");\n\t\tString port = this.environment.getProperty(\"server.port\");\n\t\tthis.identifier = String.format(\"%s:%s:%s\", host, name, port);\n\t}\n\n\tpublic PlatformTransactionManager annotationDrivenTransactionManager() {\n\t\torg.springframework.transaction.jta.JtaTransactionManager jtaTransactionManager //\n\t\t\t\t= new org.springframework.transaction.jta.JtaTransactionManager();\n\t\tjtaTransactionManager.setTransactionManager(this.applicationContext.getBean(TransactionManager.class));\n\t\tjtaTransactionManager.setUserTransaction(this.applicationContext.getBean(UserTransaction.class));\n\t\treturn jtaTransactionManager;\n\t}\n\n\t@org.springframework.context.annotation.Bean\n\t@ConditionalOnProperty(name = \"feign.hystrix.enabled\", havingValue = \"false\", matchIfMissing = true)\n\tpublic TransactionFeignBeanPostProcessor feignPostProcessor() {\n\t\treturn new TransactionFeignBeanPostProcessor();\n\t}\n\n\t@org.springframework.context.annotation.Bean\n\t@ConditionalOnProperty(name = \"feign.hystrix.enabled\")\n\t@ConditionalOnClass(feign.hystrix.HystrixFeign.class)\n\tpublic TransactionHystrixBeanPostProcessor hystrixPostProcessor() {\n\t\treturn new TransactionHystrixBeanPostProcessor();\n\t}\n\n\t@org.springframework.context.annotation.Bean\n\tpublic TransactionFeignInterceptor transactionFeignInterceptor() {\n\t\tTransactionFeignInterceptor interceptor = new TransactionFeignInterceptor();\n\t\tinterceptor.setEndpoint(this.identifier);\n\t\treturn interceptor;\n\t}\n\n\t@org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean(feign.Contract.class)\n\t@org.springframework.context.annotation.Bean\n\tpublic feign.Contract feignContract() {\n\t\treturn new SpringMvcContract();\n\t}\n\n\t@org.springframework.context.annotation.Primary\n\t@org.springframework.context.annotation.Bean\n\tpublic feign.Contract transactionFeignContract(@Autowired feign.Contract contract) {\n\t\treturn new TransactionFeignContract(contract);\n\t}\n\n\t@org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean(feign.codec.Decoder.class)\n\t@org.springframework.context.annotation.Bean\n\tpublic feign.codec.Decoder feignDecoder(@Autowired ObjectFactory<HttpMessageConverters> messageConverters) {\n\t\treturn new ResponseEntityDecoder(new SpringDecoder(messageConverters));\n\t}\n\n\t@org.springframework.context.annotation.Primary\n\t@org.springframework.context.annotation.Bean\n\tpublic feign.codec.Decoder transactionFeignDecoder(@Autowired ObjectFactory<HttpMessageConverters> objectFactory,\n\t\t\t@Autowired feign.codec.Decoder decoder) {\n\t\tTransactionFeignDecoder feignDecoder = new TransactionFeignDecoder(decoder);\n\t\tfeignDecoder.setObjectFactory(objectFactory);\n\t\treturn feignDecoder;\n\t}\n\n\t@org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean(feign.codec.ErrorDecoder.class)\n\t@org.springframework.context.annotation.Bean\n\tpublic feign.codec.ErrorDecoder errorDecoder() {\n\t\treturn new ErrorDecoder.Default();\n\t}\n\n\t@org.springframework.context.annotation.Primary\n\t@org.springframework.context.annotation.Bean\n\tpublic feign.codec.ErrorDecoder transactionErrorDecoder(@Autowired feign.codec.ErrorDecoder decoder) {\n\t\treturn new TransactionFeignErrorDecoder(decoder);\n\t}\n\n\t@org.springframework.context.annotation.Bean\n\tpublic TransactionHandlerInterceptor transactionHandlerInterceptor() {\n\t\tTransactionHandlerInterceptor interceptor = new TransactionHandlerInterceptor();\n\t\tinterceptor.setEndpoint(this.identifier);\n\t\treturn interceptor;\n\t}\n\n\t@org.springframework.context.annotation.Bean\n\tpublic TransactionRequestInterceptor transactionRequestInterceptor() {\n\t\tTransactionRequestInterceptor interceptor = new TransactionRequestInterceptor();\n\t\tinterceptor.setEndpoint(this.identifier);\n\t\treturn interceptor;\n\t}\n\n\t@org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean(ClientHttpRequestFactory.class)\n\t@org.springframework.context.annotation.Bean\n\t@SuppressWarnings(\"deprecation\")\n\tpublic ClientHttpRequestFactory defaultRequestFactory() {\n\t\treturn new org.springframework.http.client.Netty4ClientHttpRequestFactory();\n\t}\n\n\t@org.springframework.context.annotation.Bean(\"transactionRestTemplate\")\n\tpublic RestTemplate transactionTemplate(@Autowired ClientHttpRequestFactory requestFactory) {\n\t\tRestTemplate restTemplate = new RestTemplate();\n\t\trestTemplate.setRequestFactory(requestFactory);\n\t\treturn restTemplate;\n\t}\n\n\t@DependsOn(\"transactionRestTemplate\")\n\t@org.springframework.context.annotation.Bean\n\tpublic SpringCloudBeanRegistry beanRegistry(@Qualifier(\"transactionRestTemplate\") @Autowired RestTemplate restTemplate) {\n\t\tSpringCloudBeanRegistry registry = SpringCloudBeanRegistry.getInstance();\n\t\tregistry.setRestTemplate(restTemplate);\n\t\treturn registry;\n\t}\n\n\t@org.springframework.context.annotation.Primary\n\t@org.springframework.cloud.client.loadbalancer.LoadBalanced\n\t@org.springframework.context.annotation.Bean\n\tpublic RestTemplate defaultRestTemplate(@Autowired TransactionRequestInterceptor transactionRequestInterceptor) {\n\t\tRestTemplate restTemplate = new RestTemplate();\n\t\trestTemplate.getInterceptors().add(transactionRequestInterceptor);\n\t\treturn restTemplate;\n\t}\n\n\tpublic void addInterceptors(InterceptorRegistry registry) {\n\t\tTransactionHandlerInterceptor transactionHandlerInterceptor = this.applicationContext\n\t\t\t\t.getBean(TransactionHandlerInterceptor.class);\n\t\tregistry.addInterceptor(transactionHandlerInterceptor);\n\t}\n\n\tpublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n\n\t\tString[] beanNameArray = beanFactory.getBeanDefinitionNames();\n\t\tfor (int i = 0; i < beanNameArray.length; i++) {\n\t\t\tBeanDefinition beanDef = beanFactory.getBeanDefinition(beanNameArray[i]);\n\t\t\tString beanClassName = beanDef.getBeanClassName();\n\n\t\t\tif (FEIGN_FACTORY_CLASS.equals(beanClassName) == false) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tMutablePropertyValues mpv = beanDef.getPropertyValues();\n\t\t\tPropertyValue pv = mpv.getPropertyValue(\"name\");\n\t\t\tString client = String.valueOf(pv.getValue() == null ? \"\" : pv.getValue());\n\t\t\tif (StringUtils.isNotBlank(client)) {\n\t\t\t\tthis.transientClientSet.add(client);\n\t\t\t}\n\n\t\t}\n\n\t\tthis.fireAfterPropertiesSet();\n\n\t}\n\n\tpublic void fireAfterPropertiesSet() {\n\t\tTransactionClientRegistry registry = TransactionClientRegistry.getInstance();\n\n\t\tString inclusions = this.environment.getProperty(CONSTANT_INCLUSIONS);\n\t\tString exclusions = this.environment.getProperty(CONSTANT_EXCLUSIONS);\n\n\t\tif (StringUtils.isNotBlank(inclusions) && StringUtils.isNotBlank(exclusions)) {\n\t\t\tthrow new IllegalStateException(String.format(\"Property '%s' and '%s' can not be configured together!\",\n\t\t\t\t\tCONSTANT_INCLUSIONS, CONSTANT_EXCLUSIONS));\n\t\t} else if (StringUtils.isNotBlank(inclusions)) {\n\t\t\tString[] clients = inclusions.split(\"\\\\s*,\\\\s*\");\n\t\t\tfor (int i = 0; i < clients.length; i++) {\n\t\t\t\tString client = clients[i];\n\t\t\t\tregistry.registerClient(client);\n\t\t\t} // end-for (int i = 0; i < clients.length; i++)\n\n\t\t\tthis.transientClientSet.clear();\n\t\t} else if (StringUtils.isNotBlank(exclusions)) {\n\t\t\tString[] clients = exclusions.split(\"\\\\s*,\\\\s*\");\n\t\t\tfor (int i = 0; i < clients.length; i++) {\n\t\t\t\tString client = clients[i];\n\t\t\t\tthis.transientClientSet.remove(client);\n\t\t\t} // end-for (int i = 0; i < clients.length; i++)\n\n\t\t\tIterator<String> itr = this.transientClientSet.iterator();\n\t\t\twhile (itr.hasNext()) {\n\t\t\t\tString client = itr.next();\n\t\t\t\titr.remove();\n\t\t\t\tregistry.registerClient(client);\n\t\t\t} // end-while (itr.hasNext())\n\t\t} else {\n\t\t\tIterator<String> itr = this.transientClientSet.iterator();\n\t\t\twhile (itr.hasNext()) {\n\t\t\t\tString client = itr.next();\n\t\t\t\titr.remove();\n\t\t\t\tregistry.registerClient(client);\n\t\t\t} // end-while (itr.hasNext())\n\t\t}\n\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn this.identifier;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/controller/TransactionCoordinatorController.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.controller;\n\nimport java.beans.PropertyEditorSupport;\n\nimport javax.servlet.http.HttpServletResponse;\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.Xid;\n\nimport org.bytesoft.bytejta.TransactionCoordinator;\nimport org.bytesoft.common.utils.ByteUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.aware.TransactionBeanFactoryAware;\nimport org.bytesoft.transaction.xa.XidFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.MediaType;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\npublic class TransactionCoordinatorController extends PropertyEditorSupport implements TransactionBeanFactoryAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionCoordinatorController.class);\n\n\t@Autowired\n\tprivate TransactionCoordinator transactionCoordinator;\n\t@Autowired\n\tprivate TransactionBeanFactory beanFactory;\n\n\t@RequestMapping(value = \"/org/bytesoft/bytejta/prepare/{xid}\", method = RequestMethod.POST, produces = {\n\t\t\tMediaType.APPLICATION_JSON_UTF8_VALUE })\n\t@ResponseBody\n\tpublic int prepare(@PathVariable(\"xid\") String identifier, HttpServletResponse response) {\n\t\ttry {\n\t\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\t\tbyte[] byteArray = ByteUtils.stringToByteArray(identifier);\n\t\t\tXid xid = xidFactory.createGlobalXid(byteArray);\n\n\t\t\treturn this.transactionCoordinator.prepare(xid);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.error(\"Error occurred while preparing transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.addHeader(\"XA_XAER\", String.valueOf(ex.errorCode));\n\t\t\tresponse.setStatus(500);\n\t\t\treturn -1;\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while preparing transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.setStatus(500);\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\t@RequestMapping(value = \"/org/bytesoft/bytejta/commit/{xid}/{opc}\", method = RequestMethod.POST)\n\t@ResponseBody\n\tpublic void commit(@PathVariable(\"xid\") String identifier, @PathVariable(\"opc\") boolean onePhase,\n\t\t\tHttpServletResponse response) {\n\t\ttry {\n\t\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\t\tbyte[] byteArray = ByteUtils.stringToByteArray(identifier);\n\t\t\tXid xid = xidFactory.createGlobalXid(byteArray);\n\n\t\t\tthis.transactionCoordinator.commit(xid, onePhase);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.addHeader(\"XA_XAER\", String.valueOf(ex.errorCode));\n\t\t\tresponse.setStatus(500);\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while committing transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.setStatus(500);\n\t\t}\n\t}\n\n\t@RequestMapping(value = \"/org/bytesoft/bytejta/rollback/{xid}\", method = RequestMethod.POST)\n\t@ResponseBody\n\tpublic void rollback(@PathVariable(\"xid\") String identifier, HttpServletResponse response) {\n\t\ttry {\n\t\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\t\tbyte[] byteArray = ByteUtils.stringToByteArray(identifier);\n\t\t\tXid xid = xidFactory.createGlobalXid(byteArray);\n\n\t\t\tthis.transactionCoordinator.rollback(xid);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.error(\"Error occurred while rolling back transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.addHeader(\"XA_XAER\", String.valueOf(ex.errorCode));\n\t\t\tresponse.setStatus(500);\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while rolling back transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.setStatus(500);\n\t\t}\n\t}\n\n\t@RequestMapping(value = \"/org/bytesoft/bytejta/recover/{flag}\", method = RequestMethod.GET)\n\t@ResponseBody\n\tpublic Xid[] recover(@PathVariable(\"flag\") int flag, HttpServletResponse response) {\n\t\ttry {\n\t\t\treturn this.transactionCoordinator.recover(flag);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.error(\"Error occurred while recovering transactions.\", ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.addHeader(\"XA_XAER\", String.valueOf(ex.errorCode));\n\t\t\tresponse.setStatus(500);\n\t\t\treturn new Xid[0];\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while recovering transactions.\", ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.setStatus(500);\n\t\t\treturn new Xid[0];\n\t\t}\n\t}\n\n\t@RequestMapping(value = \"/org/bytesoft/bytejta/forget/{xid}\", method = RequestMethod.POST)\n\t@ResponseBody\n\tpublic void forget(@PathVariable(\"xid\") String identifier, HttpServletResponse response) {\n\t\ttry {\n\t\t\tXidFactory xidFactory = this.beanFactory.getXidFactory();\n\t\t\tbyte[] byteArray = ByteUtils.stringToByteArray(identifier);\n\t\t\tXid xid = xidFactory.createGlobalXid(byteArray);\n\n\t\t\tthis.transactionCoordinator.forget(xid);\n\t\t} catch (XAException ex) {\n\t\t\tlogger.error(\"Error occurred while forgetting transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.addHeader(\"XA_XAER\", String.valueOf(ex.errorCode));\n\t\t\tresponse.setStatus(500);\n\t\t} catch (RuntimeException ex) {\n\t\t\tlogger.error(\"Error occurred while forgetting transaction: {}.\", identifier, ex);\n\n\t\t\tresponse.addHeader(\"failure\", \"true\");\n\t\t\tresponse.setStatus(500);\n\t\t}\n\t}\n\n\tpublic TransactionBeanFactory getBeanFactory() {\n\t\treturn this.beanFactory;\n\t}\n\n\tpublic void setBeanFactory(TransactionBeanFactory tbf) {\n\t\tthis.beanFactory = tbf;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/dbcp/CommonDBCPXADataSourceWrapper.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.dbcp;\n\nimport javax.sql.DataSource;\nimport javax.sql.XADataSource;\n\nimport org.apache.commons.dbcp2.managed.BasicManagedDataSource;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.jdbc.XADataSourceWrapper;\n\npublic class CommonDBCPXADataSourceWrapper implements XADataSourceWrapper {\n\t@Autowired\n\tprivate TransactionBeanFactory beanFactory;\n\n\tpublic DataSource wrapDataSource(XADataSource xaDataSource) throws Exception {\n\t\tTransactionManager transactionManager = this.beanFactory.getTransactionManager();\n\n\t\tBasicManagedDataSource bds = new BasicManagedDataSource();\n\t\tbds.setXaDataSourceInstance(xaDataSource);\n\t\tbds.setTransactionManager(transactionManager);\n\n\t\treturn bds;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionClientRegistry.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TransactionClientRegistry {\n\tprivate static final TransactionClientRegistry instance = new TransactionClientRegistry();\n\n\tprivate final Set<String> clients = new HashSet<String>();\n\n\tprivate TransactionClientRegistry() {\n\t\tif (instance != null) {\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\tpublic static TransactionClientRegistry getInstance() {\n\t\treturn instance;\n\t}\n\n\tpublic void registerClient(String name) {\n\t\tthis.clients.add(name);\n\t}\n\n\tpublic void unRegisterClient(String name) {\n\t\tthis.clients.remove(name);\n\t}\n\n\tpublic boolean containsClient(String name) {\n\t\treturn this.clients.contains(name);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionFeignBeanPostProcessor.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Proxy;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.aop.TargetSource;\nimport org.springframework.aop.target.SingletonTargetSource;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.cloud.openfeign.FeignClient;\n\npublic class TransactionFeignBeanPostProcessor implements BeanPostProcessor, InitializingBean {\n\tstatic final String FEIGN_CLAZZ_NAME = \"feign.ReflectiveFeign$FeignInvocationHandler\";\n\n\tprivate Field singletonTargetSourceTargetField = null;\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tField field = SingletonTargetSource.class.getDeclaredField(\"target\");\n\t\tfield.setAccessible(true);\n\t\tthis.singletonTargetSourceTargetField = field;\n\t}\n\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\treturn bean;\n\t}\n\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tif (Proxy.isProxyClass(bean.getClass()) == false) {\n\t\t\treturn bean;\n\t\t}\n\n\t\tTargetSource targetSource = null;\n\t\tObject object = bean;\n\t\tif (org.springframework.aop.framework.Advised.class.isInstance(bean)) {\n\t\t\torg.springframework.aop.framework.Advised advised = (org.springframework.aop.framework.Advised) bean;\n\n\t\t\tClass<?>[] interfaces = advised.getProxiedInterfaces();\n\n\t\t\tfor (int i = 0; i < interfaces.length; i++) {\n\t\t\t\tClass<?> intf = interfaces[i];\n\t\t\t\tif (intf.getAnnotation(FeignClient.class) != null) {\n\t\t\t\t\ttargetSource = advised.getTargetSource();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tobject = targetSource.getTarget();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} catch (Exception error) {\n\t\t\t\t\t\tthrow new IllegalStateException();\n\t\t\t\t\t}\n\t\t\t\t} // end-if (intf.getAnnotation(FeignClient.class) != null)\n\t\t\t} // end-for (int i = 0; i < interfaces.length; i++)\n\t\t} // end-if (org.springframework.aop.framework.Advised.class.isInstance(bean))\n\n\t\tInvocationHandler handler = Proxy.getInvocationHandler(object);\n\t\tif (targetSource == null //\n\t\t\t\t&& StringUtils.equals(FEIGN_CLAZZ_NAME, handler.getClass().getName()) == false) {\n\t\t\treturn bean;\n\t\t}\n\n\t\tObject proxied = this.createProxiedObject(object);\n\t\tif (targetSource == null) {\n\t\t\treturn proxied;\n\t\t}\n\n\t\tif (SingletonTargetSource.class.isInstance(targetSource)) {\n\t\t\ttry {\n\t\t\t\tthis.singletonTargetSourceTargetField.set(targetSource, proxied);\n\t\t\t} catch (IllegalArgumentException error) {\n\t\t\t\tthrow new IllegalStateException(\"Error occurred!\");\n\t\t\t} catch (IllegalAccessException error) {\n\t\t\t\tthrow new IllegalStateException(\"Error occurred!\");\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t}\n\n\t\treturn bean;\n\t}\n\n\tprivate Object createProxiedObject(Object origin) {\n\t\tInvocationHandler handler = Proxy.getInvocationHandler(origin);\n\n\t\tTransactionFeignHandler feignHandler = new TransactionFeignHandler();\n\t\tfeignHandler.setDelegate(handler);\n\n\t\tClass<?> clazz = origin.getClass();\n\t\tClass<?>[] interfaces = clazz.getInterfaces();\n\t\tClassLoader loader = clazz.getClassLoader();\n\t\treturn Proxy.newProxyInstance(loader, interfaces, feignHandler);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionFeignContract.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.util.List;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.cloud.openfeign.support.SpringMvcContract;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\nimport feign.MethodMetadata;\n\npublic class TransactionFeignContract implements feign.Contract, InitializingBean, ApplicationContextAware {\n\tprivate ApplicationContext applicationContext;\n\tprivate feign.Contract delegate;\n\n\tpublic TransactionFeignContract() {\n\t}\n\n\tpublic TransactionFeignContract(feign.Contract contract) {\n\t\tthis.delegate = contract;\n\t}\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tif (this.delegate == null) {\n\t\t\tthis.invokeAfterPropertiesSet();\n\t\t} // end-if (this.delegate == null)\n\t}\n\n\tpublic void invokeAfterPropertiesSet() throws Exception {\n\t\tfeign.Contract feignContract = null;\n\n\t\tString[] beanNameArray = this.applicationContext.getBeanNamesForType(feign.Contract.class);\n\t\tfor (int i = 0; beanNameArray != null && i < beanNameArray.length; i++) {\n\t\t\tString beanName = beanNameArray[i];\n\t\t\tObject beanInst = this.applicationContext.getBean(beanName);\n\t\t\tif (TransactionFeignContract.class.isInstance(beanInst)) {\n\t\t\t\tcontinue;\n\t\t\t} else if (feignContract != null) {\n\t\t\t\tthrow new RuntimeException(\"There are more than one feign.Contract exists!\");\n\t\t\t} else {\n\t\t\t\tfeignContract = (feign.Contract) beanInst;\n\t\t\t}\n\t\t}\n\n\t\tif (feignContract == null) {\n\t\t\tfeignContract = new SpringMvcContract();\n\t\t} // end-if (feignContract == null)\n\n\t\tthis.delegate = feignContract;\n\t}\n\n\tpublic List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) {\n\t\tList<MethodMetadata> metas = this.delegate.parseAndValidatateMetadata(targetType);\n\t\tfor (int i = 0; i < metas.size(); i++) {\n\t\t\tMethodMetadata meta = metas.get(i);\n\t\t\tif (meta.returnType() == void.class) {\n\t\t\t\tmeta.returnType(String.class);\n\t\t\t}\n\t\t}\n\t\treturn metas;\n\t}\n\n\tpublic feign.Contract getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(feign.Contract delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionFeignDecoder.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.Base64;\nimport java.util.Collection;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.common.utils.SerializeUtils;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.ObjectFactory;\nimport org.springframework.boot.autoconfigure.http.HttpMessageConverters;\nimport org.springframework.cloud.openfeign.support.ResponseEntityDecoder;\nimport org.springframework.cloud.openfeign.support.SpringDecoder;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\nimport feign.FeignException;\nimport feign.Request;\nimport feign.Response;\nimport feign.codec.DecodeException;\n\npublic class TransactionFeignDecoder implements feign.codec.Decoder, InitializingBean, ApplicationContextAware {\n\tstatic Logger logger = LoggerFactory.getLogger(TransactionFeignDecoder.class);\n\n\tstatic final String HEADER_TRANCACTION_KEY = \"X-BYTEJTA-TRANSACTION\"; // org.bytesoft.bytejta.transaction\n\tstatic final String HEADER_PROPAGATION_KEY = \"X-BYTEJTA-PROPAGATION\"; // org.bytesoft.bytejta.propagation\n\n\tprivate ApplicationContext applicationContext;\n\tprivate feign.codec.Decoder delegate;\n\n\tprivate ObjectFactory<HttpMessageConverters> objectFactory;\n\n\tpublic TransactionFeignDecoder() {\n\t}\n\n\tpublic TransactionFeignDecoder(feign.codec.Decoder decoder) {\n\t\tthis.delegate = decoder;\n\t}\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tif (this.delegate == null) {\n\t\t\tthis.invokeAfterPropertiesSet();\n\t\t} // end-if (this.delegate == null)\n\t}\n\n\tpublic void invokeAfterPropertiesSet() throws Exception {\n\t\tfeign.codec.Decoder feignDecoder = null;\n\n\t\tString[] beanNameArray = this.applicationContext.getBeanNamesForType(feign.codec.Decoder.class);\n\t\tfor (int i = 0; beanNameArray != null && i < beanNameArray.length; i++) {\n\t\t\tString beanName = beanNameArray[i];\n\t\t\tObject beanInst = this.applicationContext.getBean(beanName);\n\t\t\tif (TransactionFeignDecoder.class.isInstance(beanInst)) {\n\t\t\t\tcontinue;\n\t\t\t} else if (feignDecoder != null) {\n\t\t\t\tthrow new RuntimeException(\"There are more than one feign.codec.Decoder exists!\");\n\t\t\t} else {\n\t\t\t\tfeignDecoder = (feign.codec.Decoder) beanInst;\n\t\t\t}\n\t\t}\n\n\t\tif (feignDecoder == null) {\n\t\t\tfeignDecoder = new ResponseEntityDecoder(new SpringDecoder(this.objectFactory));\n\t\t} // end-if (feignDecoder == null)\n\n\t\tthis.delegate = feignDecoder;\n\t}\n\n\tpublic Object decode(Response resp, Type type) throws IOException, DecodeException, FeignException {\n\t\tRequest request = resp.request();\n\n\t\tString reqTransactionStr = this.getHeaderValue(request, HEADER_TRANCACTION_KEY);\n\t\tString reqPropagationStr = this.getHeaderValue(request, HEADER_PROPAGATION_KEY);\n\n\t\tString respTransactionStr = this.getHeaderValue(resp, HEADER_TRANCACTION_KEY);\n\t\tString respPropagationStr = this.getHeaderValue(resp, HEADER_PROPAGATION_KEY);\n\n\t\tif (StringUtils.isBlank(reqTransactionStr)) {\n\t\t\treturn this.delegate.decode(resp, type);\n\t\t} else if (StringUtils.isBlank(reqPropagationStr)) {\n\t\t\treturn this.delegate.decode(resp, type);\n\t\t}\n\n\t\ttry {\n\t\t\tString transactionStr = StringUtils.isBlank(respTransactionStr) ? reqTransactionStr : respTransactionStr;\n\t\t\tString propagationStr = StringUtils.isBlank(respPropagationStr) ? reqPropagationStr : respPropagationStr;\n\n\t\t\tbyte[] byteArray = Base64.getDecoder().decode(transactionStr); // ByteUtils.stringToByteArray(transactionStr);\n\t\t\tTransactionContext transactionContext = (TransactionContext) SerializeUtils.deserializeObject(byteArray);\n\n\t\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\t\tRemoteCoordinator remoteCoordinator = beanRegistry.getConsumeCoordinator(propagationStr);\n\n\t\t\tTransactionResponseImpl response = new TransactionResponseImpl();\n\t\t\tresponse.setTransactionContext(transactionContext);\n\t\t\tresponse.setSourceTransactionCoordinator(remoteCoordinator);\n\t\t} catch (IOException ex) {\n\t\t\tlogger.error(\"Error occurred while decoding response({})!\", resp, ex);\n\t\t}\n\n\t\treturn this.delegate.decode(resp, type);\n\t}\n\n\tprivate String getHeaderValue(Request req, String headerName) {\n\t\tMap<String, Collection<String>> headers = req.headers();\n\t\tCollection<String> values = headers.get(headerName);\n\t\tString value = null;\n\t\tif (values != null && values.isEmpty() == false) {\n\t\t\tString[] array = new String[values.size()];\n\t\t\tvalues.toArray(array);\n\t\t\tvalue = array[0];\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate String getHeaderValue(Response resp, String headerName) {\n\t\tMap<String, Collection<String>> headers = resp.headers();\n\t\tCollection<String> values = headers.get(headerName);\n\t\tString value = null;\n\t\tif (values != null && values.isEmpty() == false) {\n\t\t\tString[] array = new String[values.size()];\n\t\t\tvalues.toArray(array);\n\t\t\tvalue = array[0];\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic feign.codec.Decoder getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(feign.codec.Decoder delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\tpublic ObjectFactory<HttpMessageConverters> getObjectFactory() {\n\t\treturn objectFactory;\n\t}\n\n\tpublic void setObjectFactory(ObjectFactory<HttpMessageConverters> objectFactory) {\n\t\tthis.objectFactory = objectFactory;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionFeignErrorDecoder.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.io.IOException;\nimport java.util.Base64;\nimport java.util.Collection;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.common.utils.SerializeUtils;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\nimport feign.Request;\nimport feign.Response;\nimport feign.codec.ErrorDecoder;\n\npublic class TransactionFeignErrorDecoder implements feign.codec.ErrorDecoder, InitializingBean, ApplicationContextAware {\n\tstatic Logger logger = LoggerFactory.getLogger(TransactionFeignErrorDecoder.class);\n\n\tstatic final String HEADER_TRANCACTION_KEY = \"X-BYTEJTA-TRANSACTION\"; // org.bytesoft.bytejta.transaction\n\tstatic final String HEADER_PROPAGATION_KEY = \"X-BYTEJTA-PROPAGATION\"; // org.bytesoft.bytejta.propagation\n\n\tprivate ApplicationContext applicationContext;\n\tprivate feign.codec.ErrorDecoder delegate;\n\n\tpublic TransactionFeignErrorDecoder() {\n\t}\n\n\tpublic TransactionFeignErrorDecoder(feign.codec.ErrorDecoder decoder) {\n\t\tthis.delegate = decoder;\n\t}\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tif (this.delegate == null) {\n\t\t\tthis.invokeAfterPropertiesSet();\n\t\t} // end-if (this.delegate == null)\n\t}\n\n\tpublic void invokeAfterPropertiesSet() throws Exception {\n\t\tfeign.codec.ErrorDecoder errorDecoder = null;\n\n\t\tString[] beanNameArray = this.applicationContext.getBeanNamesForType(feign.codec.ErrorDecoder.class);\n\t\tfor (int i = 0; beanNameArray != null && i < beanNameArray.length; i++) {\n\t\t\tString beanName = beanNameArray[i];\n\t\t\tObject beanInst = this.applicationContext.getBean(beanName);\n\t\t\tif (TransactionFeignErrorDecoder.class.isInstance(beanInst)) {\n\t\t\t\tcontinue;\n\t\t\t} else if (errorDecoder != null) {\n\t\t\t\tthrow new RuntimeException(\"There are more than one feign.codec.ErrorDecoder exists!\");\n\t\t\t} else {\n\t\t\t\terrorDecoder = (feign.codec.ErrorDecoder) beanInst;\n\t\t\t}\n\t\t}\n\n\t\tif (errorDecoder == null) {\n\t\t\terrorDecoder = new ErrorDecoder.Default();\n\t\t} // end-if (errorDecoder == null)\n\n\t\tthis.delegate = errorDecoder;\n\t}\n\n\tpublic Exception decode(String methodKey, Response resp) {\n\t\tRequest request = resp.request();\n\n\t\tString reqTransactionStr = this.getHeaderValue(request, HEADER_TRANCACTION_KEY);\n\t\tString reqPropagationStr = this.getHeaderValue(request, HEADER_PROPAGATION_KEY);\n\n\t\tString respTransactionStr = this.getHeaderValue(resp, HEADER_TRANCACTION_KEY);\n\t\tString respPropagationStr = this.getHeaderValue(resp, HEADER_PROPAGATION_KEY);\n\n\t\tif (StringUtils.isBlank(reqTransactionStr)) {\n\t\t\treturn this.delegate.decode(methodKey, resp);\n\t\t} else if (StringUtils.isBlank(reqPropagationStr)) {\n\t\t\treturn this.delegate.decode(methodKey, resp);\n\t\t}\n\n\t\t// int status = resp.status();\n\t\ttry {\n\t\t\tString transactionStr = StringUtils.isBlank(respTransactionStr) ? reqTransactionStr : respTransactionStr;\n\t\t\tString propagationStr = StringUtils.isBlank(respPropagationStr) ? reqPropagationStr : respPropagationStr;\n\n\t\t\tbyte[] byteArray = Base64.getDecoder().decode(transactionStr); // ByteUtils.stringToByteArray(transactionStr);\n\t\t\tTransactionContext transactionContext = (TransactionContext) SerializeUtils.deserializeObject(byteArray);\n\n\t\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\t\tRemoteCoordinator remoteCoordinator = beanRegistry.getConsumeCoordinator(propagationStr);\n\n\t\t\tTransactionResponseImpl response = new TransactionResponseImpl();\n\t\t\tresponse.setTransactionContext(transactionContext);\n\t\t\tresponse.setSourceTransactionCoordinator(remoteCoordinator);\n\t\t} catch (IOException ex) {\n\t\t\tlogger.error(\"Error occurred while decoding response: methodKey= {}, response= {}\", methodKey, resp, ex);\n\t\t}\n\n\t\treturn this.delegate.decode(methodKey, resp);\n\t}\n\n\tprivate String getHeaderValue(Request req, String headerName) {\n\t\tMap<String, Collection<String>> headers = req.headers();\n\t\tCollection<String> values = headers.get(headerName);\n\t\tString value = null;\n\t\tif (values != null && values.isEmpty() == false) {\n\t\t\tString[] array = new String[values.size()];\n\t\t\tvalues.toArray(array);\n\t\t\tvalue = array[0];\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate String getHeaderValue(Response resp, String headerName) {\n\t\tMap<String, Collection<String>> headers = resp.headers();\n\t\tCollection<String> values = headers.get(headerName);\n\t\tString value = null;\n\t\tif (values != null && values.isEmpty() == false) {\n\t\t\tString[] array = new String[values.size()];\n\t\t\tvalues.toArray(array);\n\t\t\tvalue = array[0];\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic feign.codec.ErrorDecoder getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(feign.codec.ErrorDecoder delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionFeignHandler.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.bytesoft.bytejta.TransactionImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionRequestImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.loadbalancer.TransactionLoadBalancerInterceptor;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.netflix.appinfo.InstanceInfo;\nimport com.netflix.loadbalancer.Server;\nimport com.netflix.loadbalancer.Server.MetaInfo;\nimport com.netflix.niws.loadbalancer.DiscoveryEnabledServer;\n\npublic class TransactionFeignHandler implements InvocationHandler {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionFeignHandler.class);\n\n\tprivate InvocationHandler delegate;\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tif (Object.class.equals(method.getDeclaringClass())) {\n\t\t\treturn method.invoke(this, args);\n\t\t} else {\n\t\t\tfinal SpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\t\tfinal TransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\t\tTransactionImpl transaction = //\n\t\t\t\t\t(TransactionImpl) transactionManager.getTransactionQuietly();\n\t\t\tif (transaction == null) {\n\t\t\t\treturn this.delegate.invoke(proxy, method, args);\n\t\t\t}\n\n\t\t\tfinal TransactionContext transactionContext = transaction.getTransactionContext();\n\n\t\t\tfinal TransactionRequestImpl request = new TransactionRequestImpl();\n\t\t\tfinal TransactionResponseImpl response = new TransactionResponseImpl();\n\n\t\t\tfinal Map<RemoteSvc, XAResourceArchive> participants = transaction.getRemoteParticipantMap();\n\t\t\tbeanRegistry.setLoadBalancerInterceptor(new TransactionLoadBalancerInterceptor() {\n\t\t\t\tpublic List<Server> beforeCompletion(List<Server> servers) {\n\t\t\t\t\tfinal List<Server> readyServerList = new ArrayList<Server>();\n\t\t\t\t\tfinal List<Server> unReadyServerList = new ArrayList<Server>();\n\n\t\t\t\t\tfor (int i = 0; servers != null && i < servers.size(); i++) {\n\t\t\t\t\t\tServer server = servers.get(i);\n\n\t\t\t\t\t\t// String instanceId = metaInfo.getInstanceId();\n\t\t\t\t\t\tString instanceId = null;\n\t\t\t\t\t\tif (DiscoveryEnabledServer.class.isInstance(server)) {\n\t\t\t\t\t\t\tDiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;\n\t\t\t\t\t\t\tInstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();\n\t\t\t\t\t\t\tString addr = instanceInfo.getIPAddr();\n\t\t\t\t\t\t\tString appName = instanceInfo.getAppName();\n\t\t\t\t\t\t\tint port = instanceInfo.getPort();\n\n\t\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMetaInfo metaInfo = server.getMetaInfo();\n\n\t\t\t\t\t\t\tString host = server.getHost();\n\t\t\t\t\t\t\tString addr = host.matches(\"\\\\d+(\\\\.\\\\d+){3}\") ? host : CommonUtils.getInetAddress(host);\n\t\t\t\t\t\t\tString appName = metaInfo.getAppName();\n\t\t\t\t\t\t\tint port = server.getPort();\n\t\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (participants.containsKey(instanceId)) {\n\t\t\t\t\t\t\tList<Server> serverList = new ArrayList<Server>();\n\t\t\t\t\t\t\tserverList.add(server);\n\t\t\t\t\t\t\treturn serverList;\n\t\t\t\t\t\t} // end-if (participants.containsKey(instanceId))\n\n\t\t\t\t\t\tif (server.isReadyToServe()) {\n\t\t\t\t\t\t\treadyServerList.add(server);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tunReadyServerList.add(server);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger.warn(\"There is no suitable server: expect= {}, actual= {}!\", participants.keySet(), servers);\n\t\t\t\t\treturn readyServerList.isEmpty() ? unReadyServerList : readyServerList;\n\t\t\t\t}\n\n\t\t\t\tpublic void afterCompletion(Server server) {\n\t\t\t\t\tbeanRegistry.removeLoadBalancerInterceptor();\n\n\t\t\t\t\tif (server == null) {\n\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\t\"There is no suitable server, the TransactionInterceptor.beforeSendRequest() operation is not executed!\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} // end-if (server == null)\n\n\t\t\t\t\t// TransactionRequestImpl request = new TransactionRequestImpl();\n\t\t\t\t\trequest.setTransactionContext(transactionContext);\n\n\t\t\t\t\t// String instanceId = metaInfo.getInstanceId();\n\t\t\t\t\tString instanceId = null;\n\n\t\t\t\t\tif (DiscoveryEnabledServer.class.isInstance(server)) {\n\t\t\t\t\t\tDiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;\n\t\t\t\t\t\tInstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();\n\t\t\t\t\t\tString addr = instanceInfo.getIPAddr();\n\t\t\t\t\t\tString appName = instanceInfo.getAppName();\n\t\t\t\t\t\tint port = instanceInfo.getPort();\n\n\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMetaInfo metaInfo = server.getMetaInfo();\n\n\t\t\t\t\t\tString host = server.getHost();\n\t\t\t\t\t\tString addr = host.matches(\"\\\\d+(\\\\.\\\\d+){3}\") ? host : CommonUtils.getInetAddress(host);\n\t\t\t\t\t\tString appName = metaInfo.getAppName();\n\t\t\t\t\t\tint port = server.getPort();\n\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t}\n\n\t\t\t\t\tRemoteCoordinator coordinator = beanRegistry.getConsumeCoordinator(instanceId);\n\t\t\t\t\trequest.setTargetTransactionCoordinator(coordinator);\n\n\t\t\t\t\ttransactionInterceptor.beforeSendRequest(request);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\treturn this.delegate.invoke(proxy, method, args);\n\t\t\t} finally {\n\t\t\t\tObject interceptedValue = response.getHeader(TransactionInterceptor.class.getName());\n\t\t\t\tif (Boolean.valueOf(String.valueOf(interceptedValue)) == false) {\n\t\t\t\t\tresponse.setTransactionContext(transactionContext);\n\n\t\t\t\t\tRemoteCoordinator coordinator = request.getTargetTransactionCoordinator();\n\t\t\t\t\tresponse.setSourceTransactionCoordinator(coordinator);\n\t\t\t\t\tresponse.setParticipantEnlistFlag(request.isParticipantEnlistFlag());\n\n\t\t\t\t\ttransactionInterceptor.afterReceiveResponse(response);\n\t\t\t\t} // end-if (response.isIntercepted() == false)\n\t\t\t}\n\n\t\t}\n\t}\n\n\tpublic InvocationHandler getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(InvocationHandler delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/feign/TransactionFeignInterceptor.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.feign;\n\nimport java.io.IOException;\nimport java.util.Base64;\nimport java.util.Collection;\nimport java.util.Map;\n\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.common.utils.SerializeUtils;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\npublic class TransactionFeignInterceptor\n\t\timplements feign.RequestInterceptor, TransactionEndpointAware, ApplicationContextAware {\n\tstatic final String HEADER_TRANCACTION_KEY = \"X-BYTEJTA-TRANSACTION\"; // org.bytesoft.bytejta.transaction\n\tstatic final String HEADER_PROPAGATION_KEY = \"X-BYTEJTA-PROPAGATION\"; // org.bytesoft.bytejta.propagation\n\n\tprivate String identifier;\n\tprivate ApplicationContext applicationContext;\n\n\tpublic void apply(feign.RequestTemplate template) {\n\t\tfinal SpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tif (transaction == null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\t\t\tbyte[] byteArray = SerializeUtils.serializeObject(transactionContext);\n\n\t\t\tString transactionText = Base64.getEncoder().encodeToString(byteArray);\n\n\t\t\tMap<String, Collection<String>> headers = template.headers();\n\t\t\tif (headers.containsKey(HEADER_TRANCACTION_KEY) == false) {\n\t\t\t\ttemplate.header(HEADER_TRANCACTION_KEY, transactionText);\n\t\t\t}\n\n\t\t\tif (headers.containsKey(HEADER_PROPAGATION_KEY) == false) {\n\t\t\t\ttemplate.header(HEADER_PROPAGATION_KEY, identifier);\n\t\t\t}\n\n\t\t} catch (IOException ex) {\n\t\t\tthrow new RuntimeException(\"Error occurred while preparing the transaction context!\", ex);\n\t\t}\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn this.identifier;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixBeanPostProcessor.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.aop.TargetSource;\nimport org.springframework.aop.target.SingletonTargetSource;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.cloud.openfeign.FeignClient;\n\nimport com.netflix.hystrix.HystrixCommand.Setter;\nimport com.netflix.hystrix.HystrixCommandGroupKey;\nimport com.netflix.hystrix.HystrixCommandKey;\n\nimport feign.InvocationHandlerFactory.MethodHandler;\nimport feign.Target;\nimport feign.hystrix.FallbackFactory;\n\npublic class TransactionHystrixBeanPostProcessor implements BeanPostProcessor, InitializingBean {\n\tstatic final String HYSTRIX_COMMAND_NAME = \"TransactionHystrixInvocationHandler#invoke(TransactionHystrixInvocation)\";\n\tstatic final String HYSTRIX_INVOKER_NAME = \"invoke\";\n\n\tstatic final String HYSTRIX_FIELD_CONSTANT = \"constant\";\n\tstatic final String HYSTRIX_FIELD_TARGET = \"target\";\n\tstatic final String HYSTRIX_FIELD_FACTORY = \"fallbackFactory\";\n\tstatic final String HYSTRIX_FIELD_FALLBACK = \"fallbackMethodMap\";\n\tstatic final String HYSTRIX_FIELD_DISPATH = \"dispatch\";\n\tstatic final String HYSTRIX_FIELD_SETTERS = \"setterMethodMap\";\n\tstatic final String HYSTRIX_SETTER_GRPKEY = \"groupKey\";\n\tstatic final String HYSTRIX_CLAZZ_NAME = \"feign.hystrix.HystrixInvocationHandler\";\n\n\tprivate Field singletonTargetSourceTargetField = null;\n\n\tpublic void afterPropertiesSet() throws Exception {\n\t\tField field = SingletonTargetSource.class.getDeclaredField(\"target\");\n\t\tfield.setAccessible(true);\n\t\tthis.singletonTargetSourceTargetField = field;\n\t}\n\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\treturn bean;\n\t}\n\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tif (Proxy.isProxyClass(bean.getClass()) == false) {\n\t\t\treturn bean;\n\t\t}\n\n\t\tTargetSource targetSource = null;\n\t\tObject object = bean;\n\t\tif (org.springframework.aop.framework.Advised.class.isInstance(bean)) {\n\t\t\torg.springframework.aop.framework.Advised advised = (org.springframework.aop.framework.Advised) bean;\n\t\t\tClass<?>[] interfaces = advised.getProxiedInterfaces();\n\t\t\tfor (int i = 0; i < interfaces.length; i++) {\n\t\t\t\tClass<?> intf = interfaces[i];\n\t\t\t\tif (intf.getAnnotation(FeignClient.class) != null) {\n\t\t\t\t\ttargetSource = advised.getTargetSource();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tobject = targetSource.getTarget();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} catch (Exception error) {\n\t\t\t\t\t\tthrow new IllegalStateException();\n\t\t\t\t\t}\n\t\t\t\t} // end-if (intf.getAnnotation(FeignClient.class) != null)\n\t\t\t} // end-for (int i = 0; i < interfaces.length; i++)\n\t\t} // end-if (org.springframework.aop.framework.Advised.class.isInstance(bean))\n\n\t\tInvocationHandler handler = Proxy.getInvocationHandler(object);\n\t\tif (targetSource == null //\n\t\t\t\t&& StringUtils.equals(HYSTRIX_CLAZZ_NAME, handler.getClass().getName()) == false) {\n\t\t\treturn bean;\n\t\t}\n\n\t\tObject proxied = this.createProxiedObject(object);\n\t\tif (targetSource == null) {\n\t\t\treturn proxied;\n\t\t}\n\n\t\tif (SingletonTargetSource.class.isInstance(targetSource)) {\n\t\t\ttry {\n\t\t\t\tthis.singletonTargetSourceTargetField.set(targetSource, proxied);\n\t\t\t} catch (IllegalArgumentException error) {\n\t\t\t\tthrow new IllegalStateException(\"Error occurred!\");\n\t\t\t} catch (IllegalAccessException error) {\n\t\t\t\tthrow new IllegalStateException(\"Error occurred!\");\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\"Not supported yet!\");\n\t\t}\n\n\t\treturn bean;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate Object createProxiedObject(Object origin) {\n\t\tInvocationHandler handler = Proxy.getInvocationHandler(origin);\n\n\t\tfinal TransactionHystrixFeignHandler feignHandler = new TransactionHystrixFeignHandler();\n\t\tfeignHandler.setDelegate(handler);\n\n\t\tClass<?> clazz = origin.getClass();\n\t\tClass<?>[] interfaces = clazz.getInterfaces();\n\t\tClassLoader loader = clazz.getClassLoader();\n\n\t\ttry {\n\t\t\tField dispatchField = handler.getClass().getDeclaredField(HYSTRIX_FIELD_DISPATH);\n\t\t\tdispatchField.setAccessible(true);\n\t\t\tMap<Method, MethodHandler> dispatch = (Map<Method, MethodHandler>) dispatchField.get(handler);\n\n\t\t\tField setterField = handler.getClass().getDeclaredField(HYSTRIX_FIELD_SETTERS);\n\t\t\tsetterField.setAccessible(true);\n\t\t\tMap<Method, Setter> setterMap = (Map<Method, Setter>) setterField.get(handler);\n\n\t\t\tField groupKeyField = Setter.class.getDeclaredField(HYSTRIX_SETTER_GRPKEY);\n\t\t\tgroupKeyField.setAccessible(true);\n\n\t\t\tField fallbackField = handler.getClass().getDeclaredField(HYSTRIX_FIELD_FALLBACK);\n\t\t\tfallbackField.setAccessible(true);\n\t\t\tMap<Method, Method> fallbackMap = (Map<Method, Method>) fallbackField.get(handler);\n\n\t\t\tField targetField = handler.getClass().getDeclaredField(HYSTRIX_FIELD_TARGET);\n\t\t\ttargetField.setAccessible(true);\n\t\t\tTarget<?> target = (Target<?>) targetField.get(handler);\n\n\t\t\tField factoryField = handler.getClass().getDeclaredField(HYSTRIX_FIELD_FACTORY);\n\t\t\tfactoryField.setAccessible(true);\n\t\t\tFallbackFactory<?> factory = (FallbackFactory<?>) factoryField.get(handler);\n\t\t\tif (factory != null) {\n\t\t\t\tif (FallbackFactory.Default.class.isInstance(factory)) {\n\t\t\t\t\tField constantField = FallbackFactory.Default.class.getDeclaredField(HYSTRIX_FIELD_CONSTANT);\n\t\t\t\t\tconstantField.setAccessible(true);\n\t\t\t\t\tObject constant = constantField.get(factory);\n\t\t\t\t\tTransactionHystrixFallbackHandler fallback = new TransactionHystrixFallbackHandler(constant);\n\t\t\t\t\tObject proxy = Proxy.newProxyInstance(constant.getClass().getClassLoader(),\n\t\t\t\t\t\t\tnew Class<?>[] { TransactionHystrixInvocationHandler.class, target.type() }, fallback);\n\t\t\t\t\tconstantField.set(factory, proxy);\n\t\t\t\t} else {\n\t\t\t\t\tTransactionHystrixFallbackFactoryHandler factoryHandler = new TransactionHystrixFallbackFactoryHandler(\n\t\t\t\t\t\t\tfactory, target.type());\n\t\t\t\t\tFallbackFactory<?> proxy = (FallbackFactory<?>) Proxy.newProxyInstance(\n\t\t\t\t\t\t\tfactory.getClass().getClassLoader(), new Class<?>[] { FallbackFactory.class },\n\t\t\t\t\t\t\tfactoryHandler);\n\t\t\t\t\tfactoryField.set(handler, proxy);\n\t\t\t\t}\n\t\t\t} // end-if (factory != null)\n\n\t\t\tHystrixCommandGroupKey hystrixCommandGroupKey = null;\n\t\t\tfor (Iterator<Map.Entry<Method, Setter>> itr = setterMap.entrySet()\n\t\t\t\t\t.iterator(); hystrixCommandGroupKey == null && itr.hasNext();) {\n\t\t\t\tMap.Entry<Method, Setter> entry = itr.next();\n\t\t\t\tSetter setter = entry.getValue();\n\n\t\t\t\thystrixCommandGroupKey = setter == null ? hystrixCommandGroupKey\n\t\t\t\t\t\t: (HystrixCommandGroupKey) groupKeyField.get(setter);\n\t\t\t}\n\n\t\t\tfinal String commandGroupKeyName = hystrixCommandGroupKey == null ? null : hystrixCommandGroupKey.name();\n\t\t\tHystrixCommandGroupKey groupKey = new HystrixCommandGroupKey() {\n\t\t\t\tpublic String name() {\n\t\t\t\t\treturn commandGroupKeyName;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tHystrixCommandKey commandKey = new HystrixCommandKey() {\n\t\t\t\tpublic String name() {\n\t\t\t\t\treturn HYSTRIX_COMMAND_NAME;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tSetter setter = Setter.withGroupKey(groupKey).andCommandKey(commandKey);\n\n\t\t\tMethod key = TransactionHystrixInvocationHandler.class.getDeclaredMethod(HYSTRIX_INVOKER_NAME,\n\t\t\t\t\tnew Class<?>[] { TransactionHystrixInvocation.class });\n\t\t\tsetterMap.put(key, setter);\n\t\t\tdispatch.put(key, new TransactionHystrixMethodHandler(dispatch));\n\t\t\tfallbackMap.put(key, key);\n\t\t} catch (Exception ex) {\n\t\t\tthrow new IllegalStateException(\"Error occurred!\");\n\t\t}\n\n\t\treturn Proxy.newProxyInstance(loader, interfaces, feignHandler);\n\t}\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixFallbackFactoryHandler.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\n\nimport feign.hystrix.FallbackFactory;\n\npublic class TransactionHystrixFallbackFactoryHandler implements InvocationHandler {\n\tprivate final FallbackFactory<?> fallbackFactory;\n\tprivate final Class<?> fallbackType;\n\n\tpublic TransactionHystrixFallbackFactoryHandler(FallbackFactory<?> fallbackFactory, Class<?> fallbackType) {\n\t\tthis.fallbackFactory = fallbackFactory;\n\t\tthis.fallbackType = fallbackType;\n\t}\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tObject fallback = method.invoke(this.fallbackFactory, args);\n\t\tTransactionHystrixFallbackHandler fallbackHandler = new TransactionHystrixFallbackHandler(fallback);\n\t\tClassLoader classLoader = fallback.getClass().getClassLoader();\n\t\tClass<?>[] interfaces = new Class<?>[] { TransactionHystrixInvocationHandler.class, this.fallbackType };\n\t\treturn Proxy.newProxyInstance(classLoader, interfaces, fallbackHandler);\n\t}\n\n\tpublic FallbackFactory<?> getFallbackFactory() {\n\t\treturn fallbackFactory;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixFallbackHandler.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\n\npublic class TransactionHystrixFallbackHandler implements InvocationHandler {\n\tprivate final Object fallback;\n\n\tpublic TransactionHystrixFallbackHandler(Object fallback) {\n\t\tthis.fallback = fallback;\n\t}\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tTransactionHystrixInvocation invocation = (TransactionHystrixInvocation) args[0];\n\t\tMethod targetMethod = invocation.getMethod(); // (Method) args[1];\n\t\tObject[] targetArgs = invocation.getArgs(); // (Object[]) args[2];\n\t\treturn targetMethod.invoke(this.fallback, targetArgs);\n\t}\n\n\tpublic Object getFallback() {\n\t\treturn fallback;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixFeignHandler.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\n\nimport org.bytesoft.bytejta.TransactionImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class TransactionHystrixFeignHandler implements InvocationHandler {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionHystrixFeignHandler.class);\n\n\tprivate InvocationHandler delegate;\n\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\t\tif (Object.class.equals(method.getDeclaringClass())) {\n\t\t\treturn this.delegate.invoke(proxy, method, args);\n\t\t} else {\n\t\t\tfinal SpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\n\t\t\tTransactionImpl transaction = //\n\t\t\t\t\t(TransactionImpl) transactionManager.getTransactionQuietly();\n\t\t\tif (transaction == null) {\n\t\t\t\treturn this.delegate.invoke(proxy, method, args);\n\t\t\t} else {\n\t\t\t\tMethod targetMethod = TransactionHystrixInvocationHandler.class.getDeclaredMethod(\n\t\t\t\t\t\tTransactionHystrixBeanPostProcessor.HYSTRIX_INVOKER_NAME,\n\t\t\t\t\t\tnew Class<?>[] { TransactionHystrixInvocation.class });\n\t\t\t\tTransactionHystrixInvocation invocation = new TransactionHystrixInvocation();\n\t\t\t\tinvocation.setThread(Thread.currentThread());\n\t\t\t\tinvocation.setMethod(method);\n\t\t\t\tinvocation.setArgs(args);\n\t\t\t\tObject[] targetArgs = new Object[] { invocation };\n\t\t\t\treturn this.delegate.invoke(proxy, targetMethod, targetArgs);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic InvocationHandler getDelegate() {\n\t\treturn delegate;\n\t}\n\n\tpublic void setDelegate(InvocationHandler delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixInvocation.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\nimport java.lang.reflect.Method;\n\npublic class TransactionHystrixInvocation {\n\n\tprivate Thread thread;\n\tprivate Method method;\n\tprivate Object[] args;\n\n\tpublic Thread getThread() {\n\t\treturn thread;\n\t}\n\n\tpublic void setThread(Thread thread) {\n\t\tthis.thread = thread;\n\t}\n\n\tpublic Method getMethod() {\n\t\treturn method;\n\t}\n\n\tpublic void setMethod(Method method) {\n\t\tthis.method = method;\n\t}\n\n\tpublic Object[] getArgs() {\n\t\treturn args;\n\t}\n\n\tpublic void setArgs(Object[] args) {\n\t\tthis.args = args;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixInvocationHandler.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\npublic interface TransactionHystrixInvocationHandler {\n\n\tpublic Object invoke(TransactionHystrixInvocation invocation);\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/hystrix/TransactionHystrixMethodHandler.java",
    "content": "/**\n * Copyright 2014-2018 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.hystrix;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.bytesoft.bytejta.TransactionImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionRequestImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.loadbalancer.TransactionLoadBalancerInterceptor;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.netflix.appinfo.InstanceInfo;\nimport com.netflix.loadbalancer.Server;\nimport com.netflix.loadbalancer.Server.MetaInfo;\nimport com.netflix.niws.loadbalancer.DiscoveryEnabledServer;\n\nimport feign.InvocationHandlerFactory.MethodHandler;\n\npublic class TransactionHystrixMethodHandler implements MethodHandler {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionHystrixMethodHandler.class);\n\n\tprivate final Map<Method, MethodHandler> dispatch;\n\n\tpublic TransactionHystrixMethodHandler(Map<Method, MethodHandler> handlerMap) {\n\t\tthis.dispatch = handlerMap;\n\t}\n\n\tpublic Object invoke(Object[] argv) throws Throwable {\n\t\tfinal SpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tfinal TransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tTransactionHystrixInvocation invocation = (TransactionHystrixInvocation) argv[0];\n\t\tThread thread = invocation.getThread(); // (Thread) argv[0];\n\t\tMethod method = invocation.getMethod(); // (Method) argv[1];\n\t\tObject[] args = invocation.getArgs(); // (Object[]) argv[2];\n\n\t\tTransactionImpl transaction = //\n\t\t\t\t(TransactionImpl) transactionManager.getTransaction(thread);\n\t\tif (transaction == null) {\n\t\t\treturn this.dispatch.get(method).invoke(args);\n\t\t}\n\n\t\tfinal TransactionContext transactionContext = transaction.getTransactionContext();\n\n\t\tfinal TransactionRequestImpl request = new TransactionRequestImpl();\n\t\tfinal TransactionResponseImpl response = new TransactionResponseImpl();\n\n\t\tfinal Map<RemoteSvc, XAResourceArchive> participants = transaction.getRemoteParticipantMap();\n\t\tbeanRegistry.setLoadBalancerInterceptor(new TransactionLoadBalancerInterceptor() {\n\t\t\tpublic List<Server> beforeCompletion(List<Server> servers) {\n\t\t\t\tfinal List<Server> readyServerList = new ArrayList<Server>();\n\t\t\t\tfinal List<Server> unReadyServerList = new ArrayList<Server>();\n\n\t\t\t\tfor (int i = 0; servers != null && i < servers.size(); i++) {\n\t\t\t\t\tServer server = servers.get(i);\n\n\t\t\t\t\t// String instanceId = metaInfo.getInstanceId();\n\t\t\t\t\tString instanceId = null;\n\n\t\t\t\t\tif (DiscoveryEnabledServer.class.isInstance(server)) {\n\t\t\t\t\t\tDiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;\n\t\t\t\t\t\tInstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();\n\t\t\t\t\t\tString addr = instanceInfo.getIPAddr();\n\t\t\t\t\t\tString appName = instanceInfo.getAppName();\n\t\t\t\t\t\tint port = instanceInfo.getPort();\n\n\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMetaInfo metaInfo = server.getMetaInfo();\n\n\t\t\t\t\t\tString host = server.getHost();\n\t\t\t\t\t\tString addr = host.matches(\"\\\\d+(\\\\.\\\\d+){3}\") ? host : CommonUtils.getInetAddress(host);\n\t\t\t\t\t\tString appName = metaInfo.getAppName();\n\t\t\t\t\t\tint port = server.getPort();\n\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (participants.containsKey(instanceId)) {\n\t\t\t\t\t\tList<Server> serverList = new ArrayList<Server>();\n\t\t\t\t\t\tserverList.add(server);\n\t\t\t\t\t\treturn serverList;\n\t\t\t\t\t} // end-if (participants.containsKey(instanceId))\n\n\t\t\t\t\tif (server.isReadyToServe()) {\n\t\t\t\t\t\treadyServerList.add(server);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tunReadyServerList.add(server);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tlogger.warn(\"There is no suitable server: expect= {}, actual= {}!\", participants.keySet(), servers);\n\t\t\t\treturn readyServerList.isEmpty() ? unReadyServerList : readyServerList;\n\t\t\t}\n\n\t\t\tpublic void afterCompletion(Server server) {\n\t\t\t\tbeanRegistry.removeLoadBalancerInterceptor();\n\n\t\t\t\tif (server == null) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\"There is no suitable server, the TransactionInterceptor.beforeSendRequest() operation is not executed!\");\n\t\t\t\t\treturn;\n\t\t\t\t} // end-if (server == null)\n\n\t\t\t\trequest.setTransactionContext(transactionContext);\n\n\t\t\t\t// String instanceId = metaInfo.getInstanceId();\n\t\t\t\tString instanceId = null;\n\n\t\t\t\tif (DiscoveryEnabledServer.class.isInstance(server)) {\n\t\t\t\t\tDiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;\n\t\t\t\t\tInstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();\n\t\t\t\t\tString addr = instanceInfo.getIPAddr();\n\t\t\t\t\tString appName = instanceInfo.getAppName();\n\t\t\t\t\tint port = instanceInfo.getPort();\n\n\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t} else {\n\t\t\t\t\tMetaInfo metaInfo = server.getMetaInfo();\n\n\t\t\t\t\tString host = server.getHost();\n\t\t\t\t\tString addr = host.matches(\"\\\\d+(\\\\.\\\\d+){3}\") ? host : CommonUtils.getInetAddress(host);\n\t\t\t\t\tString appName = metaInfo.getAppName();\n\t\t\t\t\tint port = server.getPort();\n\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t}\n\n\t\t\t\tRemoteCoordinator coordinator = beanRegistry.getConsumeCoordinator(instanceId);\n\t\t\t\trequest.setTargetTransactionCoordinator(coordinator);\n\n\t\t\t\ttransactionInterceptor.beforeSendRequest(request);\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\ttransactionManager.associateThread(transaction);\n\t\t\treturn this.dispatch.get(method).invoke(args);\n\t\t} finally {\n\n\t\t\ttry {\n\t\t\t\tObject interceptedValue = response.getHeader(TransactionInterceptor.class.getName());\n\t\t\t\tif (Boolean.valueOf(String.valueOf(interceptedValue)) == false) {\n\t\t\t\t\tresponse.setTransactionContext(transactionContext);\n\n\t\t\t\t\tRemoteCoordinator coordinator = request.getTargetTransactionCoordinator();\n\t\t\t\t\tresponse.setSourceTransactionCoordinator(coordinator);\n\t\t\t\t\tresponse.setParticipantEnlistFlag(request.isParticipantEnlistFlag());\n\n\t\t\t\t\ttransactionInterceptor.afterReceiveResponse(response);\n\t\t\t\t} // end-if (response.isIntercepted() == false)\n\t\t\t} finally {\n\t\t\t\ttransactionManager.desociateThread();\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tpublic Map<Method, MethodHandler> getDispatch() {\n\t\treturn dispatch;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/loadbalancer/TransactionLoadBalancerInterceptor.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.loadbalancer;\n\nimport java.util.List;\n\nimport com.netflix.loadbalancer.Server;\n\npublic interface TransactionLoadBalancerInterceptor {\n\n\tpublic List<Server> beforeCompletion(List<Server> servers);\n\n\tpublic void afterCompletion(Server server);\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/loadbalancer/TransactionLoadBalancerRuleImpl.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.loadbalancer;\n\nimport java.util.List;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.rule.TransactionRule;\nimport org.bytesoft.bytejta.supports.springcloud.rule.TransactionRuleImpl;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.env.Environment;\n\nimport com.netflix.client.config.IClientConfig;\nimport com.netflix.loadbalancer.AbstractLoadBalancerRule;\nimport com.netflix.loadbalancer.ILoadBalancer;\nimport com.netflix.loadbalancer.IRule;\nimport com.netflix.loadbalancer.Server;\n\npublic class TransactionLoadBalancerRuleImpl extends AbstractLoadBalancerRule implements IRule {\n\tstatic final String CONSTANT_RULE_KEY = \"org.bytesoft.bytejta.NFTransactionRuleClassName\";\n\tstatic Logger logger = LoggerFactory.getLogger(TransactionLoadBalancerRuleImpl.class);\n\n\tstatic Class<?> transactionRuleClass;\n\n\tprivate IClientConfig clientConfig;\n\n\tpublic Server choose(Object key) {\n\t\tSpringCloudBeanRegistry registry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionLoadBalancerInterceptor interceptor = registry.getLoadBalancerInterceptor();\n\n\t\tif (transactionRuleClass == null) {\n\t\t\tEnvironment environment = registry.getEnvironment();\n\t\t\tString clazzName = environment.getProperty(CONSTANT_RULE_KEY);\n\t\t\tif (StringUtils.isNotBlank(clazzName)) {\n\t\t\t\ttry {\n\t\t\t\t\tClassLoader classLoader = Thread.currentThread().getContextClassLoader();\n\t\t\t\t\ttransactionRuleClass = classLoader.loadClass(clazzName);\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tlogger.error(\"Error occurred while loading class {}.\", clazzName, ex);\n\t\t\t\t\ttransactionRuleClass = TransactionRuleImpl.class;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttransactionRuleClass = TransactionRuleImpl.class;\n\t\t\t}\n\t\t}\n\n\t\tTransactionRule transactionRule = null;\n\t\tif (TransactionRuleImpl.class.equals(transactionRuleClass)) {\n\t\t\ttransactionRule = new TransactionRuleImpl();\n\t\t} else {\n\t\t\ttry {\n\t\t\t\ttransactionRule = (TransactionRule) transactionRuleClass.newInstance();\n\t\t\t} catch (Exception ex) {\n\t\t\t\tlogger.error(\"Can not create an instance of class {}.\", transactionRuleClass.getName(), ex);\n\t\t\t\ttransactionRule = new TransactionRuleImpl();\n\t\t\t}\n\t\t}\n\t\ttransactionRule.initWithNiwsConfig(this.clientConfig);\n\t\ttransactionRule.setLoadBalancer(this.getLoadBalancer());\n\n\t\tif (interceptor == null) {\n\t\t\treturn transactionRule.chooseServer(key);\n\t\t} // end-if (interceptor == null)\n\n\t\tILoadBalancer loadBalancer = this.getLoadBalancer();\n\t\tList<Server> servers = loadBalancer.getAllServers();\n\n\t\tServer server = null;\n\t\ttry {\n\t\t\tList<Server> serverList = interceptor.beforeCompletion(servers);\n\n\t\t\tserver = transactionRule.chooseServer(key, serverList);\n\t\t} finally {\n\t\t\tinterceptor.afterCompletion(server);\n\t\t}\n\n\t\treturn server;\n\t}\n\n\tpublic void initWithNiwsConfig(IClientConfig clientConfig) {\n\t\tthis.clientConfig = clientConfig;\n\t}\n\n\tpublic IClientConfig getClientConfig() {\n\t\treturn clientConfig;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/property/TransactionPropertySource.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.property;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.supports.springcloud.feign.TransactionClientRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.loadbalancer.TransactionLoadBalancerRuleImpl;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.AbstractResource;\nimport org.springframework.core.io.support.EncodedResource;\n\npublic class TransactionPropertySource extends PropertySource<Object> {\n\n\tprivate boolean enabled;\n\n\tpublic TransactionPropertySource(String name, EncodedResource source) {\n\t\tsuper(name, source);\n\n\t\tEncodedResource encoded = (EncodedResource) this.getSource();\n\t\tAbstractResource resource = (AbstractResource) encoded.getResource();\n\t\tString path = resource.getFilename();\n\n\t\tif (StringUtils.isBlank(path)) {\n\t\t\treturn;\n\t\t}\n\n\t\tString[] values = path.split(\":\");\n\t\tif (values.length != 2) {\n\t\t\treturn;\n\t\t}\n\n\t\tString protocol = values[0];\n\t\tString resName = values[1];\n\t\tif (\"bytejta\".equalsIgnoreCase(protocol) == false) {\n\t\t\treturn;\n\t\t} else if (\"loadbalancer.config\".equalsIgnoreCase(resName) == false) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.enabled = true;\n\n\t}\n\n\tpublic Object getProperty(String name) {\n\t\tif (this.enabled == false || name == null || StringUtils.isBlank(name) || name.indexOf(\".\") < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tTransactionClientRegistry registry = TransactionClientRegistry.getInstance();\n\n\t\tint index = name.indexOf(\".\");\n\t\tString client = name.substring(0, index);\n\t\tString suffix = name.substring(index);\n\t\tif (registry.containsClient(client) && \".ribbon.NFLoadBalancerRuleClassName\".equals(suffix)) {\n\t\t\treturn TransactionLoadBalancerRuleImpl.class.getName();\n\t\t}\n\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/property/TransactionPropertySourceFactory.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.property;\n\nimport java.io.IOException;\n\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.support.EncodedResource;\nimport org.springframework.core.io.support.PropertySourceFactory;\n\npublic class TransactionPropertySourceFactory implements PropertySourceFactory {\n\n\tpublic PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {\n\t\tif (name == null) {\n\t\t\tname = String.format(\"%s@%s\", TransactionPropertySource.class, System.identityHashCode(resource));\n\t\t} // end-if (name == null)\n\n\t\treturn new TransactionPropertySource(name, resource);\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/rule/TransactionRule.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.rule;\n\nimport java.util.List;\n\nimport com.netflix.client.IClientConfigAware;\nimport com.netflix.loadbalancer.ILoadBalancer;\nimport com.netflix.loadbalancer.Server;\n\npublic interface TransactionRule extends IClientConfigAware {\n\n\tpublic Server chooseServer(Object key, List<Server> serverList);\n\n\tpublic Server chooseServer(Object key);\n\n\tpublic ILoadBalancer getLoadBalancer();\n\n\tpublic void setLoadBalancer(ILoadBalancer loadBalancer);\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/rule/TransactionRuleImpl.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.rule;\n\nimport java.util.List;\nimport java.util.Random;\n\nimport com.netflix.client.config.IClientConfig;\nimport com.netflix.loadbalancer.ILoadBalancer;\nimport com.netflix.loadbalancer.Server;\n\npublic class TransactionRuleImpl implements TransactionRule {\n\tstatic final Random RANDOM = new Random();\n\tprivate IClientConfig clientConfig;\n\tprivate ILoadBalancer loadBalancer;\n\n\tpublic void initWithNiwsConfig(IClientConfig clientConfig) {\n\t\tthis.clientConfig = clientConfig;\n\t}\n\n\tpublic Server chooseServer(Object key, List<Server> serverList) {\n\t\tif (serverList == null || serverList.isEmpty()) {\n\t\t\treturn null;\n\t\t} else if (serverList.size() == 1) {\n\t\t\treturn serverList.get(0);\n\t\t} else {\n\t\t\treturn serverList.get(RANDOM.nextInt(serverList.size()));\n\t\t}\n\t}\n\n\tpublic Server chooseServer(Object key) {\n\t\tList<Server> reachableServers = this.loadBalancer.getReachableServers();\n\t\tList<Server> allServers = this.loadBalancer.getAllServers();\n\n\t\tif (reachableServers != null && reachableServers.isEmpty() == false) {\n\t\t\treturn reachableServers.get(RANDOM.nextInt(reachableServers.size()));\n\t\t} else if (allServers != null && allServers.isEmpty() == false) {\n\t\t\treturn allServers.get(RANDOM.nextInt(allServers.size()));\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic IClientConfig getClientConfig() {\n\t\treturn clientConfig;\n\t}\n\n\tpublic ILoadBalancer getLoadBalancer() {\n\t\treturn this.loadBalancer;\n\t}\n\n\tpublic void setLoadBalancer(ILoadBalancer loadBalancer) {\n\t\tthis.loadBalancer = loadBalancer;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/serialize/XAResourceDeserializerImpl.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.serialize;\n\nimport java.lang.reflect.Proxy;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.bytesoft.bytejta.supports.internal.RemoteCoordinatorRegistry;\nimport org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudCoordinator;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.transaction.remote.RemoteAddr;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteNode;\nimport org.bytesoft.transaction.supports.resource.XAResourceDescriptor;\nimport org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.core.env.Environment;\n\npublic class XAResourceDeserializerImpl implements XAResourceDeserializer, ApplicationContextAware, EnvironmentAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(XAResourceDeserializerImpl.class);\n\tstatic Pattern pattern = Pattern.compile(\"^[^:]+\\\\s*:\\\\s*[^:]+\\\\s*:\\\\s*\\\\d+$\");\n\n\tprivate XAResourceDeserializer resourceDeserializer;\n\tprivate Environment environment;\n\tprivate ApplicationContext applicationContext;\n\n\tpublic XAResourceDescriptor deserialize(String identifier) {\n\t\tXAResourceDescriptor resourceDescriptor = this.resourceDeserializer.deserialize(identifier);\n\t\tif (resourceDescriptor != null) {\n\t\t\treturn resourceDescriptor;\n\t\t}\n\n\t\tMatcher matcher = pattern.matcher(identifier);\n\t\tif (matcher.find() == false) {\n\t\t\tlogger.error(\"can not find a matching xa-resource(identifier= {})!\", identifier);\n\t\t\treturn null;\n\t\t}\n\n\t\tRemoteCoordinatorRegistry registry = RemoteCoordinatorRegistry.getInstance();\n\t\tRemoteAddr remoteAddr = CommonUtils.getRemoteAddr(identifier);\n\t\tRemoteNode remoteNode = CommonUtils.getRemoteNode(identifier);\n\n\t\tRemoteNode targetNode = registry.getRemoteNode(remoteAddr);\n\t\tif (targetNode == null && remoteAddr != null && remoteNode != null) {\n\t\t\tregistry.putRemoteNode(remoteAddr, remoteNode);\n\t\t}\n\n\t\t// String application = CommonUtils.getApplication(identifier);\n\t\t// RemoteCoordinator participant = StringUtils.isBlank(application) ? null : registry.getParticipant(application);\n\n\t\tRemoteCoordinator physical = registry.getPhysicalInstance(remoteAddr);\n\t\tif (physical == null) {\n\t\t\tSpringCloudCoordinator springCloudCoordinator = new SpringCloudCoordinator();\n\t\t\tspringCloudCoordinator.setIdentifier(identifier);\n\t\t\tspringCloudCoordinator.setEnvironment(this.environment);\n\n\t\t\tphysical = (RemoteCoordinator) Proxy.newProxyInstance(SpringCloudCoordinator.class.getClassLoader(),\n\t\t\t\t\tnew Class[] { RemoteCoordinator.class }, springCloudCoordinator);\n\t\t\tregistry.putPhysicalInstance(remoteAddr, physical);\n\t\t}\n\n\t\tRemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();\n\t\tdescriptor.setIdentifier(identifier);\n\t\tdescriptor.setDelegate(registry.getPhysicalInstance(remoteAddr));\n\t\t// descriptor.setDelegate(registry.getParticipant(application));\n\n\t\treturn descriptor;\n\t}\n\n\tpublic XAResourceDeserializer getResourceDeserializer() {\n\t\treturn resourceDeserializer;\n\t}\n\n\tpublic void setResourceDeserializer(XAResourceDeserializer resourceDeserializer) {\n\t\tthis.resourceDeserializer = resourceDeserializer;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n}\n"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/web/TransactionHandlerInterceptor.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.web;\n\nimport java.util.Base64;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.bytesoft.bytejta.supports.rpc.TransactionRequestImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.controller.TransactionCoordinatorController;\nimport org.bytesoft.common.utils.SerializeUtils;\nimport org.bytesoft.transaction.Transaction;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.boot.web.servlet.error.ErrorController;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.web.method.HandlerMethod;\nimport org.springframework.web.servlet.HandlerInterceptor;\nimport org.springframework.web.servlet.ModelAndView;\n\npublic class TransactionHandlerInterceptor implements HandlerInterceptor, TransactionEndpointAware, ApplicationContextAware {\n\tprivate static final Logger logger = LoggerFactory.getLogger(TransactionHandlerInterceptor.class);\n\n\tstatic final String HEADER_TRANCACTION_KEY = \"X-BYTEJTA-TRANSACTION\"; // org.bytesoft.bytejta.transaction\n\tstatic final String HEADER_PROPAGATION_KEY = \"X-BYTEJTA-PROPAGATION\"; // org.bytesoft.bytejta.propagation\n\n\tprivate String identifier;\n\tprivate ApplicationContext applicationContext;\n\n\tpublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {\n\t\tif (HandlerMethod.class.isInstance(handler) == false) {\n\t\t\tlogger.warn(\"TransactionHandlerInterceptor cannot handle current request(uri= {}, handler= {}) correctly.\",\n\t\t\t\t\trequest.getRequestURI(), handler);\n\t\t\treturn true;\n\t\t}\n\n\t\tHandlerMethod hm = (HandlerMethod) handler;\n\t\tClass<?> clazz = hm.getBeanType();\n\t\tif (TransactionCoordinatorController.class.equals(clazz)) {\n\t\t\treturn true;\n\t\t} else if (ErrorController.class.isInstance(hm.getBean())) {\n\t\t\treturn true;\n\t\t}\n\n\t\tString transactionStr = request.getHeader(HEADER_TRANCACTION_KEY);\n\t\tif (StringUtils.isBlank(transactionStr)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tString propagationStr = request.getHeader(HEADER_PROPAGATION_KEY);\n\n\t\tString transactionText = StringUtils.trimToNull(transactionStr);\n\t\tString propagationText = StringUtils.trimToNull(propagationStr);\n\n\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tbyte[] byteArray = transactionText == null ? new byte[0] : Base64.getDecoder().decode(transactionText);\n\n\t\tTransactionContext transactionContext = null;\n\t\tif (byteArray != null && byteArray.length > 0) {\n\t\t\ttransactionContext = (TransactionContext) SerializeUtils.deserializeObject(byteArray);\n\t\t\ttransactionContext.setPropagated(true);\n\t\t\ttransactionContext.setPropagatedBy(propagationText);\n\t\t}\n\n\t\tTransactionRequestImpl req = new TransactionRequestImpl();\n\t\treq.setTransactionContext(transactionContext);\n\t\treq.setTargetTransactionCoordinator(beanRegistry.getConsumeCoordinator(propagationText));\n\n\t\ttransactionInterceptor.afterReceiveRequest(req);\n\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tbyte[] responseByteArray = SerializeUtils.serializeObject(transaction.getTransactionContext());\n\t\tString responseTransactionStr = Base64.getEncoder().encodeToString(responseByteArray);\n\t\tresponse.setHeader(HEADER_TRANCACTION_KEY, responseTransactionStr);\n\t\tresponse.setHeader(HEADER_PROPAGATION_KEY, this.identifier);\n\n\t\treturn true;\n\t}\n\n\tpublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)\n\t\t\tthrows Exception {\n\t}\n\n\tpublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)\n\t\t\tthrows Exception {\n\t\tif (HandlerMethod.class.isInstance(handler) == false) {\n\t\t\treturn;\n\t\t}\n\n\t\tHandlerMethod hm = (HandlerMethod) handler;\n\t\tClass<?> clazz = hm.getBeanType();\n\t\tif (TransactionCoordinatorController.class.equals(clazz)) {\n\t\t\treturn;\n\t\t} else if (ErrorController.class.isInstance(hm.getBean())) {\n\t\t\treturn;\n\t\t}\n\n\t\tString transactionText = request.getHeader(HEADER_TRANCACTION_KEY);\n\t\tif (StringUtils.isBlank(transactionText)) {\n\t\t\treturn;\n\t\t}\n\n\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tTransaction transaction = transactionManager.getTransactionQuietly();\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\n\t\t// byte[] byteArray = SerializeUtils.serializeObject(transactionContext);\n\t\t// String transactionStr = ByteUtils.byteArrayToString(byteArray);\n\t\t// response.setHeader(HEADER_TRANCACTION_KEY, transactionStr);\n\t\t// response.setHeader(HEADER_PROPAGATION_KEY, this.identifier);\n\n\t\tTransactionResponseImpl resp = new TransactionResponseImpl();\n\t\tresp.setTransactionContext(transactionContext);\n\t\tresp.setSourceTransactionCoordinator(beanRegistry.getConsumeCoordinator(null));\n\n\t\ttransactionInterceptor.beforeSendResponse(resp);\n\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn this.identifier;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n}"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/java/org/bytesoft/bytejta/supports/springcloud/web/TransactionRequestInterceptor.java",
    "content": "/**\n * Copyright 2014-2017 yangming.liu<bytefox@126.com>.\n *\n * This copyrighted material is made available to anyone wishing to use, modify,\n * copy, or redistribute it subject to the terms and conditions of the GNU\n * Lesser General Public License, as published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\n * for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this distribution; if not, see <http://www.gnu.org/licenses/>.\n */\npackage org.bytesoft.bytejta.supports.springcloud.web;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Base64;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.bytesoft.bytejta.TransactionImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionRequestImpl;\nimport org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;\nimport org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry;\nimport org.bytesoft.bytejta.supports.springcloud.loadbalancer.TransactionLoadBalancerInterceptor;\nimport org.bytesoft.common.utils.CommonUtils;\nimport org.bytesoft.common.utils.SerializeUtils;\nimport org.bytesoft.transaction.TransactionBeanFactory;\nimport org.bytesoft.transaction.TransactionContext;\nimport org.bytesoft.transaction.TransactionManager;\nimport org.bytesoft.transaction.archive.XAResourceArchive;\nimport org.bytesoft.transaction.aware.TransactionEndpointAware;\nimport org.bytesoft.transaction.remote.RemoteCoordinator;\nimport org.bytesoft.transaction.remote.RemoteSvc;\nimport org.bytesoft.transaction.supports.rpc.TransactionInterceptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.http.client.ClientHttpResponse;\nimport org.springframework.web.client.HttpClientErrorException;\n\nimport com.netflix.appinfo.InstanceInfo;\nimport com.netflix.loadbalancer.Server;\nimport com.netflix.loadbalancer.Server.MetaInfo;\nimport com.netflix.niws.loadbalancer.DiscoveryEnabledServer;\n\npublic class TransactionRequestInterceptor\n\t\timplements ClientHttpRequestInterceptor, TransactionEndpointAware, ApplicationContextAware {\n\tstatic final Logger logger = LoggerFactory.getLogger(TransactionRequestInterceptor.class);\n\n\tstatic final String HEADER_TRANCACTION_KEY = \"X-BYTEJTA-TRANSACTION\"; // org.bytesoft.bytejta.transaction\n\tstatic final String HEADER_PROPAGATION_KEY = \"X-BYTEJTA-PROPAGATION\"; // org.bytesoft.bytejta.propagation\n\tstatic final String PREFIX_TRANSACTION_KEY = \"/org/bytesoft/bytejta\";\n\n\tprivate String identifier;\n\tprivate ApplicationContext applicationContext;\n\n\tpublic ClientHttpResponse intercept(final HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution execution)\n\t\t\tthrows IOException {\n\n\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\n\t\tTransactionImpl transaction = //\n\t\t\t\t(TransactionImpl) transactionManager.getTransactionQuietly();\n\n\t\tString path = httpRequest.getURI().getPath();\n\t\tint position = path.startsWith(\"/\") ? path.indexOf(\"/\", 1) : -1;\n\t\tString pathWithoutContextPath = position > 0 ? path.substring(position) : null;\n\t\tif (StringUtils.startsWith(path, PREFIX_TRANSACTION_KEY) //\n\t\t\t\t|| StringUtils.startsWith(pathWithoutContextPath, PREFIX_TRANSACTION_KEY)) {\n\t\t\treturn execution.execute(httpRequest, body);\n\t\t} else if (transaction == null) {\n\t\t\treturn execution.execute(httpRequest, body);\n\t\t}\n\n\t\tfinal Map<RemoteSvc, XAResourceArchive> participants = transaction.getRemoteParticipantMap();\n\t\tbeanRegistry.setLoadBalancerInterceptor(new TransactionLoadBalancerInterceptor() {\n\t\t\tpublic List<Server> beforeCompletion(List<Server> servers) {\n\t\t\t\tfinal List<Server> readyServerList = new ArrayList<Server>();\n\t\t\t\tfinal List<Server> unReadyServerList = new ArrayList<Server>();\n\n\t\t\t\tfor (int i = 0; servers != null && i < servers.size(); i++) {\n\t\t\t\t\tServer server = servers.get(i);\n\n\t\t\t\t\t// String instanceId = metaInfo.getInstanceId();\n\t\t\t\t\tString instanceId = null;\n\n\t\t\t\t\tif (DiscoveryEnabledServer.class.isInstance(server)) {\n\t\t\t\t\t\tDiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;\n\t\t\t\t\t\tInstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();\n\t\t\t\t\t\tString addr = instanceInfo.getIPAddr();\n\t\t\t\t\t\tString appName = instanceInfo.getAppName();\n\t\t\t\t\t\tint port = instanceInfo.getPort();\n\n\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMetaInfo metaInfo = server.getMetaInfo();\n\n\t\t\t\t\t\tString host = server.getHost();\n\t\t\t\t\t\tString addr = host.matches(\"\\\\d+(\\\\.\\\\d+){3}\") ? host : CommonUtils.getInetAddress(host);\n\t\t\t\t\t\tString appName = metaInfo.getAppName();\n\t\t\t\t\t\tint port = server.getPort();\n\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (participants.containsKey(instanceId)) {\n\t\t\t\t\t\tList<Server> serverList = new ArrayList<Server>();\n\t\t\t\t\t\tserverList.add(server);\n\t\t\t\t\t\treturn serverList;\n\t\t\t\t\t} // end-if (participants.containsKey(instanceId))\n\n\t\t\t\t\tif (server.isReadyToServe()) {\n\t\t\t\t\t\treadyServerList.add(server);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tunReadyServerList.add(server);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tlogger.warn(\"There is no suitable server: expect= {}, actual= {}!\", participants.keySet(), servers);\n\t\t\t\treturn readyServerList.isEmpty() ? unReadyServerList : readyServerList;\n\t\t\t}\n\n\t\t\tpublic void afterCompletion(Server server) {\n\t\t\t\tif (server == null) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\"There is no suitable server, the TransactionInterceptor.beforeSendRequest() operation is not executed!\");\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// String instanceId = metaInfo.getInstanceId();\n\t\t\t\t\t\tString instanceId = null;\n\n\t\t\t\t\t\tif (DiscoveryEnabledServer.class.isInstance(server)) {\n\t\t\t\t\t\t\tDiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;\n\t\t\t\t\t\t\tInstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();\n\t\t\t\t\t\t\tString addr = instanceInfo.getIPAddr();\n\t\t\t\t\t\t\tString appName = instanceInfo.getAppName();\n\t\t\t\t\t\t\tint port = instanceInfo.getPort();\n\n\t\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMetaInfo metaInfo = server.getMetaInfo();\n\n\t\t\t\t\t\t\tString host = server.getHost();\n\t\t\t\t\t\t\tString addr = host.matches(\"\\\\d+(\\\\.\\\\d+){3}\") ? host : CommonUtils.getInetAddress(host);\n\t\t\t\t\t\t\tString appName = metaInfo.getAppName();\n\t\t\t\t\t\t\tint port = server.getPort();\n\t\t\t\t\t\t\tinstanceId = String.format(\"%s:%s:%s\", addr, appName, port);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tinvokeBeforeSendRequest(httpRequest, instanceId);\n\t\t\t\t\t} catch (IOException ex) {\n\t\t\t\t\t\tthrow new RuntimeException(ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tClientHttpResponse httpResponse = null;\n\t\tboolean serverFlag = true;\n\t\ttry {\n\t\t\thttpResponse = execution.execute(httpRequest, body);\n\t\t\treturn httpResponse;\n\t\t} catch (HttpClientErrorException clientEx) {\n\t\t\tserverFlag = false;\n\t\t\tthrow clientEx;\n\t\t} finally {\n\t\t\tbeanRegistry.removeLoadBalancerInterceptor();\n\n\t\t\tif (httpResponse != null) {\n\t\t\t\tthis.invokeAfterRecvResponse(httpResponse, serverFlag);\n\t\t\t} // end-if (httpResponse != null)\n\n\t\t}\n\n\t}\n\n\tprivate void invokeBeforeSendRequest(HttpRequest httpRequest, String identifier) throws IOException {\n\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionManager transactionManager = beanFactory.getTransactionManager();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tTransactionImpl transaction = //\n\t\t\t\t(TransactionImpl) transactionManager.getTransactionQuietly();\n\n\t\tTransactionContext transactionContext = transaction.getTransactionContext();\n\n\t\tbyte[] reqByteArray = SerializeUtils.serializeObject(transactionContext);\n\t\tString reqTransactionStr = Base64.getEncoder().encodeToString(reqByteArray);\n\n\t\tHttpHeaders reqHeaders = httpRequest.getHeaders();\n\t\treqHeaders.add(HEADER_TRANCACTION_KEY, reqTransactionStr);\n\t\treqHeaders.add(HEADER_PROPAGATION_KEY, this.identifier);\n\n\t\tTransactionRequestImpl request = new TransactionRequestImpl();\n\t\trequest.setTransactionContext(transactionContext);\n\t\tRemoteCoordinator coordinator = beanRegistry.getConsumeCoordinator(identifier);\n\t\trequest.setTargetTransactionCoordinator(coordinator);\n\n\t\ttransactionInterceptor.beforeSendRequest(request);\n\t}\n\n\tprivate void invokeAfterRecvResponse(ClientHttpResponse httpResponse, boolean serverFlag) throws IOException {\n\t\tSpringCloudBeanRegistry beanRegistry = SpringCloudBeanRegistry.getInstance();\n\t\tTransactionBeanFactory beanFactory = beanRegistry.getBeanFactory();\n\t\tTransactionInterceptor transactionInterceptor = beanFactory.getTransactionInterceptor();\n\n\t\tHttpHeaders respHeaders = httpResponse.getHeaders();\n\t\tString respTransactionStr = respHeaders.getFirst(HEADER_TRANCACTION_KEY);\n\t\tString respPropagationStr = respHeaders.getFirst(HEADER_PROPAGATION_KEY);\n\n\t\tString transactionText = StringUtils.trimToNull(respTransactionStr);\n\t\tbyte[] byteArray = StringUtils.isBlank(transactionText) ? null : Base64.getDecoder().decode(transactionText);\n\t\tTransactionContext serverContext = byteArray == null || byteArray.length == 0 //\n\t\t\t\t? null : (TransactionContext) SerializeUtils.deserializeObject(byteArray);\n\n\t\tTransactionResponseImpl txResp = new TransactionResponseImpl();\n\t\ttxResp.setTransactionContext(serverContext);\n\t\tRemoteCoordinator serverCoordinator = beanRegistry.getConsumeCoordinator(respPropagationStr);\n\t\ttxResp.setSourceTransactionCoordinator(serverCoordinator);\n\t\ttxResp.setParticipantDelistFlag(serverFlag ? false : true);\n\n\t\ttransactionInterceptor.afterReceiveResponse(txResp);\n\t}\n\n\tpublic ApplicationContext getApplicationContext() {\n\t\treturn applicationContext;\n\t}\n\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn this.identifier;\n\t}\n\n\tpublic void setEndpoint(String identifier) {\n\t\tthis.identifier = identifier;\n\t}\n\n}"
  },
  {
    "path": "bytejta-supports-springcloud/src/main/resources/bytejta-supports-springcloud.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns:context=\"http://www.springframework.org/schema/context\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n\txmlns:tx=\"http://www.springframework.org/schema/tx\"\n\txsi:schemaLocation=\"http://www.springframework.org/schema/beans    \n           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    \n           http://www.springframework.org/schema/context    \n           http://www.springframework.org/schema/context/spring-context-3.0.xsd    \n           http://www.springframework.org/schema/aop    \n           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    \n           http://www.springframework.org/schema/tx \n           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\">\n\n\t<import resource=\"classpath:bytejta-supports-core.xml\" />\n\t<import resource=\"classpath:bytejta-supports-task.xml\" />\n\n\t<bean class=\"org.bytesoft.bytejta.supports.spring.TransactionDebuggablePostProcessor\" />\n\t<bean class=\"org.bytesoft.bytejta.supports.springcloud.SpringCloudEndpointPostProcessor\" />\n\t<bean class=\"org.bytesoft.bytejta.supports.springcloud.SpringCloudBeanRegistry\" factory-method=\"getInstance\" />\n\n\t<bean class=\"org.bytesoft.bytejta.supports.springcloud.controller.TransactionCoordinatorController\" />\n\n\t<bean id=\"bytejtaXAResourceDeserializer\" class=\"org.bytesoft.bytejta.logging.deserializer.XAResourceArchiveDeserializer\" />\n\t<bean id=\"bytejtaTransactionDeserializer\" class=\"org.bytesoft.bytejta.logging.deserializer.TransactionArchiveDeserializer\">\n\t\t<property name=\"resourceArchiveDeserializer\" ref=\"bytejtaXAResourceDeserializer\" />\n\t</bean>\n\t<bean id=\"bytejtaArchiveDeserializer\" class=\"org.bytesoft.bytejta.logging.ArchiveDeserializerImpl\">\n\t\t<property name=\"transactionArchiveDeserializer\" ref=\"bytejtaTransactionDeserializer\" />\n\t\t<property name=\"xaResourceArchiveDeserializer\" ref=\"bytejtaXAResourceDeserializer\" />\n\t</bean>\n\n\t<bean id=\"commonResourceDeserializer\" class=\"org.bytesoft.bytejta.supports.serialize.XAResourceDeserializerImpl\" />\n\t<bean id=\"bytejtaResourceDeserializer\" class=\"org.bytesoft.bytejta.supports.springcloud.serialize.XAResourceDeserializerImpl\">\n\t\t<property name=\"resourceDeserializer\" ref=\"commonResourceDeserializer\" />\n\t</bean>\n\n\t<bean id=\"bytejtaBeanFactory\" class=\"org.bytesoft.bytejta.TransactionBeanFactoryImpl\" factory-method=\"getInstance\">\n\t\t<property name=\"transactionManager\" ref=\"transactionManager\" />\n\t\t<property name=\"xidFactory\" ref=\"bytejtaXidFactory\" />\n\t\t<property name=\"transactionTimer\" ref=\"transactionManager\" />\n\t\t<property name=\"transactionLogger\" ref=\"bytejtaTransactionLogger\" />\n\t\t<property name=\"transactionRepository\" ref=\"bytejtaTransactionRepository\" />\n\t\t<property name=\"transactionInterceptor\" ref=\"bytejtaTransactionInterceptor\" />\n\t\t<property name=\"transactionRecovery\" ref=\"bytejtaTransactionRecovery\" />\n\t\t<property name=\"transactionCoordinator\" ref=\"bytejtaTransactionCoordinator\" />\n\t\t<property name=\"transactionLock\" ref=\"bytejtaTransactionLock\" />\n\t\t<property name=\"archiveDeserializer\" ref=\"bytejtaArchiveDeserializer\" />\n\t\t<property name=\"resourceDeserializer\" ref=\"bytejtaResourceDeserializer\" />\n\t</bean>\n\n</beans>"
  },
  {
    "path": "pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>org.bytesoft</groupId>\n\t<artifactId>bytejta-parent</artifactId>\n\t<version>0.5.0-BETA9</version>\n\n\t<packaging>pom</packaging>\n\n\t<name>bytejta-parent</name>\n\t<description>ByteJTA is a XA-complicant transaction manager.</description>\n\t<url>http://www.bytesoft.org</url>\n\n\t<licenses>\n\t\t<license>\n\t\t\t<name>The GNU Lesser General Public License, Version 3.0</name>\n\t\t\t<url>http://www.gnu.org/licenses/lgpl-3.0.txt</url>\n\t\t</license>\n\t</licenses>\n\n\t<developers>\n\t\t<developer>\n\t\t\t<name>liuyangming</name>\n\t\t\t<email>bytefox@126.com</email>\n\t\t</developer>\n\t</developers>\n\n\t<scm>\n\t\t<connection>scm:git:git@github.com:liuyangming/ByteJTA.git</connection>\n\t\t<developerConnection>scm:git:git@github.com:liuyangming/ByteJTA.git</developerConnection>\n\t\t<url>git@github.com:liuyangming/ByteJTA.git</url>\n\t</scm>\n\n\t<issueManagement>\n\t\t<system>Github Issue</system>\n\t\t<url>https://github.com/liuyangming/ByteJTA/issues</url>\n\t</issueManagement>\n\n    <profiles>\n        <profile>\n            <id>release</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-source-plugin</artifactId>\n                        <version>2.2.1</version>\n                        <executions>\n                            <execution>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar-no-fork</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-javadoc-plugin</artifactId>\n                        <version>2.9.1</version>\n                        <executions>\n                            <execution>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-gpg-plugin</artifactId>\n                        <version>1.5</version>\n                        <executions>\n                            <execution>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>sign</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                </plugins>\n            </build>\n            <distributionManagement>\n                <snapshotRepository>\n                    <id>oss</id>\n                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>\n                </snapshotRepository>\n                <repository>\n                    <id>oss</id>\n                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>\n                </repository>\n            </distributionManagement>\n        </profile>\n    </profiles>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<!-- javax -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.transaction</groupId>\n\t\t\t\t<artifactId>javax.transaction-api</artifactId>\n\t\t\t\t<version>1.2</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.jms</groupId>\n\t\t\t\t<artifactId>javax.jms-api</artifactId>\n\t\t\t\t<version>2.0</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.resource</groupId>\n\t\t\t\t<artifactId>javax.resource-api</artifactId>\n\t\t\t\t<version>1.7</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.servlet</groupId>\n\t\t\t\t<artifactId>javax.servlet-api</artifactId>\n\t\t\t\t<version>3.1.0</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.inject</groupId>\n\t\t\t\t<artifactId>javax.inject</artifactId>\n\t\t\t\t<version>1</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.annotation</groupId>\n\t\t\t\t<artifactId>javax.annotation-api</artifactId>\n\t\t\t\t<version>1.2</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- spring -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t<artifactId>spring-context</artifactId>\n\t\t\t\t<version>5.0.8.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t<artifactId>spring-tx</artifactId>\n\t\t\t\t<version>5.0.8.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t<artifactId>spring-jdbc</artifactId>\n\t\t\t\t<version>5.0.8.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t<artifactId>spring-aop</artifactId>\n\t\t\t\t<version>5.0.8.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t<artifactId>spring-webmvc</artifactId>\n\t\t\t\t<version>5.1.0.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.retry</groupId>\n\t\t\t\t<artifactId>spring-retry</artifactId>\n\t\t\t\t<version>1.2.2.RELEASE</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- spring-boot -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot</artifactId>\n\t\t\t\t<version>2.0.4.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-autoconfigure</artifactId>\n\t\t\t\t<version>2.0.4.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t\t\t<version>2.0.4.RELEASE</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- spring-cloud -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>\n\t\t\t\t<version>2.0.2.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-netflix-eureka-client</artifactId>\n\t\t\t\t<version>2.0.1.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>\n\t\t\t\t<version>2.0.2.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-starter-openfeign</artifactId>\n\t\t\t\t<version>2.0.2.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>\n\t\t\t\t<version>2.0.2.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-netflix-core</artifactId>\n\t\t\t\t<version>2.0.1.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-openfeign-core</artifactId>\n\t\t\t\t<version>2.0.1.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-commons</artifactId>\n\t\t\t\t<version>2.0.1.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-config-client</artifactId>\n\t\t\t\t<version>2.0.1.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-zookeeper-core</artifactId>\n\t\t\t\t<version>2.0.0.RELEASE</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- bytejta -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t\t<artifactId>bytejta-core</artifactId>\n\t\t\t\t<version>0.5.0-BETA9</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t\t<artifactId>bytejta-supports</artifactId>\n\t\t\t\t<version>0.5.0-BETA9</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t\t<artifactId>bytejta-supports-springcloud</artifactId>\n\t\t\t\t<version>0.5.0-BETA9</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.bytesoft</groupId>\n\t\t\t\t<artifactId>bytejta-supports-dubbo</artifactId>\n\t\t\t\t<version>0.5.0-BETA9</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- logger -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t\t<version>1.7.6</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- dubbo -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t\t<version>2.6.9</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- apache-commons -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t\t\t<version>3.4</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>commons-io</groupId>\n\t\t\t\t<artifactId>commons-io</artifactId>\n\t\t\t\t<version>2.4</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t\t<artifactId>commons-dbcp2</artifactId>\n\t\t\t\t<version>2.1.1</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- jackson -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t\t<artifactId>jackson-core</artifactId>\n\t\t\t\t<version>2.9.9</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t\t<artifactId>jackson-databind</artifactId>\n\t\t\t\t<version>2.9.10.8</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t\t<artifactId>jackson-annotations</artifactId>\n\t\t\t\t<version>2.9.9</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- netty -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-buffer</artifactId>\n\t\t\t\t<version>4.1.9.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-codec</artifactId>\n\t\t\t\t<version>4.1.9.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-codec-http</artifactId>\n\t\t\t\t<version>4.1.71.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-common</artifactId>\n\t\t\t\t<version>4.1.9.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-handler</artifactId>\n\t\t\t\t<version>4.1.45.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-transport</artifactId>\n\t\t\t\t<version>4.1.9.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t<artifactId>netty-transport-native-epoll</artifactId>\n\t\t\t\t<version>4.1.9.Final</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- others -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.caucho</groupId>\n\t\t\t\t<artifactId>hessian</artifactId>\n\t\t\t\t<version>4.0.38</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>aopalliance</groupId>\n\t\t\t\t<artifactId>aopalliance</artifactId>\n\t\t\t\t<version>1.0</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>cglib</groupId>\n\t\t\t\t<artifactId>cglib</artifactId>\n\t\t\t\t<version>2.2.2</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.ow2.asm</groupId>\n\t\t\t\t<artifactId>asm</artifactId>\n\t\t\t\t<version>5.0.4</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.aspectj</groupId>\n\t\t\t\t<artifactId>aspectjweaver</artifactId>\n\t\t\t\t<version>1.8.13</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apache.curator</groupId>\n\t\t\t\t<artifactId>curator-framework</artifactId>\n\t\t\t\t<version>4.0.1</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apache.curator</groupId>\n\t\t\t\t<artifactId>curator-client</artifactId>\n\t\t\t\t<version>4.0.1</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t\t\t\t<artifactId>zookeeper</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apache.curator</groupId>\n\t\t\t\t<artifactId>curator-recipes</artifactId>\n\t\t\t\t<version>4.0.1</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t<artifactId>netty</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.mongodb</groupId>\n\t\t\t\t<artifactId>mongo-java-driver</artifactId>\n\t\t\t\t<version>3.8.1</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t\t<artifactId>zookeeper</artifactId>\n\t\t\t\t<version>3.4.14</version>\n\t\t\t</dependency>\n\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.esotericsoftware</groupId>\n\t\t\t\t<artifactId>kryo</artifactId>\n\t\t\t\t<version>3.0.3</version>\n\t\t\t</dependency>\n\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.reactivestreams</groupId>\n\t\t\t\t<artifactId>reactive-streams</artifactId>\n\t\t\t\t<version>1.0.2</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.projectreactor</groupId>\n\t\t\t\t<artifactId>reactor-core</artifactId>\n\t\t\t\t<version>3.1.9.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.reactivex</groupId>\n\t\t\t\t<artifactId>rxjava-reactive-streams</artifactId>\n\t\t\t\t<version>1.2.1</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.reactivex.rxjava2</groupId>\n\t\t\t\t<artifactId>rxjava</artifactId>\n\t\t\t\t<version>2.2.2</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.squareup.okhttp3</groupId>\n\t\t\t\t<artifactId>okhttp</artifactId>\n\t\t\t\t<version>3.11.0</version>\n\t\t\t</dependency>\n\n\t\t\t<!-- jpa & hibernate start -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.hibernate</groupId>\n\t\t\t\t<artifactId>hibernate-core</artifactId>\n\t\t\t\t<version>5.4.0.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.data</groupId>\n\t\t\t\t<artifactId>spring-data-jpa</artifactId>\n\t\t\t\t<version>2.1.8.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.hibernate</groupId>\n\t\t\t\t<artifactId>hibernate-entitymanager</artifactId>\n\t\t\t\t<version>5.4.0.Final</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t\t\t<version>2.1.1.RELEASE</version>\n\t\t\t</dependency>\n\t\t\t<!-- jpa & hibernate end -->\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>2.3.2</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<source>1.8</source>\n\t\t\t\t\t<target>1.8</target>\n\t\t\t\t\t<encoding>UTF-8</encoding>\n\t\t\t\t</configuration>\n\t\t\t\t<dependencies>\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.codehaus.plexus</groupId>\n\t\t\t\t\t\t<artifactId>plexus-compiler-javac</artifactId>\n\t\t\t\t\t\t<version>1.8.1</version>\n\t\t\t\t\t</dependency>\n\t\t\t\t</dependencies>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<repositories>\n\t    <repository>\n\t        <id>spring-milestones</id>\n\t        <name>Spring Milestones</name>\n\t        <url>https://repo.spring.io/libs-milestone</url>\n\t        <snapshots>\n\t            <enabled>false</enabled>\n\t        </snapshots>\n\t    </repository>\n\t</repositories>\n\n\t<modules>\n\t\t<module>bytejta-core</module>\n\t\t<module>bytejta-supports</module>\n\t\t<module>bytejta-supports-springcloud</module>\n\t\t<module>bytejta-supports-dubbo</module>\n\t</modules>\n\n</project>\n"
  }
]