/*
 * 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
<<<<<<< Updated upstream
 *
 *     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
=======
 * 
 *     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 
>>>>>>> Stashed changes
 * 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

  /**
   * 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(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);
    xref.put(PMF_ATTRIBUTE_DATASTORE_READ_TIMEOUT_MILLIS, PROPERTY_DATASTORE_READ_TIMEOUT_MILLIS);
    xref.put(PMF_ATTRIBUTE_DATASTORE_WRITE_TIMEOUT_MILLIS, 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() {}

  /**
   * 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)) {
      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.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(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, SERVICE_LOOKUP_PMF_RESOURCE_NAME);
      } catch (Throwable ex) {
        exceptions.add(ex);
      }

      if (urls != null) {
        while (urls.hasMoreElements()) {

          try {
            pmfClassName = getClassNameFromURL(urls.nextElement());

            // return the implementation that is valid.
            PersistenceManagerFactory pmf =
                invokeGetPersistenceManagerFactoryOnImplementation(
                    pmfClassName, overrides, props, pmfClassLoader);
            return pmf;

          } catch (Throwable 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 ? 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, resourceLoader);
    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", // NOI18N
                new Class[] {Map.class, Map.class});
        PersistenceManagerFactory pmf =
            (PersistenceManagerFactory) invoke(m, null, new Object[] {overrides, 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("EXC_GetPMFNoSuchMethod2", 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_GetPMFUnexpectedException"), ite); // NOI18N
      }
    } else {
      // overrides is null; use getPersistenceManagerFactory(Map props)
      try {
        Class<?> implClass = forName(pmfClassName, true, cl);
        Method m =
            getMethod(
                implClass,
                "getPersistenceManagerFactory", // NOI18N
                new Class[] {Map.class});
        PersistenceManagerFactory pmf =
            (PersistenceManagerFactory) invoke(m, null, 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("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_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<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_GetPMFIOExceptionRsrc", name), ioe); // NOI18N
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException ioe) {
        }
      }
    }
    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, 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_GetPMFIOExceptionRsrc", 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&lt;String,Map&gt; 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(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)) {
          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_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(),
              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 (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 = 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

    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 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;
    try {
      Enumeration<URL> urls = getResources(loader, SERVICE_LOOKUP_ENHANCER_RESOURCE_NAME);
      if (urls != null) {
        while (urls.hasMoreElements()) {
          numberOfJDOEnhancers++;
          try {
            String enhancerClassName = getClassNameFromURL(urls.nextElement());
            Class<?> enhancerClass = forName(enhancerClassName, true, ctrLoader);
            JDOEnhancer enhancer = (JDOEnhancer) enhancerClass.newInstance();
            return enhancer;
          } catch (Throwable ex) {
            // remember exceptions from failed enhancer invocations
            exceptions.add(ex);
          }
        }
      }
    } catch (Throwable ex) {
      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;
    }
  }

  /**
   * 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);
    }
  }
}
