/* * ==================== * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common Development * and Distribution License("CDDL") (the "License"). You may not use this file * except in compliance with the License. * * You can obtain a copy of the License at * http://opensource.org/licenses/cddl1.php * See the License for the specific language governing permissions and limitations * under the License. * * When distributing the Covered Code, include this CDDL Header Notice in each file * and include the License file at http://opensource.org/licenses/cddl1.php. * If applicable, add the following below this CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * ==================== */ package org.identityconnectors.db2; import static org.identityconnectors.db2.DB2Messages.DB2_ADMINACCOUNT_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_ADMINACCOUNT_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_ADMINPASSWORD_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_ADMINPASSWORD_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_DATABASENAME_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_DATABASENAME_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_DATASOURCE_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_DATASOURCE_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_DSJNDIENV_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_DSJNDIENV_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_HOST_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_HOST_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_JDBCDRIVER_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_JDBCDRIVER_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_JDBCSUBPROTOCOL_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_JDBCSUBPROTOCOL_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_PORT_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_PORT_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_REPLACEALLGRANTSONUPDATE_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_REPLACEALLGRANTSONUPDATE_HELP; import static org.identityconnectors.db2.DB2Messages.DB2_URL_DISPLAY; import static org.identityconnectors.db2.DB2Messages.DB2_URL_HELP; import java.sql.Connection; import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.db2.Type2ConnectionInfo.Type2ConnectionInfoBuilder; import org.identityconnectors.db2.Type4ConnectionInfo.Type4ConnectionInfoBuilder; import org.identityconnectors.dbcommon.JNDIUtil; import org.identityconnectors.dbcommon.SQLUtil; import org.identityconnectors.framework.common.exceptions.ConnectorException; import org.identityconnectors.framework.spi.AbstractConfiguration; import org.identityconnectors.framework.spi.ConfigurationProperty; /** * Configuration to access DB2 database. We will support most consistent way how * to connect to database. We will support 3 ways how to connect to DB2. * <ol> * <li>Using javax.sql.DataSource when using dataSource jndi name, see <a * href="#dataSource">datasource properties</a></li> * <li>Using concrete URL with any driver, see <a href="#url">url properties</a> * </li> * <li>Using type 4 driver, when using host,port and database name, see <a * href="#databaseName">databasename properties</a></li> * <li>Using type 2 driver, when using local alias, see <a * href="#aliasName">alias name properties</a></li> * <li>See also <a href="#commonProperties"> common properties</a> for all * drivers and <a href="#finalNotes"> final notes</a> for all IBM db2 drivers</li> * </ol> * * * The above specified order is critical. This means, we will not use any * combination, just one of the case in the specified order. * * * <h4><a name="dataSource"/>Getting connection from DataSource. Used when * <code>dataSource</code> property is set</h4> We will support these properties * when connecting to DB2 using dataSource * <ul> * <li>dataSource : Name of jndi name of dataSource : required. It must be * logical or absolute name of dataSource. No prefix will be added when trying * to do lookup</li> * <li> * dsJNDIEnv : JNDI environment entries needed to lookup datasource. In most * cases should be empty, needed only when lookuping datasource from different * server as server where connectors are running.</li> * <li>adminAccount : Administrative account : optional, default we will get * connection from DS without user/password parameters</li> * <li>adminPassword : Administrative password : optional, default we will get * connection from DS without user/password parameters</li></li> * </ul> * * <h4><a name="url"/>Getting connection from DriverManager using full jdbc url. * Used when <code>url</code> property is set</h4> We will support/require these * properties when connecting to db2 with url: * <ul> * <li>url : Full jdbc url for connecting to db2</li> * <li>jdbcDriver : Classname of jdbc driver, default to * com.ibm.db2.jcc.DB2Driver</li> * <li>adminAccount : Administrative account when connecting to DB2 in non user * contexts. E.g listing of users.</li> * <li>adminPassword : Password for admin account.</li> * </ul> * * * <h4><a name="databaseName"/>Getting connection from DriverManager using Type * 4 driver. Used when <code>host,port,databaseName</code> property are set</h4> * We will support/require these properties when connecting to db2 : * <ul> * <li>host : Name or IP of DB2 instance host. This is required property</li> * <li>port : Port db2 listener is listening to. Default to 50000</li> * <li>databaseName : Name of local/remote database</li> * <li>subprotocol : db2,db2iSeries. Default to db2</li> * <li>jdbcDriver : Classname of jdbc driver, default to * com.ibm.db2.jcc.DB2Driver</li> * <li>adminAccount : Administrative account when connecting to DB2 in non user * contexts. E.g listing of users.</li> * <li>adminPassword : Password for admin account.</li> * </ul> * * <h4><a name="aliasName"/>Getting connection from DriverManager using Type 2 * driver. Used when <code>databaseName - local alias</code> property is set</h4> * We will require these properties when connecting to db2 using local alias * <ul> * <li>databaseName : Name of local alias created using * <code>"db2 catalag database command"</code></li> * <li>jdbcDriver : Classname of jdbc driver, default to * com.ibm.db2.jcc.DB2Driver</li> * <li>subprotocol : db2,db2iSeries. Default to db2</li> * <li>adminAccount : Administrative account when connecting to DB2 in non user * contexts. E.g listing of users.</li> * <li>adminPassword : Password for admin account.</li> * </ul> * * <h4><a name="commonProperties"/>Properties common to all connection options</h4> * <ul> * <li>replaceAllGrantsOnUpdate : Kept for backward compatibility instead of * removeForeignGrants. When set to true(default) , we replace value of passed * grants on update. Otherwise we do addition of passed grants to the grants * user already has. This property can be removed in future version, when IDM * will properly call UpdateAttributeValuesOp operations.</li> * </ul> * * <h4><a name="finalNotes"/>Note that IBM ships two drivers for DB2. We have * tested only these two drivers, no other driver was tested</h4> * <ul> * <li>IBM DB2 Driver for JDBC and SQLJ</li> * This driver can be used as type4 and type2 driver. In this way driver * classname is same, we just need specify different properties. DatabaseName * property is used like remote database in case of type4 and like local alias * in case of type2. * <li>Legacy based cli driver</li> * This driver is deprecated now, although it is still included in DB2 9x * version. DB2 does not develop this driver any more and it seems it will be * removed in next major version release. However this driver was recommended * driver for Websphere. * </ul> * IBM Net Driver was deprecated in version 8, is not included in version 9. * This driver is not supported. * * @author kitko * */ public class DB2Configuration extends AbstractConfiguration implements Cloneable { /** * Constructor needed for connector framework. Will initialize fields to * default values */ public DB2Configuration() { } /** * Default clone implementation. * * @throws ConnectorException * when super.clone fails */ public DB2Configuration clone() throws ConnectorException { try { return (DB2Configuration) super.clone(); } catch (CloneNotSupportedException e) { throw new ConnectorException("Clone of DB2Configuration super class failed", e); } } /** Type of connection we will use to connect to DB2 */ static enum ConnectionType { /** Connecting using datasource */ DATASOURCE, /** Connecting using type 4 driver (host,port,databaseName) */ TYPE4, /** Connecting using type 2 driver (local alias) */ TYPE2, /** Connecting using explicit url */ URL; } /** * Name of admin user which will be used to connect to DB2 database. Note * that DB2 always uses external authentication service, default to * underlying OS */ private String adminAccount; /** Password for admin account */ private GuardedString adminPassword; /** * Subprotocol driverManager will use to find driver and connect to db2. * Probably this will be <b>db2</b>. So final URL will look like : * <p> * jdbc:db2:server/databaseName * </p> */ private String jdbcSubProtocol = "db2"; /** * Name of database we will connect to. This is the name of local/remote * database, not name of local alias. */ private String databaseName; /** * Full jndi name of datasource */ private String dataSource; /** Class name of jdbc driver */ private String jdbcDriver = DB2Specifics.JCC_DRIVER; /** DB2 host name */ private String host; /** DB2 listening port */ private String port = DB2Specifics.DEFAULT_TYPE4_PORT; /** Type/manner of connection to DB */ private ConnectionType connType; /** JNDI environment entries for lookuping DS */ private String[] dsJNDIEnv; /** * Replace all grants on update. Current version of IDM does not support * UpdateAttributeValuesOp operations, just update. This switch is only for * backward compatibility and can be removed when IDM will properly call * UpdateAttributeValuesOp operations. <br/> * When set to true, we will remove all grants and set new passed grants on * update. <br/> * When set to false we will do add. */ private boolean replaceAllGrantsOnUpdate = true; /** Full url for connecting to DB2 */ private String url; /** * @return admin account */ @ConfigurationProperty(order = 0, displayMessageKey = DB2_ADMINACCOUNT_DISPLAY, helpMessageKey = DB2_ADMINACCOUNT_HELP) public String getAdminAccount() { return adminAccount; } /** * Sets admin account * * @param account */ public void setAdminAccount(String account) { this.adminAccount = account; } /** * @return admin password */ @ConfigurationProperty(order = 1, displayMessageKey = DB2_ADMINPASSWORD_DISPLAY, helpMessageKey = DB2_ADMINPASSWORD_HELP, confidential = true) public GuardedString getAdminPassword() { return adminPassword; } /** * Sets admin password * * @param adminPassword */ public void setAdminPassword(GuardedString adminPassword) { this.adminPassword = adminPassword; } /** * @return subprotocol when connecting using type 4 driver */ @ConfigurationProperty(order = 2, displayMessageKey = DB2_JDBCSUBPROTOCOL_DISPLAY, helpMessageKey = DB2_JDBCSUBPROTOCOL_HELP) public String getJdbcSubProtocol() { return jdbcSubProtocol; } /** * @return databasename */ @ConfigurationProperty(order = 3, displayMessageKey = DB2_DATABASENAME_DISPLAY, helpMessageKey = DB2_DATABASENAME_HELP) public String getDatabaseName() { return databaseName; } /** * Sets subprotocol * * @param subProtocol */ public void setJdbcSubProtocol(String subProtocol) { this.jdbcSubProtocol = subProtocol; } /** * Sets database name * * @param databaseName */ public void setDatabaseName(String databaseName) { this.databaseName = databaseName; } /** * @return classname of jdbc driver */ @ConfigurationProperty(order = 4, displayMessageKey = DB2_JDBCDRIVER_DISPLAY, helpMessageKey = DB2_JDBCDRIVER_HELP) public String getJdbcDriver() { return jdbcDriver; } /** * Sets classname of jdbc driver * * @param jdbcDriver */ public void setJdbcDriver(String jdbcDriver) { this.jdbcDriver = jdbcDriver; } /** * @return the host */ @ConfigurationProperty(order = 5, displayMessageKey = DB2_HOST_DISPLAY, helpMessageKey = DB2_HOST_HELP) public String getHost() { return host; } /** * @param host * the host to set */ public void setHost(String host) { this.host = host; } /** * @return the port */ @ConfigurationProperty(order = 6, displayMessageKey = DB2_PORT_DISPLAY, helpMessageKey = DB2_PORT_HELP) public String getPort() { return port; } /** * @param port * the port to set */ public void setPort(String port) { this.port = port; } @ConfigurationProperty(order = 7, displayMessageKey = DB2_URL_DISPLAY, helpMessageKey = DB2_URL_HELP) public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } /** * @return the dataSource */ @ConfigurationProperty(order = 8, displayMessageKey = DB2_DATASOURCE_DISPLAY, helpMessageKey = DB2_DATASOURCE_HELP) public String getDataSource() { return dataSource; } /** * @param dataSource * the dataSource to set */ public void setDataSource(String dataSource) { this.dataSource = dataSource; } /** * @return the dsJNDIEnv */ @ConfigurationProperty(order = 9, displayMessageKey = DB2_DSJNDIENV_DISPLAY, helpMessageKey = DB2_DSJNDIENV_HELP) public String[] getDsJNDIEnv() { if (dsJNDIEnv == null) { return new String[0]; } String[] res = new String[dsJNDIEnv.length]; System.arraycopy(dsJNDIEnv, 0, res, 0, dsJNDIEnv.length); return res; } /** * @param dsJNDIEnv * the dsJNDIEnv to set */ public void setDsJNDIEnv(String[] dsJNDIEnv) { if (dsJNDIEnv == null) { this.dsJNDIEnv = null; } else { this.dsJNDIEnv = new String[dsJNDIEnv.length]; System.arraycopy(dsJNDIEnv, 0, this.dsJNDIEnv, 0, dsJNDIEnv.length); } } /** * Replace all grants on update switch Current version of IDM does not * support UpdateAttributeValuesOp operations, just update. This switch is * only for backward compatibility and can be removed when IDM will properly * call UpdateAttributeValuesOp operations. <br/> * When set to true, we will remove all grants and set new passed grants on * update. <br/> * When set to false we will do add. * * @return replaceAllGrantsOnUpdate * **/ @ConfigurationProperty(order = 10, displayMessageKey = DB2_REPLACEALLGRANTSONUPDATE_DISPLAY, helpMessageKey = DB2_REPLACEALLGRANTSONUPDATE_HELP) public boolean isReplaceAllGrantsOnUpdate() { return replaceAllGrantsOnUpdate; } /** * @param replaceAllGrantsOnUpdate * the replaceAllGrantsOnUpdate to set */ public void setReplaceAllGrantsOnUpdate(boolean replaceAllGrantsOnUpdate) { this.replaceAllGrantsOnUpdate = replaceAllGrantsOnUpdate; } /** * @return the connType */ ConnectionType getConnType() { return connType; } void setConnType(ConnectionType connType) { this.connType = connType; } @Override public void validate() { setConnType(null); new DB2ConfigurationValidator(this).validate(); } Connection createAdminConnection() { return createConnection(adminAccount, adminPassword); } Connection createConnection(String user, GuardedString password) { validate(); if (ConnectionType.DATASOURCE.equals(connType)) { if (user != null) { return DB2Specifics.createDataSourceConnection(dataSource, user, password, JNDIUtil .arrayToHashtable(dsJNDIEnv, getConnectorMessages())); } else { return DB2Specifics.createDataSourceConnection(dataSource, JNDIUtil .arrayToHashtable(dsJNDIEnv, getConnectorMessages())); } } else if (ConnectionType.TYPE4.equals(connType)) { return DB2Specifics.createType4Connection(new Type4ConnectionInfoBuilder().setDriver( jdbcDriver).setHost(host).setPort(port).setSubprotocol(jdbcSubProtocol) .setDatabase(databaseName).setUser(user).setPassword(password).build()); } else if (ConnectionType.TYPE2.equals(connType)) { return DB2Specifics.createType2Connection(new Type2ConnectionInfoBuilder().setDriver( jdbcDriver).setAliasName(databaseName).setSubprotocol(jdbcSubProtocol).setUser( user).setPassword(password).build()); } else if (ConnectionType.URL.equals(connType)) { return SQLUtil.getDriverMangerConnection(jdbcDriver, url, user, password); } throw new IllegalStateException("Invalid state of DB2Configuration"); } }