| /* |
| * 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 |
| * |
| * https://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 java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.net.URL; |
| import java.security.PrivilegedAction; |
| import java.security.PrivilegedActionException; |
| import java.security.PrivilegedExceptionAction; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| 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.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 org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| |
| /** |
| * 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<String, String> ATTRIBUTE_PROPERTY_XREF = createAttributePropertyXref(); |
| |
| /** The Internationalization message helper. */ |
| private static final I18NHelper MSG = I18NHelper.getInstance("javax.jdo.Bundle"); // NOI18N |
| |
| private static final String EXC_GET_PMF_IOEXCEPTION_RSRC = "EXC_GetPMFIOExceptionRsrc"; // NOI18N |
| |
| private static final String EXC_GET_PMF_UNEXPECTED_EXCEPTION = |
| "EXC_GetPMFUnexpectedException"; // 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<String, String> createAttributePropertyXref() { |
| Map<String, String> xref = new HashMap<>(); |
| |
| xref.put(Constants.PMF_ATTRIBUTE_CLASS, Constants.PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_CONNECTION_DRIVER_NAME, Constants.PROPERTY_CONNECTION_DRIVER_NAME); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_CONNECTION_FACTORY_NAME, |
| Constants.PROPERTY_CONNECTION_FACTORY_NAME); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_CONNECTION_FACTORY2_NAME, |
| Constants.PROPERTY_CONNECTION_FACTORY2_NAME); |
| xref.put(Constants.PMF_ATTRIBUTE_CONNECTION_PASSWORD, Constants.PROPERTY_CONNECTION_PASSWORD); |
| xref.put(Constants.PMF_ATTRIBUTE_CONNECTION_URL, Constants.PROPERTY_CONNECTION_URL); |
| xref.put(Constants.PMF_ATTRIBUTE_CONNECTION_USER_NAME, Constants.PROPERTY_CONNECTION_USER_NAME); |
| xref.put(Constants.PMF_ATTRIBUTE_IGNORE_CACHE, Constants.PROPERTY_IGNORE_CACHE); |
| xref.put(Constants.PMF_ATTRIBUTE_MAPPING, Constants.PROPERTY_MAPPING); |
| xref.put(Constants.PMF_ATTRIBUTE_MULTITHREADED, Constants.PROPERTY_MULTITHREADED); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_NONTRANSACTIONAL_READ, Constants.PROPERTY_NONTRANSACTIONAL_READ); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_NONTRANSACTIONAL_WRITE, Constants.PROPERTY_NONTRANSACTIONAL_WRITE); |
| xref.put(Constants.PMF_ATTRIBUTE_OPTIMISTIC, Constants.PROPERTY_OPTIMISTIC); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_PERSISTENCE_UNIT_NAME, Constants.PROPERTY_PERSISTENCE_UNIT_NAME); |
| xref.put(Constants.PMF_ATTRIBUTE_NAME, Constants.PROPERTY_NAME); |
| xref.put(Constants.PMF_ATTRIBUTE_RESTORE_VALUES, Constants.PROPERTY_RESTORE_VALUES); |
| xref.put(Constants.PMF_ATTRIBUTE_RETAIN_VALUES, Constants.PROPERTY_RETAIN_VALUES); |
| xref.put(Constants.PMF_ATTRIBUTE_DETACH_ALL_ON_COMMIT, Constants.PROPERTY_DETACH_ALL_ON_COMMIT); |
| xref.put(Constants.PMF_ATTRIBUTE_SERVER_TIME_ZONE_ID, Constants.PROPERTY_SERVER_TIME_ZONE_ID); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_DATASTORE_READ_TIMEOUT_MILLIS, |
| Constants.PROPERTY_DATASTORE_READ_TIMEOUT_MILLIS); |
| xref.put( |
| Constants.PMF_ATTRIBUTE_DATASTORE_WRITE_TIMEOUT_MILLIS, |
| Constants.PROPERTY_DATASTORE_WRITE_TIMEOUT_MILLIS); |
| |
| return Collections.unmodifiableMap(xref); |
| } |
| |
| /** The JDOImplHelper instance used for handling non-binary-compatible implementations. */ |
| private static final JDOImplHelper IMPL_HELPER = |
| doPrivileged((PrivilegedAction<JDOImplHelper>) JDOImplHelper::getInstance); |
| |
| /** |
| * The singleton instance of JDOHelper. |
| * |
| * @since 2.1 |
| */ |
| private static final 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() { |
| // This method is deliberately left empty, see javadoc for more info. |
| } |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of |
| * getPersistenceManager. |
| */ |
| static final StateInterrogationObjectReturn getPersistenceManager = |
| (pc, si) -> si.getPersistenceManager(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of getObjectId. |
| */ |
| static final StateInterrogationObjectReturn getObjectId = (pc, si) -> si.getObjectId(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of |
| * getTransactionalObjectId. |
| */ |
| static final StateInterrogationObjectReturn getTransactionalObjectId = |
| (pc, si) -> si.getTransactionalObjectId(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of getVersion. |
| */ |
| static final StateInterrogationObjectReturn getVersion = (pc, si) -> si.getVersion(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of isPersistent. |
| */ |
| static final StateInterrogationBooleanReturn isPersistent = (pc, si) -> si.isPersistent(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of |
| * isTransactional. |
| */ |
| static final StateInterrogationBooleanReturn isTransactional = (pc, si) -> si.isTransactional(pc); |
| |
| /** The stateless instance used for handling non-binary-compatible implementations of isDirty. */ |
| static final StateInterrogationBooleanReturn isDirty = (pc, si) -> si.isDirty(pc); |
| |
| /** The stateless instance used for handling non-binary-compatible implementations of isNew. */ |
| static final StateInterrogationBooleanReturn isNew = (pc, si) -> si.isNew(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of isDeleted. |
| */ |
| static final StateInterrogationBooleanReturn isDeleted = (pc, si) -> si.isDeleted(pc); |
| |
| /** |
| * The stateless instance used for handling non-binary-compatible implementations of isDetached. |
| */ |
| static final StateInterrogationBooleanReturn isDetached = (pc, si) -> 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) IMPL_HELPER.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 { |
| IMPL_HELPER.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 IMPL_HELPER.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<Object> getObjectIds(Collection<?> pcs) { |
| ArrayList<Object> 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 IMPL_HELPER.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 IMPL_HELPER.nonBinaryCompatibleGet(pc, getVersion); |
| } |
| } |
| /** |
| * Tests whether the parameter instance is dirty. |
| * |
| * <p>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 IMPL_HELPER.nonBinaryCompatibleIs(pc, isDirty); |
| } |
| } |
| |
| /** |
| * Tests whether the parameter instance is transactional. |
| * |
| * <p>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 IMPL_HELPER.nonBinaryCompatibleIs(pc, isTransactional); |
| } |
| } |
| |
| /** |
| * Tests whether the parameter instance is persistent. |
| * |
| * <p>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 IMPL_HELPER.nonBinaryCompatibleIs(pc, isPersistent); |
| } |
| } |
| |
| /** |
| * Tests whether the parameter instance has been newly made persistent. |
| * |
| * <p>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 IMPL_HELPER.nonBinaryCompatibleIs(pc, isNew); |
| } |
| } |
| |
| /** |
| * Tests whether the parameter instance has been deleted. |
| * |
| * <p>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 IMPL_HELPER.nonBinaryCompatibleIs(pc, isDeleted); |
| } |
| } |
| |
| /** |
| * Tests whether the parameter instance has been detached. |
| * |
| * <p>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 IMPL_HELPER.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)) { |
| return isDirty(pc) ? ObjectState.DETACHED_DIRTY : ObjectState.DETACHED_CLEAN; |
| } else { |
| if (isPersistent(pc)) { |
| return isTransactional(pc) |
| ? getPersistentTransactionalObjectState(pc) |
| : getPersistentNonTransactionalObjectState(pc); |
| } else { |
| return isTransactional(pc) |
| ? getTransientTransactionalObjectState(pc) |
| : 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, Constants.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, Constants.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.ReadOnly", |
| * <BR>"javax.jdo.option.TransactionIsolationLevel", |
| * <BR>"javax.jdo.option.TransactionType", |
| * <BR>"javax.jdo.option.ServerTimeZoneID", |
| * <BR>"javax.jdo.option.DatastoreReadTimeoutMillis", |
| * <BR>"javax.jdo.option.DatastoreWriteTimeoutMillis", |
| * <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. |
| * |
| * @param overrides Overrides of properties |
| * @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 |
| * @return the <code>PersistenceManagerFactory</code>. |
| * @throws JDOFatalUserException if |
| * <ul> |
| * <li>the pmfClassLoader passed is invalid; or |
| * <li>a valid class name cannot be obtained from either <code>props</code> or system |
| * resources (an entry in META-INF/services/javax.jdo.PersistenceManagerFactory); or |
| * <li>all implementations throw an exception. |
| * </ul> |
| * |
| * @since 2.1 |
| */ |
| protected static PersistenceManagerFactory getPersistenceManagerFactory( |
| Map<?, ?> overrides, Map<?, ?> props, ClassLoader pmfClassLoader) { |
| |
| List<Throwable> exceptions = new ArrayList<>(); |
| if (pmfClassLoader == null) |
| throw new JDOFatalUserException(MSG.msg("EXC_GetPMFNullLoader")); // NOI18N |
| |
| JDOImplHelper.assertOnlyKnownStandardProperties(overrides); |
| JDOImplHelper.assertOnlyKnownStandardProperties(props); |
| |
| // first try to get the class name from the properties object. |
| String pmfClassName = (String) props.get(Constants.PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); |
| |
| if (!isNullOrBlank(pmfClassName)) { |
| // a valid name was returned from the properties. |
| return invokeGetPersistenceManagerFactoryOnImplementation( |
| pmfClassName, overrides, props, pmfClassLoader); |
| |
| } else { |
| /* |
| * If you have a jar file that provides the jdo implementation, |
| * a file naming the implementation goes into the file |
| * packaged into the jar file, called |
| * META-INF/services/javax.jdo.PersistenceManagerFactory. |
| * The contents of the file is a string that is the PMF class name, |
| * null or blank. |
| * For each file in pmfClassLoader named |
| * META-INF/services/javax.jdo.PersistenceManagerFactory, |
| * this method will try to invoke the getPersistenceManagerFactory |
| * method of the implementation class. |
| * Return the factory if a valid class name is extracted from |
| * resources and the invocation returns an instance. |
| * Otherwise add the exception thrown to |
| * an exception list. |
| */ |
| Enumeration<URL> urls = null; |
| try { |
| urls = getResources(pmfClassLoader, Constants.SERVICE_LOOKUP_PMF_RESOURCE_NAME); |
| } catch (Exception ex) { |
| exceptions.add(ex); |
| } |
| |
| if (urls != null) { |
| while (urls.hasMoreElements()) { |
| |
| try { |
| pmfClassName = getClassNameFromURL(urls.nextElement()); |
| |
| // return the implementation that is valid. |
| return invokeGetPersistenceManagerFactoryOnImplementation( |
| pmfClassName, overrides, props, pmfClassLoader); |
| |
| } catch (Exception ex) { |
| |
| // remember exceptions from failed pmf invocations |
| exceptions.add(ex); |
| } |
| } |
| } |
| } |
| |
| // no PMF class name in props and no services. |
| |
| throw new JDOFatalUserException( |
| MSG.msg("EXC_GetPMFNoPMFClassNamePropertyOrPUNameProperty"), |
| 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 Throw if an error occurs on accessing this URL |
| * @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) |
| * @param name Name of the PMF |
| * @return PersistenceManagerFactory |
| */ |
| 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) |
| * @param name Name of the PMF |
| * @param loader ClassLoader to use |
| * @return PersistenceManagerFactory |
| */ |
| 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) |
| * @param name Name of the PMF |
| * @param resourceLoader ClassLoader to use for loading resources |
| * @param pmfLoader ClassLoader to use for loading the PMF |
| * @return PersistenceManagerFactory |
| */ |
| 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) |
| * @param name Name of the PMF |
| * @param overrides Property overrides |
| * @return PersistenceManagerFactory |
| */ |
| 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) |
| * @param overrides Property overrides |
| * @param name Name of the PMF |
| * @param resourceLoader ClassLoader to use for loading resources |
| * @return The PMF |
| */ |
| 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.DatastoreReadTimeoutMillis", |
| * <BR>"javax.jdo.option.DatastoreWriteTimeoutMillis", |
| * <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>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<Object, Object> props = null; |
| // trim spaces from name and ensure non-null |
| name = (name == null ? Constants.ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME : name.trim()); |
| if (!Constants.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(Constants.PROPERTY_SPI_RESOURCE_NAME, name); |
| props.remove(Constants.PROPERTY_NAME); |
| return getPersistenceManagerFactory(overrides, props, pmfLoader); |
| } |
| // props were null; try getting from jdoconfig.xml |
| props = getPropertiesFromJdoconfig(name, resourceLoader); |
| if (props != null) { |
| // inform the impl that the config came from a jdoconfig.xml |
| // element with the given name |
| props.put(Constants.PROPERTY_NAME, name); |
| props.remove(Constants.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 (!Constants.ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME.equals(name)) { |
| props = new Properties(); |
| props.put(Constants.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) { |
| try { |
| Class<?> implClass = forName(pmfClassName, true, cl); |
| Method m = |
| getMethod( |
| implClass, |
| "getPersistenceManagerFactory", // NOI18N |
| overrides != null ? new Class[] {Map.class, Map.class} : new Class[] {Map.class}); |
| PersistenceManagerFactory pmf = |
| (PersistenceManagerFactory) |
| invoke( |
| m, |
| null, |
| overrides != null |
| ? new Object[] {overrides, properties} |
| : new Object[] {properties}); |
| if (pmf == null) { |
| throw new JDOFatalInternalException(MSG.msg("EXC_GetPMFNullPMF", pmfClassName)); // NOI18N |
| } |
| return pmf; |
| } catch (ClassNotFoundException e) { |
| throw new JDOFatalUserException( |
| MSG.msg("EXC_GetPMFClassNotFound", pmfClassName), e); // NOI18N |
| } catch (NoSuchMethodException e) { |
| throw new JDOFatalInternalException( |
| MSG.msg( |
| overrides != null ? "EXC_GetPMFNoSuchMethod2" : "EXC_GetPMFNoSuchMethod", |
| pmfClassName), |
| e); // NOI18N |
| } 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); // NOI18N |
| } 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_GET_PMF_UNEXPECTED_EXCEPTION), ite); |
| } |
| } |
| |
| /** |
| * 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<Object, Object> 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(); |
| props.load(in); |
| } |
| } catch (IOException ioe) { |
| throw new JDOFatalUserException(MSG.msg(EXC_GET_PMF_IOEXCEPTION_RSRC, name), ioe); // NOI18N |
| } finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException ioe) { |
| // this code block is deliberately left empty |
| } |
| } |
| } |
| return props; |
| } |
| |
| /** |
| * @see #getNamedPMFProperties(String,ClassLoader,String) |
| * @since 2.1 |
| * @param name Name of the PMF |
| * @param resourceLoader ClassLoader to use for loading resources |
| * @return The properties for this PMF |
| */ |
| protected static Map<Object, Object> getPropertiesFromJdoconfig( |
| String name, ClassLoader resourceLoader) { |
| return getNamedPMFProperties(name, resourceLoader, Constants.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<Object, Object> getNamedPMFProperties( |
| String name, ClassLoader resourceLoader, String jdoconfigResourceName) { |
| // key is PU name, value is Map of PU properties |
| Map<String, Map<Object, Object>> propertiesByNameInAllConfigs = new HashMap<>(); |
| try { |
| URL firstFoundConfigURL = null; |
| |
| // get all JDO configurations |
| Enumeration<URL> resources = getResources(resourceLoader, jdoconfigResourceName); |
| |
| if (resources.hasMoreElements()) { |
| ArrayList<URL> processedResources = new ArrayList<>(); |
| |
| // get ready to parse XML |
| DocumentBuilderFactory factory = getDocumentBuilderFactory(); |
| do { |
| URL currentConfigURL = resources.nextElement(); |
| if (processedResources.contains(currentConfigURL)) { |
| continue; |
| } else { |
| processedResources.add(currentConfigURL); |
| } |
| |
| Map<String, Map<Object, Object>> 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_GET_PMF_IOEXCEPTION_RSRC, name), ioe); // NOI18N |
| } |
| |
| // done with reading all config resources; |
| // return what we found, which may very well be null |
| return propertiesByNameInAllConfigs.get(name); |
| } |
| |
| protected static DocumentBuilderFactory getDocumentBuilderFactory() { |
| @SuppressWarnings("static-access") |
| DocumentBuilderFactory factory = IMPL_HELPER.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() { |
| @SuppressWarnings("static-access") |
| ErrorHandler handler = IMPL_HELPER.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<Object, Object>> readNamedPMFProperties( |
| URL url, String requestedPMFName, DocumentBuilderFactory factory) { |
| requestedPMFName = requestedPMFName == null ? "" : requestedPMFName.trim(); |
| |
| Map<String, Map<Object, Object>> 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(Constants.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(Constants.PROPERTY_NAME); |
| String pmfNameFromElem = pmfPropertiesFromElements.getProperty(Constants.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 = Constants.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)) { |
| for (Object o : pmfPropertiesFromAttributes.keySet()) { |
| String property = (String) o; |
| 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_GET_PMF_IOEXCEPTION_RSRC, 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(), |
| e.getLineNumber(), |
| 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 = 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 (Constants.ELEMENT_PROPERTY.equalsIgnoreCase(elementName)) { |
| // <property name="..." value="..."/> |
| |
| // get the "name" attribute's value (required) |
| Node nameAtt = attributes.getNamedItem(Constants.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 = 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(Constants.PROPERTY_ATTRIBUTE_VALUE); |
| String value = valueAtt == null ? null : valueAtt.getNodeValue().trim(); |
| |
| p.put(propertyName, value); |
| } else if (Constants.ELEMENT_INSTANCE_LIFECYCLE_LISTENER.equals(elementName)) { |
| // <instance-lifecycle-listener listener="..." classes="..."/> |
| |
| // get the "listener" attribute's value |
| Node listenerAtt = |
| attributes.getNamedItem(Constants.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 = Constants.PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER + listener; |
| |
| // get the "classes" attribute's value (optional) |
| Node classesAtt = |
| attributes.getNamedItem(Constants.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 |
| |
| 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) { |
| // this code block is deliberately left empty, |
| } |
| } |
| } |
| |
| /** |
| * 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 a <code>JDOEnhancer</code> using the available enhancer(s) specified in |
| * "META-INF/services/JDOEnhancer" using the context class loader. |
| * |
| * @return the <code>JDOEnhancer</code>. |
| * @throws JDOFatalUserException if no available enhancer |
| * @since 3.0 |
| */ |
| public static JDOEnhancer getEnhancer() { |
| return getEnhancer(getContextClassLoader()); |
| } |
| |
| /** |
| * Get a <code>JDOEnhancer</code> using the available enhancer(s) specified in |
| * "META-INF/services/JDOEnhancer" |
| * |
| * @param loader the loader to use for loading the JDOEnhancer class (if any) |
| * @return the <code>JDOEnhancer</code>. |
| * @throws JDOFatalUserException if no available enhancer |
| * @since 3.0 |
| */ |
| public static JDOEnhancer getEnhancer(ClassLoader loader) { |
| ClassLoader ctrLoader = loader; |
| if (ctrLoader == null) { |
| ctrLoader = Thread.currentThread().getContextClassLoader(); |
| } |
| |
| /* |
| * If you have a jar file that provides the jdo enhancer implementation, |
| * a file naming the implementation goes into the file |
| * packaged into the jar file, called "META-INF/services/javax.jdo.JDOEnhancer". |
| * The contents of the file is a string that is the enhancer class name. |
| * For each file in the class loader named "META-INF/services/javax.jdo.JDOEnhancer", |
| * this method will invoke the default constructor of the implementation class. |
| * Return the enhancer if a valid class name is extracted from resources and |
| * the invocation returns an instance. |
| * Otherwise add the exception thrown to an exception list. |
| */ |
| ArrayList<Throwable> exceptions = new ArrayList<>(); |
| int numberOfJDOEnhancers = 0; |
| Enumeration<URL> urls = null; |
| try { |
| urls = getResources(loader, Constants.SERVICE_LOOKUP_ENHANCER_RESOURCE_NAME); |
| } catch (Throwable ex) { |
| exceptions.add(ex); |
| } |
| |
| if (urls != null) { |
| while (urls.hasMoreElements()) { |
| numberOfJDOEnhancers++; |
| try { |
| String enhancerClassName = getClassNameFromURL(urls.nextElement()); |
| Class<?> enhancerClass = forName(enhancerClassName, true, ctrLoader); |
| return (JDOEnhancer) enhancerClass.newInstance(); |
| } catch (Throwable ex) { |
| // remember exceptions from failed enhancer invocations |
| exceptions.add(ex); |
| } |
| } |
| } |
| |
| throw new JDOFatalUserException( |
| MSG.msg("EXC_GetEnhancerNoValidEnhancerAvailable", numberOfJDOEnhancers), |
| exceptions.toArray(new Throwable[exceptions.size()])); |
| } |
| |
| /** |
| * 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 doPrivileged( |
| (PrivilegedAction<ClassLoader>) () -> 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 doPrivileged( |
| (PrivilegedAction<InputStream>) () -> 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 doPrivileged( |
| (PrivilegedExceptionAction<Method>) |
| () -> 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 doPrivileged( |
| (PrivilegedExceptionAction<Object>) () -> method.invoke(instance, parameters)); |
| } catch (PrivilegedActionException ex) { |
| Exception cause = ex.getException(); |
| if (cause instanceof IllegalAccessException) { |
| throw (IllegalAccessException) cause; |
| } else if (cause instanceof InvocationTargetException) { |
| throw (InvocationTargetException) cause; |
| } else { |
| throw new JDOFatalInternalException(MSG.msg(EXC_GET_PMF_UNEXPECTED_EXCEPTION), cause); |
| } |
| } |
| } |
| |
| /** |
| * Get resources of the resource loader. Perform this operation in a doPrivileged block. |
| * |
| * @param resourceLoader ClassLoader to use for loading resources |
| * @param resourceName Name of the resource |
| * @return the resources |
| * @throws IOException if an error occurs accessing the resources |
| */ |
| protected static Enumeration<URL> getResources( |
| final ClassLoader resourceLoader, final String resourceName) throws IOException { |
| try { |
| return doPrivileged( |
| (PrivilegedExceptionAction<Enumeration<URL>>) |
| () -> 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 doPrivileged( |
| (PrivilegedExceptionAction<Class<?>>) () -> 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 doPrivileged((PrivilegedExceptionAction<InputStream>) () -> url.openStream()); |
| } catch (PrivilegedActionException ex) { |
| throw (IOException) ex.getException(); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static <T> T doPrivileged(PrivilegedAction<T> privilegedAction) { |
| try { |
| return (T) LegacyJava.doPrivilegedAction.invoke(null, privilegedAction); |
| } catch (IllegalAccessException | InvocationTargetException e) { |
| if (e.getCause() instanceof RuntimeException) { |
| throw (RuntimeException) e.getCause(); |
| } |
| throw new JDOFatalInternalException(e.getMessage()); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static <T> T doPrivileged(PrivilegedExceptionAction<T> privilegedAction) |
| throws PrivilegedActionException { |
| try { |
| return (T) LegacyJava.doPrivilegedExceptionAction.invoke(null, privilegedAction); |
| } catch (IllegalAccessException | InvocationTargetException e) { |
| if (e.getCause() instanceof PrivilegedActionException) { |
| throw (PrivilegedActionException) e.getCause(); |
| } |
| throw new PrivilegedActionException(e); |
| } |
| } |
| |
| private static ObjectState getPersistentTransactionalObjectState(Object pc) { |
| if (isDirty(pc)) { |
| if (isNew(pc)) { |
| return isDeleted(pc) ? ObjectState.PERSISTENT_NEW_DELETED : ObjectState.PERSISTENT_NEW; |
| } else { |
| return isDeleted(pc) ? ObjectState.PERSISTENT_DELETED : ObjectState.PERSISTENT_DIRTY; |
| } |
| } else { |
| // Persistent Transactional Not Dirty |
| return ObjectState.PERSISTENT_CLEAN; |
| } |
| } |
| |
| private static ObjectState getPersistentNonTransactionalObjectState(Object pc) { |
| return isDirty(pc) |
| ? ObjectState.PERSISTENT_NONTRANSACTIONAL_DIRTY |
| : ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL; |
| } |
| |
| private static ObjectState getTransientTransactionalObjectState(Object pc) { |
| return isDirty(pc) ? ObjectState.TRANSIENT_DIRTY : ObjectState.TRANSIENT_CLEAN; |
| } |
| } |