Package org.jpox.jdo

Source Code of org.jpox.jdo.AbstractPersistenceManagerFactory

/**********************************************************************
Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
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.

Contributors:
2002 Kelly Grizzle (TJDO)
2003 Erik Bengtson - refactored the persistent id generator System property
2003 Erik Bengtson - added PMFConfiguration, PMFContext
2003 Andy Jefferson - commented, and added ApplicationId to supported options
2003 Andy Jefferson - introduction of localiser
2004 Andy Jefferson - update to getProperties() method
2004 Andy Jefferson - added LifecycleListener
2004 Andy Jefferson - added Level 2 Cache
2005 Marco Schulze - implemented copying the lifecycle listeners in j2ee environment
    ...
**********************************************************************/
package org.jpox.jdo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.jdo.JDOFatalUserException;
import javax.jdo.JDOUserException;
import javax.jdo.datastore.DataStoreCache;
import javax.jdo.datastore.Sequence;
import javax.jdo.listener.InstanceLifecycleListener;
import javax.jdo.spi.JDOPermission;

import org.jpox.ClassLoaderResolver;
import org.jpox.ObjectManagerFactoryImpl;
import org.jpox.exceptions.JPOXException;
import org.jpox.properties.CorePropertyValidator;
import org.jpox.util.Localiser;

/**
* Factory used to obtain {@link javax.jdo.PersistenceManager} instances.
* The factory is configurable up to a point when it is frozen. Thereafter nothing can be changed.
*
* @version $Revision: 1.1 $
*/
public abstract class AbstractPersistenceManagerFactory extends ObjectManagerFactoryImpl
{
    /** Localisation utility for output messages from jdo. */
    protected static final Localiser LOCALISER_JDO = Localiser.getInstance("org.jpox.jdo.Localisation",
        AbstractPersistenceManagerFactory.class.getClassLoader());

    private static final String VERSION_NUMBER_PROPERTY = "VersionNumber";
    private static final String VENDOR_NAME_PROPERTY = "VendorName";

    /** The cache of PM's in use */
    private Set pmCache = new HashSet();

    /** Lifecycle Listeners */
    protected List lifecycleListeners;

    /** Map of user-defined sequences keyed by the factory class name. */
    private Map sequenceByFactoryClass;

    /** Level 2 Cache. */
    private DataStoreCache datastoreCache = null;

    /**
     * Constructor.
     */
    public AbstractPersistenceManagerFactory()
    {
        super();

        try
        {
            Class cls = javax.jdo.PersistenceManager.class;
            cls.getMethod("detachCopy",new Class[]{Object.class});
        }
        catch (SecurityException e)
        {
            throw new JDOFatalUserException(LOCALISER_JDO.msg("012003"));
        }
        catch (NoSuchMethodException e)
        {
            throw new JDOFatalUserException(LOCALISER_JDO.msg("012003"));
        }
    }

    /**
     * Freezes the current configuration.
     * @throws JPOXException if the configuration was invalid or inconsistent in some way
     */
    protected void freezeConfiguration()
    {
        if (configurable)
        {
            try
            {
                // Log the PMF configuration
                logConfiguration();

                // Set user classloader
                ClassLoaderResolver clr = getOMFContext().getClassLoaderResolver(null);
                clr.registerUserClassLoader((ClassLoader)getProperty("org.jpox.primaryClassLoader"));

                // Set up the StoreManager
                initialiseStoreManager(clr);

                // Set up the Level 2 Cache
                initialiseLevel2Cache();

                if (cache != null)
                {
                    datastoreCache = new JDODataStoreCache(cache);
                }

                configurable = false;
            }
            catch (JPOXException jpe)
            {
                throw JPOXJDOHelper.getJDOExceptionForJPOXException(jpe);
            }
        }
    }

    /**
     * Return non-configurable properties of this PersistenceManagerFactory.
     * Properties with keys VendorName and VersionNumber are required.  Other keys are optional.
     * @return the non-configurable properties of this PersistenceManagerFactory.
     */
    public Properties getProperties()
    {
        Properties props = new Properties();

        props.setProperty(VENDOR_NAME_PROPERTY, getVendorName());
        props.setProperty(VERSION_NUMBER_PROPERTY, getVersionNumber());

        return props;
    }

