001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.jdbc.conf;
020:
021: import java.sql.Connection;
022: import java.sql.ResultSet;
023: import javax.sql.DataSource;
024:
025: import org.apache.commons.lang.StringUtils;
026: import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
027: import org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager;
028: import org.apache.openjpa.jdbc.kernel.BatchingOperationOrderUpdateManager;
029: import org.apache.openjpa.jdbc.kernel.EagerFetchModes;
030: import org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory;
031: import org.apache.openjpa.jdbc.kernel.LRSSizes;
032: import org.apache.openjpa.jdbc.kernel.PessimisticLockManager;
033: import org.apache.openjpa.jdbc.kernel.UpdateManager;
034: import org.apache.openjpa.jdbc.meta.MappingDefaults;
035: import org.apache.openjpa.jdbc.meta.MappingRepository;
036: import org.apache.openjpa.jdbc.schema.DataSourceFactory;
037: import org.apache.openjpa.jdbc.schema.DriverDataSource;
038: import org.apache.openjpa.jdbc.schema.SchemaFactory;
039: import org.apache.openjpa.jdbc.sql.DBDictionary;
040: import org.apache.openjpa.jdbc.sql.DBDictionaryFactory;
041: import org.apache.openjpa.jdbc.sql.SQLFactory;
042: import org.apache.openjpa.kernel.BrokerImpl;
043: import org.apache.openjpa.kernel.StoreContext;
044: import org.apache.openjpa.lib.conf.IntValue;
045: import org.apache.openjpa.lib.conf.ObjectValue;
046: import org.apache.openjpa.lib.conf.PluginValue;
047: import org.apache.openjpa.lib.conf.ProductDerivations;
048: import org.apache.openjpa.lib.conf.StringListValue;
049: import org.apache.openjpa.lib.conf.StringValue;
050: import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
051: import org.apache.openjpa.lib.jdbc.DecoratingDataSource;
052: import org.apache.openjpa.lib.jdbc.JDBCListener;
053: import org.apache.openjpa.lib.log.Log;
054: import org.apache.openjpa.lib.util.Localizer;
055: import org.apache.openjpa.meta.MetaDataFactory;
056:
057: /**
058: * Default implementation of the {@link JDBCConfiguration} interface.
059: *
060: * @author Marc Prud'hommeaux
061: * @author Abe White
062: */
063: public class JDBCConfigurationImpl extends OpenJPAConfigurationImpl
064: implements JDBCConfiguration {
065:
066: public StringValue schema;
067: public StringListValue schemas;
068: public IntValue transactionIsolation;
069: public IntValue resultSetType;
070: public IntValue fetchDirection;
071: public FetchModeValue eagerFetchMode;
072: public FetchModeValue subclassFetchMode;
073: public IntValue lrsSize;
074: public StringValue synchronizeMappings;
075: public ObjectValue jdbcListenerPlugins;
076: public ObjectValue connectionDecoratorPlugins;
077: public PluginValue dbdictionaryPlugin;
078: public ObjectValue updateManagerPlugin;
079: public ObjectValue schemaFactoryPlugin;
080: public ObjectValue sqlFactoryPlugin;
081: public ObjectValue mappingDefaultsPlugin;
082: public PluginValue driverDataSourcePlugin;
083: public MappingFactoryValue mappingFactoryPlugin;
084:
085: // used internally
086: private String firstUser = null;
087: private String firstPass = null;
088: private DecoratingDataSource dataSource = null;
089: private DecoratingDataSource dataSource2 = null;
090:
091: /**
092: * Default constructor. Attempts to load default properties.
093: */
094: public JDBCConfigurationImpl() {
095: this (true);
096: }
097:
098: /**
099: * Constructor.
100: *
101: * @param loadGlobals whether to attempt to load the global properties
102: */
103: public JDBCConfigurationImpl(boolean loadGlobals) {
104: this (true, loadGlobals);
105: }
106:
107: /**
108: * Constructor.
109: *
110: * @param derivations whether to apply product derivations
111: * @param loadGlobals whether to attempt to load the global properties
112: */
113: public JDBCConfigurationImpl(boolean derivations,
114: boolean loadGlobals) {
115: super (false, false);
116: String[] aliases;
117:
118: schema = addString("jdbc.Schema");
119: schemas = addStringList("jdbc.Schemas");
120:
121: transactionIsolation = addInt("jdbc.TransactionIsolation");
122: aliases = new String[] {
123: "default",
124: String.valueOf(-1),
125: "none",
126: String.valueOf(Connection.TRANSACTION_NONE),
127: "read-committed",
128: String.valueOf(Connection.TRANSACTION_READ_COMMITTED),
129: "read-uncommitted",
130: String.valueOf(Connection.TRANSACTION_READ_UNCOMMITTED),
131: "repeatable-read",
132: String.valueOf(Connection.TRANSACTION_REPEATABLE_READ),
133: "serializable",
134: String.valueOf(Connection.TRANSACTION_SERIALIZABLE) };
135: transactionIsolation.setAliases(aliases);
136: transactionIsolation.setDefault(aliases[0]);
137: transactionIsolation.set(-1);
138: transactionIsolation.setAliasListComprehensive(true);
139:
140: resultSetType = addInt("jdbc.ResultSetType");
141: aliases = new String[] { "forward-only",
142: String.valueOf(ResultSet.TYPE_FORWARD_ONLY),
143: "scroll-sensitive",
144: String.valueOf(ResultSet.TYPE_SCROLL_SENSITIVE),
145: "scroll-insensitive",
146: String.valueOf(ResultSet.TYPE_SCROLL_INSENSITIVE), };
147: resultSetType.setAliases(aliases);
148: resultSetType.setDefault(aliases[0]);
149: resultSetType.set(ResultSet.TYPE_FORWARD_ONLY);
150: resultSetType.setAliasListComprehensive(true);
151:
152: fetchDirection = addInt("jdbc.FetchDirection");
153: aliases = new String[] { "forward",
154: String.valueOf(ResultSet.FETCH_FORWARD), "reverse",
155: String.valueOf(ResultSet.FETCH_REVERSE), "unknown",
156: String.valueOf(ResultSet.FETCH_UNKNOWN), };
157: fetchDirection.setAliases(aliases);
158: fetchDirection.setDefault(aliases[0]);
159: fetchDirection.set(ResultSet.FETCH_FORWARD);
160: fetchDirection.setAliasListComprehensive(true);
161:
162: eagerFetchMode = new FetchModeValue("jdbc.EagerFetchMode");
163: eagerFetchMode.setDefault(FetchModeValue.EAGER_PARALLEL);
164: eagerFetchMode.set(EagerFetchModes.EAGER_PARALLEL);
165: addValue(eagerFetchMode);
166:
167: subclassFetchMode = new FetchModeValue("jdbc.SubclassFetchMode");
168: subclassFetchMode.setDefault(FetchModeValue.EAGER_JOIN);
169: subclassFetchMode.set(EagerFetchModes.EAGER_JOIN);
170: addValue(subclassFetchMode);
171:
172: lrsSize = addInt("jdbc.LRSSize");
173: aliases = new String[] { "query",
174: String.valueOf(LRSSizes.SIZE_QUERY), "unknown",
175: String.valueOf(LRSSizes.SIZE_UNKNOWN), "last",
176: String.valueOf(LRSSizes.SIZE_LAST), };
177: lrsSize.setAliases(aliases);
178: lrsSize.setDefault(aliases[0]);
179: lrsSize.set(LRSSizes.SIZE_QUERY);
180: lrsSize.setAliasListComprehensive(true);
181:
182: synchronizeMappings = addString("jdbc.SynchronizeMappings");
183: aliases = new String[] { "false", null };
184: synchronizeMappings.setAliases(aliases);
185: synchronizeMappings.setDefault(aliases[0]);
186:
187: jdbcListenerPlugins = addPluginList("jdbc.JDBCListeners");
188: jdbcListenerPlugins
189: .setInstantiatingGetter("getJDBCListenerInstances");
190:
191: connectionDecoratorPlugins = addPluginList("jdbc.ConnectionDecorators");
192: connectionDecoratorPlugins
193: .setInstantiatingGetter("getConnectionDecoratorInstances");
194:
195: dbdictionaryPlugin = addPlugin("jdbc.DBDictionary", true);
196: aliases = new String[] { "access",
197: "org.apache.openjpa.jdbc.sql.AccessDictionary", "db2",
198: "org.apache.openjpa.jdbc.sql.DB2Dictionary", "derby",
199: "org.apache.openjpa.jdbc.sql.DerbyDictionary",
200: "empress",
201: "org.apache.openjpa.jdbc.sql.EmpressDictionary",
202: "foxpro",
203: "org.apache.openjpa.jdbc.sql.FoxProDictionary", "h2",
204: "org.apache.openjpa.jdbc.sql.H2Dictionary", "hsql",
205: "org.apache.openjpa.jdbc.sql.HSQLDictionary",
206: "informix",
207: "org.apache.openjpa.jdbc.sql.InformixDictionary",
208: "jdatastore",
209: "org.apache.openjpa.jdbc.sql.JDataStoreDictionary",
210: "mysql", "org.apache.openjpa.jdbc.sql.MySQLDictionary",
211: "oracle",
212: "org.apache.openjpa.jdbc.sql.OracleDictionary",
213: "pointbase",
214: "org.apache.openjpa.jdbc.sql.PointbaseDictionary",
215: "postgres",
216: "org.apache.openjpa.jdbc.sql.PostgresDictionary",
217: "sqlserver",
218: "org.apache.openjpa.jdbc.sql.SQLServerDictionary",
219: "sybase",
220: "org.apache.openjpa.jdbc.sql.SybaseDictionary", };
221: dbdictionaryPlugin.setAliases(aliases);
222: dbdictionaryPlugin
223: .setInstantiatingGetter("getDBDictionaryInstance");
224:
225: updateManagerPlugin = addPlugin("jdbc.UpdateManager", true);
226: aliases = new String[] {
227: "default",
228: BatchingConstraintUpdateManager.class.getName(),
229: "operation-order",
230: "org.apache.openjpa.jdbc.kernel.OperationOrderUpdateManager",
231: "constraint",
232: "org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager",
233: "batching-constraint",
234: BatchingConstraintUpdateManager.class.getName(),
235: "batching-operation-order",
236: BatchingOperationOrderUpdateManager.class.getName(), };
237: updateManagerPlugin.setAliases(aliases);
238: updateManagerPlugin.setDefault(aliases[0]);
239: updateManagerPlugin.setString(aliases[0]);
240: updateManagerPlugin
241: .setInstantiatingGetter("getUpdateManagerInstance");
242:
243: driverDataSourcePlugin = addPlugin("jdbc.DriverDataSource",
244: false);
245: aliases = new String[] {
246: "simple",
247: "org.apache.openjpa.jdbc.schema.SimpleDriverDataSource", };
248: driverDataSourcePlugin.setAliases(aliases);
249: driverDataSourcePlugin.setDefault(aliases[0]);
250: driverDataSourcePlugin.setString(aliases[0]);
251:
252: schemaFactoryPlugin = addPlugin("jdbc.SchemaFactory", true);
253: aliases = new String[] { "dynamic",
254: "org.apache.openjpa.jdbc.schema.DynamicSchemaFactory",
255: "native",
256: "org.apache.openjpa.jdbc.schema.LazySchemaFactory",
257: "file",
258: "org.apache.openjpa.jdbc.schema.FileSchemaFactory",
259: "table",
260: "org.apache.openjpa.jdbc.schema.TableSchemaFactory",
261: // deprecated alias
262: "db",
263: "org.apache.openjpa.jdbc.schema.TableSchemaFactory", };
264: schemaFactoryPlugin.setAliases(aliases);
265: schemaFactoryPlugin.setDefault(aliases[0]);
266: schemaFactoryPlugin.setString(aliases[0]);
267: schemaFactoryPlugin
268: .setInstantiatingGetter("getSchemaFactoryInstance");
269:
270: sqlFactoryPlugin = addPlugin("jdbc.SQLFactory", true);
271: aliases = new String[] { "default",
272: "org.apache.openjpa.jdbc.sql.SQLFactoryImpl", };
273: sqlFactoryPlugin.setAliases(aliases);
274: sqlFactoryPlugin.setDefault(aliases[0]);
275: sqlFactoryPlugin.setString(aliases[0]);
276: sqlFactoryPlugin
277: .setInstantiatingGetter("getSQLFactoryInstance");
278:
279: mappingFactoryPlugin = new MappingFactoryValue(
280: "jdbc.MappingFactory");
281: addValue(mappingFactoryPlugin);
282:
283: mappingDefaultsPlugin = addPlugin("jdbc.MappingDefaults", true);
284: aliases = new String[] { "default",
285: "org.apache.openjpa.jdbc.meta.MappingDefaultsImpl", };
286: mappingDefaultsPlugin.setAliases(aliases);
287: mappingDefaultsPlugin.setDefault(aliases[0]);
288: mappingDefaultsPlugin.setString(aliases[0]);
289: mappingDefaultsPlugin
290: .setInstantiatingGetter("getMappingDefaultsInstance");
291:
292: // set up broker factory defaults
293: brokerFactoryPlugin.setAlias("jdbc", JDBCBrokerFactory.class
294: .getName());
295: brokerFactoryPlugin.setDefault("jdbc");
296: brokerFactoryPlugin.setString("jdbc");
297:
298: // set new default for mapping repos
299: metaRepositoryPlugin.setAlias("default",
300: "org.apache.openjpa.jdbc.meta.MappingRepository");
301: metaRepositoryPlugin.setDefault("default");
302: metaRepositoryPlugin.setString("default");
303:
304: // set new default for lock manager
305: lockManagerPlugin.setAlias("pessimistic",
306: PessimisticLockManager.class.getName());
307: lockManagerPlugin.setDefault("pessimistic");
308: lockManagerPlugin.setString("pessimistic");
309:
310: // native savepoint manager options
311: savepointManagerPlugin.setAlias("jdbc",
312: "org.apache.openjpa.jdbc.kernel.JDBC3SavepointManager");
313:
314: // set new aliases and defaults for sequence
315: seqPlugin.setAliases(JDBCSeqValue.ALIASES);
316: seqPlugin.setDefault(JDBCSeqValue.ALIASES[0]);
317: seqPlugin.setString(JDBCSeqValue.ALIASES[0]);
318:
319: // this static initializer is to get past a weird
320: // ClassCircularityError that happens only under IBM's
321: // JDK 1.3.1 on Linux from within the JRun ClassLoader;
322: // while exact causes are unknown, it is almost certainly
323: // a bug in JRun, and we can get around it by forcing
324: // Instruction.class to be loaded and initialized
325: // before TypedInstruction.class
326: try {
327: serp.bytecode.lowlevel.Entry.class.getName();
328: } catch (Throwable t) {
329: }
330: try {
331: serp.bytecode.Instruction.class.getName();
332: } catch (Throwable t) {
333: }
334:
335: supportedOptions().add(OPTION_QUERY_SQL);
336: supportedOptions().add(OPTION_JDBC_CONNECTION);
337: supportedOptions().remove(OPTION_VALUE_INCREMENT);
338: supportedOptions().remove(OPTION_NULL_CONTAINER);
339:
340: if (derivations)
341: ProductDerivations.beforeConfigurationLoad(this );
342: if (loadGlobals)
343: loadGlobals();
344: }
345:
346: /**
347: * Copy constructor
348: */
349: public JDBCConfigurationImpl(JDBCConfiguration conf) {
350: this (true, false);
351: if (conf != null)
352: fromProperties(conf.toProperties(false));
353: }
354:
355: public void setSchema(String schema) {
356: this .schema.setString(schema);
357: }
358:
359: public String getSchema() {
360: return schema.getString();
361: }
362:
363: public void setSchemas(String schemas) {
364: this .schemas.setString(schemas);
365: }
366:
367: public String getSchemas() {
368: return schemas.getString();
369: }
370:
371: public void setSchemas(String[] schemas) {
372: this .schemas.set(schemas);
373: }
374:
375: public String[] getSchemasList() {
376: return schemas.get();
377: }
378:
379: public void setTransactionIsolation(String transactionIsolation) {
380: this .transactionIsolation.setString(transactionIsolation);
381: }
382:
383: public String getTransactionIsolation() {
384: return transactionIsolation.getString();
385: }
386:
387: public void setTransactionIsolation(int transactionIsolation) {
388: this .transactionIsolation.set(transactionIsolation);
389: }
390:
391: public int getTransactionIsolationConstant() {
392: return transactionIsolation.get();
393: }
394:
395: public void setResultSetType(String resultSetType) {
396: this .resultSetType.setString(resultSetType);
397: }
398:
399: public String getResultSetType() {
400: return resultSetType.getString();
401: }
402:
403: public void setResultSetType(int resultSetType) {
404: this .resultSetType.set(resultSetType);
405: }
406:
407: public int getResultSetTypeConstant() {
408: return resultSetType.get();
409: }
410:
411: public void setFetchDirection(String fetchDirection) {
412: this .fetchDirection.setString(fetchDirection);
413: }
414:
415: public String getFetchDirection() {
416: return fetchDirection.getString();
417: }
418:
419: public void setFetchDirection(int fetchDirection) {
420: this .fetchDirection.set(fetchDirection);
421: }
422:
423: public int getFetchDirectionConstant() {
424: return fetchDirection.get();
425: }
426:
427: public void setEagerFetchMode(String eagerFetchMode) {
428: this .eagerFetchMode.setString(eagerFetchMode);
429: }
430:
431: public String getEagerFetchMode() {
432: return eagerFetchMode.getString();
433: }
434:
435: public void setEagerFetchMode(int eagerFetchMode) {
436: this .eagerFetchMode.set(eagerFetchMode);
437: }
438:
439: public int getEagerFetchModeConstant() {
440: return eagerFetchMode.get();
441: }
442:
443: public void setSubclassFetchMode(String subclassFetchMode) {
444: this .subclassFetchMode.setString(subclassFetchMode);
445: }
446:
447: public String getSubclassFetchMode() {
448: return subclassFetchMode.getString();
449: }
450:
451: public void setSubclassFetchMode(int subclassFetchMode) {
452: this .subclassFetchMode.set(subclassFetchMode);
453: }
454:
455: public int getSubclassFetchModeConstant() {
456: return subclassFetchMode.get();
457: }
458:
459: public void setLRSSize(String lrsSize) {
460: this .lrsSize.setString(lrsSize);
461: }
462:
463: public String getLRSSize() {
464: return lrsSize.getString();
465: }
466:
467: public void setLRSSize(int lrsSize) {
468: this .lrsSize.set(lrsSize);
469: }
470:
471: public int getLRSSizeConstant() {
472: return lrsSize.get();
473: }
474:
475: public void setSynchronizeMappings(String synchronizeMappings) {
476: this .synchronizeMappings.set(synchronizeMappings);
477: }
478:
479: public String getSynchronizeMappings() {
480: return synchronizeMappings.get();
481: }
482:
483: public void setJDBCListeners(String jdbcListeners) {
484: jdbcListenerPlugins.setString(jdbcListeners);
485: }
486:
487: public String getJDBCListeners() {
488: return jdbcListenerPlugins.getString();
489: }
490:
491: public void setJDBCListeners(JDBCListener[] listeners) {
492: jdbcListenerPlugins.set(listeners);
493: }
494:
495: public JDBCListener[] getJDBCListenerInstances() {
496: if (jdbcListenerPlugins.get() == null)
497: jdbcListenerPlugins.instantiate(JDBCListener.class, this );
498: return (JDBCListener[]) jdbcListenerPlugins.get();
499: }
500:
501: public void setConnectionDecorators(String connectionDecorators) {
502: connectionDecoratorPlugins.setString(connectionDecorators);
503: }
504:
505: public String getConnectionDecorators() {
506: return connectionDecoratorPlugins.getString();
507: }
508:
509: public void setConnectionDecorators(ConnectionDecorator[] decorators) {
510: connectionDecoratorPlugins.set(decorators);
511: }
512:
513: public ConnectionDecorator[] getConnectionDecoratorInstances() {
514: if (connectionDecoratorPlugins.get() == null) {
515: connectionDecoratorPlugins.instantiate(
516: ConnectionDecorator.class, this );
517: }
518: return (ConnectionDecorator[]) connectionDecoratorPlugins.get();
519: }
520:
521: public void setDBDictionary(String dbdictionary) {
522: dbdictionaryPlugin.setString(dbdictionary);
523: }
524:
525: public String getDBDictionary() {
526: return dbdictionaryPlugin.getString();
527: }
528:
529: public void setDBDictionary(DBDictionary dbdictionary) {
530: // we can't allow the dictionary to be set after the connection
531: // factory, due to initialization issues
532: if (connectionFactory.get() != null
533: || connectionFactory2.get() != null)
534: throw new IllegalStateException();
535:
536: dbdictionaryPlugin.set(dbdictionary);
537: }
538:
539: public DBDictionary getDBDictionaryInstance() {
540: // lock on connection factory name, since getting the connection
541: // factory and getting the dictionary have to use the same locks to
542: // prevent deadlock since they call each other
543: DBDictionary dbdictionary = (DBDictionary) dbdictionaryPlugin
544: .get();
545: if (dbdictionary == null) {
546: String clsName = dbdictionaryPlugin.getClassName();
547: String props = dbdictionaryPlugin.getProperties();
548: if (!StringUtils.isEmpty(clsName)) {
549: dbdictionary = DBDictionaryFactory.newDBDictionary(
550: this , clsName, props);
551: } else {
552: // if the dictionary class isn't set, try to guess from
553: // connection URL and driver name
554: dbdictionary = DBDictionaryFactory
555: .calculateDBDictionary(this ,
556: getConnectionURL(),
557: getConnectionDriverName(), props);
558:
559: // if the url and driver name aren't enough, connect to
560: // the DB and use the connection metadata
561: if (dbdictionary == null) {
562: Log log = getLog(LOG_JDBC);
563: if (log.isTraceEnabled()) {
564: Localizer loc = Localizer
565: .forPackage(JDBCConfigurationImpl.class);
566: log.trace(loc.get("connecting-for-dictionary"));
567: }
568:
569: // use the base connection factory rather than the
570: // configured data source b/c the data source relies
571: // on passing the connection through the dictionary,
572: // resulting in infinite loops
573: DataSource ds = createConnectionFactory();
574: dbdictionary = DBDictionaryFactory.newDBDictionary(
575: this , getDataSource(null, ds), props);
576: }
577: }
578: dbdictionaryPlugin.set(dbdictionary, true);
579: }
580: return dbdictionary;
581: }
582:
583: public void setUpdateManager(String updateManager) {
584: updateManagerPlugin.setString(updateManager);
585: }
586:
587: public String getUpdateManager() {
588: return updateManagerPlugin.getString();
589: }
590:
591: public void setUpdateManager(UpdateManager updateManager) {
592: updateManagerPlugin.set(updateManager);
593: }
594:
595: public UpdateManager getUpdateManagerInstance() {
596: if (updateManagerPlugin.get() == null)
597: updateManagerPlugin.instantiate(UpdateManager.class, this );
598: return (UpdateManager) updateManagerPlugin.get();
599: }
600:
601: public void setDriverDataSource(String driverDataSource) {
602: driverDataSourcePlugin.setString(driverDataSource);
603: }
604:
605: public String getDriverDataSource() {
606: return driverDataSourcePlugin.getString();
607: }
608:
609: public DriverDataSource newDriverDataSourceInstance() {
610: return (DriverDataSource) driverDataSourcePlugin.instantiate(
611: DriverDataSource.class, this );
612: }
613:
614: public void setSchemaFactory(String schemaFactory) {
615: schemaFactoryPlugin.setString(schemaFactory);
616: }
617:
618: public String getSchemaFactory() {
619: return schemaFactoryPlugin.getString();
620: }
621:
622: public void setSchemaFactory(SchemaFactory schemaFactory) {
623: schemaFactoryPlugin.set(schemaFactory);
624: }
625:
626: public SchemaFactory getSchemaFactoryInstance() {
627: if (schemaFactoryPlugin.get() == null)
628: schemaFactoryPlugin.instantiate(SchemaFactory.class, this );
629: return (SchemaFactory) schemaFactoryPlugin.get();
630: }
631:
632: public void setSQLFactory(String sqlFactory) {
633: sqlFactoryPlugin.setString(sqlFactory);
634: }
635:
636: public String getSQLFactory() {
637: return sqlFactoryPlugin.getString();
638: }
639:
640: public void setSQLFactory(SQLFactory sqlFactory) {
641: sqlFactoryPlugin.set(sqlFactory);
642: }
643:
644: public SQLFactory getSQLFactoryInstance() {
645: if (sqlFactoryPlugin.get() == null)
646: sqlFactoryPlugin.instantiate(SQLFactory.class, this );
647: return (SQLFactory) sqlFactoryPlugin.get();
648: }
649:
650: public String getMappingFactory() {
651: return mappingFactoryPlugin.getString();
652: }
653:
654: public void setMappingFactory(String mapping) {
655: mappingFactoryPlugin.setString(mapping);
656: }
657:
658: public MetaDataFactory newMetaDataFactoryInstance() {
659: return mappingFactoryPlugin.instantiateMetaDataFactory(this ,
660: metaFactoryPlugin, getMapping());
661: }
662:
663: public void setMappingDefaults(String mapping) {
664: this .mappingDefaultsPlugin.setString(mapping);
665: }
666:
667: public String getMappingDefaults() {
668: return mappingDefaultsPlugin.getString();
669: }
670:
671: public void setMappingDefaults(MappingDefaults mapping) {
672: mappingDefaultsPlugin.set(mapping);
673: }
674:
675: public MappingDefaults getMappingDefaultsInstance() {
676: if (mappingDefaultsPlugin.get() == null)
677: mappingDefaultsPlugin.instantiate(MappingDefaults.class,
678: this );
679: return (MappingDefaults) mappingDefaultsPlugin.get();
680: }
681:
682: public MappingRepository getMappingRepositoryInstance() {
683: return (MappingRepository) getMetaDataRepositoryInstance();
684: }
685:
686: public MappingRepository newMappingRepositoryInstance() {
687: return (MappingRepository) newMetaDataRepositoryInstance();
688: }
689:
690: public BrokerImpl newBrokerInstance(String user, String pass) {
691: BrokerImpl broker = super .newBrokerInstance(user, pass);
692:
693: // record first non-null broker user and pass in case no global settings
694: if (broker != null && user != null && firstUser == null) {
695: firstUser = user;
696: firstPass = pass;
697: }
698: return broker;
699: }
700:
701: public Object getConnectionFactory() {
702: // override to configure data source
703: if (dataSource == null) {
704: DecoratingDataSource ds = createConnectionFactory();
705: dataSource = DataSourceFactory.installDBDictionary(
706: getDBDictionaryInstance(), ds, this , false);
707: }
708: return dataSource;
709: }
710:
711: public void setConnectionFactory(Object factory) {
712: // there's a lot of one-time initialization involved for
713: // connection factories, so ignore resets
714: if (factory == connectionFactory.get())
715: return;
716:
717: // override to configure data source
718: if (factory != null) {
719: // need to ensure it is decorated before we set the dict
720: DecoratingDataSource ds = setupConnectionFactory(
721: (DataSource) factory, false);
722: dataSource = DataSourceFactory.installDBDictionary(
723: getDBDictionaryInstance(), ds, this , false);
724: } else
725: connectionFactory.set(null);
726: }
727:
728: /**
729: * Ensure that the specified DataSource is decorated and set in the cache.
730: */
731: private DecoratingDataSource setupConnectionFactory(DataSource ds,
732: boolean factory2) {
733: if (ds == null)
734: return null;
735:
736: DecoratingDataSource dds;
737: if (ds instanceof DecoratingDataSource)
738: dds = (DecoratingDataSource) ds;
739: else
740: dds = DataSourceFactory.decorateDataSource(ds, this ,
741: factory2);
742:
743: if (!factory2 && connectionFactory.get() != ds)
744: connectionFactory.set(dds, true);
745: else if (factory2 && connectionFactory2.get() != ds)
746: connectionFactory2.set(dds, true);
747:
748: return dds;
749: }
750:
751: public Object getConnectionFactory2() {
752: // override to configure data source
753: if (dataSource2 == null) {
754: // superclass will lookup from JNDI.
755: DataSource ds = (DataSource) super .getConnectionFactory2();
756: if (ds == null) {
757: // the driver name is always required, so if not specified,
758: // then no connection factory 2
759: String driver = getConnection2DriverName();
760: if (!StringUtils.isEmpty(driver))
761: ds = DataSourceFactory.newDataSource(this , true);
762: }
763: if (ds != null) {
764: DecoratingDataSource dds = setupConnectionFactory(ds,
765: true); // before dict
766: dataSource2 = DataSourceFactory.installDBDictionary(
767: getDBDictionaryInstance(), dds, this , true);
768: }
769: }
770: return dataSource2;
771: }
772:
773: public void setConnectionFactory2(Object factory) {
774: if (factory == connectionFactory2.get())
775: return;
776:
777: // override to configure data source
778: if (factory != null) {
779: // need to ensure it is decorated before we set the dict
780: DecoratingDataSource ds = setupConnectionFactory(
781: (DataSource) factory, true);
782: dataSource2 = DataSourceFactory.installDBDictionary(
783: getDBDictionaryInstance(), ds, this , true);
784: } else
785: connectionFactory2.set(null);
786: }
787:
788: /**
789: * Create the connection factory if necessary.
790: */
791: private DecoratingDataSource createConnectionFactory() {
792: DataSource ds = (DataSource) connectionFactory.get();
793: if (ds != null)
794: return setupConnectionFactory(ds, false);
795:
796: ds = (DataSource) super .getConnectionFactory(); // JNDI lookup
797: if (ds == null)
798: ds = DataSourceFactory.newDataSource(this , false);
799:
800: return setupConnectionFactory(ds, false);
801: }
802:
803: public DataSource getDataSource(StoreContext ctx) {
804: return getDataSource(ctx, (DataSource) getConnectionFactory());
805: }
806:
807: public DataSource getDataSource2(StoreContext ctx) {
808: // if there is no connection factory 2, use the primary factory
809: DataSource ds = (DataSource) getConnectionFactory2();
810: if (ds == null)
811: return getDataSource(ctx);
812:
813: // prefer the global connection 2 auth info if given
814: String user = getConnection2UserName();
815: String pass = getConnection2Password();
816: if (user == null && pass == null) {
817: // no global auth info; use the context if given, or the first
818: // context if not
819: if (ctx == null) {
820: user = firstUser;
821: pass = firstPass;
822: } else {
823: user = ctx.getConnectionUserName();
824: pass = ctx.getConnectionPassword();
825: }
826: }
827: return DataSourceFactory.defaultsDataSource(ds, user, pass);
828: }
829:
830: /**
831: * This version allows us to pass in which data source to wrap internally;
832: * useful during initialization before the connection factory is
833: * completely configured.
834: */
835: private DataSource getDataSource(StoreContext ctx, DataSource ds) {
836: String user, pass;
837: if (ctx == null) {
838: // if no context, default to the global auth info, or the auth info
839: // of the first context if none
840: user = getConnectionUserName();
841: if (user == null)
842: user = firstUser;
843: pass = getConnectionPassword();
844: if (pass == null)
845: pass = firstPass;
846: } else {
847: // use the context's auth info
848: user = ctx.getConnectionUserName();
849: pass = ctx.getConnectionPassword();
850: }
851: return DataSourceFactory.defaultsDataSource(ds, user, pass);
852: }
853:
854: /**
855: * Free the data sources.
856: */
857: protected void preClose() {
858: if (dataSource != null) {
859: getDBDictionaryInstance().closeDataSource(dataSource);
860: connectionFactory.set(null, true); // so super doesn't close it
861: }
862: if (dataSource2 != null) {
863: getDBDictionaryInstance().closeDataSource(dataSource);
864: connectionFactory2.set(null, true); // so super doesn't close it
865: }
866: super .preClose();
867: }
868:
869: protected boolean isInvalidProperty(String propName) {
870: if (super .isInvalidProperty(propName))
871: return true;
872:
873: // handle openjpa.jdbc.SomeMisspelledProperty, but not
874: // openjpa.someotherimplementation.SomeProperty
875: String[] prefixes = ProductDerivations
876: .getConfigurationPrefixes();
877: for (int i = 0; i < prefixes.length; i++)
878: if (propName.toLowerCase()
879: .startsWith(prefixes[i] + ".jdbc"))
880: return true;
881: return false;
882: }
883: }
|