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