
com.ibm.as400.access.AS400JDBCDriverForcedCcsid Maven / Gradle / Ivy
///////////////////////////////////////////////////////////////////////////////
//
//JTOpen (IBM Toolbox for Java - OSS version)
//
//Filename: AS400JDBCDriver.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-2010 International Business Machines Corporation and
//others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.net.InetAddress; // @C2A
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.logging.Logger;
/**
* A JDBC 3.0/4.0/4.2 driver that accesses DB2 for IBM i databases.
*
*
* To use this driver, the application or caller must register the driver with
* the JDBC DriverManager. This class also registers itself automatically when
* it is loaded.
*
*
* After registering the driver, applications make connection requests to the
* DriverManager, which dispatches them to the appropriate driver. This driver
* accepts connection requests for databases specified by the URLs that match
* the following syntax:
*
*
jdbc:as400://system-name/default-schema;properties
*
*
*
* The driver uses the specified system name to connect to a corresponding IBM i
* system. If an IPV6 address is used as the system name, it must be enclosed
* within braces, i.e. [fd13:ac12:18:17::16]. If a system name is not specified,
* then the user will be prompted.
*
*
* The default SQL schema is optional and the driver uses it to resolve
* unqualified names in SQL statements. If no default SQL schema is set, then
* the driver resolves unqualified names based on the naming convention for the
* connection. If SQL naming is being used, and no default SQL schema is set,
* then the driver resolves unqualified names using the schema with the same
* name as the user. If system naming is being used, and no default SQL schema
* is set, then the driver resolves unqualified names using the server job's
* library list. See
* JDBC properties
* for more details on how to set the naming convention and library list.
*
*
* Several properties can optionally be set within the URL. They are separated
* by semicolons and are in the form:
*
*
name1=value1;name2=value2;...
*
*
* See JDBC
* properties for a complete list of properties supported by this driver.
*
*
* The following example URL specifies a connection to the database on system
* mysystem.helloworld.com with mylibrary as the default SQL
* schema. The connection will use the system naming convention and return full
* error messages:
*
*
jdbc:as400://mysystem.helloworld.com/mylibrary;naming=system;errors=full
*
**/
//
//Implementation note:
//
//1. A goal stated in the JDBC specification is to keep
//the Driver class as small and standalone as possible,
//so that it can be quickly loaded when choosing a
//driver for a particular database.
//
//2. It was proposed that we also accept URLs with the
//"db2" subprotocol. This would make us consistent with
//other IBM drivers. In addition, it would also allow
//developers to hardcode URLs in programs and they would
//run as-is with both this driver and the "native" driver.
//
//We realized, though, that if running on a client with
//both this driver and another DB2 client for that platform,
//how do the drivers differentiate themselves? Therefore
//we are chosing NOT to recognized the "db2" subprotocol.
//Instead, suggest to developers to externalize the URL
//to users, rather than hardcoding it.
//
//
//Note: Change log is now in Copyright.java
//
public class AS400JDBCDriverForcedCcsid implements java.sql.Driver {
// Constants.
static final int MAJOR_VERSION_ = Copyright.MAJOR_VERSION;
static final int MINOR_VERSION_ = Copyright.MINOR_VERSION;
static final String DATABASE_PRODUCT_NAME_ = "DB2 UDB for AS/400"; // @D0A
static final String DRIVER_NAME_ = "AS/400 Toolbox for Java JDBC Driver"; // @D0C @C5C @C6C
static final String DRIVER_LEVEL_ = Copyright.DRIVER_LEVEL;
public static final int JDBC_MAJOR_VERSION_ = 4;
public static final int JDBC_MINOR_VERSION_ = 3;
// This string "9999:9999" is returned when resource
// bundle errors occur. No significance to this string,
// except that Client Access used to use it. It would
// probably be more helpful to return some other string.
//
private static final String MRI_NOT_FOUND_ = "9999:9999";
// Private data.
// Toolbox resources needed in proxy jar file. @A1C
private static ResourceBundle resources_;
// Toolbox resources NOT needed in proxy jar file. @A1A
private static ResourceBundle resources2_;
private static final String CLASSNAME = "com.ibm.as400.access.AS400JDBCDriverForcedCcsid";
private static Driver nativeDriver = null;
/**
* Static initializer. Registers the JDBC driver with the JDBC driver manager
* and loads the appropriate resource bundle for the current locale.
**/
static {
try {
// Log where the toolbox is loaded from @B1A
if (Trace.traceOn_)
Trace.logLoadPath(CLASSNAME, Trace.JDBC);
AS400JDBCDriverRegistration.registerCcsidDriver();
resources_ = ResourceBundle.getBundle("com.ibm.as400.access.JDMRI");
resources2_ = ResourceBundle.getBundle("com.ibm.as400.access.JDMRI2");
// Note: When using the proxy jar file, we do not expect to find JDMRI2.
} catch (MissingResourceException e) {
// Catch the exception. This is because exceptions
// thrown from static initializers are hard to debug.
// Instead, we will handle the error when the
// driver needs to get at particular methods.
// See getResource().
} catch (SQLException e) {
// Ignore.
}
}
/**
* Indicates if the driver understands how to connect to the database named by
* the URL.
*
* @param url The URL for the database.
* @return true if the driver understands how to connect to the database; false
* otherwise.
*
* @exception SQLException If an error occurs.
**/
public boolean acceptsURL(String url) throws SQLException {
JDDataSourceURL dataSourceUrl = new JDDataSourceURL(url);
return dataSourceUrl.isValid();
}
/**
* Connects to the database named by the specified URL. There are many optional
* properties that can be specified. Properties can be specified either as part
* of the URL or in a java.util.Properties object. See
* JDBC properties
* for a complete list of properties supported by this driver.
*
* @param url The URL for the database.
* @param info The connection properties.
* @return The connection to the database or null if the driver does not
* understand how to connect to the database.
*
* @exception SQLException If the driver is unable to make the connection.
**/
public java.sql.Connection connect(String url, Properties info) throws SQLException {
// Check first thing to see if the trace property is
// turned on. This way we can trace everything, including
// the important stuff like loading the properties.
JDDataSourceURL dataSourceUrl = new JDDataSourceURL(url);
Properties urlProperties = dataSourceUrl.getProperties();
// If trace property was set to true, turn on tracing. If trace property was set to false,
// turn off tracing. If trace property was not set, do not change.
if (JDProperties.isTraceSet(urlProperties, info) == JDProperties.TRACE_SET_ON) { // @B5C
if (!JDTrace.isTraceOn())
JDTrace.setTraceOn(true);
} else if (JDProperties.isTraceSet(urlProperties, info) == JDProperties.TRACE_SET_OFF) // @B5A
{
//@B5A
if (JDTrace.isTraceOn()) // @B5A
JDTrace.setTraceOn(false); // @B5A
} // @B5A
//@B4D Deleted lines because trace should not be set off just because property
//@B4D not specified.
//@B4D else
//@B4D JDTrace.setTraceOn (false);
// If toolbox trace is set to datastream. Turn on datastream tracing.
if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_DATASTREAM) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceDatastreamOn(true);
}
// If toolbox trace is set to diagnostic. Turn on diagnostic tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_DIAGNOSTIC) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceDiagnosticOn(true);
}
// If toolbox trace is set to error. Turn on error tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_ERROR) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceErrorOn(true);
}
// If toolbox trace is set to information. Turn on information tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_INFORMATION) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceInformationOn(true);
}
// If toolbox trace is set to warning. Turn on warning tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_WARNING) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceWarningOn(true);
}
// If toolbox trace is set to conversion. Turn on conversion tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_CONVERSION) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceConversionOn(true);
}
// If toolbox trace is set to proxy. Turn on proxy tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_PROXY) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceProxyOn(true);
}
// If toolbox trace is set to pcml. Turn on pcml tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_PCML) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTracePCMLOn(true);
}
// If toolbox trace is set to jdbc. Turn on jdbc tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_JDBC) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceJDBCOn(true);
}
// If toolbox trace is set to all. Turn on tracing for all categories.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_ALL) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceAllOn(true);
}
// If toolbox trace is set to thread. Turn on thread tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_THREAD) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceThreadOn(true);
}
// If toolbox trace is set to none. Turn off tracing.
else if (JDProperties.isToolboxTraceSet(urlProperties, info) == JDProperties.TRACE_TOOLBOX_NONE) {
//@K1A
if (Trace.isTraceOn()) {
Trace.setTraceOn(false);
}
}
if (JDTrace.isTraceOn()) {
String traceUrl = url;
int passwordIndex = url.indexOf("password=");
if (passwordIndex >= 0) {
int semicolonIndex = url.indexOf(";", passwordIndex);
if (semicolonIndex < 0) {
traceUrl = url.substring(0, passwordIndex) + "password=******";
} else {
traceUrl = url.substring(0, passwordIndex) + "password=******" + url.substring(semicolonIndex);
}
}
JDTrace.logInformation(this, "connect called with URL: " + traceUrl);
}
JDProperties jdProperties = new JDProperties(urlProperties, info);
// Initialize the connection if the URL is valid.
Connection connection = null; // @A0C
if (dataSourceUrl.isValid())
connection = initializeConnection(dataSourceUrl, jdProperties, info); // @A0C
return connection;
}
//@B5A
/**
* Connects to the database on the specified system.
*
* Note: Since this method is not defined in the JDBC Driver interface, you
* typically need to create a Driver object in order to call this method:
*
*
*
* AS400JDBCDriver d = new AS400JDBCDriver();
* AS400 o = new AS400(myAS400, myUserId, myPwd);
* Connection c = d.connect(o);
*
*
*
*
*
* @param system The IBM i system to connect.
* @return The connection to the database or null if the driver does not
* understand how to connect to the database.
*
* @exception SQLException If the driver is unable to make the connection.
**/
public java.sql.Connection connect(AS400 system) throws SQLException {
if (system == null)
throw new NullPointerException("system");
if (system instanceof SecureAS400)
return initializeConnection(new SecureAS400(system));
else
return initializeConnection(new AS400(system));
// Initialize the connection.
//@B7D Connection connection = null;
//@B7D connection = initializeConnection (o);
//@B7D return connection;
}
//@KKB
/**
* Connects to the database on the specified system.
*
* Note: Since this method is not defined in the JDBC Driver interface, you
* typically need to create a Driver object in order to call this method:
*
*
*
* AS400JDBCDriver d = new AS400JDBCDriver();
* AS400 o = new AS400(myAS400, myUserId, myPwd);
* Connection c = d.connect(o, false);
*
*
*
*
*
* @param system The IBM i system to connect.
* @param clone True if the AS400 object should be cloned, false otherwise.
* @return The connection to the database or null if the driver does not
* understand how to connect to the database.
*
* @exception SQLException If the driver is unable to make the connection.
**/
public java.sql.Connection connect(AS400 system, boolean clone) throws SQLException {
if (system == null)
throw new NullPointerException("system");
if (!clone) // Do not clone the AS400 object, use the one passed in
return initializeConnection(system);
else // clone the AS400 object
return connect(system);
}
//@D4A
/**
* Connects to the database on the specified system.
*
* Note: Since this method is not defined in the JDBC Driver interface, you
* typically need to create a Driver object in order to call this method:
*
*
*
* AS400JDBCDriver d = new AS400JDBCDriver();
* AS400 o = new AS400(myAS400, myUserId, myPwd);
* String mySchema = "defaultSchema";
* Properties prop = new Properties();
* Connection c = d.connect(o, prop, mySchema, false);
*
*
*
*
*
* @param system The IBM i system to connect.
* @param info The connection properties.
* @param schema The default SQL schema or null meaning no default SQL schema
* specified.
* @param clone True if the AS400 object should be cloned, false otherwise.
* @return The connection to the database or null if the driver does not
* understand how to connect to the database.
*
* @exception SQLException If the driver is unable to make the connection.
**/
public java.sql.Connection connect(AS400 system, Properties info, String schema, boolean clone)
throws SQLException {
if (system == null)
throw new NullPointerException("system");
if (info == null)
throw new NullPointerException("properties");
//@PDD not needed, just pass in null to isXTraceSet(null, info) below
//Properties urlProperties = new Properties();
// Check first thing to see if the trace property is
// turned on. This way we can trace everything, including
// the important stuff like loading the properties.
// If trace property was set to true, turn on tracing. If trace property was set to false,
// turn off tracing. If trace property was not set, do not change.
if (JDProperties.isTraceSet(null, info) == JDProperties.TRACE_SET_ON) {
if (!JDTrace.isTraceOn())
JDTrace.setTraceOn(true);
} else if (JDProperties.isTraceSet(null, info) == JDProperties.TRACE_SET_OFF) {
if (JDTrace.isTraceOn())
JDTrace.setTraceOn(false);
}
// If toolbox trace is set to datastream. Turn on datastream tracing.
if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_DATASTREAM) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceDatastreamOn(true);
}
// If toolbox trace is set to diagnostic. Turn on diagnostic tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_DIAGNOSTIC) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceDiagnosticOn(true);
}
// If toolbox trace is set to error. Turn on error tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_ERROR) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceErrorOn(true);
}
// If toolbox trace is set to information. Turn on information tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_INFORMATION) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceInformationOn(true);
}
// If toolbox trace is set to warning. Turn on warning tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_WARNING) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceWarningOn(true);
}
// If toolbox trace is set to conversion. Turn on conversion tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_CONVERSION) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceConversionOn(true);
}
// If toolbox trace is set to proxy. Turn on proxy tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_PROXY) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceProxyOn(true);
}
// If toolbox trace is set to pcml. Turn on pcml tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_PCML) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTracePCMLOn(true);
}
// If toolbox trace is set to jdbc. Turn on jdbc tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_JDBC) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceJDBCOn(true);
}
// If toolbox trace is set to all. Turn on tracing for all categories.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_ALL) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceAllOn(true);
}
// If toolbox trace is set to thread. Turn on thread tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_THREAD) {
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceThreadOn(true);
}
// If toolbox trace is set to none. Turn off tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_NONE) {
if (Trace.isTraceOn()) {
Trace.setTraceOn(false);
}
}
if (!clone) // Do not clone the AS400 object, use the one passed in
return initializeConnection(schema, info, system);
else // clone the AS400 object
{
if (system instanceof SecureAS400)
return initializeConnection(schema, info, new SecureAS400(system));
else
return initializeConnection(schema, info, new AS400(system));
}
}
//@B5A
/**
* Connects to the database on the specified system. There are many optional
* properties that can be specified. Properties can be specified in a
* java.util.Properties object. See
* JDBC properties
* for a complete list of properties supported by this driver.
*
*
* Note: Since this method is not defined in the JDBC Driver interface, you
* typically need to create a Driver object in order to call this method:
*
*
*
* AS400JDBCDriver d = new AS400JDBCDriver();
* String mySchema = "defaultSchema";
* Properties p = new Properties();
* AS400 o = new AS400(myAS400, myUserId, myPwd);
* Connection c = d.connect(o, p, mySchema);
*
*
*
*
* @param system The IBM i system to connect.
* @param info The connection properties.
* @param schema The default SQL schema or null meaning no default SQL schema
* specified.
* @return The connection to the database or null if the driver does not
* understand how to connect to the database.
*
* @exception SQLException If the driver is unable to make the connection.
**/
public java.sql.Connection connect(AS400 system, Properties info, String schema) throws SQLException {
if (system == null)
throw new NullPointerException("system");
if (info == null)
throw new NullPointerException("properties");
//@B7D AS400 o = new AS400(system);
//@PDD not needed, just pass in null to isXTraceSet(null, info) below
//Properties urlProperties = new Properties();
// Check first thing to see if the trace property is
// turned on. This way we can trace everything, including
// the important stuff like loading the properties.
// If trace property was set to true, turn on tracing. If trace property was set to false,
// turn off tracing. If trace property was not set, do not change.
if (JDProperties.isTraceSet(null, info) == JDProperties.TRACE_SET_ON) {
if (!JDTrace.isTraceOn())
JDTrace.setTraceOn(true);
} else if (JDProperties.isTraceSet(null, info) == JDProperties.TRACE_SET_OFF) {
if (JDTrace.isTraceOn())
JDTrace.setTraceOn(false);
}
// If toolbox trace is set to datastream. Turn on datastream tracing.
if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_DATASTREAM) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceDatastreamOn(true);
}
// If toolbox trace is set to diagnostic. Turn on diagnostic tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_DIAGNOSTIC) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceDiagnosticOn(true);
}
// If toolbox trace is set to error. Turn on error tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_ERROR) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceErrorOn(true);
}
// If toolbox trace is set to information. Turn on information tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_INFORMATION) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceInformationOn(true);
}
// If toolbox trace is set to warning. Turn on warning tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_WARNING) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceWarningOn(true);
}
// If toolbox trace is set to conversion. Turn on conversion tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_CONVERSION) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceConversionOn(true);
}
// If toolbox trace is set to proxy. Turn on proxy tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_PROXY) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceProxyOn(true);
}
// If toolbox trace is set to pcml. Turn on pcml tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_PCML) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTracePCMLOn(true);
}
// If toolbox trace is set to jdbc. Turn on jdbc tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_JDBC) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceJDBCOn(true);
}
// If toolbox trace is set to all. Turn on tracing for all categories.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_ALL) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceAllOn(true);
}
// If toolbox trace is set to thread. Turn on thread tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_THREAD) {
//@K1A
if (!Trace.isTraceOn()) {
Trace.setTraceOn(true);
}
Trace.setTraceThreadOn(true);
}
// If toolbox trace is set to none. Turn off tracing.
else if (JDProperties.isToolboxTraceSet(null, info) == JDProperties.TRACE_TOOLBOX_NONE) {
//@K1A
if (Trace.isTraceOn()) {
Trace.setTraceOn(false);
}
}
//@PDD not used JDProperties jdProperties = new JDProperties (null, info);
if (system instanceof SecureAS400)
return initializeConnection(schema, info, new SecureAS400(system));
else
return initializeConnection(schema, info, new AS400(system));
// Initialize the connection if the URL is valid.
//@B7D Connection connection = null;
//@B7D connection = initializeConnection (schema, info, o);
//@B7D return connection;
}
/**
* Returns the driver's major version number.
*
* @return The major version number.
**/
public int getMajorVersion() {
return MAJOR_VERSION_;
}
/**
* Returns the driver's minor version number.
*
* @return The minor version number.
**/
public int getMinorVersion() {
return MINOR_VERSION_;
}
/**
* Returns an array of DriverPropertyInfo objects that describe the properties
* that are supported by this driver.
*
* @param url The URL for the database.
* @param info The connection properties.
* @return The descriptions of all possible properties or null if the driver
* does not understand how to connect to the database.
*
* @exception SQLException If an error occurs.
**/
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
JDDataSourceURL dataSourceUrl = new JDDataSourceURL(url);
DriverPropertyInfo[] dpi = null;
if (dataSourceUrl.isValid()) {
JDProperties properties = new JDProperties(dataSourceUrl.getProperties(), info);
dpi = properties.getInfo();
}
return dpi;
}
/**
* Returns a resource from the resource bundle.
*
* @param key The resource key.
* @param replacementVariables -- replacement variables for the message
* @return The resource String.
**/
static String getResource(String key, String[] replacementVariables) {
// If the resource bundle or resource is not found,
// do not thrown an exception. Instead, return a
// default string. This is because some JVMs will
// not recover quite right from such errors, and
// claim a security exception (e.g. Netscape starts
// looking in the client class path, which is
// not allowed.)
//
String resource;
if (resources_ == null)
resource = MRI_NOT_FOUND_;
else {
try {
resource = resources_.getString(key);
} catch (MissingResourceException e) {
if (resources2_ == null) // @A1A
resource = MRI_NOT_FOUND_; // @A1A
else { // @A1A
try { // @A1A
resource = resources2_.getString(key); // @A1A
} // @A1A
catch (MissingResourceException e1) { // @A1A
JDTrace.logInformation(AS400JDBCDriver.class, "Missing resource [" + key + "]"); // @A1A
resource = MRI_NOT_FOUND_;
}
}
}
}
if (replacementVariables != null) {
resource = substitute(resource, replacementVariables);
}
return resource;
}
// Replaces substitution variables in a string.
// @param text The text string, with substitution variables (e.g. "Error &0 in table &1.")
// @param values The replacement values.
// @return The text string with all substitution variables replaced.
static String substitute(String text, Object[] values) {
String result = text;
if (values != null) {
for (int i = 0; i < values.length; ++i) {
String variable = "&" + i;
int j = result.indexOf(variable);
if (j >= 0) {
StringBuffer buffer = new StringBuffer();
buffer.append(result.substring(0, j));
buffer.append(values[i].toString());
buffer.append(result.substring(j + variable.length()));
result = buffer.toString();
}
}
}
return result;
}
//@B3A - This logic was formerly in the initializeConnection() method.
static AS400 initializeAS400(JDDataSourceURL dataSourceUrl, JDProperties jdProperties, Properties info)
throws SQLException // @pw1
{
// We must handle the different combinations of input
// user names and passwords.
String serverName = dataSourceUrl.getServerName();
String userName = jdProperties.getString(JDProperties.USER);
String password = jdProperties.getString(JDProperties.PASSWORD);
String prompt = jdProperties.getString(JDProperties.PROMPT); // @B8C
boolean secure = jdProperties.getBoolean(JDProperties.SECURE);
boolean useThreads = jdProperties.getBoolean(JDProperties.THREAD_USED);
//@pw1 Decided to leave connections via AS400() as-is and just implement to mimic Native JDBC
//@pw1 info contains args from DriverMangager.getConnection(args)
//@pw1 jdProperties does not represent null values. Both null and "" have a value of "".
//@pw1 if info contains id/pass of "" then they must not be "" in jdProperties (allowing jdProperties to override)
//@pw1 throw exception if info id/pass == "" and change info id/pass to "" if they are null
//@pw3 Add way to get old behavior allowing "" (!but also need to allow new behavior of allowing null is/passwd so customers can slowly migrate)
//check if "".
String secureCurrentUser = SystemProperties.getProperty(SystemProperties.JDBC_SECURE_CURRENT_USER); // @pw3
boolean isSecureCurrentUser = true; // @pw3
//if system property or jdbc property is set to false then secure current user code is not used
//null value for system property means not specified...so true by default
if (((secureCurrentUser != null) && (Boolean.valueOf(secureCurrentUser).booleanValue() == false))
|| !jdProperties.getBoolean(JDProperties.SECURE_CURRENT_USER)) // @pw3
isSecureCurrentUser = false; // @pw3
if (info == null)
info = new Properties();
String userParm = info.getProperty("user"); // @pw1
String passwordParm = info.getProperty("password"); // @pw1
boolean forcePrompt = false; // @prompt
if ("".equals(userName) && "".equals(userParm)) // @pw1 //@pw2
{ // @pw1
if (isSecureCurrentUser)// @pw3
{ // @pw3
if (JDTrace.isTraceOn()) // jdbc category trace //@pw1
JDTrace.logInformation(AS400JDBCDriverForcedCcsid.class,
"Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); // @pw1
//JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 //@prompt
forcePrompt = true; // @prompt
} // @pw3
} // @pw1
if ("".equals(password) && "".equals(passwordParm)) // @pw1 //@pw2
{ // @pw1
if (isSecureCurrentUser)// @pw3
{ // @pw3
if (JDTrace.isTraceOn()) // jdbc category trace //@pw1
JDTrace.logInformation(AS400JDBCDriverForcedCcsid.class,
"Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); // @pw1
//JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 //@prompt
forcePrompt = true; // @prompt
} // @pw3
} // @pw1
if (userParm != null) // @pw1
{ // @pw1
//check for *current //@pw1
if (userParm.compareToIgnoreCase("*CURRENT") == 0) // @pw1
{ // @pw1
if (isSecureCurrentUser)// @pw3
{ // @pw3
if (JDTrace.isTraceOn()) // jdbc category trace //@pw1
JDTrace.logInformation(AS400JDBCDriverForcedCcsid.class,
"Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); // @pw1
//JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1
forcePrompt = true; // @prompt
} // @pw3
} // @pw1
} // @pw1
else // @pw1
{ // @pw1
//since info is null, jdProperty must not be "" or *current, but it can be the default value (ie not set by user)
if (!JDProperties.EMPTY_.equals(userName)) // @pw1
{ // @pw1
//userName was updated by app
if (userName.equals("") || (userName.compareToIgnoreCase("*CURRENT") == 0)) // @pw1
{ // @pw1
if (isSecureCurrentUser)// @pw3
{ // @pw3
if (JDTrace.isTraceOn()) // jdbc category trace //@pw1
JDTrace.logInformation(AS400JDBCDriverForcedCcsid.class,
"Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); // @pw1
//JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1
forcePrompt = true; // @prompt
} // @pw3
} // @pw1
} // @pw1
} // @pw1
if (passwordParm != null) // @pw1
{ // @pw1
if (passwordParm.compareToIgnoreCase("*CURRENT") == 0) // @pw1
{ // @pw1
if (isSecureCurrentUser)// @pw3
{ // @pw3
if (JDTrace.isTraceOn()) // jdbc category trace //@pw1
JDTrace.logInformation(AS400JDBCDriverForcedCcsid.class,
"Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); // @pw1
//JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1
forcePrompt = true; // @prompt
} // @pw3
} // @pw1
} // @pw1
else // @pw1
{ // @pw1
//since info is null, jdProperty must not be "" or *current, but it can be the default value (ie not set by user)
if (!JDProperties.EMPTY_.equals(password)) // @pw1
{ // @pw1
//password was updated by app
if (password.equals("") || (password.compareToIgnoreCase("*CURRENT") == 0)) // @pw1
{ // @pw1
if (isSecureCurrentUser)// @pw3
{ // @pw3
if (JDTrace.isTraceOn()) // jdbc category trace //@pw1
JDTrace.logInformation(AS400JDBCDriverForcedCcsid.class,
"Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); // @pw1
//JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1
forcePrompt = true; // @prompt
} // @pw3
} // @pw1
} // @pw1
} // @pw1
// Create the AS400 object, so we can create a Connection via loadImpl2.
AS400 as400 = null;
if (secure) {
if (serverName.length() == 0)
as400 = new SecureAS400();
else if (userName.length() == 0)
as400 = new SecureAS400(serverName);
else if (password.length() == 0)
as400 = new SecureAS400(serverName, userName);
else
as400 = new SecureAS400(serverName, userName, password);
} else {
if (serverName.length() == 0)
as400 = new AS400();
else if (userName.length() == 0)
as400 = new AS400(serverName);
else if (password.length() == 0)
as400 = new AS400(serverName, userName);
else
as400 = new AS400(serverName, userName, password);
}
// Determine when the signon GUI can be presented..
try {
if (!prompt.equals(JDProperties.NOT_SPECIFIED)) // @B8A
as400.setGuiAvailable(jdProperties.getBoolean(JDProperties.PROMPT)); // @B8C
} catch (java.beans.PropertyVetoException e) {
// This will never happen, as there are no listeners.
}
//Determine if threads should be used in communication with the host servers
try {
if (!useThreads)
as400.setThreadUsed(useThreads);
} catch (java.beans.PropertyVetoException e) {
}
if (forcePrompt) // @prompt
as400.forcePrompt(); // @prompt
return as400;
}
//@A0A - This logic was formerly in the AS400JDBCConnection ctor and open() method.
private Connection initializeConnection(JDDataSourceURL dataSourceUrl, JDProperties jdProperties, Properties info)
throws SQLException {
//@B7D Connection connection = null;
AS400 as400 = null;
boolean proxyServerWasSpecifiedInUrl = false;
boolean proxyServerWasSpecifiedInProperties = false;
boolean proxyServerWasSpecified = false;
//@C4A Check for native driver only if driver property is not set to Toolbox
String driverImplementation = jdProperties.getString(JDProperties.DRIVER); // @C4M
if (!driverImplementation.equals(JDProperties.DRIVER_TOOLBOX)) // @C4A
{ // @C4A
// @B2A
// Determine whether the native driver is available.
if (nativeDriver == null) {
try {
nativeDriver = (Driver) Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
if (JDTrace.isTraceOn()) // @C2A
JDTrace.logInformation(this,
"Native IBM Developer Kit for Java JDBC driver implementation was loaded"); // @C2A
} catch (Throwable e) {
nativeDriver = null;
}
}
// @B2A
// Decide which JDBC driver implementation to use. If the
// native driver is available AND there is no secondary URL
// available AND the "driver" property was not set to "toolbox",
// then use the native driver implementation.
//@C4M String driverImplementation = jdProperties.getString(JDProperties.DRIVER);
if ((nativeDriver != null) && (dataSourceUrl.getSecondaryURL().length() == 0))
//@C4D Already checked above && (!driverImplementation.equals(JDProperties.DRIVER_TOOLBOX)))
{
//@C3M
boolean isLocal = false; // @C2A
String serverName = dataSourceUrl.getServerName(); // @C2A
if (serverName.length() == 0 || serverName.equalsIgnoreCase("localhost")) // @C2A //@locala
isLocal = true; // @C2A
else { // @C2A
try { // @C2A
InetAddress localInet = InetAddress.getLocalHost(); // @C2A
InetAddress[] remoteInet = InetAddress.getAllByName(serverName); // @C2A
for (int i = 0; i < remoteInet.length; ++i) { // @C2A
if (localInet.equals(remoteInet[i])) { // @C2A
isLocal = true; // @C2A
} // @C2A
} // @C2A
} // @C2A
catch (Throwable e) { // @C2A
// Ignore. We will just assume that we are not local. @C2A
} // @C2A
}
if (isLocal) { // @C2A
if (JDTrace.isTraceOn()) // @C2A
JDTrace.logInformation(this, "Connection is local"); // @C2A
String nativeURL = dataSourceUrl.getNativeURL();
if (JDTrace.isTraceOn())
JDTrace.logInformation(this,
"Using native IBM Developer Kit for Java JDBC driver implementation");// @native don't
// print passwd
return nativeDriver.connect(nativeURL, info);
} // @C2A
}
} // @C4A
// @C2D else
// @C2D {
if (JDTrace.isTraceOn())
JDTrace.logInformation(this, "Using IBM Toolbox for Java JDBC driver implementation");
// @C2D }
// @A0A
// See if a proxy server was specified.
//if (jdProperties.getIndex (JDProperties.PROXY_SERVER) != -1) //@A3D
if (jdProperties.getString(JDProperties.PROXY_SERVER).length() != 0) // @A3C
proxyServerWasSpecifiedInUrl = true;
if (SystemProperties.getProperty(SystemProperties.AS400_PROXY_SERVER) != null)
proxyServerWasSpecifiedInProperties = true;
if (proxyServerWasSpecifiedInUrl || proxyServerWasSpecifiedInProperties)
proxyServerWasSpecified = true;
// If no proxy server was specified, and there is a secondary URL,
// simply pass the secondary URL to the DriverManager and ask it for
// an appropriate Connection object.
if (!proxyServerWasSpecified) {
String secondaryUrl = dataSourceUrl.getSecondaryURL();
if (secondaryUrl.length() != 0) {
if (JDTrace.isTraceOn())
JDTrace.logInformation(this, "Secondary URL [" + secondaryUrl + "]");
return DriverManager.getConnection(secondaryUrl, info);
}
}
as400 = initializeAS400(dataSourceUrl, jdProperties, info); // @B3C
if (proxyServerWasSpecifiedInUrl) {
// A proxy server was specified in URL,
// so we need to inform the AS400 object.
//boolean proxyServerSecure = jdProperties.getBoolean (JDProperties.PROXY_SERVER_SECURE); // TBD
String proxyServerNameAndPort = jdProperties.getString(JDProperties.PROXY_SERVER);
// Note: The PROXY_SERVER property is of the form:
// hostName[:portNumber]
// where portNumber is optional.
try {
as400.setProxyServer(proxyServerNameAndPort);
//as400.setProxyServerSecure (proxyServerSecure); // TBD
} catch (java.beans.PropertyVetoException e) {
} // Will never happen.
}
//@B6C Moved common code to prepareConnection.
return prepareConnection(as400, dataSourceUrl, info, jdProperties);
}
//@B5A
private Connection initializeConnection(AS400 as400) throws SQLException {
JDDataSourceURL dataSourceUrl = new JDDataSourceURL(null);
Properties info = new Properties();
JDProperties jdProperties = new JDProperties(null, info);
//@B6C Moved common code to prepareConnection.
return prepareConnection(as400, dataSourceUrl, info, jdProperties);
}
//@B5A
private Connection initializeConnection(String schema, Properties info, AS400 as400) throws SQLException {
boolean proxyServerWasSpecifiedInUrl = false;
String url = null;
if (schema != null) // @B6A
url = "jdbc:as400://" + as400.getSystemName() + "/" + schema;
else // @B6A
url = "jdbc:as400://" + as400.getSystemName(); // @B6A
JDDataSourceURL dataSourceUrl = new JDDataSourceURL(url);
JDProperties jdProperties = new JDProperties(null, info);
if (JDTrace.isTraceOn())
JDTrace.logInformation(this, "Using IBM Toolbox for Java JDBC driver implementation");
// See if a proxy server was specified.
if (jdProperties.getString(JDProperties.PROXY_SERVER).length() != 0)
proxyServerWasSpecifiedInUrl = true;
if (proxyServerWasSpecifiedInUrl) {
// A proxy server was specified in URL, so we need to inform the AS400 object.
//boolean proxyServerSecure = jdProperties.getBoolean (JDProperties.PROXY_SERVER_SECURE);// TBD
String proxyServerNameAndPort = jdProperties.getString(JDProperties.PROXY_SERVER);
// Note: The PROXY_SERVER property is of the form:
// hostName[:portNumber]
// where portNumber is optional.
try {
as400.setProxyServer(proxyServerNameAndPort);
//as400.setProxyServerSecure (proxyServerSecure); // TBD
} catch (java.beans.PropertyVetoException e) {
} // Will never happen.
}
//@B6C Moved common code to prepareConnection.
return prepareConnection(as400, dataSourceUrl, info, jdProperties);
}
/**
* Indicates if the driver is a genuine JDBC compliant driver.
*
* @return Always true.
**/
public boolean jdbcCompliant() {
return true;
}
//@B6A -- This logic was formerly in the initializeConnection() method.
private Connection prepareConnection(AS400 as400, JDDataSourceURL dataSourceUrl, Properties info,
JDProperties jdProperties) throws SQLException {
// set socket properties
SocketProperties sockProps = null;
//if == "", then take platform defaults...do not set
//only get/set properties is one is updated
if (jdProperties.getString(JDProperties.KEEP_ALIVE).equals("") == false) {
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setKeepAlive(jdProperties.getBoolean(JDProperties.KEEP_ALIVE));
}
if (jdProperties.getString(JDProperties.RECEIVE_BUFFER_SIZE).equals("") == false) {
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setReceiveBufferSize(jdProperties.getInt(JDProperties.RECEIVE_BUFFER_SIZE));
}
if (jdProperties.getString(JDProperties.SEND_BUFFER_SIZE).equals("") == false) {
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setSendBufferSize(jdProperties.getInt(JDProperties.SEND_BUFFER_SIZE));
}
//@timeout2
//First get setting from DriverManager, then override with property updates
if (!as400.arePropertiesFrozen()) // @timeout3 AS400JDBCDriverForcedCcsid.connect(clone=false) cannot update props. We
// don't know if DriverManager.setLoginTimeout() has been updated.
{
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setLoginTimeout(DriverManager.getLoginTimeout() * 1000); // @STIMEOUT
}
//@timeout
if (jdProperties.getString(JDProperties.LOGIN_TIMEOUT).equals("") == false) {
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setLoginTimeout(jdProperties.getInt(JDProperties.LOGIN_TIMEOUT) * 1000); // @STIMEOUT
}
//@STIMEOUT
if (jdProperties.getString(JDProperties.SOCKET_TIMEOUT).equals("") == false) {
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setSoTimeout(jdProperties.getInt(JDProperties.SOCKET_TIMEOUT)); // @STIMEOUT already in
// milliseconds
}
if (jdProperties.getBoolean(JDProperties.TCP_NO_DELAY) == true) {
if (sockProps == null)
sockProps = as400.getSocketProperties();
sockProps.setTcpNoDelay(true);
if (JDTrace.isTraceOn())
JDTrace.logInformation(this, "Setting sockProps.setTcpNoDelay(true)");
}
String defaultImpl = "com.ibm.as400.access.AS400JDBCConnectionForcedCcsid";
if (jdProperties.getInt(JDProperties.ENABLE_CLIENT_AFFINITIES_LIST) == 1) {
defaultImpl = "com.ibm.as400.access.AS400JDBCConnectionRedirect";
}
if (sockProps != null)
as400.setSocketProperties(sockProps);
// Create the appropriate kind of Connection object.
Connection connection = (Connection) as400.loadImpl2(defaultImpl, "com.ibm.as400.access.JDConnectionProxy");
// Set the properties on the Connection object.
if (connection != null) {
// If we get an exception, make sure the connection is closed.
// The common case is when an exit program prevents access to the system.
// @AB1A
try {
if (connection instanceof JDConnectionProxy) {
((JDConnectionProxy) connection).setSystem(as400);
((JDConnectionProxy) connection).setProperties(dataSourceUrl, jdProperties, as400);
} else {
((AS400JDBCConnection) connection).setSystem(as400);
((AS400JDBCConnection) connection).setProperties(dataSourceUrl, jdProperties, as400, info);
}
} catch (SQLException sqlex) {
try {
connection.close();
} catch (Exception e) {
// Just ignore
}
throw sqlex;
}
}
return connection;
}
/**
* Returns the name of the driver.
*
* @return The driver name.
**/
public String toString() {
return DRIVER_NAME_; // @D0C
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
}