    /**
     * The application can determine from the results of this method which
     * optional features, and which query languages are supported by the JDO
     * implementation. Se esection 11.6 of the JDO 2 specification.
     * @return A Collection of String representing the supported options.
     */
    public Collection supportedOptions()
    {
        // TODO Update this to use StoreManager.getOptions so that if a datastore doesnt support
        // for example datastore identity then we return correctly here
        return Collections.unmodifiableList(Arrays.asList(OPTION_ARRAY));
    }

    /**
     * The JDO spec optional features that JPOX supports.
     * See JDO 2.0 spec section 11.6 for the full list of possibilities.
     **/
    private static final String[] OPTION_ARRAY =
    {
        "javax.jdo.option.TransientTransactional",
        "javax.jdo.option.NontransactionalWrite",
        "javax.jdo.option.NontransactionalRead",
        "javax.jdo.option.RetainValues",
        "javax.jdo.option.Optimistic",
        "javax.jdo.option.ApplicationIdentity",
        "javax.jdo.option.DatastoreIdentity",
        "javax.jdo.option.NonDurableIdentity",
        "javax.jdo.option.ArrayList",
        "javax.jdo.option.LinkedList",
        "javax.jdo.option.TreeSet",
        "javax.jdo.option.TreeMap",
        "javax.jdo.option.Vector",
        "javax.jdo.option.List",
        "javax.jdo.option.Stack", // Not a listed JDO2 feature
        "javax.jdo.option.Map", // Not a listed JDO2 feature
        "javax.jdo.option.HashMap", // Not a listed JDO2 feature
        "javax.jdo.option.Hashtable", // Not a listed JDO2 feature
        "javax.jdo.option.SortedSet", // Not a listed JDO2 feature
        "javax.jdo.option.SortedMap", // Not a listed JDO2 feature
        "javax.jdo.option.Array",
        "javax.jdo.option.NullCollection",
        // "javax.jdo.option.ChangeApplicationIdentity",
        "javax.jdo.option.BinaryCompatibility",
        "javax.jdo.option.GetDataStoreConnection",
        "javax.jdo.option.GetJDBCConnection",
        "javax.jdo.query.SQL",
        "javax.jdo.option.UnconstrainedQueryVariables",
        "javax.jdo.option.version.DateTime",
        "javax.jdo.option.PreDirtyEvent",
        "javax.jdo.option.mapping.HeterogeneousObjectType",
        "javax.jdo.option.mapping.HeterogeneousInterfaceType",
        "javax.jdo.option.mapping.JoinedTablePerClass",
        "javax.jdo.option.mapping.JoinedTablePerConcreteClass",
        "javax.jdo.option.mapping.NonJoinedTablePerConcreteClass",
        // "javax.jdo.option.mapping.RelationSubclassTable", // Not yet supported for multiple subclasses
        "javax.jdo.query.JDOQL", // Not a listed optional feature
        "javax.jdo.query.JPOXSQL"
    };

    /**
     * Return the Set of PersistenceManagers actually in cache
     * @return Set this contains instances of PersistenceManagers in the cache
     */
    protected Set getPmCache()
    {
        return pmCache;
    }

    /**
     * Remove a PersistenceManager from the cache
     * Only the PersistenceManager is allowed to call this method
     * @param om  the PersistenceManager to be removed from cache
     */
    public void releasePersistenceManager(AbstractPersistenceManager om)
    {
        getPmCache().remove(om);
    }

    /**
     * Asserts that the PMF is open.
     * @throws JDOUserException if it is already closed
     */
    protected void assertIsOpen()
    {
        try
        {
            super.assertIsOpen();
        }
        catch (JPOXException jpe)
        {
            // Comply with Section 11.4 of the JDO2 spec (throw JDOUserException if already closed)
            throw JPOXJDOHelper.getJDOExceptionForJPOXException(jpe);
        }
    }

