All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.access.JDPackageManager Maven / Gradle / Ivy

There is a newer version: 20.0.7
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                                 
//                                                                             
// Filename: JDPackageManager.java
//                                                                             
// The source code contained herein is licensed under the IBM Public License   
// Version 1.0, which has been approved by the Open Source Initiative.         
// Copyright (C) 1997-2001 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.sql.SQLException;



/**

This class manages a SQL packages. **/ class JDPackageManager { static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others."; //private static final String SUFFIX_INVARIANT_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; //@G0D // because we only send unicode to the system anyway we don't check if the system //@G0A // supports unicode first like ODBC does //@G0A private static final String SUFFIX_INVARIANT_ = "9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA"; //@G0A private boolean cache_; private DBReplyPackageInfo cachedPackage_; private ConvTable cachedPackageConverter_; //@P0C private int cachedStatementCount_; private boolean clear_; private AS400JDBCConnection connection_; private boolean created_; private boolean enabled_; private String error_; private int id_; private String libraryName_; private String name_; private int threshold_; /** Constructs a JDPackageManager object. @param connection the connection to the system. @param id the id. @param properties the connection properties. @param commitMode the current commit mode for connection. @exception SQLException If an error occurs. **/ JDPackageManager (AS400JDBCConnection connection, int id, JDProperties properties, int commitMode) throws SQLException { // Determine if extended support is enabled. enabled_ = properties.getBoolean (JDProperties.EXTENDED_DYNAMIC); if (enabled_) { // Initialization. cache_ = properties.getBoolean (JDProperties.PACKAGE_CACHE); clear_ = properties.getBoolean (JDProperties.PACKAGE_CLEAR); connection_ = connection; created_ = false; error_ = properties.getString (JDProperties.PACKAGE_ERROR); id_ = id; threshold_ = clear_ ? 512 : 0; // Determine the library name. String packageLibrary = properties.getString (JDProperties.PACKAGE_LIBRARY); if (packageLibrary.length () > 0) libraryName_ = packageLibrary.toUpperCase (); else libraryName_ = "QGPL"; // Make sure a package was specified. String packageName = properties.getString (JDProperties.PACKAGE); if (packageName.length() > 0) { // Normalize the package name to 6 characters and tack // on the appropriate 4 character suffix. StringBuffer buffer = new StringBuffer (10); String normalizedName; if (packageName.length() >= 6) //@hex normalizedName = packageName.substring (0, 6); //@hex else normalizedName = packageName; buffer.append (normalizedName.toUpperCase().replace (' ', '_')); buffer.append (getSuffix (properties, commitMode)); name_ = buffer.toString (); } else { enabled_ = false; postError (JDError.WARN_EXTENDED_DYNAMIC_DISABLED); } } } /** Downloads the package from the system and caches it in memory. @exception SQLException If an error occurs. **/ private void cache () throws SQLException { if (enabled_) { try { if (JDTrace.isTraceOn()) JDTrace.logInformation (connection_, "Caching package [" + name_ + "]"); DBSQLRequestDS request = null; //@P0A DBReplyRequestedDS reply = null; //@P0A try { request = DBDSPool.getDBSQLRequestDS ( //@P0C DBSQLRequestDS.FUNCTIONID_RETURN_PACKAGE, id_, DBSQLRequestDS.ORS_BITMAP_RETURN_DATA + DBSQLRequestDS.ORS_BITMAP_PACKAGE_INFO, 0); request.setPackageName (name_, connection_.getConverter()); //@P0C request.setLibraryName (libraryName_, connection_.getConverter()); //@P0C request.setReturnSize (0); reply = connection_.sendAndReceive (request, id_); //@P0C int errorClass = reply.getErrorClass(); // int returnCode = reply.getReturnCode(); if (errorClass != 0) { cache_ = false; postError (JDError.WARN_PACKAGE_CACHE_DISABLED); } else { cachedPackage_ = reply.getPackageInfo (); cachedPackageConverter_ = connection_.getConverter (cachedPackage_.getCCSID()); cachedStatementCount_ = cachedPackage_.getStatementCount (); } } finally { if (request != null) { request.returnToPool(); request =null; } if (reply != null) { reply.returnToPool(); reply =null; } // only ErrorClass used from reply } } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } } } /** Creates the package on the system, if extended dynamic support is enabled. If the package already existed on the system, and the user has enabled package caching, then this downloads and caches the package. @exception SQLException If an error occurs. **/ void create () throws SQLException { if (enabled_) { try { if (JDTrace.isTraceOn()) JDTrace.logInformation (connection_, "Creating package [" + name_ + " in "+libraryName_+"]"); DBSQLRequestDS request = null; //@P0A DBReplyRequestedDS reply = null; //@P0A try { request = DBDSPool.getDBSQLRequestDS ( //@P0C DBSQLRequestDS.FUNCTIONID_CREATE_PACKAGE, id_, DBSQLRequestDS.ORS_BITMAP_RETURN_DATA, 0); request.setPackageName (name_, connection_.getConverter()); //@P0C request.setLibraryName (libraryName_, connection_.getConverter()); //@P0C // $F1 This parameter no longer needs to be passed on a data stream. Package clearing // $F1 and the decision for the threshold where package clearing is needed is now handled // $F1 automatically by the database. Passing this code point results in a no-op. // @F1D request.setPackageThresholdValue (threshold_); reply = connection_.sendAndReceive (request, id_); //@P0C int errorClass = reply.getErrorClass(); int returnCode = reply.getReturnCode(); // If the package already exists, then download and // cache it if needed. if ((errorClass == 1) && (returnCode == -601)) { if (JDTrace.isTraceOn()) JDTrace.logInformation (connection_, "Package [" + name_ + "] already exists"); if (cache_) cache (); } // If the default collection in the package is // different than the one for this connection, then // we can not use the package because strange and // unexpected things may happen to data. else if (returnCode == -999999) { enabled_ = false; postError (JDError.WARN_EXTENDED_DYNAMIC_DISABLED); } else if (errorClass != 0) { enabled_ = false; postError (connection_, id_, errorClass, returnCode); } } finally { if (request != null) { request.returnToPool(); request =null; } if (reply != null) { reply.returnToPool(); reply = null; } // only errorClass used in reply } } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } } created_ = true; } /** Returns a cached data format. @param statementIndex the cached statement index. @return the data format, or null if not cached @exception SQLException If the statement index is not valid. **/ DBDataFormat getCachedDataFormat (int statementIndex) throws SQLException { try { if (isCached ()) return(cachedPackage_.getDataFormat (statementIndex)); } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } return null; } /** Returns a cached parameter marker format. @param statementIndex the cached statement index. @return the parameter marker format. @exception SQLException If the statement index is not valid. **/ DBDataFormat getCachedParameterMarkerFormat (int statementIndex) throws SQLException { try { if (isCached ()) return(cachedPackage_.getParameterMarkerFormat (statementIndex)); } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } return null; } /** Returns an index identifying the cached statement. @param sqlStatement the SQL statement. @return the index, or -1 if not cached. @exception SQLException If the data stream is problematic. **/ int getCachedStatementIndex (JDSQLStatement sqlStatement) throws SQLException { if (! isCached()) return -1; String statementText = sqlStatement.toString (); int statementTextLength = statementText.length (); //@G1M Moved this if statement. It should not have been in the for loop. //@F2A If we are running to a v5r1 or higher system, the cached //@F2A package is now in unicode. if (connection_.getVRM() >= JDUtilities.vrm510) //@F2A { //@F2A statementTextLength = statementTextLength * 2; //@F2A } //@F2A for (int i = 0; i < cachedStatementCount_; ++i) { try { // Compare lengths first, before going to the // expense of a full String comparison. if (statementTextLength == cachedPackage_.getStatementTextLength (i)) { // The lengths match, so now do the String // comparison. if (statementText.equals (cachedPackage_.getStatementText (i, cachedPackageConverter_))) return i; } } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } } return -1; } /** Returns a cached statement name. @param statementIndex the cached statement index. @return the statement name, or null if not cached. @exception SQLException If the statement index is not valid. **/ String getCachedStatementName (int statementIndex) throws SQLException { try { if (isCached ()) return(cachedPackage_.getStatementName (statementIndex, null)); //@F2C //@F2D return(cachedPackage_.getStatementName (statementIndex, cachedPackageConverter_)); //@F2D Statement name is in jobCCSID_, not unicode which is what //@F2D cachedPackageConverter_ converts. } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } return null; } /** Returns the library name for the package. @return the library name. **/ String getLibraryName () { return libraryName_; } /** Returns the name of the package. @return the package name. **/ String getName () { return name_; } /** Returns the suffix (the last 4 characters) of the package name. These are generated based on various property values, which influence the effectiveness of the package. This is necessary because the properties in question affect the contents of the packages in a way that if the property value changes, we want to use a different package. This mechanism is exactly the same as is used in Client Access/ODBC. @param properties the connection properties. @param commitMode the current commit mode for the connection. @return the suffix of the package name. **/ private String getSuffix (JDProperties properties, int commitMode) { // The last four characters of the package name (the // suffix) are generated based on various property // values. This is necessary because the properties // in question affect the contents of the packages // in a way that if the property value changes, we // want to use a different package. // // This mechanism is exactly the same as is used in // Client Access/ODBC. // StringBuffer suffix = new StringBuffer (4); //@hex int index; //@hex adding additional char at front of (now 4 length) suffix. // Base the 1st suffix character on: // // translate hex (h) - values 0-1 (0 is char, 1 is binary) // // The index into the invariant is formed as 0000000h. index = (properties.getIndex (JDProperties.TRANSLATE_HEX)); //@hex suffix.append (SUFFIX_INVARIANT_.charAt (index)); //@hex // Base the 2nd suffix character on: // // commit mode (c) - values 0-3 // date format (f) - values 0-7 // // The index into the invariant is formed as 000ccfff. // int dateSep = properties.getIndex(JDProperties.DATE_SEPARATOR); //@G0A // if commitMode is 4 (*RR), it won't fit in 2 bits, use part of DateSep to store the commitMode //@G0A // and use commitMode to store part of DateSep. This takes advantage of the fact that DateSep //@G0A // values only range from 0-4. We still have a DateSep of 5 available for future expansion. //@G0A if (commitMode == 4) { // we dont use a constant for the RR commit mode because there isnt one available //@G0A // the different DateSep are: 0=/, 1=-, 2=., 3=comma, 4=blank //@G0A switch(dateSep) { //@G0A case 0: case 1: case 2: //@G0A commitMode = dateSep; //@G0A dateSep = 6; //@G0A break; //@G0A case 3: case 4: //@G0A commitMode = dateSep - 2; //@G0A dateSep = 7; //@G0A break; //@G0A } //@G0A } //@G0A index = (commitMode << 3) | (properties.getIndex (JDProperties.DATE_FORMAT)); suffix.append (SUFFIX_INVARIANT_.charAt (index)); // Base the 3rd suffix character on: // // decimal separator (d) - values 0-1 // naming (n) - values 0-1 // date separator (s) - values 0-4 // // The index into the invariant is formed as 000dnsss. index = (properties.getIndex (JDProperties.DECIMAL_SEPARATOR) << 4) | (properties.getIndex (JDProperties.NAMING) << 3) | (dateSep); //@G0A suffix.append (SUFFIX_INVARIANT_.charAt (index)); // Base the 4th suffix character on: // // time format (f) - values 0-4 // time separator (s) - values 0-3 // // The index into the invariant is formed as 000fffss. index = (properties.getIndex (JDProperties.TIME_FORMAT) << 2) | (properties.getIndex (JDProperties.TIME_SEPARATOR)); suffix.append (SUFFIX_INVARIANT_.charAt (index)); return suffix.toString (); } /** Returns the package threshold. This is the total number of statements that the package can contain before being cleared. @return the package threshold; or 0 for unlimited number of statements. **/ int getThreshold () { return threshold_; } /** Indicates if the package is cached. @return true if the package is cached; false otherwise. **/ boolean isCached () { return(cachedPackage_ != null); } /** Indicates if the package was created. @return true if the package was created; false otherwise. **/ boolean isCreated () { return created_; } /** Indicates if extended dynamic support is enabled. @return true if extended dynamic support is enabled; false otherwise. **/ boolean isEnabled () { return enabled_; } /** Posts an error for the connection. This will post the error as a warning or exception as specified in the properties. @param sqlState the SQL state. @exception SQLException The generated exception, if the error is to be an exception. **/ private void postError (String sqlState) throws SQLException { if (error_.equalsIgnoreCase (JDProperties.PACKAGE_ERROR_EXCEPTION)) { JDError.throwSQLException (sqlState); } else if (error_.equalsIgnoreCase (JDProperties.PACKAGE_ERROR_WARNING)) connection_.postWarning (JDError.getSQLWarning (sqlState)); } /** Posts an error for the connection. This will post the error as a warning or exception as specified in the properties. @param connection connection to the system. @param id id for the last operation. @param errorClass error class from the system reply. @param returnCode return code from the system reply. @exception SQLException The generated exception, if the error is to be an exception. **/ private void postError (AS400JDBCConnection connection, int id, int errorClass, int returnCode) throws SQLException { if (error_.equalsIgnoreCase (JDProperties.PACKAGE_ERROR_EXCEPTION)) { JDError.throwSQLException (this, connection, id, errorClass, returnCode); } else if (error_.equalsIgnoreCase (JDProperties.PACKAGE_ERROR_WARNING)) connection_.postWarning (JDError.getSQLWarning (connection, id, errorClass, returnCode)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy