| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /* |
| * JDOHelper.java |
| * |
| */ |
| |
| package javax.jdo; |
| |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.ErrorHandler; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NamedNodeMap; |
| |
| import javax.jdo.spi.I18NHelper; |
| import javax.jdo.spi.JDOImplHelper; |
| import javax.jdo.spi.JDOImplHelper.StateInterrogationBooleanReturn; |
| import javax.jdo.spi.JDOImplHelper.StateInterrogationObjectReturn; |
| import javax.jdo.spi.PersistenceCapable; |
| import javax.jdo.spi.StateInterrogation; |
| import javax.naming.Context; |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| import javax.rmi.PortableRemoteObject; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.FactoryConfigurationError; |
| import javax.xml.parsers.ParserConfigurationException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.net.URL; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.security.PrivilegedActionException; |
| import java.security.PrivilegedExceptionAction; |
| import java.util.Map; |
| import java.util.HashMap; |
| import java.util.Collections; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ArrayList; |
| import java.util.Properties; |
| import java.util.Enumeration; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.BufferedReader; |
| import java.io.InputStreamReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| |
| |
| /** |
| * This class can be used by a JDO-aware application to call the JDO behavior |
| * of <code>PersistenceCapable</code> instances without declaring them to be |
| * <code>PersistenceCapable</code>. |
| * <P>It is also used to acquire a <code>PersistenceManagerFactory</code> via |
| * various methods. |
| * <P>This helper class defines static methods that allow a JDO-aware |
| * application to examine the runtime state of instances. For example, |
| * an application can discover whether the instance is persistent, |
| * transactional, dirty, new, deleted, or detached; and to get its associated |
| * <code>PersistenceManager</code> if it has one. |
| * |
| * @version 2.1 |
| */ |
| public class JDOHelper implements Constants { |
| |
| /** |
| * A mapping from jdoconfig.xsd element attributes to PMF properties. |
| */ |
| static final Map ATTRIBUTE_PROPERTY_XREF |
| = createAttributePropertyXref(); |
| |
| /** The Internationalization message helper. |
| */ |
| private final static I18NHelper msg = |
| I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N |
| |
| /** |
| * Creates a map from jdoconfig.xsd element attributes to PMF properties. |
| * @return An unmodifiable Map of jdoconfig.xsd element attributes to PMF |
| * properties. |
| */ |
| static Map createAttributePropertyXref() { |
| Map xref = new HashMap(); |
| |
| xref.put( |
| PMF_ATTRIBUTE_CLASS, |
| PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); |
| xref.put( |
| PMF_ATTRIBUTE_CONNECTION_DRIVER_NAME, |
| PROPERTY_CONNECTION_DRIVER_NAME); |
| xref.put( |
| PMF_ATTRIBUTE_CONNECTION_FACTORY_NAME, |
| PROPERTY_CONNECTION_FACTORY_NAME); |
| xref.put( |
| PMF_ATTRIBUTE_CONNECTION_FACTORY2_NAME, |
| PROPERTY_CONNECTION_FACTORY2_NAME); |
| xref.put( |
| PMF_ATTRIBUTE_CONNECTION_PASSWORD, |
| PROPERTY_CONNECTION_PASSWORD); |
| xref.put( |
| PMF_ATTRIBUTE_CONNECTION_URL, |
| PROPERTY_CONNECTION_URL); |
| xref.put( |
| PMF_ATTRIBUTE_CONNECTION_USER_NAME, |
| PROPERTY_CONNECTION_USER_NAME); |
| xref.put( |
| PMF_ATTRIBUTE_IGNORE_CACHE, |
| PROPERTY_IGNORE_CACHE); |
| xref.put( |
| PMF_ATTRIBUTE_MAPPING, |
| PROPERTY_MAPPING); |
| xref.put( |
| PMF_ATTRIBUTE_MULTITHREADED, |
| PROPERTY_MULTITHREADED); |
| xref.put( |
| PMF_ATTRIBUTE_NONTRANSACTIONAL_READ, |
| PROPERTY_NONTRANSACTIONAL_READ); |
| xref.put( |
| PMF_ATTRIBUTE_NONTRANSACTIONAL_WRITE, |
| PROPERTY_NONTRANSACTIONAL_WRITE); |
| xref.put( |
| PMF_ATTRIBUTE_OPTIMISTIC, |
| PROPERTY_OPTIMISTIC); |
| xref.put( |
| PMF_ATTRIBUTE_PERSISTENCE_UNIT_NAME, |
| PROPERTY_PERSISTENCE_UNIT_NAME); |
| xref.put( |
| PMF_ATTRIBUTE_NAME, |
| PROPERTY_NAME); |
| xref.put( |
| PMF_ATTRIBUTE_RESTORE_VALUES, |
| PROPERTY_RESTORE_VALUES); |
| xref.put( |
| PMF_ATTRIBUTE_RETAIN_VALUES, |
| PROPERTY_RETAIN_VALUES); |
| xref.put( |
| PMF_ATTRIBUTE_DETACH_ALL_ON_COMMIT, |
| PROPERTY_DETACH_ALL_ON_COMMIT); |
| xref.put( |
| PMF_ATTRIBUTE_SERVER_TIME_ZONE_ID, |
| PROPERTY_SERVER_TIME_ZONE_ID); |
| |
| return Collections.unmodifiableMap(xref); |
| } |
| |
| /** The JDOImplHelper instance used for handling non-binary-compatible |
| * implementations. |
| */ |
| private static JDOImplHelper implHelper = (JDOImplHelper) |
| AccessController.doPrivileged( |
| new PrivilegedAction () { |
| public Object run () { |
| return JDOImplHelper.getInstance(); |
| } |
| } |
| ); |
| |
| /** The singleton instance of JDOHelper. |
| * @since 2.1 |
| */ |
| private static JDOHelper instance = new JDOHelper(); |
| |
| /** |
| * Return the singleton instance of JDOHelper. This instance is |
| * thread-safe. |
| * @since 2.1 |
| * @return the thread-safe singleton JDOHelper |
| */ |
| public static JDOHelper getInstance() { |
| return instance; |
| } |
| |
| /** Some applications might prefer to use instance |
| * methods instead of static methods. |
| * @since 2.1 |
| */ |
| public JDOHelper() {} |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of getPersistenceManager. |
| */ |
| static StateInterrogationObjectReturn getPersistenceManager = |
| new StateInterrogationObjectReturn() { |
| public Object get(Object pc, StateInterrogation si) { |
| return si.getPersistenceManager(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of getObjectId. |
| */ |
| static StateInterrogationObjectReturn getObjectId = |
| new StateInterrogationObjectReturn() { |
| public Object get(Object pc, StateInterrogation si) { |
| return si.getObjectId(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of getTransactionalObjectId. |
| */ |
| static StateInterrogationObjectReturn getTransactionalObjectId = |
| new StateInterrogationObjectReturn() { |
| public Object get(Object pc, StateInterrogation si) { |
| return si.getTransactionalObjectId(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of getVersion. |
| */ |
| static StateInterrogationObjectReturn getVersion = |
| new StateInterrogationObjectReturn() { |
| public Object get(Object pc, StateInterrogation si) { |
| return si.getVersion(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of isPersistent. |
| */ |
| static StateInterrogationBooleanReturn isPersistent = |
| new StateInterrogationBooleanReturn() { |
| public Boolean is(Object pc, StateInterrogation si) { |
| return si.isPersistent(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of isTransactional. |
| */ |
| static StateInterrogationBooleanReturn isTransactional = |
| new StateInterrogationBooleanReturn() { |
| public Boolean is(Object pc, StateInterrogation si) { |
| return si.isTransactional(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of isDirty. |
| */ |
| static StateInterrogationBooleanReturn isDirty = |
| new StateInterrogationBooleanReturn() { |
| public Boolean is(Object pc, StateInterrogation si) { |
| return si.isDirty(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of isNew. |
| */ |
| static StateInterrogationBooleanReturn isNew = |
| new StateInterrogationBooleanReturn() { |
| public Boolean is(Object pc, StateInterrogation si) { |
| return si.isNew(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of isDeleted. |
| */ |
| static StateInterrogationBooleanReturn isDeleted = |
| new StateInterrogationBooleanReturn() { |
| public Boolean is(Object pc, StateInterrogation si) { |
| return si.isDeleted(pc); |
| } |
| }; |
| |
| /** The stateless instance used for handling non-binary-compatible |
| * implementations of isDetached. |
| */ |
| static StateInterrogationBooleanReturn isDetached = |
| new StateInterrogationBooleanReturn() { |
| public Boolean is(Object pc, StateInterrogation si) { |
| return si.isDetached(pc); |
| } |
| }; |
| |
| /** Return the associated <code>PersistenceManager</code> if there is one. |
| * Transactional and persistent instances return the associated |
| * <code>PersistenceManager</code>. |
| * |
| * <P>Transient non-transactional instances and instances of classes |
| * that do not implement <code>PersistenceCapable</code> return |
| * <code>null</code>. |
| * @see PersistenceCapable#jdoGetPersistenceManager() |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return the <code>PersistenceManager</code> associated with the parameter |
| * instance. |
| */ |
| public static PersistenceManager getPersistenceManager(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoGetPersistenceManager(); |
| } else { |
| return (PersistenceManager) |
| implHelper.nonBinaryCompatibleGet(pc, getPersistenceManager); |
| } |
| } |
| |
| /** Explicitly mark the parameter instance and field dirty. |
| * Normally, <code>PersistenceCapable</code> classes are able to detect |
| * changes made to their fields. However, if a reference to an array is |
| * given to a method outside the class, and the array is modified, then the |
| * persistent instance is not aware of the change. This API allows the |
| * application to notify the instance that a change was made to a field. |
| * |
| * <P>Transient instances and instances of classes |
| * that do not implement <code>PersistenceCapable</code> ignore this method. |
| * @see PersistenceCapable#jdoMakeDirty(String fieldName) |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @param fieldName the name of the field to be marked dirty. |
| */ |
| public static void makeDirty(Object pc, String fieldName) { |
| if (pc instanceof PersistenceCapable) { |
| ((PersistenceCapable)pc).jdoMakeDirty(fieldName); |
| } else { |
| implHelper.nonBinaryCompatibleMakeDirty(pc, fieldName); |
| } |
| } |
| |
| /** Return a copy of the JDO identity associated with the parameter |
| * instance. |
| * |
| * <P>Persistent instances of <code>PersistenceCapable</code> classes have a |
| * JDO identity managed by the <code>PersistenceManager</code>. This method |
| * returns a copy of the ObjectId that represents the JDO identity. |
| * |
| * <P>Transient instances and instances of classes that do not implement |
| * <code>PersistenceCapable</code> return <code>null</code>. |
| * |
| * <P>The ObjectId may be serialized |
| * and later restored, and used with a <code>PersistenceManager</code> from |
| * the same JDO implementation to locate a persistent instance with the same |
| * data store identity. |
| * |
| * <P>If the JDO identity is managed by the application, then the ObjectId |
| * may be used with a <code>PersistenceManager</code> from any JDO |
| * implementation that supports the <code>PersistenceCapable</code> class. |
| * |
| * <P>If the JDO identity is not managed by the application or the data |
| * store, then the ObjectId returned is only valid within the current |
| * transaction. |
| *<P> |
| * @see PersistenceManager#getObjectId(Object pc) |
| * @see PersistenceCapable#jdoGetObjectId() |
| * @see PersistenceManager#getObjectById(Object oid, boolean validate) |
| * @param pc the PersistenceCapable instance. |
| * @return a copy of the ObjectId of the parameter instance as of the |
| * beginning of the transaction. |
| */ |
| public static Object getObjectId(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoGetObjectId(); |
| } else { |
| return implHelper.nonBinaryCompatibleGet(pc, getObjectId); |
| } |
| } |
| |
| /** Get object ids for a collection of instances. For each instance |
| * in the parameter, the getObjectId method is called. This method |
| * returns one identity instance for each element |
| * in the parameter. The order of iteration of the returned |
| * Collection exactly matches the order of iteration of the |
| * parameter Collection. |
| * @param pcs the persistence-capable instances |
| * @return the object ids of the parameters |
| * @see #getObjectId(Object pc) |
| * @see #getObjectIds(Object[] pcs) |
| * @since 2.0 |
| */ |
| public static Collection getObjectIds(Collection pcs) { |
| ArrayList result = new ArrayList(); |
| for (Iterator it = pcs.iterator(); it.hasNext();) { |
| result.add(getObjectId(it.next())); |
| } |
| return result; |
| } |
| |
| /** Get object ids for an array of instances. For each instance |
| * in the parameter, the getObjectId method is called. This method |
| * returns one identity instance for each element |
| * in the parameter. The order of instances of the returned |
| * array exactly matches the order of instances of the |
| * parameter array. |
| * @param pcs the persistence-capable instances |
| * @return the object ids of the parameters |
| * @see #getObjectId(Object pc) |
| * @see #getObjectIds(Collection pcs) |
| * @since 2.0 |
| */ |
| public static Object[] getObjectIds(Object[] pcs) { |
| Object[] result = new Object[pcs.length]; |
| for (int i = 0; i < pcs.length; ++i) { |
| result[i] = getObjectId(pcs[i]); |
| } |
| return result; |
| } |
| |
| /** Return a copy of the JDO identity associated with the parameter |
| * instance. |
| * |
| * @see PersistenceCapable#jdoGetTransactionalObjectId() |
| * @see PersistenceManager#getObjectById(Object oid, boolean validate) |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return a copy of the ObjectId of the parameter instance as modified in |
| * this transaction. |
| */ |
| public static Object getTransactionalObjectId(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoGetTransactionalObjectId(); |
| } else { |
| return implHelper.nonBinaryCompatibleGet( |
| pc, getTransactionalObjectId); |
| } |
| } |
| |
| /** |
| * Return the version of the instance. |
| * @since 2.0 |
| * @param pc the instance |
| * @return the version of the instance |
| */ |
| public static Object getVersion (Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoGetVersion(); |
| } else { |
| return implHelper.nonBinaryCompatibleGet(pc, getVersion); |
| } |
| } |
| /** Tests whether the parameter instance is dirty. |
| * |
| * Instances that have been modified, deleted, or newly |
| * made persistent in the current transaction return <code>true</code>. |
| * |
| *<P>Transient instances and instances of classes that do not implement |
| * <code>PersistenceCapable</code> return <code>false</code>. |
| *<P> |
| * @see javax.jdo.spi.StateManager#makeDirty(PersistenceCapable pc, |
| * String fieldName) |
| * @see PersistenceCapable#jdoIsDirty() |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return <code>true</code> if the parameter instance has been modified in |
| * the current transaction. |
| */ |
| public static boolean isDirty(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoIsDirty(); |
| } else { |
| return implHelper.nonBinaryCompatibleIs(pc, isDirty); |
| } |
| } |
| |
| /** Tests whether the parameter instance is transactional. |
| * |
| * Instances whose state is associated with the current transaction |
| * return true. |
| * |
| *<P>Transient instances and instances of classes that do not implement |
| * <code>PersistenceCapable</code> return <code>false</code>. |
| * @see PersistenceCapable#jdoIsTransactional() |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return <code>true</code> if the parameter instance is transactional. |
| */ |
| public static boolean isTransactional(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoIsTransactional(); |
| } else { |
| return implHelper.nonBinaryCompatibleIs(pc, isTransactional); |
| } |
| } |
| |
| /** Tests whether the parameter instance is persistent. |
| * |
| * Instances that represent persistent objects in the data store |
| * return <code>true</code>. |
| * |
| *<P>Transient instances and instances of classes that do not implement |
| * <code>PersistenceCapable</code> return <code>false</code>. |
| *<P> |
| * @see PersistenceManager#makePersistent(Object pc) |
| * @see PersistenceCapable#jdoIsPersistent() |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return <code>true</code> if the parameter instance is persistent. |
| */ |
| public static boolean isPersistent(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoIsPersistent(); |
| } else { |
| return implHelper.nonBinaryCompatibleIs(pc, isPersistent); |
| } |
| } |
| |
| /** Tests whether the parameter instance has been newly made persistent. |
| * |
| * Instances that have been made persistent in the current transaction |
| * return <code>true</code>. |
| * |
| *<P>Transient instances and instances of classes that do not implement |
| * <code>PersistenceCapable</code> return <code>false</code>. |
| *<P> |
| * @see PersistenceManager#makePersistent(Object pc) |
| * @see PersistenceCapable#jdoIsNew() |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return <code>true</code> if the parameter instance was made persistent |
| * in the current transaction. |
| */ |
| public static boolean isNew(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoIsNew(); |
| } else { |
| return implHelper.nonBinaryCompatibleIs(pc, isNew); |
| } |
| } |
| |
| /** Tests whether the parameter instance has been deleted. |
| * |
| * Instances that have been deleted in the current transaction return |
| * <code>true</code>. |
| * |
| *<P>Transient instances and instances of classes that do not implement |
| * <code>PersistenceCapable</code> return <code>false</code>. |
| *<P> |
| * @see PersistenceManager#deletePersistent(Object pc) |
| * @see PersistenceCapable#jdoIsDeleted() |
| * @param pc the <code>PersistenceCapable</code> instance. |
| * @return <code>true</code> if the parameter instance was deleted |
| * in the current transaction. |
| */ |
| public static boolean isDeleted(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoIsDeleted(); |
| } else { |
| return implHelper.nonBinaryCompatibleIs(pc, isDeleted); |
| } |
| } |
| |
| /** |
| * Tests whether the parameter instance has been detached. |
| * |
| * Instances that have been detached return true. |
| * |
| * <P>Transient instances return false. |
| * <P> |
| * @see PersistenceCapable#jdoIsDetached() |
| * @return <code>true</code> if this instance is detached. |
| * @since 2.0 |
| * @param pc the instance |
| */ |
| public static boolean isDetached(Object pc) { |
| if (pc instanceof PersistenceCapable) { |
| return ((PersistenceCapable)pc).jdoIsDetached(); |
| } else { |
| return implHelper.nonBinaryCompatibleIs(pc, isDetached); |
| } |
| } |
| |
| /** Accessor for the state of the passed object. |
| * @param pc The object |
| * @return The object state |
| * @since 2.1 |
| */ |
| public static ObjectState getObjectState(Object pc) { |
| if (pc == null) { |
| return null; |
| } |
| |
| if (isDetached(pc)) { |
| if (isDirty(pc)) { |
| // Detached Dirty |
| return ObjectState.DETACHED_DIRTY; |
| } |
| else { |
| // Detached Not Dirty |
| return ObjectState.DETACHED_CLEAN; |
| } |
| } |
| else { |
| if (isPersistent(pc)) { |
| if (isTransactional(pc)) { |
| if (isDirty(pc)) { |
| if (isNew(pc)) { |
| if (isDeleted(pc)) { |
| // Persistent Transactional Dirty New Deleted |
| return ObjectState.PERSISTENT_NEW_DELETED; |
| } else { |
| // Persistent Transactional Dirty New Not Deleted |
| return ObjectState.PERSISTENT_NEW; |
| } |
| } else { |
| if (isDeleted(pc)) { |
| // Persistent Transactional Dirty Not New Deleted |
| return ObjectState.PERSISTENT_DELETED; |
| } else { |
| // Persistent Transactional Dirty Not New Not Deleted |
| return ObjectState.PERSISTENT_DIRTY; |
| } |
| } |
| } else { |
| // Persistent Transactional Not Dirty |
| return ObjectState.PERSISTENT_CLEAN; |
| } |
| } |
| else { |
| if (isDirty(pc)) { |
| // Persistent Nontransactional Dirty |
| return ObjectState.PERSISTENT_NONTRANSACTIONAL_DIRTY; |
| } |
| else { |
| // Persistent Nontransactional Not Dirty |
| return ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL; |
| } |
| } |
| } |
| else { |
| if (isTransactional(pc)) { |
| if (isDirty(pc)) { |
| // Not Persistent Transactional Dirty |
| return ObjectState.TRANSIENT_DIRTY; |
| } else { |
| // Not Persistent Transactional Not Dirty |
| return ObjectState.TRANSIENT_CLEAN; |
| } |
| } |
| else { |
| // Not Persistent Not Transactional |
| return ObjectState.TRANSIENT; |
| } |
| } |
| } |
| } |
| |
| /** Get the anonymous <code>PersistenceManagerFactory</code> configured via |
| * the standard configuration file resource "META-INF/jdoconfig.xml", using |
| * the current thread's context class loader |
| * to locate the configuration file resource(s). |
| * @return the anonymous <code>PersistenceManagerFactory</code>. |
| * @since 2.1 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory() { |
| ClassLoader cl = getContextClassLoader(); |
| return getPersistenceManagerFactory( |
| null, ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, cl, cl); |
| } |
| |
| /** Get the anonymous <code>PersistenceManagerFactory</code> configured via |
| * the standard configuration file resource "META-INF/jdoconfig.xml", using |
| * the given class loader. |
| * @return the anonymous <code>PersistenceManagerFactory</code>. |
| * @param pmfClassLoader the ClassLoader used to load resources and classes |
| * @since 2.1 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory( |
| ClassLoader pmfClassLoader) { |
| return getPersistenceManagerFactory( |
| null, |
| ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, |
| pmfClassLoader, pmfClassLoader); |
| } |
| |
| /** Get a <code>PersistenceManagerFactory</code> based on a <code>Properties</code> |
| * instance, using the current thread's context class loader to locate the |
| * <code>PersistenceManagerFactory</code> class. |
| * @return the <code>PersistenceManagerFactory</code>. |
| * @param props a <code>Properties</code> instance with properties of the |
| * <code>PersistenceManagerFactory</code>. |
| * @see #getPersistenceManagerFactory(java.util.Map,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (Map props) { |
| return getPersistenceManagerFactory( |
| null, props, getContextClassLoader()); |
| } |
| |
| |
| /** Get a <code>PersistenceManagerFactory</code> based on a |
| * <code>Map</code> and a class loader. |
| * This method delegates to the getPersistenceManagerFactory |
| * method that takes a Map of overrides and a Map of properties, |
| * passing null as the overrides parameter. |
| * @see #getPersistenceManagerFactory(java.util.Map, java.util.Map, ClassLoader) |
| * @return the <code>PersistenceManagerFactory</code>. |
| * @param props a <code>Map</code> with properties of the |
| * <code>PersistenceManagerFactory</code>. |
| * @param pmfClassLoader the class loader used to load the |
| * <code>PersistenceManagerFactory</code> class |
| * @since 1.0 |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (Map props, ClassLoader pmfClassLoader) { |
| return getPersistenceManagerFactory( |
| null, props, pmfClassLoader); |
| } |
| |
| /** |
| * Get a <code>PersistenceManagerFactory</code> based on a |
| * <code>Map</code> of overrides, a <code>Map</code> of |
| * properties, and a class loader. |
| * The following are standard key names: |
| * <BR><code>"javax.jdo.PersistenceManagerFactoryClass" |
| * <BR>"javax.jdo.option.Optimistic", |
| * <BR>"javax.jdo.option.RetainValues", |
| * <BR>"javax.jdo.option.RestoreValues", |
| * <BR>"javax.jdo.option.IgnoreCache", |
| * <BR>"javax.jdo.option.NontransactionalRead", |
| * <BR>"javax.jdo.option.NontransactionalWrite", |
| * <BR>"javax.jdo.option.Multithreaded", |
| * <BR>"javax.jdo.option.ConnectionUserName", |
| * <BR>"javax.jdo.option.ConnectionPassword", |
| * <BR>"javax.jdo.option.ConnectionURL", |
| * <BR>"javax.jdo.option.ConnectionFactoryName", |
| * <BR>"javax.jdo.option.ConnectionFactory2Name", |
| * <BR>"javax.jdo.option.Mapping", |
| * <BR>"javax.jdo.mapping.Catalog", |
| * <BR>"javax.jdo.mapping.Schema", |
| * <BR>"javax.jdo.option.PersistenceUnitName". |
| * <BR>"javax.jdo.option.DetachAllOnCommit". |
| * <BR>"javax.jdo.option.CopyOnAttach". |
| * <BR>"javax.jdo.option.TransactionType". |
| * <BR>"javax.jdo.option.ServerTimeZoneID". |
| * <BR>"javax.jdo.option.Name". |
| * </code> |
| * and properties of the form |
| * <BR><code>javax.jdo.option.InstanceLifecycleListener.{listenerClass}[=[{pcClasses}]]</code> |
| * where <code>{listenerClass}</code> is the fully qualified name of a |
| * class that implements |
| * {@link javax.jdo.listener.InstanceLifecycleListener}, and |
| * <code>{pcClasses}</code> is an optional comma- or whitespace-delimited |
| * list of persistence-capable classes to be observed; the absence of a |
| * value for a property of this form means that instances of all |
| * persistence-capable classes will be observed by an instance of the given |
| * listener class. |
| * <P>JDO implementations |
| * are permitted to define key values of their own. Any key values not |
| * recognized by the implementation must be ignored. Key values that are |
| * recognized but not supported by an implementation must result in a |
| * <code>JDOFatalUserException</code> thrown by the method. |
| * <P>The returned <code>PersistenceManagerFactory</code> is not |
| * configurable (the <code>set<I>XXX</I></code> methods will throw an |
| * exception). |
| * <P>JDO implementations might manage a map of instantiated |
| * <code>PersistenceManagerFactory</code> instances based on specified |
| * property key values, and return a previously instantiated |
| * <code>PersistenceManagerFactory</code> instance. In this case, the |
| * properties of the returned instance must exactly match the requested |
| * properties. |
| * @return the <code>PersistenceManagerFactory</code>. |
| * @param props a <code>Properties</code> instance with properties of the |
| * <code>PersistenceManagerFactory</code>. |
| * @param pmfClassLoader the class loader to use to load the |
| * <code>PersistenceManagerFactory</code> class |
| * @since 2.1 |
| */ |
| protected static PersistenceManagerFactory getPersistenceManagerFactory |
| (Map overrides, Map props, ClassLoader pmfClassLoader) { |
| List exceptions = new ArrayList(); |
| if (pmfClassLoader == null) |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNullLoader")); //NOI18N |
| |
| String pmfClassName = (String) props.get ( |
| PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); |
| |
| if (!isNullOrBlank(pmfClassName)) { |
| return invokeGetPersistenceManagerFactoryOnImplementation( |
| pmfClassName, overrides, props, pmfClassLoader); |
| |
| } else { |
| // PMF class name null or blank -- try services |
| // for each file META-INF/services/javax.jdo.PersistenceManagerFactory |
| // try to invoke the getPersistenceManagerFactory method of the |
| // implementation class |
| try { |
| Enumeration urls = getResources(pmfClassLoader, |
| SERVICE_LOOKUP_PMF_RESOURCE_NAME); |
| while (urls.hasMoreElements()) { |
| pmfClassName = getClassNameFromURL((URL)urls.nextElement()); |
| return invokeGetPersistenceManagerFactoryOnImplementation( |
| pmfClassName, overrides, props, pmfClassLoader); |
| } |
| } catch (Throwable ex) { |
| // remember exceptions from failed pmf invocations |
| exceptions.add(ex); |
| } |
| } |
| |
| // no PMF class name and no services |
| |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFNoPMFClassNamePropertyOrPUNameProperty"), |
| (Throwable[]) |
| exceptions.toArray(new Throwable[exceptions.size()])); |
| } |
| |
| /** Get a class name from a URL. The URL is from getResources with |
| * e.g. META-INF/services/javax.jdo.PersistenceManagerFactory as the |
| * parameter. Parse the file, removing blank lines, comment lines, |
| * and comments. |
| * @param url the URL of the services file |
| * @return the name of the class contained in the file |
| * @throws java.io.IOException |
| * @since 2.1 |
| */ |
| |
| protected static String getClassNameFromURL (URL url) |
| throws IOException { |
| InputStream is = openStream(url); |
| BufferedReader reader = new BufferedReader(new InputStreamReader(is)); |
| String line = null; |
| try { |
| while ((line = reader.readLine()) != null) { |
| line = line.trim(); |
| if (line.length() == 0 || line.startsWith("#")) { |
| continue; |
| } |
| // else assume first line of text is the PMF class name |
| String[] tokens = line.split("\\s"); |
| String pmfClassName = tokens[0]; |
| int indexOfComment = pmfClassName.indexOf("#"); |
| if (indexOfComment == -1) { |
| return pmfClassName; |
| } |
| // else pmfClassName has a comment at the end of it -- remove |
| return pmfClassName.substring(0, indexOfComment); |
| } |
| return null; |
| } finally { |
| try { |
| reader.close(); |
| } |
| catch (IOException x) { |
| // gulp |
| } |
| } |
| } |
| |
| /** |
| * Returns a named {@link PersistenceManagerFactory} or persistence |
| * unit. |
| * |
| * @since 2.1 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (String name) { |
| ClassLoader cl = getContextClassLoader(); |
| return getPersistenceManagerFactory(null, name, cl, cl); |
| } |
| |
| /** |
| * Returns a named {@link PersistenceManagerFactory} or persistence |
| * unit. |
| * |
| * @since 1.0 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (String name, ClassLoader loader) { |
| |
| return getPersistenceManagerFactory(null, name, loader, loader); |
| } |
| |
| /** |
| * Returns a named {@link PersistenceManagerFactory} or persistence |
| * unit. |
| * |
| * @since 2.0 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (String name, ClassLoader resourceLoader, ClassLoader pmfLoader) { |
| |
| return getPersistenceManagerFactory( |
| null, name, resourceLoader, pmfLoader); |
| } |
| |
| /** |
| * Returns a named {@link PersistenceManagerFactory} or persistence |
| * unit. |
| * |
| * @since 2.1 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (Map overrides, String name) { |
| |
| ClassLoader cl = getContextClassLoader(); |
| return getPersistenceManagerFactory(overrides, name, cl, cl); |
| } |
| |
| /** |
| * Returns a named {@link PersistenceManagerFactory} or persistence |
| * unit. |
| * |
| * @since 2.1 |
| * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader) |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (Map overrides, String name, ClassLoader resourceLoader) { |
| |
| return getPersistenceManagerFactory( |
| overrides, name, resourceLoader, resourceLoader); |
| } |
| |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} configured based |
| * on the properties stored in the resource at |
| * <code>name</code>, or, if not found, returns a |
| * {@link PersistenceManagerFactory} with the given |
| * name or, if not found, returns a |
| * <code>javax.persistence.EntityManagerFactory</code> cast to a |
| * {@link PersistenceManagerFactory}. If the name given is null or consists |
| * only of whitespace, it is interpreted as |
| * {@link Constants#ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME}. |
| * The following are standard key names: |
| * <BR><code>"javax.jdo.PersistenceManagerFactoryClass" |
| * <BR>"javax.jdo.option.Optimistic", |
| * <BR>"javax.jdo.option.RetainValues", |
| * <BR>"javax.jdo.option.RestoreValues", |
| * <BR>"javax.jdo.option.IgnoreCache", |
| * <BR>"javax.jdo.option.NontransactionalRead", |
| * <BR>"javax.jdo.option.NontransactionalWrite", |
| * <BR>"javax.jdo.option.Multithreaded", |
| * <BR>"javax.jdo.option.ConnectionUserName", |
| * <BR>"javax.jdo.option.ConnectionPassword", |
| * <BR>"javax.jdo.option.ConnectionURL", |
| * <BR>"javax.jdo.option.ConnectionFactoryName", |
| * <BR>"javax.jdo.option.ConnectionFactory2Name", |
| * <BR>"javax.jdo.option.Mapping", |
| * <BR>"javax.jdo.mapping.Catalog", |
| * <BR>"javax.jdo.mapping.Schema", |
| * <BR>"javax.jdo.option.PersistenceUnitName". |
| * <BR>"javax.jdo.option.DetachAllOnCommit". |
| * <BR>"javax.jdo.option.CopyOnAttach". |
| * <BR>"javax.jdo.option.TransactionType". |
| * <BR>"javax.jdo.option.ServerTimeZoneID". |
| * <BR>"javax.jdo.option.Name". |
| * </code> |
| * and properties of the form |
| * <BR><code>javax.jdo.option.InstanceLifecycleListener.{listenerClass}[=[{pcClasses}]]</code> |
| * where <code>{listenerClass}</code> is the fully qualified name of a |
| * class that implements |
| * {@link javax.jdo.listener.InstanceLifecycleListener}, and |
| * <code>{pcClasses}</code> is an optional comma- or whitespace-delimited |
| * list of persistence-capable classes to be observed; the absence of a |
| * value for a property of this form means that instances of all |
| * persistence-capable classes will be observed by an instance of the given |
| * listener class. |
| * <P>JDO implementations |
| * are permitted to define key values of their own. Any key values not |
| * recognized by the implementation must be ignored. Key values that are |
| * recognized but not supported by an implementation must result in a |
| * <code>JDOFatalUserException</code> thrown by the method. |
| * <P>The returned <code>PersistenceManagerFactory</code> is not |
| * configurable (the <code>set<I>XXX</I></code> methods will throw an |
| * exception). |
| * |
| * This method loads the properties found at <code>name</code>, if any, via |
| * <code>resourceLoader</code>, and creates a {@link |
| * PersistenceManagerFactory} with <code>pmfLoader</code>. Any |
| * exceptions thrown during resource loading will |
| * be wrapped in a {@link JDOFatalUserException}. |
| * If multiple PMFs with the requested name are found, a |
| * {@link JDOFatalUserException} is thrown. |
| * @since 2.1 |
| * @param overrides a Map containing properties that override properties |
| * defined in any resources loaded according to the "name" parameter |
| * @param name interpreted as the name of the resource containing the PMF |
| * properties, the name of the PMF, or the persistence unit name, in that |
| * order; if name is null, blank or whitespace, it is interpreted as |
| * indicating the anonymous {@link PersistenceManagerFactory}. |
| * @param resourceLoader the class loader to use to load properties file |
| * resources; must be non-null if <code>name</code> is non-null or blank |
| * @param pmfLoader the class loader to use to load the |
| * {@link PersistenceManagerFactory} or |
| * <code>javax.persistence.EntityManagerFactory</code> classes |
| * @return the {@link PersistenceManagerFactory} with properties in the |
| * given resource, with the given name, or with the given persitence unit |
| * name |
| * @see Constants#ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory( |
| Map overrides, |
| String name, |
| ClassLoader resourceLoader, |
| ClassLoader pmfLoader) { |
| if (pmfLoader == null) |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNullPMFLoader")); //NOI18N |
| if (resourceLoader == null) { |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFNullPropsLoader")); //NOI18N |
| } |
| |
| Map props = null; |
| // trim spaces from name and ensure non-null |
| name = (name == null?ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME:name.trim()); |
| if (!ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME.equals(name)) { |
| props = loadPropertiesFromResource(resourceLoader, name); |
| } |
| |
| if (props != null) { |
| // add the SPI property to inform the implementation that |
| // the PMF was configured by the given resource name |
| // and not via named PMF for proper deserialization |
| props.put(PROPERTY_SPI_RESOURCE_NAME, name); |
| props.remove(PROPERTY_NAME); |
| return getPersistenceManagerFactory(overrides, props, pmfLoader); |
| } |
| // props were null; try getting from jdoconfig.xml |
| props = getPropertiesFromJdoconfig(name, pmfLoader); |
| if (props != null) { |
| // inform the impl that the config came from a jdoconfig.xml |
| // element with the given name |
| props.put(PROPERTY_NAME, name); |
| props.remove(PROPERTY_SPI_RESOURCE_NAME); |
| // we have loaded a Properties, delegate to implementation |
| return getPersistenceManagerFactory(overrides, props, pmfLoader); |
| } |
| // no properties found; last try to see if name is a JPA PU name |
| if (!ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME.equals(name)) { |
| props = new Properties(); |
| props.put(PROPERTY_PERSISTENCE_UNIT_NAME, name); |
| return getPersistenceManagerFactory(overrides, props, pmfLoader); |
| } |
| |
| // no PMF found; give up |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_NoPMFConfigurableViaPropertiesOrXML", name)); //NOI18N |
| } |
| |
| /** Invoke the getPersistenceManagerFactory method on the implementation. |
| * If the overrides parameter to this method is not null, the static method |
| * with Map overrides, Map properties parameters will be invoked. |
| * If the overrides parameter to this method is null, the static method |
| * with Map properties parameter will be invoked. |
| * @param pmfClassName the name of the implementation factory class |
| * @param overrides a Map of overrides |
| * @param properties a Map of properties |
| * @param cl the class loader to use to load the implementation class |
| * @return the PersistenceManagerFactory |
| */ |
| protected static PersistenceManagerFactory |
| invokeGetPersistenceManagerFactoryOnImplementation( |
| String pmfClassName, Map overrides, Map properties, ClassLoader cl) { |
| if (overrides != null) { |
| // overrides is not null; use getPersistenceManagerFactory(Map overrides, Map props) |
| try { |
| Class implClass = forName(pmfClassName, true, cl); |
| Method m = getMethod(implClass, |
| "getPersistenceManagerFactory", |
| new Class[]{Map.class, Map.class}); |
| return (PersistenceManagerFactory) invoke(m, |
| null, new Object[]{overrides, properties}); |
| |
| } catch (ClassNotFoundException e) { |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFClassNotFound", pmfClassName), e); |
| } catch (NoSuchMethodException e) { |
| throw new JDOFatalInternalException(msg.msg( |
| "EXC_GetPMFNoSuchMethod2", pmfClassName), e); |
| } catch (NullPointerException e) { |
| throw new JDOFatalInternalException (msg.msg( |
| "EXC_GetPMFNullPointerException", pmfClassName), e); //NOI18N |
| } catch (IllegalAccessException e) { |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFIllegalAccess", pmfClassName), e); |
| } catch (ClassCastException e) { |
| throw new JDOFatalInternalException (msg.msg( |
| "EXC_GetPMFClassCastException", pmfClassName), e); //NOI18N |
| } catch (InvocationTargetException ite) { |
| Throwable nested = ite.getTargetException(); |
| if (nested instanceof JDOException) { |
| throw (JDOException)nested; |
| } else throw new JDOFatalInternalException (msg.msg( |
| "EXC_GetPMFUnexpectedException"), ite); //NOI18N |
| } |
| } else { |
| // overrides is null; use getPersistenceManagerFactory(Map props) |
| try { |
| Class implClass = forName(pmfClassName, true, cl); |
| Method m = getMethod(implClass, |
| "getPersistenceManagerFactory", |
| new Class[]{Map.class}); |
| return (PersistenceManagerFactory) invoke(m, |
| null, new Object[]{properties}); |
| } catch (ClassNotFoundException e) { |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFClassNotFound", pmfClassName), e); |
| } catch (NoSuchMethodException e) { |
| throw new JDOFatalInternalException(msg.msg( |
| "EXC_GetPMFNoSuchMethod2", pmfClassName), e); |
| } catch (NullPointerException e) { |
| throw new JDOFatalInternalException (msg.msg( |
| "EXC_GetPMFNullPointerException", pmfClassName), e); //NOI18N |
| } catch (IllegalAccessException e) { |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFIllegalAccess", pmfClassName), e); |
| } catch (ClassCastException e) { |
| throw new JDOFatalInternalException (msg.msg( |
| "EXC_GetPMFClassCastException", pmfClassName), e); //NOI18N |
| } catch (InvocationTargetException ite) { |
| Throwable nested = ite.getTargetException(); |
| if (nested instanceof JDOException) { |
| throw (JDOException)nested; |
| } else throw new JDOFatalInternalException (msg.msg( |
| "EXC_GetPMFUnexpectedException"), ite); //NOI18N |
| } |
| } |
| } |
| |
| /** Load a Properties instance by name from the class loader. |
| * |
| * @param resourceLoader the class loader from which to load the properties |
| * @param name the name of the resource |
| * @return a Properties instance or null if no resource is found |
| */ |
| protected static Map loadPropertiesFromResource( |
| ClassLoader resourceLoader, String name) { |
| InputStream in = null; |
| Properties props = null; |
| // try to load resources from properties file |
| try { |
| in = getResourceAsStream(resourceLoader, name); |
| if (in != null) { |
| // then some kind of resource was found by the given name; |
| // assume that it's a properties file |
| props = new Properties(); |
| ((Properties) props).load(in); |
| } |
| } catch (IOException ioe) { |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_GetPMFIOExceptionRsrc", name), ioe); //NOI18N |
| } finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException ioe) { |
| } |
| } |
| } |
| return props; |
| } |
| |
| /** |
| * @see #getNamedPMFProperties(String,ClassLoader,String) |
| * @since 2.1 |
| */ |
| protected static Map getPropertiesFromJdoconfig( |
| String name, |
| ClassLoader resourceLoader) { |
| return getNamedPMFProperties( |
| name, resourceLoader, JDOCONFIG_RESOURCE_NAME); |
| } |
| |
| /** |
| * Find and return the named {@link PersistenceManagerFactory}'s properties, |
| * or null if not found. |
| * If multiple named PMF property sets with |
| * the given name are found (including anonymous ones), throw |
| * {@link JDOFatalUserException}. |
| * This method is here only to facilitate testing; the parameter |
| * "jdoconfigResourceName" in public usage should always have the value |
| * given in the constant {@link Constants#JDOCONFIG_RESOURCE_NAME}. |
| * |
| * @param name The persistence unit name; null is disallowed. |
| * @param resourceLoader The ClassLoader used to load the standard JDO |
| * configuration file. |
| * @param jdoconfigResourceName The name of the configuration file to read. |
| * In public usage, this should always be the value of |
| * {@link Constants#JDOCONFIG_RESOURCE_NAME}. |
| * @return The named <code>PersistenceManagerFactory</code> properties if |
| * found, null if not. |
| * @since 2.1 |
| * @throws JDOFatalUserException if multiple named PMF property sets are |
| * found with the given name, or any other exception is encountered. |
| */ |
| protected static Map getNamedPMFProperties( |
| String name, |
| ClassLoader resourceLoader, |
| String jdoconfigResourceName) { |
| // key is PU name, value is Map of PU properties |
| Map/*<String,Map>*/ propertiesByNameInAllConfigs |
| = new HashMap/*<String,Map>*/(); |
| try { |
| URL firstFoundConfigURL = null; |
| |
| // get all JDO configurations |
| Enumeration resources = |
| getResources(resourceLoader, jdoconfigResourceName); |
| |
| if (resources.hasMoreElements()) { |
| ArrayList processedResources = new ArrayList(); |
| |
| // get ready to parse XML |
| DocumentBuilderFactory factory = getDocumentBuilderFactory(); |
| do { |
| URL currentConfigURL = (URL) resources.nextElement(); |
| if (processedResources.contains(currentConfigURL)) { |
| continue; |
| } |
| else { |
| processedResources.add(currentConfigURL); |
| } |
| |
| Map/*<String,Map>*/ propertiesByNameInCurrentConfig = |
| readNamedPMFProperties( |
| currentConfigURL, |
| name, |
| factory); |
| |
| // try to detect duplicate requested PU |
| if (propertiesByNameInCurrentConfig.containsKey(name)) { |
| // possible dup -- check for it |
| if (firstFoundConfigURL == null) { |
| firstFoundConfigURL = currentConfigURL; |
| } |
| |
| if (propertiesByNameInAllConfigs.containsKey(name)) |
| throw new JDOFatalUserException (msg.msg( |
| "EXC_DuplicateRequestedNamedPMFFoundInDifferentConfigs", |
| "".equals(name) |
| ? "(anonymous)" |
| : name, |
| firstFoundConfigURL.toExternalForm(), |
| currentConfigURL.toExternalForm())); //NOI18N |
| } |
| // no dups -- add found PUs to all PUs and keep going |
| propertiesByNameInAllConfigs |
| .putAll(propertiesByNameInCurrentConfig); |
| } while (resources.hasMoreElements()); |
| } |
| } |
| catch (FactoryConfigurationError e) { |
| throw new JDOFatalUserException( |
| msg.msg("ERR_NoDocumentBuilderFactory"), e); |
| } |
| catch (IOException ioe) { |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFIOExceptionRsrc", name), ioe); //NOI18N |
| } |
| |
| // done with reading all config resources; |
| // return what we found, which may very well be null |
| return (Map) propertiesByNameInAllConfigs.get(name); |
| } |
| |
| |
| protected static DocumentBuilderFactory getDocumentBuilderFactory() { |
| DocumentBuilderFactory factory = |
| implHelper.getRegisteredDocumentBuilderFactory(); |
| if (factory == null) { |
| factory = getDefaultDocumentBuilderFactory(); |
| } |
| return factory; |
| } |
| |
| protected static DocumentBuilderFactory getDefaultDocumentBuilderFactory() { |
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
| factory.setIgnoringComments(true); |
| factory.setNamespaceAware(true); |
| factory.setValidating(false); |
| factory.setIgnoringElementContentWhitespace(true); |
| factory.setExpandEntityReferences(true); |
| |
| return factory; |
| } |
| |
| protected static ErrorHandler getErrorHandler() { |
| ErrorHandler handler = implHelper.getRegisteredErrorHandler(); |
| if (handler == null) { |
| handler = getDefaultErrorHandler(); |
| } |
| return handler; |
| } |
| |
| protected static ErrorHandler getDefaultErrorHandler() { |
| return new ErrorHandler() { |
| public void error(SAXParseException exception) |
| throws SAXException { |
| throw exception; |
| } |
| |
| public void fatalError(SAXParseException exception) |
| throws SAXException { |
| throw exception; |
| } |
| |
| public void warning(SAXParseException exception) |
| throws SAXException { |
| // gulp: ignore warnings |
| } |
| }; |
| } |
| |
| |
| /** Reads JDO configuration file, creates a Map for each |
| * persistence-manager-factory, then returns the map. |
| * @param url URL of a JDO configuration file compliant with |
| * javax/jdo/jdoconfig.xsd. |
| * @param requestedPMFName The name of the requested |
| * persistence unit (allows for fail-fast). |
| * @param factory The <code>DocumentBuilderFactory</code> to use for XML |
| * parsing. |
| * @return a Map<String,Map> holding persistence unit configurations; for |
| * the anonymous persistence unit, the |
| * value of the String key is the empty string, "". |
| */ |
| protected static Map/*<String,Map>*/ readNamedPMFProperties( |
| URL url, |
| String requestedPMFName, |
| DocumentBuilderFactory factory) { |
| requestedPMFName = requestedPMFName == null |
| ? "" |
| : requestedPMFName.trim(); |
| |
| Map propertiesByName = new HashMap(); |
| InputStream in = null; |
| try { |
| DocumentBuilder builder = factory.newDocumentBuilder(); |
| builder.setErrorHandler(getErrorHandler()); |
| |
| in = openStream(url); |
| Document doc = builder.parse(in); |
| |
| Element root = doc.getDocumentElement(); |
| if (root == null) { |
| throw new JDOFatalUserException( |
| msg.msg("EXC_InvalidJDOConfigNoRoot", url.toExternalForm()) |
| ); |
| } |
| |
| NodeList pmfs = root.getElementsByTagName( |
| ELEMENT_PERSISTENCE_MANAGER_FACTORY); |
| |
| for(int i = 0; i < pmfs.getLength(); i++) { |
| Node pmfElement = pmfs.item(i); |
| |
| Properties pmfPropertiesFromAttributes |
| = readPropertiesFromPMFElementAttributes(pmfElement); |
| |
| Properties pmfPropertiesFromElements |
| = readPropertiesFromPMFSubelements(pmfElement, url); |
| |
| // for informative error handling, get name (or names) now |
| String pmfNameFromAtts = |
| pmfPropertiesFromAttributes.getProperty(PROPERTY_NAME); |
| String pmfNameFromElem = |
| pmfPropertiesFromElements.getProperty(PROPERTY_NAME); |
| |
| String pmfName = null; |
| if (isNullOrBlank(pmfNameFromAtts)) { |
| // no PMF name attribute given |
| if (!isNullOrBlank(pmfNameFromElem)) { |
| // PMF name element was given |
| pmfName = pmfNameFromElem; |
| } |
| else { |
| // PMF name not given at all, means the "anonymous" PMF |
| pmfName = ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME; |
| } |
| } |
| else { |
| // PMF name given in an attribute |
| if (!isNullOrBlank(pmfNameFromElem)) { |
| // exception -- PMF name given as both att & elem |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_DuplicatePMFNamePropertyFoundWithinConfig", |
| pmfNameFromAtts, |
| pmfNameFromElem, |
| url.toExternalForm())); |
| } |
| pmfName = pmfNameFromAtts; |
| } |
| pmfName = pmfName == null ? "" : pmfName.trim(); |
| |
| // check for duplicate properties among atts & elems |
| if (requestedPMFName.equals(pmfName)) { |
| Iterator it = |
| pmfPropertiesFromAttributes.keySet().iterator(); |
| while (it.hasNext()) { |
| String property = (String) it.next(); |
| if (pmfPropertiesFromElements.contains(property)) { |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_DuplicatePropertyFound", |
| property, |
| pmfName, |
| url.toExternalForm())); |
| } |
| } |
| } |
| |
| // at this point, we're guaranteed not to have duplicate |
| // properties -- merge them |
| Properties pmfProps = new Properties(); |
| pmfProps.putAll(pmfPropertiesFromAttributes); |
| pmfProps.putAll(pmfPropertiesFromElements); |
| |
| // check for duplicate requested PMF name |
| if (pmfName.equals(requestedPMFName) |
| && propertiesByName.containsKey(pmfName)) { |
| |
| throw new JDOFatalUserException(msg.msg( |
| "EXC_DuplicateRequestedNamedPMFFoundInSameConfig", |
| pmfName, |
| url.toExternalForm())); |
| } |
| propertiesByName.put(pmfName, pmfProps); |
| } |
| return propertiesByName; |
| } |
| catch (IOException ioe) { |
| throw new JDOFatalUserException( |
| msg.msg("EXC_GetPMFIOExceptionRsrc", url.toString()), |
| ioe); //NOI18N |
| } |
| catch (ParserConfigurationException e) { |
| throw new JDOFatalInternalException( |
| msg.msg("EXC_ParserConfigException"), |
| e); |
| } |
| catch (SAXParseException e) { |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_SAXParseException", |
| url.toExternalForm(), |
| new Integer(e.getLineNumber()), |
| new Integer(e.getColumnNumber())), |
| e); |
| } |
| catch (SAXException e) { |
| throw new JDOFatalUserException( |
| msg.msg("EXC_SAXException", url.toExternalForm()), |
| e); |
| } |
| catch (JDOException e) { |
| throw e; |
| } |
| catch (RuntimeException e) { |
| throw new JDOFatalUserException( |
| msg.msg("EXC_SAXException", url.toExternalForm()), |
| e); |
| } |
| finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } |
| catch (IOException ioe) { /* gulp */ } |
| } |
| } |
| } |
| |
| protected static Properties readPropertiesFromPMFElementAttributes( |
| Node pmfElement) { |
| Properties p = new Properties(); |
| NamedNodeMap attributes = pmfElement.getAttributes(); |
| if (attributes == null) { |
| return p; |
| } |
| |
| for(int i = 0; i < attributes.getLength(); i++) { |
| Node att = attributes.item(i); |
| String attName = att.getNodeName(); |
| String attValue = att.getNodeValue().trim(); |
| |
| String jdoPropertyName = |
| (String) ATTRIBUTE_PROPERTY_XREF.get(attName); |
| |
| p.put( |
| jdoPropertyName != null |
| ? jdoPropertyName |
| : attName, |
| attValue); |
| } |
| |
| return p; |
| } |
| |
| protected static Properties readPropertiesFromPMFSubelements( |
| Node pmfElement, URL url) { |
| Properties p = new Properties(); |
| NodeList elements = pmfElement.getChildNodes(); |
| if (elements == null) { |
| return p; |
| } |
| for(int i = 0; i < elements.getLength(); i++) { |
| Node element = elements.item(i); |
| if (element.getNodeType() != Node.ELEMENT_NODE) { |
| continue; |
| } |
| |
| String elementName = element.getNodeName(); |
| NamedNodeMap attributes = element.getAttributes(); |
| if (ELEMENT_PROPERTY.equalsIgnoreCase(elementName)) { |
| // <property name="..." value="..."/> |
| |
| // get the "name" attribute's value (required) |
| Node nameAtt = attributes.getNamedItem(PROPERTY_ATTRIBUTE_NAME); |
| if (nameAtt == null) { |
| throw new JDOFatalUserException( |
| msg.msg("EXC_PropertyElementHasNoNameAttribute", url)); |
| } |
| String name = nameAtt.getNodeValue().trim(); |
| if ("".equals(name)) { |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_PropertyElementNameAttributeHasNoValue", |
| name, |
| url)); |
| } |
| // The next call allows users to use either the |
| // <persistence-manager-factory> attribute names or the |
| // "javax.jdo" property names in <property> element "name" |
| // attributes. Handy-dandy. |
| String jdoPropertyName = |
| (String) ATTRIBUTE_PROPERTY_XREF.get(name); |
| |
| String propertyName = jdoPropertyName != null |
| ? jdoPropertyName |
| : name; |
| |
| if (p.containsKey(propertyName)) { |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_DuplicatePropertyNameGivenInPropertyElement", |
| propertyName, |
| url)); |
| } |
| |
| // get the "value" attribute's value (optional) |
| Node valueAtt = attributes.getNamedItem( |
| PROPERTY_ATTRIBUTE_VALUE); |
| String value = valueAtt == null |
| ? null |
| : valueAtt.getNodeValue().trim(); |
| |
| p.put(propertyName, value); |
| } |
| else if (ELEMENT_INSTANCE_LIFECYCLE_LISTENER.equals(elementName)) { |
| // <instance-lifecycle-listener listener="..." classes="..."/> |
| |
| // get the "listener" attribute's value |
| Node listenerAtt = attributes.getNamedItem( |
| INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_LISTENER); |
| if (listenerAtt == null) { |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_MissingListenerAttribute", |
| url)); |
| } |
| String listener = listenerAtt.getNodeValue().trim(); |
| if ("".equals(listener)) { |
| throw new JDOFatalUserException( |
| msg.msg( |
| "EXC_MissingListenerAttributeValue", |
| url)); |
| } |
| |
| // listener properties are of the form |
| // "javax.jdo.option.InstanceLifecycleListener." + listener |
| listener = |
| PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER + listener; |
| |
| // get the "classes" attribute's value (optional) |
| Node classesAtt = attributes.getNamedItem( |
| INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_CLASSES); |
| String value = classesAtt == null |
| ? "" |
| : classesAtt.getNodeValue().trim(); |
| |
| p.put(listener, value); |
| } |
| } |
| return p; |
| } |
| |
| protected static boolean isNullOrBlank(String s) { |
| return s == null || "".equals(s.trim()); |
| } |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} configured based |
| * on the properties stored in the file at |
| * <code>propsFile</code>. This method is equivalent to |
| * invoking {@link |
| * #getPersistenceManagerFactory(File,ClassLoader)} with |
| * <code>Thread.currentThread().getContextClassLoader()</code> as |
| * the <code>loader</code> argument. |
| * @since 2.0 |
| * @param propsFile the file containing the Properties |
| * @return the PersistenceManagerFactory |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (File propsFile) { |
| return getPersistenceManagerFactory( |
| propsFile, getContextClassLoader()); |
| } |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} configured based |
| * on the properties stored in the file at |
| * <code>propsFile</code>. Creates a {@link |
| * PersistenceManagerFactory} with <code>loader</code>. Any |
| * <code>IOException</code>s or |
| * <code>FileNotFoundException</code>s thrown during resource |
| * loading will be wrapped in a {@link JDOFatalUserException}. |
| * @since 2.0 |
| * @param propsFile the file containing the Properties |
| * @param loader the class loader to use to load the |
| * <code>PersistenceManagerFactory</code> class |
| * @return the PersistenceManagerFactory |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (File propsFile, ClassLoader loader) { |
| if (propsFile == null) |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNullFile")); //NOI18N |
| |
| Properties props = new Properties(); |
| InputStream in = null; |
| try { |
| in = new FileInputStream(propsFile); |
| return getPersistenceManagerFactory(in, loader); |
| } catch (FileNotFoundException fnfe) { |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNoFile", propsFile), fnfe); //NOI18N |
| } finally { |
| if (in != null) |
| try { |
| in.close (); |
| } catch (IOException ioe) { } |
| } |
| } |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} at the JNDI |
| * location specified by <code>jndiLocation</code> in the context |
| * <code>context</code>. If <code>context</code> is |
| * <code>null</code>, <code>new InitialContext()</code> will be |
| * used. This method is equivalent to invoking {@link |
| * #getPersistenceManagerFactory(String,Context,ClassLoader)} |
| * with <code>Thread.currentThread().getContextClassLoader()</code> as |
| * the <code>loader</code> argument. |
| * @since 2.0 |
| * @param jndiLocation the JNDI location containing the |
| * PersistenceManagerFactory |
| * @param context the context in which to find the named |
| * PersistenceManagerFactory |
| * @return the PersistenceManagerFactory |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (String jndiLocation, Context context) { |
| return getPersistenceManagerFactory (jndiLocation, context, |
| getContextClassLoader()); |
| } |
| |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} at the JNDI |
| * location specified by <code>jndiLocation</code> in the context |
| * <code>context</code>. If <code>context</code> is |
| * <code>null</code>, <code>new InitialContext()</code> will be |
| * used. Creates a {@link PersistenceManagerFactory} with |
| * <code>loader</code>. Any <code>NamingException</code>s thrown |
| * will be wrapped in a {@link JDOFatalUserException}. |
| * @since 2.0 |
| * @param jndiLocation the JNDI location containing the |
| * PersistenceManagerFactory |
| * @param context the context in which to find the named |
| * PersistenceManagerFactory |
| * @param loader the class loader to use to load the |
| * <code>PersistenceManagerFactory</code> class |
| * @return the PersistenceManagerFactory |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (String jndiLocation, Context context, ClassLoader loader) { |
| if (jndiLocation == null) |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNullJndiLoc")); //NOI18N |
| if (loader == null) |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNullLoader")); //NOI18N |
| try { |
| if (context == null) |
| context = new InitialContext (); |
| |
| Object o = context.lookup (jndiLocation); |
| return (PersistenceManagerFactory) PortableRemoteObject.narrow |
| (o, PersistenceManagerFactory.class); |
| } catch (NamingException ne) { |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNamingException", jndiLocation, loader), ne); //NOI18N |
| } |
| } |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} configured based |
| * on the Properties stored in the input stream at |
| * <code>stream</code>. This method is equivalent to |
| * invoking {@link |
| * #getPersistenceManagerFactory(InputStream,ClassLoader)} with |
| * <code>Thread.currentThread().getContextClassLoader()</code> as |
| * the <code>loader</code> argument. |
| * @since 2.0 |
| * @param stream the stream containing the Properties |
| * @return the PersistenceManagerFactory |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (InputStream stream) { |
| return getPersistenceManagerFactory( |
| stream, getContextClassLoader()); |
| } |
| |
| /** |
| * Returns a {@link PersistenceManagerFactory} configured based |
| * on the Properties stored in the input stream at |
| * <code>stream</code>. Creates a {@link |
| * PersistenceManagerFactory} with <code>loader</code>. Any |
| * <code>IOException</code>s thrown during resource |
| * loading will be wrapped in a {@link JDOFatalUserException}. |
| * @since 2.0 |
| * @param stream the stream containing the Properties |
| * @param loader the class loader to use to load the |
| * <code>PersistenceManagerFactory</code> class |
| * @return the PersistenceManagerFactory |
| */ |
| public static PersistenceManagerFactory getPersistenceManagerFactory |
| (InputStream stream, ClassLoader loader) { |
| if (stream == null) |
| throw new JDOFatalUserException (msg.msg ( |
| "EXC_GetPMFNullStream")); //NOI18N |
| |
| Properties props = new Properties (); |
| try { |
| props.load (stream); |
| } catch (IOException ioe) { |
| throw new JDOFatalUserException |
| (msg.msg ("EXC_GetPMFIOExceptionStream"), ioe); //NOI18N |
| } |
| return getPersistenceManagerFactory (props, loader); |
| } |
| |
| /** Get the context class loader associated with the current thread. |
| * This is done in a doPrivileged block because it is a secure method. |
| * @return the current thread's context class loader. |
| * @since 2.0 |
| */ |
| private static ClassLoader getContextClassLoader() { |
| return (ClassLoader)AccessController.doPrivileged( |
| new PrivilegedAction () { |
| public Object run () { |
| return Thread.currentThread().getContextClassLoader(); |
| } |
| } |
| ); |
| } |
| |
| /** Get the named resource as a stream from the resource loader. |
| * Perform this operation in a doPrivileged block. |
| */ |
| private static InputStream getResourceAsStream( |
| final ClassLoader resourceLoader, final String name) { |
| return (InputStream)AccessController.doPrivileged( |
| new PrivilegedAction() { |
| public Object run() { |
| return resourceLoader.getResourceAsStream(name); |
| } |
| } |
| ); |
| } |
| |
| |
| /** Get the named Method from the named class. |
| * Perform this operation in a doPrivileged block. |
| * |
| * @param implClass the class |
| * @param methodName the name of the method |
| * @param parameterTypes the parameter types of the method |
| * @return the Method instance |
| */ |
| private static Method getMethod( |
| final Class implClass, |
| final String methodName, |
| final Class[] parameterTypes) |
| throws NoSuchMethodException { |
| try { |
| return (Method) AccessController.doPrivileged( |
| new PrivilegedExceptionAction() { |
| public Object run() throws NoSuchMethodException { |
| return implClass.getMethod(methodName, parameterTypes); |
| } |
| } |
| ); |
| } catch (PrivilegedActionException ex) { |
| throw (NoSuchMethodException)ex.getException(); |
| } |
| } |
| |
| /** Invoke the method. |
| * Perform this operation in a doPrivileged block. |
| */ |
| private static Object invoke(final Method method, |
| final Object instance, final Object[] parameters) |
| throws IllegalAccessException, InvocationTargetException { |
| try { |
| return (Object) AccessController.doPrivileged( |
| new PrivilegedExceptionAction() { |
| public Object run() |
| throws IllegalAccessException, |
| InvocationTargetException { |
| return method.invoke (instance, parameters); |
| } |
| } |
| ); |
| } catch (PrivilegedActionException ex) { |
| Exception cause = (Exception)ex.getException(); |
| if (cause instanceof IllegalAccessException) |
| throw (IllegalAccessException)cause; |
| else //if (cause instanceof InvocationTargetException) |
| throw (InvocationTargetException)cause; |
| } |
| } |
| |
| /** Get resources of the resource loader. |
| * Perform this operation in a doPrivileged block. |
| * @param resourceLoader |
| * @param resourceName |
| * @return the resources |
| */ |
| protected static Enumeration getResources( |
| final ClassLoader resourceLoader, |
| final String resourceName) |
| throws IOException { |
| try { |
| return (Enumeration) AccessController.doPrivileged( |
| new PrivilegedExceptionAction() { |
| public Object run() throws IOException { |
| return resourceLoader.getResources(resourceName); |
| } |
| } |
| ); |
| } catch (PrivilegedActionException ex) { |
| throw (IOException)ex.getException(); |
| } |
| } |
| |
| /** Get the named class. |
| * Perform this operation in a doPrivileged block. |
| * |
| * @param name the name of the class |
| * @param init whether to initialize the class |
| * @param loader which class loader to use |
| * @return the class |
| */ |
| private static Class forName( |
| final String name, |
| final boolean init, |
| final ClassLoader loader) |
| throws ClassNotFoundException { |
| try { |
| return (Class) AccessController.doPrivileged( |
| new PrivilegedExceptionAction() { |
| public Object run() throws ClassNotFoundException { |
| return Class.forName(name, init, loader); |
| } |
| } |
| ); |
| } catch (PrivilegedActionException ex) { |
| throw (ClassNotFoundException)ex.getException(); |
| } |
| } |
| |
| /** Open an input stream on the url. |
| * Perform this operation in a doPrivileged block. |
| * |
| * @param url |
| * @return the input stream |
| */ |
| private static InputStream openStream(final URL url) |
| throws IOException { |
| try { |
| return (InputStream) AccessController.doPrivileged( |
| new PrivilegedExceptionAction() { |
| public Object run() throws IOException { |
| return url.openStream(); |
| } |
| } |
| ); |
| } catch (PrivilegedActionException ex) { |
| throw (IOException)ex.getException(); |
| } |
| } |
| |
| } |