Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / drda / org / apache / derby / impl / drda / Database.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/Database.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/Database.java
new file mode 100644 (file)
index 0000000..5f9274a
--- /dev/null
@@ -0,0 +1,455 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.drda.Database\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.drda;\r
+\r
+import java.sql.Connection;\r
+import java.sql.Driver;\r
+import java.sql.PreparedStatement;\r
+import java.sql.Statement;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.util.Hashtable;\r
+import java.util.Enumeration;\r
+import java.util.Properties;\r
+\r
+import org.apache.derby.iapi.jdbc.EngineConnection;\r
+import org.apache.derby.iapi.reference.Attribute;\r
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+/**\r
+       Database stores information about the current database\r
+       It is used so that a session may have more than one database\r
+*/\r
+class Database\r
+{\r
+\r
+       protected String dbName;                        // database name \r
+       protected String shortDbName;       // database name without attributes\r
+       String attrString="";               // attribute string\r
+       protected int securityMechanism;        // Security mechanism\r
+       protected String userId;                        // User Id\r
+       protected String password;                      // password\r
+       protected String decryptedUserId;       // Decrypted User id\r
+       protected String decryptedPassword;     // Decrypted password\r
+    protected byte[] passwordSubstitute;// password substitute - SECMEC_USRSSBPWD\r
+       protected boolean rdbAllowUpdates = true; // Database allows updates -default is true           \r
+       protected int   accessCount;            // Number of times we have tried to\r
+                                                                               // set up access to this database (only 1 \r
+                                                                               // allowed)\r
+    protected byte[] secTokenIn;               // Security token from app requester\r
+    protected byte[] secTokenOut;              // Security token sent to app requester\r
+       protected byte[] crrtkn;                        // Correlation token\r
+       protected String typDefNam;                     // Type definition name\r
+       protected int byteOrder;                        //deduced from typDefNam, save String comparisons\r
+       protected int ccsidSBC;                         // Single byte CCSID\r
+       protected int ccsidDBC;                         // Double byte CCSID\r
+       protected int ccsidMBC;                         // Mixed byte CCSID\r
+       protected String ccsidSBCEncoding;      // Encoding for single byte code page\r
+       protected String ccsidDBCEncoding;      // Encoding for double byte code page\r
+       protected String ccsidMBCEncoding;      // Encoding for mixed byte code page\r
+       protected boolean RDBUPDRM_sent = false;        //We have sent that an update\r
+                                                                                       // occurred in this transaction\r
+       protected boolean sendTRGDFTRT = false; // Send package target default value\r
+\r
+    /**\r
+     * Connection to the database in the embedded engine.\r
+     */\r
+       private EngineConnection conn;\r
+       DRDAStatement defaultStatement;    // default statement used \r
+                                                                                                          // for execute imm\r
+       private DRDAStatement currentStatement; // current statement we are working on\r
+       private Hashtable stmtTable;            // Hash table for storing statements\r
+\r
+       boolean forXA = false;\r
+\r
+       // constructor\r
+       /**\r
+        * Database constructor\r
+        * \r
+        * @param dbName        database name\r
+        */\r
+       Database (String dbName)\r
+       {\r
+               if (dbName != null)\r
+               {\r
+                       int attrOffset = dbName.indexOf(';');\r
+                       if (attrOffset != -1)\r
+                       {\r
+                               this.attrString = dbName.substring(attrOffset,dbName.length());\r
+                               this.shortDbName = dbName.substring(0,attrOffset);\r
+                       }\r
+                       else\r
+                               this.shortDbName = dbName;\r
+               }\r
+\r
+               this.dbName = dbName;\r
+               this.stmtTable = new Hashtable();\r
+               initializeDefaultStatement();\r
+       }\r
+\r
+\r
+       private void initializeDefaultStatement()\r
+       {\r
+               this.defaultStatement = new DRDAStatement(this);\r
+       }\r
+\r
+       /**\r
+        * Set connection and create the SQL statement for the default statement\r
+        *\r
+        * @param conn Connection\r
+        * @exception SQLException\r
+        */\r
+       final void setConnection(EngineConnection conn)\r
+               throws SQLException\r
+       {\r
+               this.conn = conn;\r
+               if(conn != null)\r
+                       defaultStatement.setStatement(conn);\r
+       }\r
+       /**\r
+        * Get the connection\r
+        *\r
+        * @return connection\r
+        */\r
+       final EngineConnection getConnection()\r
+       {\r
+               return conn;\r
+       }\r
+       /**\r
+        * Get current DRDA statement \r
+        *\r
+        * @return DRDAStatement\r
+        * @exception SQLException\r
+        */\r
+       protected DRDAStatement getCurrentStatement() \r
+       {\r
+               return currentStatement;\r
+       }\r
+       /**\r
+        * Get default statement for use in EXCIMM\r
+        *\r
+        * @return DRDAStatement\r
+        */\r
+       protected DRDAStatement getDefaultStatement() \r
+       {\r
+               currentStatement = defaultStatement;\r
+               return defaultStatement;\r
+       }\r
+\r
+       /**\r
+        * Get default statement for use in EXCIMM with specified pkgnamcsn\r
+        * The pkgnamcsn has the encoded isolation level\r
+        *\r
+        * @param pkgnamcsn package/ section # for statement\r
+        * @return DRDAStatement\r
+        */\r
+       protected DRDAStatement getDefaultStatement(Pkgnamcsn pkgnamcsn) \r
+       {\r
+               currentStatement = defaultStatement;\r
+               currentStatement.setPkgnamcsn(pkgnamcsn);\r
+               return currentStatement;\r
+       }\r
+\r
+       /**\r
+        * Get a new DRDA statement and store it in the stmtTable if stortStmt is \r
+        * true. If possible recycle an existing statement. When the server gets a\r
+        * new statement with a previously used pkgnamcsn, it means that \r
+        * client-side statement associated with this pkgnamcsn has been closed. In \r
+        * this case, server can re-use the DRDAStatement by doing the following:  \r
+        * 1) Retrieve the old DRDAStatement associated with this pkgnamcsn and\r
+        * close it.\r
+        * 2) Reset the DRDAStatement state for re-use.\r
+        * \r
+        * @param pkgnamcsn  Package name and section\r
+        * @return DRDAStatement  \r
+        */\r
+       protected DRDAStatement newDRDAStatement(Pkgnamcsn pkgnamcsn)\r
+       throws SQLException\r
+       {\r
+               DRDAStatement stmt = getDRDAStatement(pkgnamcsn);\r
+               if (stmt != null) {\r
+                       stmt.close();\r
+                       stmt.reset();\r
+               }\r
+               else\r
+               {\r
+                       stmt = new DRDAStatement(this);\r
+                       stmt.setPkgnamcsn(pkgnamcsn);\r
+                       storeStatement(stmt);\r
+               }\r
+               return stmt;\r
+       }\r
+\r
+       /**\r
+        * Get DRDA statement based on pkgnamcsn\r
+        *\r
+        * @param pkgnamcsn - key to access statement\r
+        * @return DRDAStatement\r
+        */\r
+       protected DRDAStatement getDRDAStatement(Pkgnamcsn pkgnamcsn) {\r
+               DRDAStatement newStmt =\r
+                       (DRDAStatement) stmtTable.get(pkgnamcsn.getStatementKey());\r
+               if (newStmt != null) {\r
+                       currentStatement = newStmt;\r
+                       currentStatement.setCurrentDrdaResultSet(pkgnamcsn);\r
+               }\r
+               return newStmt;\r
+       }\r
+\r
+       /**\r
+        * Make a new connection using the database name and set \r
+        * the connection in the database\r
+        * @param p Properties for connection attributes to pass to connect\r
+        */\r
+       void makeConnection(Properties p) throws SQLException\r
+       {\r
+               p.put(Attribute.USERNAME_ATTR, userId);\r
+                \r
+        // take care of case of SECMEC_USRIDONL\r
+        if (password != null) \r
+                   p.put(Attribute.PASSWORD_ATTR, password);\r
+                \r
+        // Contract between network server and embedded engine\r
+        // is that any connection returned implements EngineConnection.\r
+        EngineConnection conn = (EngineConnection)\r
+            NetworkServerControlImpl.getDriver().connect(Attribute.PROTOCOL\r
+                                                        + shortDbName + attrString, p);\r
+               if (conn != null) {\r
+                       conn.setAutoCommit(false);\r
+               }\r
+               setConnection(conn);\r
+       }\r
+\r
+    /**\r
+     * This makes a dummy connection to the database in order to \r
+     * boot and/or create this last one. If database cannot\r
+     * be found or authentication does not succeed, this will throw\r
+     * a SQLException which we catch and do nothing. We don't pass a\r
+     * userid and password here as we don't need to for the purpose\r
+     * of this method - main goal is to cause the database to be\r
+     * booted via a dummy connection.\r
+     */\r
+    void makeDummyConnection()\r
+    {\r
+        try {\r
+            // Contract between network server and embedded engine\r
+            // is that any connection returned implements EngineConnection.\r
+            EngineConnection conn = (EngineConnection)\r
+                NetworkServerControlImpl.getDriver().connect(Attribute.PROTOCOL\r
+                    + shortDbName + attrString, new Properties());\r
+\r
+            // If we succeeded in getting a connection, well just close it\r
+            if (conn != null) {\r
+                conn.close();\r
+            }\r
+        } catch (SQLException se) {} // Simply do nothing\r
+    }\r
+    \r
+       // Create string to pass to DataSource.setConnectionAttributes\r
+       String appendAttrString(Properties p)\r
+       {\r
+               if (p == null)\r
+                       return null;\r
+               \r
+               Enumeration pKeys = p.propertyNames();\r
+               while (pKeys.hasMoreElements()) \r
+               {\r
+                       String key = (String) pKeys.nextElement();\r
+                       attrString +=";" + key  + "=" + p.getProperty(key);\r
+               }\r
+\r
+               return attrString;\r
+       }\r
+\r
+       /**\r
+        * Store DRDA prepared statement\r
+        * @param  stmt DRDA prepared statement\r
+        */\r
+       protected void storeStatement(DRDAStatement stmt) throws SQLException\r
+       {\r
+               stmtTable.put(stmt.getPkgnamcsn().getStatementKey(), stmt);\r
+       }\r
+\r
+       protected void removeStatement(DRDAStatement stmt) throws SQLException\r
+       {\r
+               stmtTable.remove(stmt.getPkgnamcsn().getStatementKey());\r
+               stmt.close();\r
+       }\r
+       \r
+       /**\r
+        * Make statement the current statement\r
+        * @param stmt\r
+        *\r
+        */\r
+\r
+       protected void setCurrentStatement(DRDAStatement stmt)\r
+       {\r
+               currentStatement = stmt;\r
+       }\r
+\r
+   \r
+       protected void commit() throws SQLException\r
+       {\r
+               \r
+               if (conn != null)\r
+                       conn.commit();\r
+       }\r
+\r
+       protected void rollback() throws SQLException\r
+       {\r
+               \r
+               if (conn != null)\r
+                       conn.rollback();\r
+       }\r
+       /**\r
+         * Close the connection and clean up the statement table\r
+         * @throws SQLException on conn.close() error to be handled in DRDAConnThread.\r
+         */\r
+       protected void close() throws SQLException\r
+       {\r
+\r
+               try {\r
+                       if (stmtTable != null)\r
+                       {\r
+                               for (Enumeration e = stmtTable.elements() ; e.hasMoreElements() ;) \r
+                               {\r
+                                       ((DRDAStatement) e.nextElement()).close();\r
+                               }\r
+                       \r
+                       }\r
+                       if (defaultStatement != null)                   \r
+                               defaultStatement.close();\r
+                       if ((conn != null) && !conn.isClosed())\r
+                       {\r
+                               if (! forXA)\r
+                               {\r
+                                       conn.rollback();\r
+                               }\r
+                               conn.close();                                   \r
+                       }\r
+               }\r
+               finally {\r
+                       conn = null;\r
+                       currentStatement = null;\r
+                       defaultStatement = null;\r
+                       stmtTable=null;\r
+               }\r
+       }\r
+\r
+       final void setDrdaID(String drdaID)\r
+       {\r
+               if (conn != null)\r
+                       conn.setDrdaID(drdaID);\r
+       }\r
+\r
+       /**\r
+        *  Set the internal isolation level to use for preparing statements.\r
+        *  Subsequent prepares will use this isoalation level\r
+        * @param level internal isolation level \r
+        *\r
+        * @throws SQLException\r
+        * @see EngineConnection#setPrepareIsolation\r
+        * \r
+        */\r
+       final void setPrepareIsolation(int level) throws SQLException\r
+       {\r
+               conn.setPrepareIsolation(level);\r
+       }\r
+\r
+       final int getPrepareIsolation() throws SQLException\r
+       {\r
+               return conn.getPrepareIsolation();\r
+       }\r
+\r
+       protected String buildRuntimeInfo(String indent, LocalizedResource localLangUtil)\r
+       {       \r
+         \r
+               String s = indent + \r
+               localLangUtil.getTextMessage("DRDA_RuntimeInfoDatabase.I") +\r
+                       dbName + "\n" +  \r
+               localLangUtil.getTextMessage("DRDA_RuntimeInfoUser.I")  +\r
+                       userId +  "\n" +\r
+               localLangUtil.getTextMessage("DRDA_RuntimeInfoNumStatements.I") +\r
+                       stmtTable.size() + "\n";\r
+               s += localLangUtil.getTextMessage("DRDA_RuntimeInfoPreparedStatementHeader.I");\r
+               for (Enumeration e = stmtTable.elements() ; e.hasMoreElements() ;) \r
+                               {\r
+                                       s += ((DRDAStatement) e.nextElement()).toDebugString(indent\r
+                                                                                                                                                +"\t") +"\n";\r
+                               }\r
+               return s;\r
+       }\r
+    \r
+    private boolean locatorSupport = false;\r
+    private boolean locatorSupportChecked = false;\r
+    \r
+    /**\r
+     * Checks whether database can support locators.  This is done by\r
+     * checking whether one of the stored procedures needed for\r
+     * locators exists.  (If the database has been soft-upgraded from\r
+     * an earlier version, the procedures will not exist).\r
+     *\r
+     * @throws SQLException if metadata call fails\r
+     * @return <code>true</code> if locators are supported,\r
+     *         <code>false</code otherwise\r
+     */\r
+    boolean supportsLocator() throws SQLException\r
+    {\r
+        if (!locatorSupportChecked) {\r
+            // Check if locator procedures exist\r
+            ResultSet rs = getConnection().getMetaData()\r
+                    .getProcedures(null, "SYSIBM", "BLOBTRUNCATE");\r
+            locatorSupport =  rs.next();  // True if procedure exists\r
+            rs.close();\r
+            locatorSupportChecked = true;\r
+        }\r
+        \r
+        return locatorSupport;\r
+    }\r
+       \r
+\r
+    /**\r
+     * This method resets the state of this Database object so that it can\r
+     * be re-used.\r
+     * Note: currently this method resets the variables related to security\r
+     * mechanisms that have been investigated as needing a reset.  \r
+     * TODO: Investigate what all variables in this class need to be \r
+     * reset when this database object is re-used on a connection pooling or\r
+     * transaction pooling. see DRDAConnThread.parseACCSEC (CodePoint.RDBNAM)\r
+     * where database object is re-used on a connection reset.\r
+     */\r
+    public void reset()\r
+    {\r
+        // Reset variables for connection re-use. Currently only takes care\r
+        // of reset the variables that affect EUSRIDPWD and USRSSBPWD\r
+        // security mechanisms.  (DERBY-1080)\r
+        decryptedUserId = null;\r
+        decryptedPassword = null;\r
+        passwordSubstitute = null;\r
+        secTokenIn = null;\r
+        secTokenOut = null;\r
+        userId = null;\r
+        password = null;\r
+        securityMechanism = 0;\r
+    }\r
+}\r