    /**
     * Close this PersistenceManagerFactory. Check for JDOPermission("closePersistenceManagerFactory")
     * and if not authorized, throw SecurityException.
     * <P>If the authorization check succeeds, check to see that all PersistenceManager instances obtained
     * from this PersistenceManagerFactory have no active transactions. If any PersistenceManager instances
     * have an active transaction, throw a JDOUserException, with one nested JDOUserException for each
     * PersistenceManager with an active Transaction.
     * <P>If there are no active transactions, then close all PersistenceManager instances obtained from
     * this PersistenceManagerFactory, mark this PersistenceManagerFactory as closed, disallow
     * getPersistenceManager methods, and allow all other get methods. If a set method or getPersistenceManager
     * method is called after close, then JDOUserException is thrown.
     * @see javax.jdo.PersistenceManagerFactory#close()
     */
    public synchronized void close()
    {
        assertIsOpen();

        SecurityManager secmgr = System.getSecurityManager();
        if (secmgr != null)
        {
            // checkPermission will throw SecurityException if not authorized
            secmgr.checkPermission(JDOPermission.CLOSE_PERSISTENCE_MANAGER_FACTORY);
        }

        // iterate though the list of pms to release resources
        Iterator pms = new HashSet(getPmCache()).iterator();
        Set exceptions = new HashSet();
        while (pms.hasNext())
        {
            try
            {
                ((AbstractPersistenceManager)pms.next()).close();
            }
            catch (JDOUserException ex)
            {
                exceptions.add(ex);
            }
        }
        if (!exceptions.isEmpty())
        {
            throw new JDOUserException(LOCALISER_JDO.msg("012002"),(Throwable[])exceptions.toArray(new Throwable[exceptions.size()]));
        }

        // Let superclass close its resources
        super.close();
    }

    /**
     * Accessor for the DataStore (level 2) Cache
     * @return The datastore cache
     * @since 1.1
     */
    public DataStoreCache getDataStoreCache()
    {
        freezeConfiguration();

        return datastoreCache;
    }

