/* * Copyright 2005 Werner Guttmann, Ralf Joachim * * Licensed 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.castor.jdo.engine; import java.util.Enumeration; import java.util.Properties; import javax.transaction.TransactionManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.castor.core.util.AbstractProperties; import org.castor.core.util.Messages; import org.castor.cpa.CPAProperties; import org.castor.cpa.persistence.sql.connection.ConnectionFactory; import org.castor.cpa.util.JDOClassDescriptorResolver; import org.castor.cpa.util.JDOClassDescriptorResolverImpl; import org.castor.jdo.conf.Database; import org.castor.jdo.conf.JdoConf; import org.castor.jdo.util.JDOConfAdapter; import org.castor.mapping.BindingType; import org.castor.mapping.MappingUnmarshaller; import org.castor.transactionmanager.TransactionManagerAcquireException; import org.castor.transactionmanager.TransactionManagerRegistry; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.mapping.MappingLoader; import org.exolab.castor.persist.LockEngine; import org.exolab.castor.persist.PersistenceEngineFactory; import org.exolab.castor.persist.PersistenceFactoryRegistry; import org.exolab.castor.persist.spi.PersistenceFactory; /** * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a> * @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a> * @version $Revision$ $Date: 2006-04-10 16:39:24 -0600 (Mon, 10 Apr 2006) $ * @since 0.9.9 */ public final class DatabaseContext { /** The name of the generic SQL engine, if no SQL engine specified. */ public static final String GENERIC_ENGINE = "generic"; /** The <a href="http://jakarta.apache.org/commons/logging/">Jakarta * Commons Logging</a> instance used for all logging. */ private static final Log LOG = LogFactory.getLog(DatabaseContext.class); /** Has the factory been initialized? */ private boolean _initialized = false; /** The JDO configuration. */ private JdoConf _jdoConf; /** Index of the database configuration in the jdo configuration. */ private int _index; /** The name of the database configuration. */ private String _name; /** The mapping to load. */ private Mapping _mapping; /** The transaction manager. */ private TransactionManager _txManager; /** The LockEngine only available after initialization. */ private LockEngine _engine = null; /** * A {@link ClassDescriptorResolver} instance to be used for class to * class descriptor resolution. */ private JDOClassDescriptorResolver _classDescriptorResolver = null; private ConnectionFactory _factory; /** * Constructs a new AbstractConnectionFactory with given name, engine and mapping. * Factory will be ready to use without calling initialize first. * * @param name The Name of the database configuration. * @param engine The Name of the persistence factory to use. * @param txManager The transaction manager to use. * @param mapping The previously loaded mapping. * @throws MappingException If LockEngine could not be initialized. */ protected DatabaseContext(final String name, final String engine, final Mapping mapping, final TransactionManager txManager, final ConnectionFactory factory) throws MappingException { _jdoConf = null; _index = -1; _name = name; _mapping = mapping; _txManager = txManager; _factory = factory; if (_classDescriptorResolver == null) { _classDescriptorResolver = new JDOClassDescriptorResolverImpl(); } initializeEngine(engine); _initialized = true; } /** * Constructs a new AbstractConnectionFactory with given database and mapping. * Initialize needs to be called before using the factory to create connections. * * @param jdoConf The JDO configuration. * @param index Index of the database configuration in the JDO configuration. * @param mapping The mapping to load. */ protected DatabaseContext(final JdoConf jdoConf, final int index, final Mapping mapping, final ConnectionFactory factory) { _jdoConf = jdoConf; _index = index; _name = jdoConf.getDatabase(index).getName(); _mapping = mapping; _txManager = null; _factory = factory; } /** * Initialize factory if it had not been initialized before. * * @throws MappingException If concrete factory or LockEngine fail to initialize * or mapping could not be loaded. */ public void initialize() throws MappingException { // If the factory was already initialized, ignore // this request to initialize it. if (!_initialized) { if (_classDescriptorResolver == null) { _classDescriptorResolver = new JDOClassDescriptorResolverImpl(); } initializeMapping(); JDOConfAdapter adapt = new JDOConfAdapter(_jdoConf); String name = adapt.getName(); String txm = adapt.getTransactionManager(); Properties prop = adapt.getTransactionManagerParameters(); AbstractProperties properties = CPAProperties.getInstance(); TransactionManagerRegistry txr = new TransactionManagerRegistry(properties); try { txr.registerTransactionManager(name, txm, prop); _txManager = txr.getTransactionManager(name); } catch (TransactionManagerAcquireException ex) { throw new MappingException(ex); } initializeEngine(_jdoConf.getDatabase(_index).getEngine()); initializeFactory(); _initialized = true; } } /** * Load mapping. * * @throws MappingException If mapping could not be loaded. */ private void initializeMapping() throws MappingException { try { // Initialize all the class mappings of the database. Enumeration<? extends org.castor.jdo.conf.ClassMapping> classMappings = _jdoConf.getDatabase(_index).enumerateClassMapping(); while (classMappings.hasMoreElements()) { org.castor.jdo.conf.ClassMapping classConf = classMappings.nextElement(); String className = classConf.getName(); _classDescriptorResolver.addClass(Class.forName(className)); } // Initialize all the package mappings of the database. Enumeration<? extends org.castor.jdo.conf.PackageMapping> packageMappings = _jdoConf.getDatabase(_index).enumeratePackageMapping(); while (packageMappings.hasMoreElements()) { org.castor.jdo.conf.PackageMapping packageConf = packageMappings.nextElement(); String packageName = packageConf.getName(); _classDescriptorResolver.addPackage(packageName); } // Initialize all the mappings of the database. Enumeration<? extends org.castor.jdo.conf.Mapping> mappings = _jdoConf.getDatabase(_index).enumerateMapping(); while (mappings.hasMoreElements()) { org.castor.jdo.conf.Mapping mapConf = mappings.nextElement(); if (LOG.isDebugEnabled()) { LOG.debug("Loading the mapping descriptor: " + mapConf.getHref()); } if (mapConf.getHref() != null) { _mapping.loadMapping(mapConf.getHref()); } } } catch (MappingException ex) { throw ex; } catch (Exception ex) { throw new MappingException(ex); } } /** * Initialize LockEngine. * * @param engine Name of the persistence factory to use. * @throws MappingException If LockEngine could not be initialized. */ private void initializeEngine(final String engine) throws MappingException { // Complain if no database engine was specified, otherwise get // a persistence factory for that database engine. PersistenceFactory factory; if (engine == null) { factory = PersistenceFactoryRegistry.getPersistenceFactory(GENERIC_ENGINE); } else { factory = PersistenceFactoryRegistry.getPersistenceFactory(engine); } if (factory == null) { String msg = Messages.format("jdo.noSuchEngine", engine); LOG.error(msg); throw new MappingException(msg); } MappingUnmarshaller mappingUnmarshaller = new MappingUnmarshaller(); MappingLoader mappingLoader = mappingUnmarshaller.getMappingLoader( _mapping, BindingType.JDO, factory); _classDescriptorResolver.setMappingLoader(mappingLoader); _engine = new PersistenceEngineFactory().createEngine( this, _classDescriptorResolver, factory); } public void initializeFactory() throws MappingException { _factory.initializeFactory(); } public ConnectionFactory getConnectionFactory() { return _factory; } /** * Get the name of the database configuration. * * @return The name of the database configuration. */ public String getName() { return _name; } /** * Get the database configuration. * * @return The database configuration. */ public Database getDatabase() { return _jdoConf.getDatabase(_index); } /** * Get the mapping to load. * * @return The mapping to load. */ public Mapping getMapping() { return _mapping; } /** * Get the transaction manager. * * @return The transaction manager. */ public TransactionManager getTransactionManager() { return _txManager; } /** * Get the LockEngine only available after initialization. * * @return The LockEngine. */ public LockEngine getEngine() { return _engine; } /** * Sets a custom {@link ClassDescriptorResolver} instance. * @param classDescriptorResolver A custom {@link ClassDescriptorResolver} instance to be used. */ public void setClassDescriptorResolver( final JDOClassDescriptorResolver classDescriptorResolver) { _classDescriptorResolver = classDescriptorResolver; } }