| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.jdbc.conf; |
| |
| import java.sql.Connection; |
| import java.sql.ResultSet; |
| import java.util.Locale; |
| |
| import javax.sql.DataSource; |
| |
| import org.apache.openjpa.conf.OpenJPAConfigurationImpl; |
| import org.apache.openjpa.jdbc.identifier.DBIdentifierUtil; |
| import org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager; |
| import org.apache.openjpa.jdbc.kernel.BatchingOperationOrderUpdateManager; |
| import org.apache.openjpa.jdbc.kernel.EagerFetchModes; |
| import org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory; |
| import org.apache.openjpa.jdbc.kernel.LRSSizes; |
| import org.apache.openjpa.jdbc.kernel.PessimisticLockManager; |
| import org.apache.openjpa.jdbc.kernel.UpdateManager; |
| import org.apache.openjpa.jdbc.meta.MappingDefaults; |
| import org.apache.openjpa.jdbc.meta.MappingRepository; |
| import org.apache.openjpa.jdbc.schema.DataSourceFactory; |
| import org.apache.openjpa.jdbc.schema.SchemaFactory; |
| import org.apache.openjpa.jdbc.sql.DBDictionary; |
| import org.apache.openjpa.jdbc.sql.DBDictionaryFactory; |
| import org.apache.openjpa.jdbc.sql.MaxDBDictionary; |
| import org.apache.openjpa.jdbc.sql.SQLFactory; |
| import org.apache.openjpa.kernel.BrokerImpl; |
| import org.apache.openjpa.kernel.StoreContext; |
| import org.apache.openjpa.lib.conf.IntValue; |
| import org.apache.openjpa.lib.conf.ObjectValue; |
| import org.apache.openjpa.lib.conf.PluginValue; |
| import org.apache.openjpa.lib.conf.ProductDerivations; |
| import org.apache.openjpa.lib.conf.StringListValue; |
| import org.apache.openjpa.lib.conf.StringValue; |
| import org.apache.openjpa.lib.jdbc.ConnectionDecorator; |
| import org.apache.openjpa.lib.jdbc.DecoratingDataSource; |
| import org.apache.openjpa.lib.jdbc.JDBCListener; |
| import org.apache.openjpa.lib.log.Log; |
| import org.apache.openjpa.lib.util.Localizer; |
| import org.apache.openjpa.lib.util.StringUtil; |
| import org.apache.openjpa.meta.MetaDataFactory; |
| import org.apache.openjpa.util.UserException; |
| |
| /** |
| * Default implementation of the {@link JDBCConfiguration} interface. |
| * |
| * @author Marc Prud'hommeaux |
| * @author Abe White |
| */ |
| public class JDBCConfigurationImpl |
| extends OpenJPAConfigurationImpl |
| implements JDBCConfiguration { |
| |
| public StringValue schema; |
| public StringListValue schemas; |
| public IntValue transactionIsolation; |
| public IntValue resultSetType; |
| public IntValue fetchDirection; |
| public FetchModeValue eagerFetchMode; |
| public FetchModeValue subclassFetchMode; |
| public IntValue lrsSize; |
| public StringValue synchronizeMappings; |
| public ObjectValue jdbcListenerPlugins; |
| public ObjectValue connectionDecoratorPlugins; |
| public PluginValue dbdictionaryPlugin; |
| public ObjectValue updateManagerPlugin; |
| public ObjectValue schemaFactoryPlugin; |
| public ObjectValue sqlFactoryPlugin; |
| public ObjectValue mappingDefaultsPlugin; |
| public PluginValue driverDataSourcePlugin; |
| public MappingFactoryValue mappingFactoryPlugin; |
| public ObjectValue identifierUtilPlugin; |
| |
| // used internally |
| private String firstUser = null; |
| private String firstPass = null; |
| private DecoratingDataSource dataSource = null; |
| private DecoratingDataSource dataSource2 = null; |
| |
| private static final Localizer _loc = Localizer.forPackage(JDBCConfigurationImpl.class); |
| |
| /** |
| * Default constructor. Attempts to load default properties. |
| */ |
| public JDBCConfigurationImpl() { |
| this(true); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param loadGlobals whether to attempt to load the global properties |
| */ |
| public JDBCConfigurationImpl(boolean loadGlobals) { |
| this(true, loadGlobals); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param derivations whether to apply product derivations |
| * @param loadGlobals whether to attempt to load the global properties |
| */ |
| public JDBCConfigurationImpl(boolean derivations, boolean loadGlobals) { |
| super(false, false); |
| String[] aliases; |
| |
| schema = addString("jdbc.Schema"); |
| schemas = addStringList("jdbc.Schemas"); |
| |
| transactionIsolation = addInt("jdbc.TransactionIsolation"); |
| aliases = new String[]{ |
| "default", String.valueOf(-1), |
| "none", String.valueOf(Connection.TRANSACTION_NONE), |
| "read-committed", String.valueOf |
| (Connection.TRANSACTION_READ_COMMITTED), |
| "read-uncommitted", String.valueOf |
| (Connection.TRANSACTION_READ_UNCOMMITTED), |
| "repeatable-read", String.valueOf |
| (Connection.TRANSACTION_REPEATABLE_READ), |
| "serializable", String.valueOf(Connection.TRANSACTION_SERIALIZABLE) |
| }; |
| transactionIsolation.setAliases(aliases); |
| transactionIsolation.setDefault(aliases[0]); |
| transactionIsolation.set(-1); |
| transactionIsolation.setAliasListComprehensive(true); |
| |
| resultSetType = addInt("jdbc.ResultSetType"); |
| aliases = new String[]{ |
| "forward-only", String.valueOf(ResultSet.TYPE_FORWARD_ONLY), |
| "scroll-sensitive", String.valueOf |
| (ResultSet.TYPE_SCROLL_SENSITIVE), |
| "scroll-insensitive", String.valueOf |
| (ResultSet.TYPE_SCROLL_INSENSITIVE), |
| }; |
| resultSetType.setAliases(aliases); |
| resultSetType.setDefault(aliases[0]); |
| resultSetType.set(ResultSet.TYPE_FORWARD_ONLY); |
| resultSetType.setAliasListComprehensive(true); |
| |
| fetchDirection = addInt("jdbc.FetchDirection"); |
| aliases = new String[]{ |
| "forward", String.valueOf(ResultSet.FETCH_FORWARD), |
| "reverse", String.valueOf(ResultSet.FETCH_REVERSE), |
| "unknown", String.valueOf(ResultSet.FETCH_UNKNOWN), |
| }; |
| fetchDirection.setAliases(aliases); |
| fetchDirection.setDefault(aliases[0]); |
| fetchDirection.set(ResultSet.FETCH_FORWARD); |
| fetchDirection.setAliasListComprehensive(true); |
| |
| eagerFetchMode = new FetchModeValue("jdbc.EagerFetchMode"); |
| eagerFetchMode.setDefault(FetchModeValue.EAGER_PARALLEL); |
| eagerFetchMode.set(EagerFetchModes.EAGER_PARALLEL); |
| addValue(eagerFetchMode); |
| |
| subclassFetchMode = new FetchModeValue("jdbc.SubclassFetchMode"); |
| subclassFetchMode.setDefault(FetchModeValue.EAGER_JOIN); |
| subclassFetchMode.set(EagerFetchModes.EAGER_JOIN); |
| addValue(subclassFetchMode); |
| |
| lrsSize = addInt("jdbc.LRSSize"); |
| aliases = new String[]{ |
| "query", String.valueOf(LRSSizes.SIZE_QUERY), |
| "unknown", String.valueOf(LRSSizes.SIZE_UNKNOWN), |
| "last", String.valueOf(LRSSizes.SIZE_LAST), |
| }; |
| lrsSize.setAliases(aliases); |
| lrsSize.setDefault(aliases[0]); |
| lrsSize.set(LRSSizes.SIZE_QUERY); |
| lrsSize.setAliasListComprehensive(true); |
| |
| synchronizeMappings = addString("jdbc.SynchronizeMappings"); |
| aliases = new String[]{ "false", null }; |
| synchronizeMappings.setAliases(aliases); |
| synchronizeMappings.setDefault(aliases[0]); |
| |
| jdbcListenerPlugins = addPluginList("jdbc.JDBCListeners"); |
| jdbcListenerPlugins.setInstantiatingGetter("getJDBCListenerInstances"); |
| |
| connectionDecoratorPlugins = addPluginList |
| ("jdbc.ConnectionDecorators"); |
| connectionDecoratorPlugins.setInstantiatingGetter |
| ("getConnectionDecoratorInstances"); |
| |
| dbdictionaryPlugin = addPlugin("jdbc.DBDictionary", true); |
| aliases = new String[]{ |
| "access", org.apache.openjpa.jdbc.sql.AccessDictionary.class.getName(), |
| "db2", org.apache.openjpa.jdbc.sql.DB2Dictionary.class.getName(), |
| "derby", org.apache.openjpa.jdbc.sql.DerbyDictionary.class.getName(), |
| "empress", org.apache.openjpa.jdbc.sql.EmpressDictionary.class.getName(), |
| "foxpro", org.apache.openjpa.jdbc.sql.FoxProDictionary.class.getName(), |
| "h2", org.apache.openjpa.jdbc.sql.H2Dictionary.class.getName(), |
| "hsql", org.apache.openjpa.jdbc.sql.HSQLDictionary.class.getName(), |
| "informix", org.apache.openjpa.jdbc.sql.InformixDictionary.class.getName(), |
| "ingres", org.apache.openjpa.jdbc.sql.IngresDictionary.class.getName(), |
| "jdatastore", org.apache.openjpa.jdbc.sql.JDataStoreDictionary.class.getName(), |
| "mariadb", org.apache.openjpa.jdbc.sql.MariaDBDictionary.class.getName(), |
| "mysql", org.apache.openjpa.jdbc.sql.MySQLDictionary.class.getName(), |
| "oracle", org.apache.openjpa.jdbc.sql.OracleDictionary.class.getName(), |
| "pointbase", org.apache.openjpa.jdbc.sql.PointbaseDictionary.class.getName(), |
| "postgres", org.apache.openjpa.jdbc.sql.PostgresDictionary.class.getName(), |
| "soliddb", org.apache.openjpa.jdbc.sql.SolidDBDictionary.class.getName(), |
| "sqlserver", org.apache.openjpa.jdbc.sql.SQLServerDictionary.class.getName(), |
| "sybase", org.apache.openjpa.jdbc.sql.SybaseDictionary.class.getName(), |
| "maxdb", MaxDBDictionary.class.getName(), |
| }; |
| dbdictionaryPlugin.setAliases(aliases); |
| dbdictionaryPlugin.setInstantiatingGetter("getDBDictionaryInstance"); |
| |
| updateManagerPlugin = addPlugin("jdbc.UpdateManager", true); |
| aliases = new String[]{ |
| "default", |
| BatchingConstraintUpdateManager.class.getName(), |
| "operation-order", |
| "org.apache.openjpa.jdbc.kernel.OperationOrderUpdateManager", |
| "constraint", |
| "org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager", |
| "batching-constraint", |
| BatchingConstraintUpdateManager.class.getName(), |
| "batching-operation-order", |
| BatchingOperationOrderUpdateManager.class.getName(), |
| }; |
| updateManagerPlugin.setAliases(aliases); |
| updateManagerPlugin.setDefault(aliases[0]); |
| updateManagerPlugin.setString(aliases[0]); |
| updateManagerPlugin.setInstantiatingGetter("getUpdateManagerInstance"); |
| |
| driverDataSourcePlugin = addPlugin("jdbc.DriverDataSource", false); |
| aliases = new String[]{ |
| "simple", "org.apache.openjpa.jdbc.schema.SimpleDriverDataSource", |
| "dbcp", "org.apache.commons.dbcp2.BasicDataSource" |
| }; |
| driverDataSourcePlugin.setAliases(aliases); |
| driverDataSourcePlugin.setDefault(aliases[0]); |
| driverDataSourcePlugin.setString(aliases[0]); |
| |
| schemaFactoryPlugin = addPlugin("jdbc.SchemaFactory", true); |
| aliases = new String[]{ |
| "dynamic", "org.apache.openjpa.jdbc.schema.DynamicSchemaFactory", |
| "native", "org.apache.openjpa.jdbc.schema.LazySchemaFactory", |
| "file", "org.apache.openjpa.jdbc.schema.FileSchemaFactory", |
| "table", "org.apache.openjpa.jdbc.schema.TableSchemaFactory", |
| // deprecated alias |
| "db", "org.apache.openjpa.jdbc.schema.TableSchemaFactory", |
| }; |
| schemaFactoryPlugin.setAliases(aliases); |
| schemaFactoryPlugin.setDefault(aliases[0]); |
| schemaFactoryPlugin.setString(aliases[0]); |
| schemaFactoryPlugin.setInstantiatingGetter("getSchemaFactoryInstance"); |
| |
| sqlFactoryPlugin = addPlugin("jdbc.SQLFactory", true); |
| aliases = new String[]{ |
| "default", "org.apache.openjpa.jdbc.sql.SQLFactoryImpl", |
| }; |
| sqlFactoryPlugin.setAliases(aliases); |
| sqlFactoryPlugin.setDefault(aliases[0]); |
| sqlFactoryPlugin.setString(aliases[0]); |
| sqlFactoryPlugin.setInstantiatingGetter("getSQLFactoryInstance"); |
| |
| mappingFactoryPlugin = new MappingFactoryValue("jdbc.MappingFactory"); |
| addValue(mappingFactoryPlugin); |
| |
| mappingDefaultsPlugin = addPlugin("jdbc.MappingDefaults", true); |
| aliases = new String[]{ |
| "default", "org.apache.openjpa.jdbc.meta.MappingDefaultsImpl", |
| }; |
| mappingDefaultsPlugin.setAliases(aliases); |
| mappingDefaultsPlugin.setDefault(aliases[0]); |
| mappingDefaultsPlugin.setString(aliases[0]); |
| mappingDefaultsPlugin.setInstantiatingGetter |
| ("getMappingDefaultsInstance"); |
| |
| // set up broker factory defaults |
| brokerFactoryPlugin.setAlias("jdbc", JDBCBrokerFactory.class.getName()); |
| brokerFactoryPlugin.setDefault("jdbc"); |
| brokerFactoryPlugin.setString("jdbc"); |
| |
| // set new default for mapping repos |
| metaRepositoryPlugin.setAlias("default", |
| "org.apache.openjpa.jdbc.meta.MappingRepository"); |
| metaRepositoryPlugin.setDefault("default"); |
| metaRepositoryPlugin.setString("default"); |
| |
| // set new default for lock manager |
| lockManagerPlugin.setAlias("pessimistic", |
| PessimisticLockManager.class.getName()); |
| lockManagerPlugin.setDefault("pessimistic"); |
| lockManagerPlugin.setString("pessimistic"); |
| |
| // native savepoint manager options |
| savepointManagerPlugin.setAlias("jdbc", |
| "org.apache.openjpa.jdbc.kernel.JDBC3SavepointManager"); |
| |
| // set new aliases and defaults for sequence |
| seqPlugin.setAliases(JDBCSeqValue.ALIASES); |
| seqPlugin.setDefault(JDBCSeqValue.ALIASES[0]); |
| seqPlugin.setString(JDBCSeqValue.ALIASES[0]); |
| |
| // This plug-in is declared in superclass but defined here |
| // because PreparedQueryCache is currently available for JDBC |
| // backend only |
| preparedQueryCachePlugin = addPlugin("jdbc.QuerySQLCache", true); |
| aliases = new String[] { |
| "true", "org.apache.openjpa.jdbc.kernel.PreparedQueryCacheImpl", |
| "false", null |
| }; |
| preparedQueryCachePlugin.setAliases(aliases); |
| preparedQueryCachePlugin.setAliasListComprehensive(true); |
| preparedQueryCachePlugin.setDefault(aliases[0]); |
| preparedQueryCachePlugin.setClassName(aliases[1]); |
| preparedQueryCachePlugin.setDynamic(true); |
| preparedQueryCachePlugin.setInstantiatingGetter( |
| "getQuerySQLCacheInstance"); |
| |
| finderCachePlugin = addPlugin("jdbc.FinderCache", true); |
| aliases = new String[] { |
| "true", "org.apache.openjpa.jdbc.kernel.FinderCacheImpl", |
| "false", null |
| }; |
| finderCachePlugin.setAliases(aliases); |
| finderCachePlugin.setAliasListComprehensive(true); |
| finderCachePlugin.setDefault(aliases[0]); |
| finderCachePlugin.setClassName(aliases[1]); |
| finderCachePlugin.setDynamic(true); |
| finderCachePlugin.setInstantiatingGetter("getFinderCacheInstance"); |
| |
| identifierUtilPlugin = addPlugin("jdbc.IdentifierUtil", true); |
| aliases = new String[] { |
| "default", "org.apache.openjpa.jdbc.identifier.DBIdentifierUtilImpl" }; |
| identifierUtilPlugin.setAliases(aliases); |
| identifierUtilPlugin.setDefault(aliases[0]); |
| identifierUtilPlugin.setString(aliases[0]); |
| identifierUtilPlugin.setInstantiatingGetter("getIdentifierUtilInstance"); |
| |
| |
| // this static initializer is to get past a weird |
| // ClassCircularityError that happens only under IBM's |
| // JDK 1.3.1 on Linux from within the JRun ClassLoader; |
| // while exact causes are unknown, it is almost certainly |
| // a bug in JRun, and we can get around it by forcing |
| // Instruction.class to be loaded and initialized |
| // before TypedInstruction.class |
| try { serp.bytecode.lowlevel.Entry.class.getName(); } |
| catch (Throwable t) {} |
| try { serp.bytecode.Instruction.class.getName(); } |
| catch (Throwable t) {} |
| |
| supportedOptions().add(OPTION_QUERY_SQL); |
| supportedOptions().add(OPTION_JDBC_CONNECTION); |
| supportedOptions().remove(OPTION_VALUE_INCREMENT); |
| supportedOptions().remove(OPTION_NULL_CONTAINER); |
| |
| if (derivations) |
| ProductDerivations.beforeConfigurationLoad(this); |
| if (loadGlobals) |
| loadGlobals(); |
| } |
| |
| /** |
| * Copy constructor |
| */ |
| public JDBCConfigurationImpl(JDBCConfiguration conf) { |
| this(true, false); |
| if (conf != null) |
| fromProperties(conf.toProperties(false)); |
| } |
| |
| @Override |
| public void setSchema(String schema) { |
| this.schema.setString(schema); |
| } |
| |
| @Override |
| public String getSchema() { |
| return schema.getString(); |
| } |
| |
| @Override |
| public void setSchemas(String schemas) { |
| this.schemas.setString(schemas); |
| } |
| |
| @Override |
| public String getSchemas() { |
| return schemas.getString(); |
| } |
| |
| @Override |
| public void setSchemas(String[] schemas) { |
| this.schemas.set(schemas); |
| } |
| |
| @Override |
| public String[] getSchemasList() { |
| return schemas.get(); |
| } |
| |
| @Override |
| public void setTransactionIsolation(String transactionIsolation) { |
| this.transactionIsolation.setString(transactionIsolation); |
| } |
| |
| @Override |
| public String getTransactionIsolation() { |
| return transactionIsolation.getString(); |
| } |
| |
| @Override |
| public void setTransactionIsolation(int transactionIsolation) { |
| this.transactionIsolation.set(transactionIsolation); |
| } |
| |
| @Override |
| public int getTransactionIsolationConstant() { |
| return transactionIsolation.get(); |
| } |
| |
| @Override |
| public void setResultSetType(String resultSetType) { |
| this.resultSetType.setString(resultSetType); |
| } |
| |
| @Override |
| public String getResultSetType() { |
| return resultSetType.getString(); |
| } |
| |
| @Override |
| public void setResultSetType(int resultSetType) { |
| this.resultSetType.set(resultSetType); |
| } |
| |
| @Override |
| public int getResultSetTypeConstant() { |
| return resultSetType.get(); |
| } |
| |
| @Override |
| public void setFetchDirection(String fetchDirection) { |
| this.fetchDirection.setString(fetchDirection); |
| } |
| |
| @Override |
| public String getFetchDirection() { |
| return fetchDirection.getString(); |
| } |
| |
| @Override |
| public void setFetchDirection(int fetchDirection) { |
| this.fetchDirection.set(fetchDirection); |
| } |
| |
| @Override |
| public int getFetchDirectionConstant() { |
| return fetchDirection.get(); |
| } |
| |
| @Override |
| public void setEagerFetchMode(String eagerFetchMode) { |
| this.eagerFetchMode.setString(eagerFetchMode); |
| } |
| |
| @Override |
| public String getEagerFetchMode() { |
| return eagerFetchMode.getString(); |
| } |
| |
| @Override |
| public void setEagerFetchMode(int eagerFetchMode) { |
| this.eagerFetchMode.set(eagerFetchMode); |
| } |
| |
| @Override |
| public int getEagerFetchModeConstant() { |
| return eagerFetchMode.get(); |
| } |
| |
| @Override |
| public void setSubclassFetchMode(String subclassFetchMode) { |
| this.subclassFetchMode.setString(subclassFetchMode); |
| } |
| |
| @Override |
| public String getSubclassFetchMode() { |
| return subclassFetchMode.getString(); |
| } |
| |
| @Override |
| public void setSubclassFetchMode(int subclassFetchMode) { |
| this.subclassFetchMode.set(subclassFetchMode); |
| } |
| |
| @Override |
| public int getSubclassFetchModeConstant() { |
| return subclassFetchMode.get(); |
| } |
| |
| @Override |
| public void setLRSSize(String lrsSize) { |
| this.lrsSize.setString(lrsSize); |
| } |
| |
| @Override |
| public String getLRSSize() { |
| return lrsSize.getString(); |
| } |
| |
| @Override |
| public void setLRSSize(int lrsSize) { |
| this.lrsSize.set(lrsSize); |
| } |
| |
| @Override |
| public int getLRSSizeConstant() { |
| return lrsSize.get(); |
| } |
| |
| @Override |
| public void setSynchronizeMappings(String synchronizeMappings) { |
| this.synchronizeMappings.set(synchronizeMappings); |
| } |
| |
| @Override |
| public String getSynchronizeMappings() { |
| return synchronizeMappings.get(); |
| } |
| |
| @Override |
| public void setJDBCListeners(String jdbcListeners) { |
| jdbcListenerPlugins.setString(jdbcListeners); |
| } |
| |
| @Override |
| public String getJDBCListeners() { |
| return jdbcListenerPlugins.getString(); |
| } |
| |
| @Override |
| public void setJDBCListeners(JDBCListener[] listeners) { |
| jdbcListenerPlugins.set(listeners); |
| } |
| |
| @Override |
| public JDBCListener[] getJDBCListenerInstances() { |
| if (jdbcListenerPlugins.get() == null) |
| jdbcListenerPlugins.instantiate(JDBCListener.class, this); |
| return (JDBCListener[]) jdbcListenerPlugins.get(); |
| } |
| |
| @Override |
| public void setConnectionDecorators(String connectionDecorators) { |
| connectionDecoratorPlugins.setString(connectionDecorators); |
| } |
| |
| @Override |
| public String getConnectionDecorators() { |
| return connectionDecoratorPlugins.getString(); |
| } |
| |
| @Override |
| public void setConnectionDecorators(ConnectionDecorator[] decorators) { |
| connectionDecoratorPlugins.set(decorators); |
| } |
| |
| @Override |
| public ConnectionDecorator[] getConnectionDecoratorInstances() { |
| if (connectionDecoratorPlugins.get() == null) { |
| connectionDecoratorPlugins.instantiate |
| (ConnectionDecorator.class, this); |
| } |
| return (ConnectionDecorator[]) connectionDecoratorPlugins.get(); |
| } |
| |
| @Override |
| public void setDBDictionary(String dbdictionary) { |
| dbdictionaryPlugin.setString(dbdictionary); |
| } |
| |
| @Override |
| public String getDBDictionary() { |
| return dbdictionaryPlugin.getString(); |
| } |
| |
| @Override |
| public void setDBDictionary(DBDictionary dbdictionary) { |
| // we can't allow the dictionary to be set after the connection |
| // factory, due to initialization issues |
| if (connectionFactory.get() != null |
| || connectionFactory2.get() != null) |
| throw new IllegalStateException(); |
| |
| dbdictionaryPlugin.set(dbdictionary); |
| } |
| |
| @Override |
| public DBDictionary getDBDictionaryInstance() { |
| // lock on connection factory name, since getting the connection |
| // factory and getting the dictionary have to use the same locks to |
| // prevent deadlock since they call each other |
| DBDictionary dbdictionary = (DBDictionary) dbdictionaryPlugin.get(); |
| if (dbdictionary == null) { |
| String clsName = dbdictionaryPlugin.getClassName(); |
| String props = dbdictionaryPlugin.getProperties(); |
| if (!StringUtil.isEmpty(clsName)) { |
| dbdictionary = DBDictionaryFactory.newDBDictionary |
| (this, clsName, props); |
| } else { |
| // if the dictionary class isn't set, try to guess from |
| // connection URL and driver name |
| dbdictionary = DBDictionaryFactory.calculateDBDictionary |
| (this, getConnectionURL(), getConnectionDriverName(), |
| props); |
| |
| // if the url and driver name aren't enough, connect to |
| // the DB and use the connection metadata |
| if (dbdictionary == null) { |
| Log log = getLog(LOG_JDBC); |
| if (log.isTraceEnabled()) { |
| Localizer loc = Localizer.forPackage |
| (JDBCConfigurationImpl.class); |
| log.trace(loc.get("connecting-for-dictionary")); |
| } |
| |
| // use the base connection factory rather than the |
| // configured data source b/c the data source relies |
| // on passing the connection through the dictionary, |
| // resulting in infinite loops |
| DataSource ds = createConnectionFactory(); |
| dbdictionary = DBDictionaryFactory.newDBDictionary |
| (this, getDataSource(null, ds), props); |
| } |
| } |
| dbdictionaryPlugin.set(dbdictionary, true); |
| } |
| return dbdictionary; |
| } |
| |
| @Override |
| public void setUpdateManager(String updateManager) { |
| updateManagerPlugin.setString(updateManager); |
| } |
| |
| @Override |
| public String getUpdateManager() { |
| return updateManagerPlugin.getString(); |
| } |
| |
| @Override |
| public void setUpdateManager(UpdateManager updateManager) { |
| updateManagerPlugin.set(updateManager); |
| } |
| |
| @Override |
| public UpdateManager getUpdateManagerInstance() { |
| if (updateManagerPlugin.get() == null) |
| updateManagerPlugin.instantiate(UpdateManager.class, this); |
| return (UpdateManager) updateManagerPlugin.get(); |
| } |
| |
| @Override |
| public void setDriverDataSource(String driverDataSource) { |
| driverDataSourcePlugin.setString(driverDataSource); |
| } |
| |
| @Override |
| public String getDriverDataSource() { |
| return driverDataSourcePlugin.getString(); |
| } |
| |
| @Override |
| public DataSource newDriverDataSourceInstance() { |
| return (DataSource) driverDataSourcePlugin. |
| instantiate(DataSource.class, this); |
| } |
| |
| @Override |
| public void setSchemaFactory(String schemaFactory) { |
| schemaFactoryPlugin.setString(schemaFactory); |
| } |
| |
| @Override |
| public String getSchemaFactory() { |
| return schemaFactoryPlugin.getString(); |
| } |
| |
| @Override |
| public void setSchemaFactory(SchemaFactory schemaFactory) { |
| schemaFactoryPlugin.set(schemaFactory); |
| } |
| |
| @Override |
| public SchemaFactory getSchemaFactoryInstance() { |
| if (schemaFactoryPlugin.get() == null) |
| schemaFactoryPlugin.instantiate(SchemaFactory.class, this); |
| return (SchemaFactory) schemaFactoryPlugin.get(); |
| } |
| |
| @Override |
| public void setSQLFactory(String sqlFactory) { |
| sqlFactoryPlugin.setString(sqlFactory); |
| } |
| |
| @Override |
| public String getSQLFactory() { |
| return sqlFactoryPlugin.getString(); |
| } |
| |
| @Override |
| public void setSQLFactory(SQLFactory sqlFactory) { |
| sqlFactoryPlugin.set(sqlFactory); |
| } |
| |
| @Override |
| public SQLFactory getSQLFactoryInstance() { |
| if (sqlFactoryPlugin.get() == null) |
| sqlFactoryPlugin.instantiate(SQLFactory.class, this); |
| return (SQLFactory) sqlFactoryPlugin.get(); |
| } |
| |
| @Override |
| public String getMappingFactory() { |
| return mappingFactoryPlugin.getString(); |
| } |
| |
| @Override |
| public void setMappingFactory(String mapping) { |
| mappingFactoryPlugin.setString(mapping); |
| } |
| |
| @Override |
| public MetaDataFactory newMetaDataFactoryInstance() { |
| return mappingFactoryPlugin.instantiateMetaDataFactory(this, |
| metaFactoryPlugin, getMapping()); |
| } |
| |
| @Override |
| public void setMappingDefaults(String mapping) { |
| this.mappingDefaultsPlugin.setString(mapping); |
| } |
| |
| @Override |
| public String getMappingDefaults() { |
| return mappingDefaultsPlugin.getString(); |
| } |
| |
| @Override |
| public void setMappingDefaults(MappingDefaults mapping) { |
| mappingDefaultsPlugin.set(mapping); |
| } |
| |
| @Override |
| public MappingDefaults getMappingDefaultsInstance() { |
| if (mappingDefaultsPlugin.get() == null) |
| mappingDefaultsPlugin.instantiate(MappingDefaults.class, this); |
| return (MappingDefaults) mappingDefaultsPlugin.get(); |
| } |
| |
| @Override |
| public MappingRepository getMappingRepositoryInstance() { |
| return (MappingRepository) getMetaDataRepositoryInstance(); |
| } |
| |
| @Override |
| public MappingRepository newMappingRepositoryInstance() { |
| return (MappingRepository) newMetaDataRepositoryInstance(); |
| } |
| |
| @Override |
| public BrokerImpl newBrokerInstance(String user, String pass) { |
| BrokerImpl broker = super.newBrokerInstance(user, pass); |
| |
| // record first non-null broker user and pass in case no global settings |
| if (broker != null && user != null && firstUser == null) { |
| firstUser = user; |
| firstPass = pass; |
| } |
| return broker; |
| } |
| |
| @Override |
| public Object getConnectionFactory() { |
| // override to configure data source |
| if (dataSource == null) { |
| DecoratingDataSource ds = createConnectionFactory(); |
| dataSource = DataSourceFactory.installDBDictionary |
| (getDBDictionaryInstance(), ds, this, false); |
| } |
| return dataSource; |
| } |
| |
| @Override |
| public void setConnectionFactory(Object factory) { |
| // there's a lot of one-time initialization involved for |
| // connection factories, so ignore resets |
| if (factory == connectionFactory.get()) |
| return; |
| |
| // override to configure data source |
| if (factory != null) { |
| // need to ensure it is decorated before we set the dict |
| DecoratingDataSource ds = |
| setupConnectionFactory((DataSource) factory, false); |
| dataSource = DataSourceFactory.installDBDictionary |
| (getDBDictionaryInstance(), ds, this, false); |
| } else |
| connectionFactory.set(null); |
| } |
| |
| /** |
| * Ensure that the specified DataSource is decorated and set in the cache. |
| */ |
| private DecoratingDataSource setupConnectionFactory(DataSource ds, |
| boolean factory2) { |
| if (ds == null) |
| return null; |
| |
| DecoratingDataSource dds; |
| if (ds instanceof DecoratingDataSource) |
| dds = (DecoratingDataSource) ds; |
| else |
| dds = DataSourceFactory.decorateDataSource(ds, this, factory2); |
| |
| if (!factory2 && connectionFactory.get() != ds) |
| connectionFactory.set(dds, true); |
| else if (factory2 && connectionFactory2.get() != ds) |
| connectionFactory2.set(dds, true); |
| |
| return dds; |
| } |
| |
| @Override |
| public Object getConnectionFactory2() { |
| // override to configure data source |
| if (dataSource2 == null) { |
| // superclass will lookup from JNDI. |
| Object obj = super.getConnectionFactory2(); |
| DataSource ds = null; |
| if (obj != null) { |
| if (obj instanceof DataSource) |
| ds = (DataSource) obj; |
| else { |
| Log log = getLog(LOG_JDBC); |
| if (log.isTraceEnabled()) { |
| Localizer loc = Localizer.forPackage(JDBCConfigurationImpl.class); |
| log.trace(loc.get("unknown-datasource", getConnectionFactory2Name(), |
| obj.getClass().getName())); |
| } |
| } |
| } |
| |
| if (ds == null) { |
| // the driver name is always required, so if not specified, |
| // then no connection factory 2 |
| String driver = getConnection2DriverName(); |
| if (!StringUtil.isEmpty(driver)) |
| ds = DataSourceFactory.newDataSource(this, true); |
| } |
| if (ds != null) { |
| DecoratingDataSource dds = |
| setupConnectionFactory(ds, true); // before dict |
| dataSource2 = DataSourceFactory.installDBDictionary |
| (getDBDictionaryInstance(), dds, this, true); |
| } |
| } |
| return dataSource2; |
| } |
| |
| @Override |
| public void setConnectionFactory2(Object factory) { |
| if (factory == connectionFactory2.get()) |
| return; |
| |
| // override to configure data source |
| if (factory != null) { |
| // need to ensure it is decorated before we set the dict |
| DecoratingDataSource ds = setupConnectionFactory((DataSource) |
| factory, true); |
| dataSource2 = DataSourceFactory.installDBDictionary |
| (getDBDictionaryInstance(), ds, this, true); |
| } else |
| connectionFactory2.set(null); |
| } |
| |
| /** |
| * Create the connection factory if necessary. |
| */ |
| public DecoratingDataSource createConnectionFactory() { |
| DataSource ds = (DataSource) connectionFactory.get(); |
| Log log = getLog(LOG_JDBC); |
| if (ds != null) { |
| if (log.isTraceEnabled()) |
| log.trace("createConnectionFactory: DataSource:" + ds); |
| |
| return setupConnectionFactory(ds, false); |
| } |
| |
| if (log.isTraceEnabled()) |
| log.trace("createConnectionFactory: connectionFactory not created yet, attempt JNDI lookup..."); |
| |
| ds = (DataSource) super.getConnectionFactory(); // JNDI lookup |
| if (ds == null) { |
| if (log.isTraceEnabled()) |
| log.trace("createConnectionFactory: JNDI lookup failed, attempt DataSource properties..."); |
| ds = DataSourceFactory.newDataSource(this, false); |
| } |
| |
| if (log.isTraceEnabled()) |
| log.trace("createConnectionFactory: DataSource="+ds); |
| |
| return setupConnectionFactory(ds, false); |
| } |
| |
| @Override |
| public DataSource getDataSource(StoreContext ctx) { |
| Log log = getLog(LOG_RUNTIME); |
| DataSource ds = null; |
| |
| if(ctx != null && StringUtil.isNotEmpty(ctx.getConnectionFactoryName())) { |
| ds = getDataSource(ctx, (DataSource) ctx.getConnectionFactory()); |
| // fail fast if a cfName has been provided, but was not available in JNDI |
| if (ds == null) { |
| throw new UserException(_loc.get("invalid-datasource", ctx.getConnectionFactoryName())).setFatal(true); |
| } |
| if(! (ds instanceof DecoratingDataSource)) { |
| ds = DataSourceFactory.decorateDataSource(ds, this, false); |
| } |
| if (log.isTraceEnabled()) { |
| log.trace("Found datasource1: " + ds + " from StoreContext using jndiName: " |
| + ctx.getConnectionFactory2Name()); |
| } |
| return ds; |
| } |
| else { |
| ds = getDataSource(ctx, (DataSource) getConnectionFactory()); |
| if (log.isTraceEnabled()) { |
| log.trace("Found datasource1: " + ds + " from configuration. StoreContext: " + ctx ); |
| } |
| return ds; |
| } |
| } |
| |
| @Override |
| public DataSource getDataSource2(StoreContext ctx) { |
| Log log = getLog(LOG_RUNTIME); |
| DataSource ds = null; |
| |
| // Try to obtain from the StoreContext first. |
| if (ctx != null && StringUtil.isNotEmpty(ctx.getConnectionFactory2Name())) { |
| ds = (DataSource) ctx.getConnectionFactory2(); |
| if (ds == null) { |
| // fail fast. If the non-jta-data-source is configured on the context we want an immediate error. |
| throw new UserException(_loc.get("invalid-datasource", ctx.getConnectionFactory2Name())).setFatal(true); |
| } |
| if(! (ds instanceof DecoratingDataSource)) { |
| ds = DataSourceFactory.decorateDataSource(ds, this, false); |
| } |
| if (log.isTraceEnabled()) { |
| log.trace("Found datasource2: " + ds + " from StoreContext using jndiName: " |
| + ctx.getConnectionFactory2Name()); |
| } |
| return ds; |
| } |
| |
| // If not set on context or value from context is not available try cf2 from config |
| else{ |
| ds = (DataSource) getConnectionFactory2(); |
| if (log.isTraceEnabled()) { |
| log.trace("Found datasource 2: "+ ds + " from config. StoreContext: " + ctx); |
| } |
| } |
| |
| // fallback to cf1 / datasource1 |
| if (ds == null) { |
| if(log.isTraceEnabled()) { |
| log.trace("Trying datasource1"); |
| } |
| return getDataSource(ctx); |
| } |
| |
| // prefer the global connection 2 auth info if given |
| String user = getConnection2UserName(); |
| String pass = getConnection2Password(); |
| if (user == null && pass == null) { |
| // no global auth info; use the context if given, or the first |
| // context if not |
| if (ctx == null) { |
| user = firstUser; |
| pass = firstPass; |
| } else { |
| user = ctx.getConnectionUserName(); |
| pass = ctx.getConnectionPassword(); |
| } |
| } |
| return DataSourceFactory.defaultsDataSource(ds, user, pass); |
| } |
| |
| /** |
| * This version allows us to pass in which data source to wrap internally; |
| * useful during initialization before the connection factory is |
| * completely configured. |
| */ |
| private DataSource getDataSource(StoreContext ctx, DataSource ds) { |
| String user, pass; |
| if (ctx == null) { |
| // if no context, default to the global auth info, or the auth info |
| // of the first context if none |
| user = getConnectionUserName(); |
| if (user == null) |
| user = firstUser; |
| pass = getConnectionPassword(); |
| if (pass == null) |
| pass = firstPass; |
| } else { |
| // use the context's auth info |
| user = ctx.getConnectionUserName(); |
| pass = ctx.getConnectionPassword(); |
| } |
| return DataSourceFactory.defaultsDataSource(ds, user, pass); |
| } |
| |
| /** |
| * Free the data sources. |
| */ |
| @Override |
| protected void preClose() { |
| if (dataSource != null) { |
| getDBDictionaryInstance().closeDataSource(dataSource); |
| connectionFactory.set(null, true); // so super doesn't close it |
| } |
| if (dataSource2 != null) { |
| getDBDictionaryInstance().closeDataSource(dataSource); |
| connectionFactory2.set(null, true); // so super doesn't close it |
| } |
| super.preClose(); |
| } |
| |
| @Override |
| protected boolean isInvalidProperty(String propName) { |
| if (super.isInvalidProperty(propName)) |
| return true; |
| |
| // handle openjpa.jdbc.SomeMisspelledProperty, but not |
| // openjpa.someotherimplementation.SomeProperty |
| String[] prefixes = ProductDerivations.getConfigurationPrefixes(); |
| for (int i = 0; i < prefixes.length; i++) |
| if (propName.toLowerCase(Locale.ENGLISH).startsWith(prefixes[i] + ".jdbc")) |
| return true; |
| return false; |
| } |
| |
| @Override |
| public String getIdentifierUtil() { |
| return identifierUtilPlugin.getString(); |
| } |
| |
| @Override |
| public DBIdentifierUtil getIdentifierUtilInstance() { |
| if (identifierUtilPlugin.get() == null) |
| identifierUtilPlugin.instantiate(DBIdentifierUtil.class, this); |
| return (DBIdentifierUtil) identifierUtilPlugin.get(); |
| } |
| |
| @Override |
| public void setIdentifierUtil(DBIdentifierUtil util) { |
| identifierUtilPlugin.set(util); |
| } |
| |
| } |