001: /**********************************************************************
002: Copyright (c) 2004 Erik Bengtson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: 2004 Andy Jefferson - added MetaDataManager
017: 2006 Andy Jefferson - added ClassLoaderResolver
018: 2006 Andy Jefferson - added direct relation with StoreManager
019: ...
020: **********************************************************************/package org.jpox;
021:
022: import java.lang.reflect.Constructor;
023: import java.util.ArrayList;
024: import java.util.HashMap;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.Random;
028:
029: import org.jpox.ObjectManager.ObjectManagerListener;
030: import org.jpox.api.ApiAdapter;
031: import org.jpox.api.ApiAdapterFactory;
032: import org.jpox.exceptions.ClassNotResolvedException;
033: import org.jpox.exceptions.JPOXException;
034: import org.jpox.exceptions.JPOXUserException;
035: import org.jpox.jta.TransactionManagerFinder;
036: import org.jpox.management.ManagementManager;
037: import org.jpox.metadata.MetaDataManager;
038: import org.jpox.plugin.ConfigurationElement;
039: import org.jpox.plugin.Extension;
040: import org.jpox.plugin.PluginManager;
041: import org.jpox.store.StoreManager;
042: import org.jpox.store.query.QueryManager;
043: import org.jpox.transaction.JPOXTransactionException;
044: import org.jpox.transaction.TransactionManager;
045: import org.jpox.util.JPOXLogger;
046: import org.jpox.util.Localiser;
047: import org.jpox.util.StringUtils;
048:
049: /**
050: * Represents the context of an ObjectManagerFactory, holding state information and components that it needs
051: * to perform its task.
052: * <ul>
053: * <li><b>Lifecycle</b> - created by a PMF/EMF when constructed, and closed by the PMF/EMF when it closes</li>
054: * <li><b>Role</b> - maintains key components/resources required by a PMF/EMF during its lifetime</li>
055: * </ul>
056: *
057: * @version $Revision: 1.21 $
058: */
059: public class OMFContext {
060: /** Localisation of messages. */
061: protected static final Localiser LOCALISER = Localiser.getInstance(
062: "org.jpox.Localisation", ObjectManager.class
063: .getClassLoader());
064:
065: /** ImplementationCreator for any persistent interfaces. */
066: private ImplementationCreator ic;
067:
068: /** Flag for whetehr we have initialised the implementation creator. */
069: private boolean implementationCreatorInitialised = false;
070:
071: /** Manager for the datastore used by this PMF. */
072: private StoreManager storeMgr = null;
073:
074: /** MetaDataManager for handling the MetaData for this PMF. */
075: private MetaDataManager metaDataManager = null;
076:
077: /** Transaction Manager. */
078: private TransactionManager txManager = null;
079:
080: /** JTA Transaction Manager. TODO Maybe merge this with txManager above. */
081: private javax.transaction.TransactionManager jtaTxManager = null;
082:
083: /** The PersistenceConfiguration defining features of the persistence process. */
084: private final PersistenceConfiguration persistenceConfig;
085:
086: /** Manager for JMX features. */
087: private ManagementManager mgmtManager = null;
088:
089: /** Manager for Plug-ins. **/
090: private final PluginManager pluginManager;
091:
092: /** Manager for types and JavaTypeMappings **/
093: private final TypeManager typeManager;
094:
095: /** ApiAdapter to be used by the factory. **/
096: private ApiAdapter apiAdapter;
097:
098: /** Name of the API used by this factory. **/
099: private String apiName = "JDO";
100:
101: /** Map of the ClassLoaderResolver, keyed by the clr class and the primaryLoader name. */
102: private Map classLoaderResolverMap = new HashMap();
103:
104: /** Name of the class providing the ClassLoaderResolver. */
105: private String classLoaderResolverClassName = null;
106:
107: /** Class to use for datastore-identity. */
108: private Class datastoreIdentityClass = null;
109:
110: /** domain name for this JPOX configuration **/
111: private String domainName;
112:
113: /** instance name for this JPOX configuration **/
114: private String instanceName;
115:
116: /** ConnectionFactoryRegistry **/
117: private ConnectionFactoryRegistry connFactoryRegistry;
118:
119: /** ConnectionManager **/
120: private ConnectionManager connmgr;
121:
122: /** QueryManager **/
123: private QueryManager queryManager;
124:
125: private List objectManagerListeners = new ArrayList();
126:
127: /**
128: * Constructor for the context.
129: * @param persistenceConfig The persistence configuration
130: */
131: public OMFContext(PersistenceConfiguration persistenceConfig) {
132: this .persistenceConfig = persistenceConfig;
133:
134: // Use JDOClassLoaderResolver here since we need the plugin mechanism before being able to create our specified CLR
135: ClassLoaderResolver clr = new JDOClassLoaderResolver(this
136: .getClass().getClassLoader());
137: clr.registerUserClassLoader(persistenceConfig
138: .getPrimaryClassLoader());
139:
140: // Instantiate manager for the plugins
141: this .pluginManager = new PluginManager(this .persistenceConfig,
142: clr);
143: this .pluginManager.registerExtensionPoints();
144: this .pluginManager.registerExtensions();
145: this .pluginManager.resolveConstraints();
146:
147: // Initialise JPOX instance/domain names
148: this .domainName = this .persistenceConfig
149: .getPersistenceUnitName();
150: if (this .domainName == null) {
151: this .domainName = "jpox";
152: }
153: this .instanceName = "jpox-" + new Random().nextInt();
154:
155: // Initialise API in use
156: ApiAdapterFactory.getInstance().initializeApiAdapterExtensions(
157: getClassLoaderResolver(null), this .pluginManager);
158: apiAdapter = ApiAdapterFactory.getInstance().getApiAdapter(
159: apiName);
160:
161: // Initialise type support
162: this .typeManager = new TypeManager(apiAdapter,
163: this .pluginManager, getClassLoaderResolver(null));
164:
165: // Initialise API in use
166: ApiAdapterFactory.getInstance().initializeApiAdapterExtensions(
167: getClassLoaderResolver(null), this .pluginManager);
168: apiAdapter = ApiAdapterFactory.getInstance().getApiAdapter(
169: apiName);
170:
171: // Initialise Management system
172: mgmtManager = getManagement();
173:
174: txManager = new TransactionManager();
175: if (mgmtManager != null) {
176: txManager.registerMbean(getDomainName(), getInstanceName(),
177: getManagement().getManagementServer());
178: }
179:
180: // Initialise connection system
181: connFactoryRegistry = new ConnectionFactoryRegistry(this );
182:
183: queryManager = new QueryManager(this );
184: }
185:
186: /**
187: * Instance name for this JPOX instance
188: * @return Instance name
189: */
190: public String getInstanceName() {
191: return instanceName;
192: }
193:
194: /**
195: * Domain name for this JPOX configuration/instance
196: * @return Domain name
197: */
198: public String getDomainName() {
199: return domainName;
200: }
201:
202: /**
203: * Clear out resources
204: */
205: public synchronized void close() {
206: if (storeMgr != null) {
207: storeMgr.close();
208: storeMgr = null;
209: }
210:
211: if (metaDataManager != null) {
212: metaDataManager.close();
213: metaDataManager = null;
214: }
215:
216: if (mgmtManager != null) {
217: mgmtManager.close();
218: mgmtManager = null;
219: }
220:
221: classLoaderResolverMap.clear();
222: classLoaderResolverMap = null;
223: classLoaderResolverClassName = null;
224:
225: datastoreIdentityClass = null;
226: }
227:
228: /**
229: * Accessor for the class to use for datastore identity.
230: * @return Class for datastore-identity
231: */
232: public Class getDatastoreIdentityClass() {
233: if (datastoreIdentityClass == null) {
234: String dsidName = persistenceConfig
235: .getDatastoreIdentityClassName();
236: String datastoreIdentityClassName = pluginManager
237: .getAttributeValueForExtension(
238: "org.jpox.store_datastoreidentity", "name",
239: dsidName, "class-name");
240: if (datastoreIdentityClassName == null) {
241: // User has specified a datastore_identity plugin that has not registered
242: throw new JPOXUserException(LOCALISER.msg("002001",
243: dsidName)).setFatal();
244: }
245:
246: // Try to load the class
247: ClassLoaderResolver clr = getClassLoaderResolver(null);
248: try {
249: datastoreIdentityClass = clr.classForName(
250: datastoreIdentityClassName, OMFContext.class
251: .getClassLoader());
252: } catch (ClassNotResolvedException cnre) {
253: throw new JPOXUserException(LOCALISER.msg("002002",
254: dsidName, datastoreIdentityClassName))
255: .setFatal();
256: }
257: }
258: return datastoreIdentityClass;
259: }
260:
261: /**
262: * Accessor for the management manager (if required).
263: * If the user has set the persistence property "org.jpox.managedRuntime" to true then this will
264: * return a management manager.
265: * @return The management manager
266: */
267: public ManagementManager getManagement() {
268: if (mgmtManager == null
269: && persistenceConfig.getManagedRuntime() == Boolean.TRUE) {
270: // User requires managed runtime, and not yet present so create manager
271: mgmtManager = new ManagementManager(this );
272: }
273: return mgmtManager;
274: }
275:
276: /**
277: * Accessor for a ClassLoaderResolver to use in resolving classes.
278: * @param primaryLoader Loader to use as the primary loader.
279: * @return The ClassLoader resolver
280: */
281: public ClassLoaderResolver getClassLoaderResolver(
282: ClassLoader primaryLoader) {
283: // Commented out since it is possible to find the JDOClassLoaderResolver and then the users specified loader
284: // if (classLoaderResolverClassName == null)
285: // {
286: // See what the factory has been specified to use
287: String clrName = persistenceConfig.getClassLoaderResolverName();
288: classLoaderResolverClassName = pluginManager
289: .getAttributeValueForExtension(
290: "org.jpox.classloader_resolver", "name",
291: clrName, "class-name");
292: if (classLoaderResolverClassName == null) {
293: // User has specified a classloader_resolver plugin that has not registered
294: throw new JPOXUserException(LOCALISER
295: .msg("001001", clrName)).setFatal();
296: }
297: // }
298:
299: // Set the key we will refer to this loader by
300: String key = classLoaderResolverClassName;
301: if (primaryLoader != null) {
302: key += ":[" + StringUtils.toJVMIDString(primaryLoader)
303: + "]";
304: }
305:
306: // See if we have the loader cached
307: ClassLoaderResolver clr = (ClassLoaderResolver) classLoaderResolverMap
308: .get(key);
309: if (clr == null) {
310: // Create the ClassLoaderResolver of this type with this primary loader
311: try {
312: Class cls = Class.forName(classLoaderResolverClassName);
313: Class[] ctrArgs = null;
314: Object[] ctrParams = null;
315: if (primaryLoader != null) {
316: ctrArgs = new Class[] { ClassLoader.class };
317: ctrParams = new Object[] { primaryLoader };
318: }
319: Constructor ctor = cls.getConstructor(ctrArgs);
320: clr = (ClassLoaderResolver) ctor.newInstance(ctrParams);
321: clr.registerUserClassLoader(persistenceConfig
322: .getPrimaryClassLoader());
323: } catch (ClassNotFoundException cnfe) {
324: throw new JPOXUserException(LOCALISER.msg("001002",
325: classLoaderResolverClassName), cnfe).setFatal();
326: } catch (Exception e) {
327: throw new JPOXUserException(LOCALISER.msg("001003",
328: classLoaderResolverClassName), e).setFatal();
329: }
330: classLoaderResolverMap.put(key, clr);
331: }
332:
333: return clr;
334: }
335:
336: /**
337: * Accessor for the implementation creator for this context.
338: * @return The implementation creator
339: */
340: public ImplementationCreator getImplementationCreator() {
341: if (!implementationCreatorInitialised) {
342: // Create if not already present
343: try {
344: Class cls = null;
345:
346: String implCreatorName = persistenceConfig
347: .getImplementationCreatorName();
348: ConfigurationElement elem = getPluginManager()
349: .getConfigurationElementForExtension(
350: "org.jpox.implementation_creator",
351: "name", implCreatorName);
352: if (elem != null) {
353: try {
354: cls = Class.forName(elem
355: .getAttribute("class-name"), true,
356: ObjectManagerFactoryImpl.class
357: .getClassLoader());
358: ic = (ImplementationCreator) cls.newInstance();
359: } catch (Exception e) {
360: // Creator not found
361: JPOXLogger.PERSISTENCE
362: .info(LOCALISER
363: .msg(
364: "008006",
365: persistenceConfig
366: .getImplementationCreatorName()));
367: }
368: }
369: if (ic == null) {
370: // Selection not found so find the first available
371: Extension[] exts = getPluginManager()
372: .getExtensionPoint(
373: "org.jpox.implementation_creator")
374: .getExtensions();
375: for (int i = 0; ic == null && i < exts.length; i++) {
376: for (int j = 0; ic == null
377: && j < exts[i]
378: .getConfigurationElements().length; j++) {
379: cls = Class.forName(exts[i]
380: .getConfigurationElements()[j]
381: .getAttribute("class-name"), true,
382: ObjectManagerFactoryImpl.class
383: .getClassLoader());
384: ic = (ImplementationCreator) cls
385: .newInstance();
386: if (ic != null) {
387: // Found one that is present so use it
388: break;
389: }
390: }
391: }
392: }
393: if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
394: if (ic == null) {
395: JPOXLogger.PERSISTENCE.debug(LOCALISER
396: .msg("008007"));
397: } else {
398: JPOXLogger.PERSISTENCE.debug(LOCALISER.msg(
399: "008008", cls.getName()));
400: }
401: }
402: } catch (InstantiationException e) {
403: throw new JPOXException(e.toString(), e).setFatal();
404: } catch (IllegalAccessException e) {
405: throw new JPOXException(e.toString(), e).setFatal();
406: } catch (ClassNotFoundException e) {
407: // Implementation creator not present maybe
408: JPOXLogger.PERSISTENCE.warn(LOCALISER.msg("008006",
409: persistenceConfig
410: .getImplementationCreatorName()));
411: ic = null;
412: } catch (NoClassDefFoundError e) {
413: // Dependency (of implementation creator) not present maybe
414: JPOXLogger.PERSISTENCE.warn(LOCALISER.msg("008006",
415: persistenceConfig
416: .getImplementationCreatorName()));
417: ic = null;
418: }
419: }
420: implementationCreatorInitialised = true;
421: return ic;
422: }
423:
424: /**
425: * Accessor for the Meta-Data Manager.
426: * @return Returns the MetaDataManager.
427: */
428: public synchronized MetaDataManager getMetaDataManager() {
429: if (metaDataManager == null) {
430: try {
431: metaDataManager = (MetaDataManager) getPluginManager()
432: .createExecutableExtension(
433: "org.jpox.metadata_manager",
434: new String[] { "name" },
435: new String[] { apiName }, "class",
436: new Class[] { OMFContext.class },
437: new Object[] { this });
438: } catch (Exception e) {
439: throw new JPOXException(LOCALISER.msg("008010",
440: apiName, e.getMessage()), e);
441: }
442: if (metaDataManager == null) {
443: throw new JPOXException(LOCALISER
444: .msg("008009", apiName));
445: }
446: }
447:
448: return metaDataManager;
449: }
450:
451: /**
452: * Accessor for the persistence onfiguration.
453: * @return Returns the persistence configuration.
454: */
455: public PersistenceConfiguration getPersistenceConfiguration() {
456: return persistenceConfig;
457: }
458:
459: /**
460: * Accessor for the Plugin Manager
461: * @return the PluginManager
462: */
463: public PluginManager getPluginManager() {
464: return pluginManager;
465: }
466:
467: /**
468: * Accessor for the Type Manager
469: * @return the TypeManager
470: */
471: public TypeManager getTypeManager() {
472: return typeManager;
473: }
474:
475: /**
476: * Accessor for the transaction manager.
477: * @return The transaction manager.
478: */
479: public TransactionManager getTransactionManager() {
480: return txManager;
481: }
482:
483: /**
484: * Accessor for the JTA transaction manager (if using JTA).
485: * @return the JTA Transaction Manager
486: */
487: public javax.transaction.TransactionManager getJtaTransactionManager() {
488: if (jtaTxManager == null) {
489: // Find the JTA transaction manager
490: // Before J2EE 5 there is no standard way to do this so use the finder process.
491: // See http://www.onjava.com/pub/a/onjava/2005/07/20/transactions.html
492: jtaTxManager = new TransactionManagerFinder(this )
493: .getTransactionManager(getClassLoaderResolver(persistenceConfig
494: .getPrimaryClassLoader()));
495: if (jtaTxManager == null) {
496: throw new JPOXTransactionException(LOCALISER
497: .msg("015030"));
498: }
499: }
500: return jtaTxManager;
501: }
502:
503: /**
504: * Accessor for the StoreManager
505: * @return the StoreManager
506: */
507: public StoreManager getStoreManager() {
508: return storeMgr;
509: }
510:
511: /**
512: * Mutator for the store manager.
513: * Can only be set once.
514: * @param storeMgr The store manager
515: */
516: public void setStoreManager(StoreManager storeMgr) {
517: if (this .storeMgr == null) {
518: this .storeMgr = storeMgr;
519: }
520: }
521:
522: /**
523: * Accessor for the ApiAdapter
524: * @return the ApiAdapter
525: */
526: public ApiAdapter getApiAdapter() {
527: return apiAdapter;
528: }
529:
530: /**
531: * Accessor for the API name
532: * @return the api
533: */
534: public String getApi() {
535: return apiName;
536: }
537:
538: /**
539: * Configure the API to be used
540: * @param name the API name
541: */
542: public void setApi(String name) {
543: this .apiName = name;
544: ApiAdapter adapter = ApiAdapterFactory.getInstance()
545: .getApiAdapter(name);
546: if (adapter != null) {
547: this .apiAdapter = adapter;
548: } else {
549: JPOXLogger.JDO.warn(LOCALISER.msg("008003", name));
550: }
551: }
552:
553: public ConnectionFactoryRegistry getConnectionFactoryRegistry() {
554: return connFactoryRegistry;
555: }
556:
557: public ConnectionManager getConnectionManager() {
558: return connmgr;
559: }
560:
561: public void setConnectionManager(ConnectionManager connmgr) {
562: this .connmgr = connmgr;
563: }
564:
565: /**
566: * Object the array of registered ObjectManagerListener's
567: * @return array of {@link ObjectManagerListener}
568: */
569: public ObjectManagerListener[] getObjectManagerListeners() {
570: return (ObjectManagerListener[]) objectManagerListeners
571: .toArray(new ObjectManagerListener[objectManagerListeners
572: .size()]);
573: }
574:
575: /**
576: * Register a new Listener for ObjectManager's events
577: * @param listener the listener to register
578: */
579: public void addObjectManagerListener(ObjectManagerListener listener) {
580: objectManagerListeners.add(listener);
581: }
582:
583: /**
584: * Unregister a Listener from ObjectManager's events
585: * @param listener the listener to unregister
586: */
587: public void removeObjectManagerListener(
588: ObjectManagerListener listener) {
589: objectManagerListeners.remove(listener);
590: }
591:
592: /**
593: * Accessor to the QueryManager
594: * @return the QueryManager
595: */
596: public QueryManager getQueryManager() {
597: return queryManager;
598: }
599: }
|