--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.tools.ij.xaHelper\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.tools.ij;\r
+\r
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;\r
+import java.sql.Connection;\r
+import java.sql.SQLException;\r
+import java.util.Locale;\r
+import java.util.Vector;\r
+\r
+import javax.transaction.xa.Xid;\r
+import javax.transaction.xa.XAResource;\r
+import javax.transaction.xa.XAException;\r
+import javax.sql.PooledConnection;\r
+import javax.sql.XAConnection;\r
+import javax.sql.XADataSource;\r
+import javax.sql.DataSource;\r
+import javax.sql.ConnectionPoolDataSource;\r
+import org.apache.derby.iapi.services.info.JVMInfo;\r
+\r
+/*\r
+ * The real xa helper class. Load this class only if we know the javax classes\r
+ * are in the class path.\r
+ */\r
+class xaHelper implements xaAbstractHelper\r
+{\r
+\r
+ private XADataSource currentXADataSource;\r
+ private XAConnection currentXAConnection;\r
+\r
+ private String databaseName;\r
+\r
+ // non xa stuff\r
+ private DataSource currentDataSource;\r
+ private ConnectionPoolDataSource currentCPDataSource;\r
+ private PooledConnection currentPooledConnection;\r
+\r
+ private boolean isJCC;\r
+ private boolean isNetClient;\r
+ private String framework;\r
+\r
+ xaHelper()\r
+ {\r
+ }\r
+ \r
+ \r
+ public void setFramework(String fm)\r
+ {\r
+ if (fm == null) {\r
+ return;\r
+ }\r
+ framework = fm.toUpperCase(Locale.ENGLISH);\r
+ if (framework.endsWith("NET") ||\r
+ framework.equals("DB2JCC"))\r
+ isJCC = true;\r
+ else if (framework.equals("DERBYNETCLIENT"))\r
+ isNetClient = true;\r
+\r
+ }\r
+ \r
+ private Xid makeXid(int xid)\r
+ {\r
+ return new ijXid(xid, databaseName.getBytes());\r
+ }\r
+\r
+ public void XADataSourceStatement(ij parser, Token dbname, Token shutdown,\r
+ String create)\r
+ throws SQLException\r
+ {\r
+ try\r
+ {\r
+ currentXADataSource = (XADataSource) getXADataSource();\r
+\r
+ databaseName = parser.stringValue(dbname.image);\r
+ \r
+ if (isJCC || isNetClient)\r
+ {\r
+ String hostName = System.getProperty("hostName");\r
+ if ((hostName != null ) && (!hostName.equals("localhost")))\r
+ { \r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "ServerName", hostName);\r
+ }\r
+ else\r
+ { \r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "ServerName", "localhost");\r
+ }\r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "portNumber", 1527);\r
+ \r
+ String user;\r
+ String password;\r
+ user = "APP";\r
+ password = "APP";\r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "user", user);\r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "password", password);\r
+ //xaHelper.setDataSourceProperty(currentXADataSource,\r
+ //"traceFile", "trace.out." + framework);\r
+ }\r
+ if (isJCC)\r
+ {\r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "driverType", 4);\r
+\r
+ xaHelper.setDataSourceProperty(currentXADataSource, \r
+ "retrieveMessagesFromServerOnGetMessage", true);\r
+ }\r
+ xaHelper.setDataSourceProperty(currentXADataSource, "databaseName", databaseName);\r
+\r
+ if (shutdown != null && shutdown.toString().toLowerCase(Locale.ENGLISH).equals("shutdown"))\r
+ { \r
+ if (isJCC || isNetClient)\r
+ xaHelper.setDataSourceProperty(currentXADataSource,"databaseName", databaseName + ";shutdown=true");\r
+ else\r
+ xaHelper.setDataSourceProperty(currentXADataSource, "shutdownDatabase", "shutdown");\r
+\r
+ // do a getXAConnection to shut it down */\r
+ currentXADataSource.getXAConnection().getConnection();\r
+ currentXADataSource = null;\r
+ currentXAConnection = null;\r
+ }\r
+ else if (create != null && create.toLowerCase(java.util.Locale.ENGLISH).equals("create"))\r
+ {\r
+ if (isJCC || isNetClient)\r
+ xaHelper.setDataSourceProperty(currentXADataSource,"databaseName", databaseName + ";create=true");\r
+ else\r
+ xaHelper.setDataSourceProperty(currentXADataSource,\r
+ "createDatabase", "create");\r
+\r
+ /* do a getXAConnection to create it */\r
+ XAConnection conn = currentXADataSource.getXAConnection();\r
+ conn.close();\r
+ \r
+ xaHelper.setDataSourceProperty(currentXADataSource, "createDatabase", null);\r
+ }\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ handleException(t);\r
+ } \r
+ }\r
+\r
+\r
+ public void XAConnectStatement(ij parser, Token user, Token pass, String id)\r
+ throws SQLException\r
+ {\r
+ try\r
+ {\r
+ if (currentXAConnection != null)\r
+ {\r
+ try {\r
+ currentXAConnection.close();\r
+ } catch (SQLException sqle) {\r
+ }\r
+\r
+ currentXAConnection = null;\r
+ }\r
+\r
+ String username = null;\r
+ String password = "";\r
+\r
+ if (pass != null)\r
+ password = parser.stringValue(pass.image);\r
+\r
+ if (user != null)\r
+ {\r
+ username = parser.stringValue(user.image);\r
+\r
+ currentXAConnection = \r
+ currentXADataSource.getXAConnection(username, password);\r
+ }\r
+ else\r
+ {\r
+\r
+ currentXAConnection = currentXADataSource.getXAConnection();\r
+ }\r
+\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ }\r
+\r
+ public void XADisconnectStatement(ij parser, String n) throws SQLException\r
+ {\r
+ if (currentXAConnection == null)\r
+ throw ijException.noSuchConnection("XAConnection");\r
+ currentXAConnection.close();\r
+ currentXAConnection = null;\r
+ }\r
+\r
+ public Connection XAGetConnectionStatement(ij parser, String n) throws SQLException\r
+ {\r
+ try\r
+ {\r
+ return currentXAConnection.getConnection();\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public void CommitStatement(ij parser, Token onePhase, Token twoPhase, \r
+ int xid) \r
+ throws SQLException\r
+ {\r
+ try\r
+ { \r
+ currentXAConnection.getXAResource().commit(makeXid(xid), (onePhase != null));\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ }\r
+\r
+ public void EndStatement(ij parser, int flag, int xid) throws SQLException\r
+ {\r
+ try\r
+ { \r
+ currentXAConnection.getXAResource().end(makeXid(xid), flag);\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ }\r
+\r
+ public void ForgetStatement(ij parser, int xid) throws SQLException\r
+ {\r
+ try\r
+ { \r
+ currentXAConnection.getXAResource().forget(makeXid(xid));\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ }\r
+\r
+ public void PrepareStatement(ij parser, int xid) throws SQLException\r
+ {\r
+ try\r
+ { \r
+ currentXAConnection.getXAResource().prepare(makeXid(xid));\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ }\r
+\r
+ public ijResult RecoverStatement(ij parser, int flag) throws SQLException\r
+ {\r
+ Object[] val = null;\r
+\r
+ try\r
+ { \r
+ val = currentXAConnection.getXAResource().recover(flag);\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+\r
+ Vector v = new Vector();\r
+ v.addElement("");\r
+ v.addElement(LocalizedResource.getMessage("IJ_Reco0InDoubT", LocalizedResource.getNumber(val.length)));\r
+ v.addElement("");\r
+ for (int i = 0; i < val.length; i++)\r
+ v.addElement(LocalizedResource.getMessage("IJ_Tran01", LocalizedResource.getNumber(i+1), val[i].toString()));\r
+\r
+ return new ijVectorResult(v,null);\r
+\r
+ }\r
+\r
+ public void RollbackStatement(ij parser, int xid) throws SQLException\r
+ {\r
+ try\r
+ { \r
+ currentXAConnection.getXAResource().rollback(makeXid(xid));\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+\r
+ }\r
+\r
+ public void StartStatement(ij parser, int flag, int xid) throws SQLException\r
+ {\r
+ try\r
+ { \r
+ currentXAConnection.getXAResource().start(makeXid(xid), flag);\r
+ }\r
+ catch(Throwable t)\r
+ {\r
+ handleException(t);\r
+ }\r
+ }\r
+\r
+ private void handleException(Throwable t) throws SQLException\r
+ {\r
+ if (t instanceof SQLException)\r
+ {\r
+ // let ij handle it\r
+ throw (SQLException)t;\r
+ }\r
+ if (t instanceof XAException)\r
+ {\r
+ int errorCode = ((XAException)t).errorCode;\r
+ String error = LocalizedResource.getMessage("IJ_IlleValu");\r
+\r
+ // XA_RBBASE 100\r
+ // XA_RBROLLBACK 100\r
+ // XA_RBCOMMFAIL 101\r
+ // XA_RBDEADLOCK 102\r
+ // XA_RBINTEGRITY 103\r
+ // XA_RBOTHER 104\r
+ // XA_RBPROTO 105\r
+ // XA_RBTIMEOUT 106\r
+ // XA_RBTRANSIENT 107\r
+ // XA_RBEND 107\r
+ //\r
+ // XA_RDONLY 3\r
+ // XA_RETRY 4\r
+ // XA_HEURMIX 5\r
+ // XA_HEURRB 6\r
+ // XA_HEURCOM 7\r
+ // XA_HEURHAZ 8\r
+ // XA_NOMIGRATE 9\r
+ //\r
+ // XAER_ASYNC -2\r
+ // XAER_RMERR -3\r
+ // XAER_NOTA -4\r
+ // XAER_INVAL -5\r
+ // XAER_PROTO -6\r
+ // XAER_RMFAIL -7\r
+ // XAER_DUPID -8\r
+ // XAER_OUTSIDE -9\r
+\r
+ switch(errorCode)\r
+ {\r
+ case XAException.XA_HEURCOM : error = "XA_HEURCOM "; break;\r
+ case XAException.XA_HEURHAZ : error = "XA_HEURHAZ"; break;\r
+ case XAException.XA_HEURMIX : error = "XA_HEURMIX"; break;\r
+ case XAException.XA_HEURRB : error = "XA_HEURRB "; break;\r
+ case XAException.XA_NOMIGRATE : error = "XA_NOMIGRATE "; break;\r
+ // case XAException.XA_RBBASE : error = "XA_RBBASE "; break;\r
+ case XAException.XA_RBCOMMFAIL : error = "XA_RBCOMMFAIL "; break;\r
+ case XAException.XA_RBDEADLOCK : error = "XA_RBDEADLOCK "; break;\r
+ // case XAException.XA_RBEND : error = "XA_RBEND "; break;\r
+ case XAException.XA_RBINTEGRITY : error = "XA_RBINTEGRITY "; break;\r
+ case XAException.XA_RBOTHER : error = "XA_RBOTHER "; break;\r
+ case XAException.XA_RBPROTO : error = "XA_RBPROTO "; break;\r
+ case XAException.XA_RBROLLBACK : error = "XA_RBROLLBACK "; break;\r
+ case XAException.XA_RBTIMEOUT : error = "XA_RBTIMEOUT "; break;\r
+ case XAException.XA_RBTRANSIENT : error = "XA_RBTRANSIENT "; break;\r
+ case XAException.XA_RDONLY : error = "XA_RDONLY "; break;\r
+ case XAException.XA_RETRY : error = "XA_RETRY "; break;\r
+ case XAException.XAER_ASYNC : error = "XAER_ASYNC "; break;\r
+ case XAException.XAER_DUPID : error = "XAER_DUPID "; break;\r
+ case XAException.XAER_INVAL : error = "XAER_INVAL "; break;\r
+ case XAException.XAER_NOTA : error = "XAER_NOTA "; break;\r
+ case XAException.XAER_OUTSIDE : error = "XAER_OUTSIDE "; break;\r
+ case XAException.XAER_PROTO : error = "XAER_PROTO "; break;\r
+ case XAException.XAER_RMERR : error = "XAER_RMERR "; break;\r
+ case XAException.XAER_RMFAIL : error = "XAER_RMFAIL "; break;\r
+ }\r
+ //t.printStackTrace(System.out);\r
+ throw new ijException(error);\r
+\r
+ }\r
+ else // StandardException or run time exception, log it first\r
+ {\r
+ String info = LocalizedResource.getMessage("IJ_01SeeLog", t.toString(), t.getMessage());\r
+ // t.printStackTrace(System.out);\r
+ throw new ijException(info);\r
+ }\r
+ }\r
+\r
+\r
+ // non-xa stuff. DataSource and ConnectionPoolDataSource\r
+ public Connection DataSourceStatement(ij parser, Token dbname, Token protocol,\r
+ Token userT, Token passT, String id)\r
+ throws SQLException\r
+ {\r
+\r
+ try {\r
+ currentDataSource = (DataSource) (Class.forName("org.apache.derby.jdbc.EmbeddedDataSource").newInstance());\r
+ //Added by Jeff Huang\r
+ currentDataSource = new org.apache.derby.jdbc.EmbeddedDataSource();\r
+ \r
+ } catch (Exception e) {\r
+ throw new SQLException(e.toString());\r
+ }\r
+ databaseName = parser.stringValue(dbname.image);\r
+ xaHelper.setDataSourceProperty(currentDataSource, "databaseName", databaseName);\r
+ xaHelper.setDataSourceProperty(currentXADataSource, "dataSourceName", databaseName);\r
+ // make a connection\r
+ Connection c = null;\r
+ String username = null;\r
+ String password = "";\r
+\r
+ if (passT != null)\r
+ password = parser.stringValue(passT.image);\r
+\r
+ if (userT != null)\r
+ {\r
+ username = parser.stringValue(userT.image);\r
+ c = currentDataSource.getConnection(username, password);\r
+ }\r
+ else\r
+ {\r
+ c = currentDataSource.getConnection();\r
+ }\r
+\r
+ return c;\r
+\r
+ }\r
+\r
+ public void CPDataSourceStatement(ij parser, Token dbname, Token protocol)\r
+ throws SQLException\r
+ {\r
+ try {\r
+ currentCPDataSource = (ConnectionPoolDataSource) (Class.forName("org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource").newInstance());\r
+ //Added by Jeff Huang\r
+ currentCPDataSource = new org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource();\r
+\r
+ } catch (Exception e) {\r
+ throw new SQLException(e.toString());\r
+ }\r
+ databaseName = parser.stringValue(dbname.image);\r
+ xaHelper.setDataSourceProperty(currentCPDataSource, "databaseName", databaseName);\r
+ }\r
+\r
+ public void CPConnectStatement(ij parser, Token userT, Token passT, String n)\r
+ throws SQLException\r
+ {\r
+ String username = null;\r
+ String password = "";\r
+\r
+ if (passT != null)\r
+ password = parser.stringValue(passT.image);\r
+\r
+ if (userT != null)\r
+ {\r
+ username = parser.stringValue(userT.image);\r
+ currentPooledConnection =\r
+ currentCPDataSource.getPooledConnection(username, password);\r
+ }\r
+ else\r
+ {\r
+ currentPooledConnection =\r
+ currentCPDataSource.getPooledConnection();\r
+ }\r
+ }\r
+\r
+ public Connection CPGetConnectionStatement(ij parser, String n) \r
+ throws SQLException \r
+ {\r
+ return currentPooledConnection.getConnection();\r
+ }\r
+\r
+ public void CPDisconnectStatement(ij parser, String n) throws SQLException\r
+ {\r
+ if (currentPooledConnection == null)\r
+ throw ijException.noSuchConnection(LocalizedResource.getMessage("IJ_Pool"));\r
+ currentPooledConnection.close();\r
+ currentPooledConnection = null;\r
+ }\r
+\r
+ /**\r
+ * Get a DataSource that supports distributed transactions.\r
+ *\r
+ * @return XADataSource object \r
+ *\r
+ * @exception Exception if XaDataSource is not in class path.\r
+ */\r
+ private XADataSource getXADataSource() throws Exception\r
+ {\r
+ // We need to construct this object in this round about fashion because\r
+ // if we new it directly, then it will the tools.jar file to bloat.\r
+ try\r
+ {\r
+ if (isJCC)\r
+// return (XADataSource) \r
+// (Class.forName("com.ibm.db2.jcc.DB2XADataSource").newInstance());\r
+ //Added by Jeff Huang\r
+ //return new com.ibm.db2.jcc.DB2XADataSource();\r
+ throw new RuntimeException("Added by Jeff Huang: missing com.ibm.db2.jcc.DB2XADataSource");\r
+ else if (isNetClient){\r
+ if (JVMInfo.JDK_ID >= JVMInfo.J2SE_16) {\r
+ //running under jdk1.6 or higher \r
+ // try instantiating EmbeddedXADataSource40\r
+ try {\r
+ return (XADataSource)(Class.forName(\r
+ "org.apache.derby.jdbc." +\r
+ "ClientXADataSource40").newInstance());\r
+ //Added by Jeff Huang\r
+// return new org.apache.derby.jdbc.ClientXADataSource40();\r
+ }\r
+ catch (ClassNotFoundException e) {\r
+ //probably it was not compiled with jdbc4.0\r
+ //support go ahead with EmbeddedXADataSource\r
+ }\r
+ }\r
+ return (XADataSource) (Class.forName(\r
+ "org.apache.derby.jdbc.ClientXADataSource"\r
+ ).newInstance());\r
+ //Added by Jeff Huang\r
+// return new org.apache.derby.jdbc.ClientXADataSource();\r
+ }\r
+ else {\r
+ if (JVMInfo.JDK_ID >= JVMInfo.J2SE_16) {\r
+ //running under jdk1.6 or higher \r
+ // try instantiating EmbeddedXADataSource40\r
+ try {\r
+// return (XADataSource)(Class.forName(\r
+// "org.apache.derby.jdbc." +\r
+// "EmbeddedXADataSource40").newInstance()); \r
+ //Added by Jeff Huang\r
+ return new org.apache.derby.jdbc.EmbeddedXADataSource40(); \r
+ }\r
+ catch (Exception e) {\r
+ //probably it was not compiled with jdbc4.0\r
+ //support go ahead with EmbeddedXADataSource\r
+ }\r
+ }\r
+ //return (XADataSource)(Class.forName("org.apache.derby.jdbc.EmbeddedXADataSource").newInstance());\r
+ //Added by Jeff Huang\r
+ return new org.apache.derby.jdbc.EmbeddedXADataSource();\r
+ }\r
+ }\r
+ catch(ClassNotFoundException cnfe) {\r
+ throw new ijException(LocalizedResource.getMessage("IJ_XAClass"));\r
+ }\r
+ catch (InstantiationException e) { }\r
+ catch (IllegalAccessException e) { }\r
+\r
+ throw new ijException(LocalizedResource.getMessage("IJ_XANoI"));\r
+ }\r
+ private static final Class[] STRING_P = { "".getClass() };\r
+ private static final Class[] INT_P = { Integer.TYPE };\r
+ private static final Class[] BOOLEAN_P = {Boolean.TYPE };\r
+\r
+ private static void setDataSourceProperty(Object ds, String property, int \r
+ value) throws SQLException\r
+ {\r
+ String methodName =\r
+ "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1);\r
+ try {\r
+ java.lang.reflect.Method m = ds.getClass().getMethod(methodName, INT_P);\r
+ m.invoke(ds, new Object[] {new Integer(value)});\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ throw new SQLException(property + " ???" + e.getMessage());\r
+ } \r
+ \r
+ }\r
+ \r
+ private static void setDataSourceProperty(Object ds, String property, String value) throws SQLException {\r
+\r
+ String methodName =\r
+ "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1);\r
+\r
+ try {\r
+ java.lang.reflect.Method m = ds.getClass().getMethod(methodName, STRING_P);\r
+ m.invoke(ds, new Object[] {value});\r
+ return;\r
+ } catch (/*NoSuchMethod*/Exception nsme) {\r
+ throw new SQLException(property + " ???");\r
+ //java.lang.reflect.Method m = ds.getClass().getMethod("set" + property, INT_P);\r
+ //m.invoke(ds, new Object[] {Integer.valueOf(value)});\r
+ }\r
+ }\r
+\r
+private static void setDataSourceProperty(Object ds, String property, boolean value) throws SQLException {\r
+\r
+ String methodName =\r
+ "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1);\r
+\r
+ try {\r
+ java.lang.reflect.Method m = ds.getClass().getMethod(methodName, BOOLEAN_P);\r
+ m.invoke(ds, new Object[] {new Boolean(value)});\r
+ return;\r
+ } catch (Exception nsme) {\r
+ throw new SQLException(property + " ???");\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
+class ijXid implements Xid, java.io.Serializable\r
+{\r
+ private static final long serialVersionUID = 64467452100036L;\r
+\r
+ private final int format_id;\r
+ private final byte[] global_id;\r
+ private final byte[] branch_id;\r
+\r
+\r
+ ijXid(int xid, byte[] id)\r
+ {\r
+ format_id = xid;\r
+ global_id = id;\r
+ branch_id = id;\r
+ \r
+ }\r
+ /**\r
+ * Obtain the format id part of the Xid.\r
+ * <p>\r
+ *\r
+ * @return Format identifier. O means the OSI CCR format.\r
+ **/\r
+ public int getFormatId()\r
+ {\r
+ return(format_id);\r
+ }\r
+\r
+ /**\r
+ * Obtain the global transaction identifier part of XID as an array of \r
+ * bytes.\r
+ * <p>\r
+ *\r
+ * @return A byte array containing the global transaction identifier.\r
+ **/\r
+ public byte[] getGlobalTransactionId()\r
+ {\r
+ return(global_id);\r
+ }\r
+\r
+ /**\r
+ * Obtain the transaction branch qualifier part of the Xid in a byte array.\r
+ * <p>\r
+ *\r
+ * @return A byte array containing the branch qualifier of the transaction.\r
+ **/\r
+ public byte[] getBranchQualifier()\r
+ {\r
+ return(branch_id);\r
+ }\r
+}\r
+\r
+\r