    /**
     * Set the user name for the data store connection.
     * @param userName the user name for the data store connection.
     */
    public synchronized void setConnectionUserName(String userName)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionUserName", userName);
    }

    /**
     * Set the password for the data store connection.
     * @param password the password for the data store connection.
     */
    public synchronized void setConnectionPassword(String password)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionPassword", password);
    }

    /**
     * Set the URL for the data store connection.
     * @param url the URL for the data store connection.
     */
    public synchronized void setConnectionURL(String url)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionURL", url);
    }

    /**
     * Set the driver name for the data store connection.
     * @param driverName the driver name for the data store connection.
     */
    public synchronized void setConnectionDriverName(String driverName)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionDriverName", driverName);
    }

    /**
     * Set the name for the data store connection factory.
     * @param connectionFactoryName name of the data store connection factory.
     */
    public synchronized void setConnectionFactoryName(String connectionFactoryName)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionFactoryName", connectionFactoryName);
    }

    /**
     * Set the data store connection factory.  JDO implementations
     * will support specific connection factories.  The connection
     * factory interfaces are not part of the JDO specification.
     * @param connectionFactory the data store connection factory.
     */
    public synchronized void setConnectionFactory(Object connectionFactory)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionFactory", connectionFactory);
    }

    /**
     * Set the name for the second data store connection factory.  This is
     * needed for managed environments to get nontransactional connections for
     * optimistic transactions.
     * @param connectionFactoryName name of the data store connection factory.
     */
    public synchronized void setConnectionFactory2Name(String connectionFactoryName)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionFactory2Name", connectionFactoryName);
    }

    /**
     * Set the second data store connection factory.  This is
     * needed for managed environments to get nontransactional connections for
     * optimistic transactions.  JDO implementations
     * will support specific connection factories.  The connection
     * factory interfaces are not part of the JDO specification.
     * @param connectionFactory the data store connection factory.
     */
    public synchronized void setConnectionFactory2(Object connectionFactory)
    {
        assertConfigurable();
        setProperty("org.jpox.ConnectionFactory2", connectionFactory);
    }

    /**
     * Set the default Multithreaded setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @param flag the default Multithreaded setting.
     */
    public synchronized void setMultithreaded(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.Multithreaded", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the default Optimistic setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @param flag the default Optimistic setting.
     */
    public synchronized void setOptimistic(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.Optimistic", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the default RetainValues setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @param flag the default RetainValues setting.
     */
    public synchronized void setRetainValues(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.RetainValues", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the default RestoreValues setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @param flag the default RestoreValues setting.
     */
    public synchronized void setRestoreValues(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.RestoreValues", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the default NontransactionalRead setting for all
     * <tt>PersistenceManager</tt> instances obtained from this factory.
     * @param flag the default NontransactionalRead setting.
     */
    public synchronized void setNontransactionalRead(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.NontransactionalRead", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the default NontransactionalWrite setting for all
     * <tt>PersistenceManager</tt> instances obtained from this factory.
     * @param flag the default NontransactionalWrite setting.
     */
    public synchronized void setNontransactionalWrite(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.NontransactionalWrite", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the default IgnoreCache setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @param flag the default IgnoreCache setting.
     */
    public synchronized void setIgnoreCache(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.IgnoreCache", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Mutator for the DetachAllOnCommit setting.
     * @param flag the default DetachAllOnCommit setting.
     * @since 1.1
     */
    public synchronized void setDetachAllOnCommit(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.DetachAllOnCommit", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Mutator for the CopyOnAttach setting.
     * @param flag the default CopyOnAttach setting.
     * @since 1.2
     */
    public synchronized void setCopyOnAttach(boolean flag)
    {
        assertConfigurable();
        setProperty("org.jpox.CopyOnAttach", flag ? Boolean.TRUE : Boolean.FALSE);
    }

    /**
     * Set the name for any mapping, used in searching for ORM/Query metadata files.
     * @param mapping the mapping name
     */
    public synchronized void setMapping(String mapping)
    {
        assertConfigurable();
        setProperty("org.jpox.Mapping", mapping);
    }

    /**
     * Mutator for the catalog to use for this persistence factory.
     * @param catalog Name of the catalog
     * @since 1.1
     */
    public synchronized void setCatalog(String catalog)
    {
        assertConfigurable();
        setProperty("org.jpox.mapping.Catalog", catalog);
    }

    /**
     * Mutator for the schema to use for this persistence factory.
     * @param schema Name of the schema
     * @since 1.1
     */
    public synchronized void setSchema(String schema)
    {
        assertConfigurable();
        setProperty("org.jpox.mapping.Schema", schema);
    }

    /**
     * Mutator for the transaction type to use for this persistence factory.
     * @param type Transaction type
     */
    public synchronized void setTransactionType(String type)
    {
        assertConfigurable();
        boolean validated = new CorePropertyValidator().validate("org.jpox.TransactionType", type);
        if (validated)
        {
            setProperty("org.jpox.TransactionType", type);
        }
        else
        {
            throw new JDOUserException(LOCALISER.msg("008012", "javax.jdo.option.TransactionType", type));
        }
    }

    /**
     * Mutator for the name of the persistence unit.
     * @param name Name of the persistence unit
     */
    public synchronized void setPersistenceUnitName(String name)
    {
        assertConfigurable();
        setProperty("org.jpox.PersistenceUnitName", name);
    }

    /**
     * Mutator for the filename of the persistence.xml file.
     * @param name Filename of the persistence.xml file
     */
    public synchronized void setPersistenceXmlFilename(String name)
    {
        assertConfigurable();
        setProperty("org.jpox.persistenceXmlFilename", name);
    }

    /**
     * Mutator for the name of the persistence factory.
     * @param name Name of the persistence factory (if any)
     */
    public synchronized void setName(String name)
    {
        assertConfigurable();
        setProperty("org.jpox.Name", name);
    }

    /**
     * Mutator for the timezone id of the datastore server.
     * If not set assumes that it is running in the same timezone as this JVM.
     * @param id Timezone Id to use
     */
    public void setServerTimeZoneID(String id)
    {
        boolean validated = new CorePropertyValidator().validate("org.jpox.ServerTimeZoneID", id);
        if (validated)
        {
            setProperty("org.jpox.ServerTimeZoneID", id);
        }
        else
        {
            throw new JDOUserException("Invalid TimeZone ID specified");
        }
    }

    /**
     * Get the user name for the data store connection.
     * @return the user name for the data store connection.
     */
    public String getConnectionUserName()
    {
        return getStringProperty("org.jpox.ConnectionUserName");
    }

    /**
     * Get the password for the data store connection.
     * @return the password for the data store connection.
     */
    public String getConnectionPassword()
    {
        return getStringProperty("org.jpox.ConnectionPassword");
    }

    /**
     * Get the URL for the data store connection.
     * @return the URL for the data store connection.
     */
    public String getConnectionURL()
    {
        return getStringProperty("org.jpox.ConnectionURL");
    }

    /**
     * Get the driver name for the data store connection.
     * @return the driver name for the data store connection.
     */
    public String getConnectionDriverName()
    {
        return getStringProperty("org.jpox.ConnectionDriverName");
    }

    /**
     * Get the name for the data store connection factory.
     * @return the name of the data store connection factory.
     */
    public String getConnectionFactoryName()
    {
        return getStringProperty("org.jpox.ConnectionFactoryName");
    }

    /**
     * Get the name for the second data store connection factory.  This is
     * needed for managed environments to get nontransactional connections for
     * optimistic transactions.
     * @return the name of the data store connection factory.
     */
    public String getConnectionFactory2Name()
    {
        return getStringProperty("org.jpox.ConnectionFactory2Name");
    }

    /**
     * Get the data store connection factory.
     * @return the data store connection factory.
     */
    public Object getConnectionFactory()
    {
        return getProperty("org.jpox.ConnectionFactory");
    }

    /**
     * Get the second data store connection factory.  This is
     * needed for managed environments to get nontransactional connections for
     * optimistic transactions.
     * @return the data store connection factory.
     */
    public Object getConnectionFactory2()
    {
        return getProperty("org.jpox.ConnectionFactory2");
    }

    /**
     * Get the default Multithreaded setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @return the default Multithreaded setting.
     */
    public boolean getMultithreaded()
    {
        return getBooleanProperty("org.jpox.Multithreaded");
    }

    /**
     * Get the default Optimistic setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @return the default Optimistic setting.
     */
    public boolean getOptimistic()
    {
        return getBooleanProperty("org.jpox.Optimistic");
    }

    /**
     * Get the default RetainValues setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @return the default RetainValues setting.
     */
    public boolean getRetainValues()
    {
        return getBooleanProperty("org.jpox.RetainValues");
    }

    /**
     * Get the default RestoreValues setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @return the default RestoreValues setting.
     */
    public boolean getRestoreValues()
    {
        return getBooleanProperty("org.jpox.RestoreValues");
    }

    /**
     * Get the default NontransactionalRead setting for all
     * <tt>PersistenceManager</tt> instances obtained from this factory.
     * @return the default NontransactionalRead setting.
     */
    public boolean getNontransactionalRead()
    {
        return getBooleanProperty("org.jpox.NontransactionalRead");
    }

    /**
     * Get the default NontransactionalWrite setting for all
     * <tt>PersistenceManager</tt> instances obtained from this factory.
     * @return the default NontransactionalWrite setting.
     */
    public boolean getNontransactionalWrite()
    {
        return getBooleanProperty("org.jpox.NontransactionalWrite");
    }

    /**
     * Get the default IgnoreCache setting for all <tt>PersistenceManager</tt>
     * instances obtained from this factory.
     * @return the IgnoreCache setting.
     */
    public boolean getIgnoreCache()
    {
        return getBooleanProperty("org.jpox.IgnoreCache");
    }

    /**
     * Accessor for the DetachAllOnCommit setting.
     * @return the DetachAllOnCommit setting.
     */
    public boolean getDetachAllOnCommit()
    {
        return getBooleanProperty("org.jpox.DetachAllOnCommit");
    }

    /**
     * Accessor for the CopyOnAttach setting.
     * @return the CopyOnAttach setting.
     */
    public boolean getCopyOnAttach()
    {
        return getBooleanProperty("org.jpox.CopyOnAttach");
    }

    /**
     * Get the name for any mapping, used in retrieving metadata files for ORM/Query data.
     * @return the name for the mapping.
     */
    public String getMapping()
    {
        return getStringProperty("org.jpox.Mapping");
    }

    /**
     * Accessor for the catalog to use for this persistence factory.
     * @return the name of the catalog
     */
    public String getCatalog()
    {
        return getStringProperty("org.jpox.mapping.Catalog");
    }

    /**
     * Accessor for the schema to use for this persistence factory.
     * @return the name of the schema
     */
    public String getSchema()
    {
        return getStringProperty("org.jpox.mapping.Schema");
    }

    /**
     * Accessor for the name of the persistence factory (if any).
     * @return the name of the persistence factory
     */
    public String getName()
    {
        return getStringProperty("org.jpox.Name");
    }

    /**
     * Accessor for the name of the persistence unit
     * @return the name of the persistence unit
     */
    public String getPersistenceUnitName()
    {
        return getStringProperty("org.jpox.PersistenceUnitName");
    }

    /**
     * Accessor for the filename of the persistence.xml file
     * @return the filename of the persistence.xml file
     */
    public String getPersistenceXmlFilename()
    {
        return getStringProperty("org.jpox.persistenceXmlFilename");
    }

    /**
     * Accessor for the timezone "id" of the datastore server (if any).
     * If not set assumes the same as the JVM JPOX is running in.
     * @return Server timezone id
     */
    public String getServerTimeZoneID()
    {
        return getStringProperty("org.jpox.ServerTimeZoneID");
    }

    /**
     * Accessor for the transaction type to use with this persistence factory.
     * @return transaction type
     */
    public String getTransactionType()
    {
        return getStringProperty("org.jpox.TransactionType");
    }

    /**
     * Asserts that a change to a configuration property is allowed.
     */
    protected void assertConfigurable()
    {
        if (!configurable)
        {
            throw new JDOUserException(LOCALISER.msg("008016"));
        }
    }

    // -------------------------------- Lifecycle Listeners -------------------------------

    /**
     * @return Returns either <tt>null</tt> or a <tt>List</tt> with instances of
     *    <tt>LifecycleListenerSpecification</tt>.
     */
    public List getLifecycleListenerSpecifications()
    {
      return lifecycleListeners;
    }

    /**
     * Method to add lifecycle listeners for particular classes.
     * Adds the listener to all PMs already created.
     * @param listener The listener
     * @param classes The classes that the listener relates to
     * @since 1.1
     */
    public void addInstanceLifecycleListener(InstanceLifecycleListener listener, Class[] classes)
    {
        if (listener == null)
        {
            return;
        }

        synchronized (pmCache)
        {
            // Add to any PMs - make sure that the PM Cache isnt changed while doing so
            Iterator pms = getPmCache().iterator();
            while (pms.hasNext())
            {
                AbstractPersistenceManager pm = (AbstractPersistenceManager)pms.next();
                pm.addInstanceLifecycleListener(listener, classes);
            }
        }

        // Register the lifecycle listener
        if (lifecycleListeners == null)
        {
            lifecycleListeners = new ArrayList(5);
        }
        lifecycleListeners.add(new LifecycleListenerForClass(listener, classes));
    }

    /**
     * Method to remove a lifecycle listener. Removes the listener from all PM's as well.
     * @param listener The Listener
     * @since 1.1
     */
    public void removeInstanceLifecycleListener(InstanceLifecycleListener listener)
    {
        if (listener == null || lifecycleListeners == null)
        {
            return;
        }

        synchronized (pmCache)
        {
            // Remove from any PMs - make sure that the PM Cache isnt changed while doing so
            Iterator pms = getPmCache().iterator();
            while (pms.hasNext())
            {
                AbstractPersistenceManager pm = (AbstractPersistenceManager)pms.next();
                pm.removeInstanceLifecycleListener(listener);
            }
        }

        // Remove from the PMF
        Iterator iter = lifecycleListeners.iterator();
        while (iter.hasNext())
        {
            LifecycleListenerForClass classListener = (LifecycleListenerForClass) iter.next();
            if (classListener.getListener() == listener)
            {
                iter.remove();
            }
        }
    }

    // --------------------------- Sequences ----------------------------------

    /**
     * Method to register a sequence for a particular factory class.
     * @param factoryClassName Name of the factory class
     * @param sequence The sequence
     */
    public void addSequenceForFactoryClass(String factoryClassName, Sequence sequence)
    {
        if (sequenceByFactoryClass == null)
        {
            sequenceByFactoryClass = new HashMap();
        }

        sequenceByFactoryClass.put(factoryClassName, sequence);
    }

    /**
     * Accessor for the sequence for a factory class.
     * @param factoryClassName The name of the factory class
     * @return The sequence
     */
    public Sequence getSequenceForFactoryClass(String factoryClassName)
    {
        if (sequenceByFactoryClass == null)
        {
            return null;
        }

        return (Sequence)sequenceByFactoryClass.get(factoryClassName);
    }
}
TOP

Related Classes of org.jpox.jdo.AbstractPersistenceManagerFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.