/*
 * 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.
 */

/*
 * JDOImplHelper.java
 *
 */

package javax.jdo.spi;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.PrivilegedAction;
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import javax.jdo.Constants;
import javax.jdo.JDOException;
import javax.jdo.JDOFatalInternalException;
import javax.jdo.JDOFatalUserException;
import javax.jdo.JDOUserException;
import javax.jdo.LegacyJava;
import javax.jdo.LegacyJava.SecurityManager;
import javax.xml.parsers.DocumentBuilderFactory;
import org.xml.sax.ErrorHandler;

/**
 * This class is a helper class for JDO implementations. It contains methods to register metadata
 * for persistence-capable classes and to perform common operations needed by implementations, not
 * by end users.
 *
 * <p><code>JDOImplHelper</code> allows construction of instances of persistence-capable classes
 * without using reflection.
 *
 * <p>Persistence-capable classes register themselves via a static method at class load time. There
 * is no security restriction on this access. JDO implementations get access to the functions
 * provided by this class only if they are authorized by the security manager. To avoid having every
 * call go through the security manager, only the call to get an instance is checked. Once an
 * implementation has an instance, any of the methods can be invoked without security checks.
 *
 * @version 2.1
 */
public class JDOImplHelper extends java.lang.Object {

  /**
   * This synchronized <code>HashMap</code> contains a static mapping of <code>PersistenceCapable
   * </code> class to metadata for the class used for constructing new instances. New entries are
   * added by the static method in each <code>PersistenceCapable</code> class. Entries are never
   * removed.
   */
  private static final Map<Class<?>, Meta> registeredClasses =
      Collections.synchronizedMap(new HashMap<>());

  /**
   * This Set contains all classes that have registered for setStateManager permissions via
   * authorizeStateManagerClass. Only the key is used in order to maintain a weak set of classes.
   */
  private static final Map<Class<?>, Class<?>> authorizedStateManagerClasses = new WeakHashMap<>();

  /** This list contains the registered listeners for <code>RegisterClassEvent</code>s. */
  private static final List<RegisterClassListener> listeners = new ArrayList<>();

  /** The list of registered StateInterrogation instances */
  private static List<StateInterrogation> stateInterrogations = new ArrayList<>();

  /** The singleton <code>JDOImplHelper</code> instance. */
  private static final JDOImplHelper jdoImplHelper = new JDOImplHelper();

  /** The Internationalization message helper. */
  private static final I18NHelper msg = I18NHelper.getInstance("javax.jdo.Bundle"); // NOI18N

  /** The DateFormat pattern. */
  private static String dateFormatPattern;

  /** The default DateFormat instance. */
  private static DateFormat dateFormat;

  /** The DocumentBuilderFactory used during jdoconfig.xml parsing. */
  private static DocumentBuilderFactory documentBuilderFactory;

  /** The ErrorHandler used during jdoconfig.xml parsing. */
  private static ErrorHandler errorHandler;

  /** JDO standard properties that the user can configure. */
  public static final Set<String> USER_CONFIGURABLE_STANDARD_PROPERTIES =
      createUserConfigurableStandardProperties();

  private static Set<String> createUserConfigurableStandardProperties() {
    Set<String> props = new HashSet<>();

    props.add(Constants.PROPERTY_CONNECTION_DRIVER_NAME);
    props.add(Constants.PROPERTY_CONNECTION_FACTORY2_NAME);
    props.add(Constants.PROPERTY_CONNECTION_FACTORY_NAME);
    props.add(Constants.PROPERTY_CONNECTION_PASSWORD);
    props.add(Constants.PROPERTY_CONNECTION_URL);
    props.add(Constants.PROPERTY_CONNECTION_USER_NAME);
    props.add(Constants.PROPERTY_COPY_ON_ATTACH);
    props.add(Constants.PROPERTY_DATASTORE_READ_TIMEOUT_MILLIS);
    props.add(Constants.PROPERTY_DATASTORE_WRITE_TIMEOUT_MILLIS);
    props.add(Constants.PROPERTY_DETACH_ALL_ON_COMMIT);
    props.add(Constants.PROPERTY_IGNORE_CACHE);
    props.add(Constants.PROPERTY_INSTANCE_LIFECYCLE_LISTENER);
    props.add(Constants.PROPERTY_MAPPING);
    props.add(Constants.PROPERTY_MAPPING_CATALOG);
    props.add(Constants.PROPERTY_MAPPING_SCHEMA);
    props.add(Constants.PROPERTY_MULTITHREADED);
    props.add(Constants.PROPERTY_NAME);
    props.add(Constants.PROPERTY_NONTRANSACTIONAL_READ);
    props.add(Constants.PROPERTY_NONTRANSACTIONAL_WRITE);
    props.add(Constants.PROPERTY_OPTIMISTIC);
    props.add(Constants.PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS);
    props.add(Constants.PROPERTY_PERSISTENCE_UNIT_NAME);
    props.add(Constants.PROPERTY_READONLY);
    props.add(Constants.PROPERTY_RESTORE_VALUES);
    props.add(Constants.PROPERTY_RETAIN_VALUES);
    props.add(Constants.PROPERTY_SERVER_TIME_ZONE_ID);
    props.add(Constants.PROPERTY_SPI_RESOURCE_NAME);
    props.add(Constants.PROPERTY_TRANSACTION_ISOLATION_LEVEL);
    props.add(Constants.PROPERTY_TRANSACTION_TYPE);

    return Collections.unmodifiableSet(props);
  }

  static final String JAVAX_JDO_PREFIX_LOWER_CASED = Constants.JAVAX_JDO_PREFIX.toLowerCase();

  static final String PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER_LOWER_CASED =
      Constants.PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER.toLowerCase();

  static final Set<String> USER_CONFIGURABLE_STANDARD_PROPERTIES_LOWER_CASED =
      createUserConfigurableStandardPropertiesLowerCased();

  static Set<String> createUserConfigurableStandardPropertiesLowerCased() {
    Set<String> mixedCased = createUserConfigurableStandardProperties();
    Set<String> lowerCased = new HashSet<>(mixedCased.size());

    for (String propertyName : mixedCased) {
      lowerCased.add(propertyName.toLowerCase());
    }
    return Collections.unmodifiableSet(lowerCased);
  }

  /** Register the default DateFormat instance. */
  static {
    jdoImplHelper.registerDateFormat(getDateTimeInstance());
  }

  /** Creates new JDOImplHelper */
  private JDOImplHelper() {}

  /**
   * Get an instance of <code>JDOImplHelper</code>. This method checks that the caller is authorized
   * for <code>JDOPermission("getMetadata")</code>, and if not, throws <code>SecurityException
   * </code>.
   *
   * @return an instance of <code>JDOImplHelper</code>.
   * @throws SecurityException if the caller is not authorized for JDOPermission("getMetadata").
   */
  public static JDOImplHelper getInstance() throws SecurityException {
    SecurityManager sec = LegacyJava.getSecurityManager();
    if (sec != null) {
      // throws exception if caller is not authorized
      sec.checkPermission(JDOPermission.GET_METADATA);
    }
    return jdoImplHelper;
  }

  /**
   * Get the field names for a <code>PersistenceCapable</code> class. The order of fields is the
   * natural ordering of the <code>String</code> class (without considering localization).
   *
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @return the field names for the class.
   */
  public String[] getFieldNames(Class<?> pcClass) {
    Meta meta = getMeta(pcClass);
    return meta.getFieldNames();
  }

  /**
   * Get the field types for a <code>PersistenceCapable</code> class. The order of fields is the
   * same as for field names.
   *
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @return the field types for the class.
   */
  public Class<?>[] getFieldTypes(Class<?> pcClass) {
    Meta meta = getMeta(pcClass);
    return meta.getFieldTypes();
  }

  /**
   * Get the field flags for a <code>PersistenceCapable</code> class. The order of fields is the
   * same as for field names.
   *
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @return the field types for the class.
   */
  public byte[] getFieldFlags(Class<?> pcClass) {
    Meta meta = getMeta(pcClass);
    return meta.getFieldFlags();
  }

  /**
   * Get the persistence-capable superclass for a <code>PersistenceCapable</code> class.
   *
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @return The <code>PersistenceCapable</code> superclass for this class, or <code>null</code> if
   *     there isn't one.
   */
  public Class<?> getPersistenceCapableSuperclass(Class<?> pcClass) {
    Meta meta = getMeta(pcClass);
    return meta.getPersistenceCapableSuperclass();
  }

  /**
   * Create a new instance of the class and assign its <code>jdoStateManager</code>. The new
   * instance has its <code>jdoFlags</code> set to <code>LOAD_REQUIRED</code>.
   *
   * @see PersistenceCapable#jdoNewInstance(StateManager sm)
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @param sm the <code>StateManager</code> which will own the new instance.
   * @return the new instance, or <code>null</code> if the class is not registered.
   */
  public PersistenceCapable newInstance(Class<?> pcClass, StateManager sm) {
    Meta meta = getMeta(pcClass);
    PersistenceCapable pcInstance = meta.getPC();
    return pcInstance == null ? null : pcInstance.jdoNewInstance(sm);
  }

  /**
   * Create a new instance of the class and assign its <code>jdoStateManager</code> and key values
   * from the ObjectId. If the oid parameter is <code>null</code>, no key values are copied. The new
   * instance has its <code>jdoFlags</code> set to <code>LOAD_REQUIRED</code>.
   *
   * @see PersistenceCapable#jdoNewInstance(StateManager sm, Object oid)
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @param sm the <code>StateManager</code> which will own the new instance.
   * @return the new instance, or <code>null</code> if the class is not registered.
   * @param oid the ObjectId instance from which to copy key field values.
   */
  public PersistenceCapable newInstance(Class<?> pcClass, StateManager sm, Object oid) {
    Meta meta = getMeta(pcClass);
    PersistenceCapable pcInstance = meta.getPC();
    return pcInstance == null ? null : pcInstance.jdoNewInstance(sm, oid);
  }

  /**
   * Create a new instance of the ObjectId class of this <code>PersistenceCapable</code> class. It
   * is intended only for application identity. This method should not be called for classes that
   * use single field identity; newObjectIdInstance(Class, Object) should be used instead. If the
   * class has been enhanced for datastore identity, or if the class is abstract, null is returned.
   *
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @return the new ObjectId instance, or <code>null</code> if the class is not registered.
   */
  public Object newObjectIdInstance(Class<?> pcClass) {
    Meta meta = getMeta(pcClass);
    PersistenceCapable pcInstance = meta.getPC();
    return pcInstance == null ? null : pcInstance.jdoNewObjectIdInstance();
  }

  /**
   * Create a new instance of the class used by the parameter Class for JDO identity, using the key
   * constructor of the object id class. It is intended for single field identity. The identity
   * instance returned has no relationship with the values of the primary key fields of the
   * persistence-capable instance on which the method is called. If the key is the wrong class for
   * the object id class, null is returned.
   *
   * <p>For classes that use single field identity, if the parameter is of one of the following
   * types, the behavior must be as specified:
   *
   * <ul>
   *   <li><code>Number</code> or <code>Character</code>: the parameter must be the single field
   *       type or the wrapper class of the primitive field type; the parameter is passed to the
   *       single field identity constructor
   *   <li><code>ObjectIdFieldSupplier</code>: the field value is fetched from the <code>
   *       ObjectIdFieldSupplier</code> and passed to the single field identity constructor
   *   <li><code>String</code>: the String is passed to the single field identity constructor
   * </ul>
   *
   * @return the new ObjectId instance, or <code>null</code> if the class is not registered.
   * @param obj the <code>Object</code> form of the object id
   * @param pcClass the <code>PersistenceCapable</code> class.
   * @since 2.0
   */
  public Object newObjectIdInstance(Class<?> pcClass, Object obj) {
    Meta meta = getMeta(pcClass);
    PersistenceCapable pcInstance = meta.getPC();
    return (pcInstance == null) ? null : pcInstance.jdoNewObjectIdInstance(obj);
  }

  /**
   * Copy fields from an outside source to the key fields in the ObjectId. This method is generated
   * in the <code>PersistenceCapable</code> class to generate a call to the field manager for each
   * key field in the ObjectId.
   *
   * <p>For example, an ObjectId class that has three key fields (<code>int id</code>, <code>
   * String name</code>, and <code>Float salary</code>) would have the method generated:
   *
   * <p><code>
   * void jdoCopyKeyFieldsToObjectId (Object oid, ObjectIdFieldSupplier fm) {
   * <BR>    oid.id = fm.fetchIntField (0);
   * <BR>    oid.name = fm.fetchStringField (1);
   * <BR>    oid.salary = fm.fetchObjectField (2);
   * <BR>}</code>
   *
   * <p>The implementation is responsible for implementing the <code>ObjectIdFieldSupplier</code> to
   * provide the values for the key fields.
   *
   * @param pcClass the <code>PersistenceCapable Class</code>.
   * @param oid the ObjectId target of the copy.
   * @param fm the field manager that supplies the field values.
   */
  public void copyKeyFieldsToObjectId(
      Class<?> pcClass, PersistenceCapable.ObjectIdFieldSupplier fm, Object oid) {
    Meta meta = getMeta(pcClass);
    PersistenceCapable pcInstance = meta.getPC();
    if (pcInstance == null) {
      throw new JDOFatalInternalException(
          msg.msg("ERR_AbstractClassNoIdentity", pcClass.getName())); // NOI18N
    }
    pcInstance.jdoCopyKeyFieldsToObjectId(fm, oid);
  }

  /**
   * Copy fields to an outside source from the key fields in the ObjectId. This method is generated
   * in the <code>PersistenceCapable</code> class to generate a call to the field manager for each
   * key field in the ObjectId. For example, an ObjectId class that has three key fields (<code>
   * int id</code>, <code>String name</code>, and <code>Float salary</code>) would have the method
   * generated:
   *
   * <p><code>void jdoCopyKeyFieldsFromObjectId
   * <BR>        (PersistenceCapable oid, ObjectIdFieldConsumer fm) {
   * <BR>     fm.storeIntField (0, oid.id);
   * <BR>     fm.storeStringField (1, oid.name);
   * <BR>     fm.storeObjectField (2, oid.salary);
   * <BR>}</code>
   *
   * <p>The implementation is responsible for implementing the <code>ObjectIdFieldConsumer</code> to
   * store the values for the key fields.
   *
   * @param pcClass the <code>PersistenceCapable</code> class
   * @param oid the ObjectId source of the copy.
   * @param fm the field manager that receives the field values.
   */
  public void copyKeyFieldsFromObjectId(
      Class<?> pcClass, PersistenceCapable.ObjectIdFieldConsumer fm, Object oid) {
    Meta meta = getMeta(pcClass);
    PersistenceCapable pcInstance = meta.getPC();
    if (pcInstance == null) {
      throw new JDOFatalInternalException(
          msg.msg("ERR_AbstractClassNoIdentity", pcClass.getName())); // NOI18N
    }
    pcInstance.jdoCopyKeyFieldsFromObjectId(fm, oid);
  }

  /**
   * Register metadata by class. The registration will be done in the class named <code>
   * JDOImplHelper</code> loaded by the same or an ancestor class loader as the <code>
   * PersistenceCapable</code> class performing the registration.
   *
   * @param pcClass the <code>PersistenceCapable</code> class used as the key for lookup.
   * @param fieldNames an array of <code>String</code> field names for persistent and transactional
   *     fields
   * @param fieldTypes an array of <code>Class</code> field types
   * @param fieldFlags the Field Flags for persistent and transactional fields
   * @param pc an instance of the <code>PersistenceCapable</code> class
   * @param persistenceCapableSuperclass the most immediate superclass that is <code>
   *     PersistenceCapable</code>
   */
  public static void registerClass(
      Class<?> pcClass,
      String[] fieldNames,
      Class<?>[] fieldTypes,
      byte[] fieldFlags,
      Class<?> persistenceCapableSuperclass,
      PersistenceCapable pc) {
    if (pcClass == null) throw new NullPointerException(msg.msg("ERR_NullClass")); // NOI18N
    Meta meta = new Meta(fieldNames, fieldTypes, fieldFlags, persistenceCapableSuperclass, pc);
    registeredClasses.put(pcClass, meta);

    // handle class registration listeners
    synchronized (listeners) {
      if (!listeners.isEmpty()) {
        RegisterClassEvent event =
            new RegisterClassEvent(
                jdoImplHelper,
                pcClass,
                fieldNames,
                fieldTypes,
                fieldFlags,
                persistenceCapableSuperclass);
        for (Iterator<RegisterClassListener> i = listeners.iterator(); i.hasNext(); ) {
          RegisterClassListener crl = i.next();
          if (crl != null) {
            crl.registerClass(event);
          }
        }
      }
    }
  }

  /**
   * Unregister metadata by class loader. This method unregisters all registered <code>
   * PersistenceCapable</code> classes loaded by the specified class loader. Any attempt to get
   * metadata for unregistered classes will result in a <code>JDOFatalUserException</code>.
   *
   * @param cl the class loader.
   * @since 1.0.2
   */
  public void unregisterClasses(ClassLoader cl) {
    SecurityManager sec = LegacyJava.getSecurityManager();
    if (sec != null) {
      // throws exception if caller is not authorized
      sec.checkPermission(JDOPermission.MANAGE_METADATA);
    }
    synchronized (registeredClasses) {
      for (Iterator<Class<?>> i = registeredClasses.keySet().iterator(); i.hasNext(); ) {
        Class<?> pcClass = i.next();
        // Note, the pc class was registered by calling the static
        // method JDOImplHelper.registerClass. This means the
        // JDOImplHelper class loader is the same as or an ancestor
        // of the class loader of the pc class. In this case method
        // getClassLoader does not perform a security check for
        // RuntimePermission("getClassLoader") and thus we do not
        // need a privileged block for the getClassLoader call.
        if ((pcClass != null) && (pcClass.getClassLoader() == cl)) {
          // unregister pc class, if its class loader is the
          // specified one.
          i.remove();
        }
      }
    }
  }

  /**
   * Unregister metadata by class. This method unregisters the specified class. Any further attempt
   * to get metadata for the specified class will result in a <code>JDOFatalUserException</code>.
   *
   * @param pcClass the <code>PersistenceCapable</code> class to be unregistered.
   * @since 1.0.2
   */
  public void unregisterClass(Class<?> pcClass) {
    if (pcClass == null) throw new NullPointerException(msg.msg("ERR_NullClass")); // NOI18N
    SecurityManager sec = LegacyJava.getSecurityManager();
    if (sec != null) {
      // throws exception if caller is not authorized
      sec.checkPermission(JDOPermission.MANAGE_METADATA);
    }
    registeredClasses.remove(pcClass);
  }

  /**
   * Add the specified <code>RegisterClassListener</code> to the listener list.
   *
   * @param crl the listener to be added
   */
  public void addRegisterClassListener(RegisterClassListener crl) {
    HashSet<Class<?>> alreadyRegisteredClasses = null;
    synchronized (listeners) {
      listeners.add(crl);
      // Make a copy of the existing set of registered classes.
      // Between these two lines of code, any number of new class
      // registrations might occur, and will then all wait until this
      // synchronized block completes. Some of the class registrations
      // might be delivered twice to the newly registered listener.
      alreadyRegisteredClasses = new HashSet<>(registeredClasses.keySet());
    }
    // new registrations will call the new listener while the following
    // occurs notify the new listener about already-registered classes
    for (Iterator<Class<?>> it = alreadyRegisteredClasses.iterator(); it.hasNext(); ) {
      Class<?> pcClass = it.next();
      Meta meta = getMeta(pcClass);
      RegisterClassEvent event =
          new RegisterClassEvent(
              this,
              pcClass,
              meta.getFieldNames(),
              meta.getFieldTypes(),
              meta.getFieldFlags(),
              meta.getPersistenceCapableSuperclass());
      crl.registerClass(event);
    }
  }

  /**
   * Remove the specified <code>RegisterClassListener</code> from the listener list.
   *
   * @param crl the listener to be removed
   */
  public void removeRegisterClassListener(RegisterClassListener crl) {
    synchronized (listeners) {
      listeners.remove(crl);
    }
  }

  /**
   * Returns a collection of class objects of the registered persistence-capable classes.
   *
   * @return registered persistence-capable classes
   */
  public Collection<Class<?>> getRegisteredClasses() {
    return Collections.unmodifiableCollection(registeredClasses.keySet());
  }

  /**
   * Look up the metadata for a <code>PersistenceCapable</code> class.
   *
   * @param pcClass the <code>Class</code>.
   * @return the <code>Meta</code> for the <code>Class</code>.
   */
  private static Meta getMeta(Class<?> pcClass) {
    Meta ret = registeredClasses.get(pcClass);
    if (ret == null) {
      throw new JDOFatalUserException(msg.msg("ERR_NoMetadata", pcClass.getName())); // NOI18N
    }
    return ret;
  }

  /**
   * Register a class authorized to replaceStateManager. The caller of this method must be
   * authorized for JDOPermission("setStateManager"). During replaceStateManager, a
   * persistence-capable class will call the corresponding checkAuthorizedStateManager and the class
   * of the instance of the parameter must have been registered.
   *
   * @param smClass a Class that is authorized for JDOPermission("setStateManager").
   * @throws SecurityException if the caller is not authorized for JDOPermission("setStateManager").
   * @since 1.0.1
   */
  public static void registerAuthorizedStateManagerClass(Class<?> smClass)
      throws SecurityException {
    if (smClass == null) throw new NullPointerException(msg.msg("ERR_NullClass")); // NOI18N
    SecurityManager sm = LegacyJava.getSecurityManager();
    if (sm != null) {
      sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
    }
    synchronized (authorizedStateManagerClasses) {
      authorizedStateManagerClasses.put(smClass, null);
    }
  }

  /**
   * Register classes authorized to replaceStateManager. The caller of this method must be
   * authorized for JDOPermission("setStateManager"). During replaceStateManager, a
   * persistence-capable class will call the corresponding checkAuthorizedStateManager and the class
   * of the instance of the parameter must have been registered.
   *
   * @param smClasses a Collection of Classes that are authorized for
   *     JDOPermission("setStateManager").
   * @throws SecurityException if the caller is not authorized for JDOPermission("setStateManager").
   * @since 1.0.1
   */
  public static void registerAuthorizedStateManagerClasses(Collection<?> smClasses)
      throws SecurityException {
    SecurityManager sm = LegacyJava.getSecurityManager();
    if (sm != null) {
      sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
      synchronized (authorizedStateManagerClasses) {
        for (Iterator<?> it = smClasses.iterator(); it.hasNext(); ) {
          Object smClass = it.next();
          if (!(smClass instanceof Class)) {
            throw new ClassCastException(
                msg.msg(
                    "ERR_StateManagerClassCast", // NOI18N
                    smClass.getClass().getName()));
          }
          registerAuthorizedStateManagerClass((Class<?>) it.next());
        }
      }
    }
  }

  /**
   * Register a DocumentBuilderFactory instance for use in parsing the resource(s)
   * META-INF/jdoconfig.xml. The default is governed by the semantics of
   * DocumentBuilderFactory.newInstance().
   *
   * @param factory the DocumentBuilderFactory instance to use
   * @since 2.1
   */
  public synchronized void registerDocumentBuilderFactory(DocumentBuilderFactory factory) {
    documentBuilderFactory = factory;
  }

  /**
   * Return the registered instance of DocumentBuilderFactory.
   *
   * @return the DocumentBuilderFactory if registered; null otherwise
   * @since 2.1
   */
  public static DocumentBuilderFactory getRegisteredDocumentBuilderFactory() {
    return documentBuilderFactory;
  }

  /**
   * Register an ErrorHandler instance for use in parsing the resource(s) META-INF/jdoconfig.xml.
   * The default is an ErrorHandler that throws on error or fatalError and ignores warnings.
   *
   * @param handler the ErrorHandler instance to use
   * @since 2.1
   */
  public synchronized void registerErrorHandler(ErrorHandler handler) {
    errorHandler = handler;
  }

  /**
   * Return the registered instance of ErrorHandler.
   *
   * @return the registered ErrorHandler if registered; null otherwise
   * @since 2.1
   */
  public static ErrorHandler getRegisteredErrorHandler() {
    return errorHandler;
  }

  /**
   * Check that the parameter instance is of a class that is authorized for
   * JDOPermission("setStateManager"). This method is called by the replaceStateManager method in
   * persistence-capable classes. A class that is passed as the parameter to replaceStateManager
   * must be authorized for JDOPermission("setStateManager"). To improve performance, first the set
   * of authorized classes is checked, and if not present, a regular permission check is made. The
   * regular permission check requires that all callers on the stack, including the
   * persistence-capable class itself, must be authorized for JDOPermission("setStateManager").
   *
   * @param sm an instance of StateManager whose class is to be checked.
   * @since 1.0.1
   */
  public static void checkAuthorizedStateManager(StateManager sm) {
    checkAuthorizedStateManagerClass(sm.getClass());
  }

  /**
   * Check that the parameter instance is a class that is authorized for
   * JDOPermission("setStateManager"). This method is called by the constructors of JDO Reference
   * Implementation classes.
   *
   * @param smClass a Class to be checked for JDOPermission("setStateManager")
   * @since 1.0.1
   */
  public static void checkAuthorizedStateManagerClass(Class<?> smClass) {
    final SecurityManager scm = LegacyJava.getSecurityManager();
    if (scm == null) {
      // if no security manager, no checking.
      return;
    }
    synchronized (authorizedStateManagerClasses) {
      if (authorizedStateManagerClasses.containsKey(smClass)) {
        return;
      }
    }
    // if not already authorized, perform "long" security checking.
    scm.checkPermission(JDOPermission.SET_STATE_MANAGER);
  }

  /**
   * Construct an instance of a key class using a String as input. This is a helper interface for
   * use with ObjectIdentity. Classes without a String constructor (such as those in java.lang and
   * java.util) will use this interface for constructing new instances. The result might be a
   * singleton or use some other strategy.
   */
  public interface StringConstructor {
    /**
     * Construct an instance of the class for which this instance is registered.
     *
     * @param s the parameter for construction
     * @return the constructed object
     */
    public Object construct(String s);
  }

  /**
   * Special StringConstructor instances for use with specific classes that have no public String
   * constructor. The Map is keyed on class instance and the value is an instance of
   * StringConstructor.
   */
  static final Map<Class<?>, StringConstructor> stringConstructorMap = new HashMap<>();

  /**
   * Register special StringConstructor instances. These instances are for constructing instances
   * from String parameters where there is no String constructor for them.
   *
   * @param cls the class to register a StringConstructor for
   * @param sc the StringConstructor instance
   * @return the previous StringConstructor registered for this class
   */
  public Object registerStringConstructor(Class<?> cls, StringConstructor sc) {
    synchronized (stringConstructorMap) {
      return stringConstructorMap.put(cls, sc);
    }
  }

  /** Register the default special StringConstructor instances. */
  static {
    if (isClassLoadable("java.util.Currency")) {
      jdoImplHelper.registerStringConstructor(
          Currency.class,
          s -> {
            try {
              return Currency.getInstance(s);
            } catch (IllegalArgumentException ex) {
              throw new JDOUserException(
                  msg.msg(
                      "EXC_CurrencyStringConstructorIllegalArgument", // NOI18N
                      s),
                  ex);
            } catch (Exception ex) {
              throw new JDOUserException(
                  msg.msg("EXC_CurrencyStringConstructorException"), // NOI18N
                  ex);
            }
          });
    }
    jdoImplHelper.registerStringConstructor(
        Locale.class,
        s -> {
          try {
            return getLocale(s);
          } catch (Exception ex) {
            throw new JDOUserException(
                msg.msg("EXC_LocaleStringConstructorException"), ex); // NOI18N
          }
        });
    jdoImplHelper.registerStringConstructor(
        Date.class,
        new StringConstructor() {
          public synchronized Object construct(String s) {
            try {
              // first, try the String as a Long
              return new Date(Long.parseLong(s));
            } catch (NumberFormatException ex) {
              // not a Long; try the formatted date
              ParsePosition pp = new ParsePosition(0);
              Date result = dateFormat.parse(s, pp);
              if (result == null) {
                throw new JDOUserException(
                    msg.msg(
                        "EXC_DateStringConstructor",
                        new Object[] // NOI18N
                        {s, pp.getErrorIndex(), dateFormatPattern}));
              }
              return result;
            }
          }
        });
  }

  /**
   * Parse the String to a Locale.
   *
   * @param s the name of the Locale
   * @return the Locale corresponding to the name
   */
  private static Locale getLocale(String s) {
    String lang = s;
    int firstUnderbar = s.indexOf('_');
    if (firstUnderbar == -1) {
      // nothing but language
      return new Locale(lang);
    }
    lang = s.substring(0, firstUnderbar);
    String country;
    int secondUnderbar = s.indexOf('_', firstUnderbar + 1);
    if (secondUnderbar == -1) {
      // nothing but language, country
      country = s.substring(firstUnderbar + 1);
      return new Locale(lang, country);
    }
    country = s.substring(firstUnderbar + 1, secondUnderbar);
    String variant = s.substring(secondUnderbar + 1);
    return new Locale(lang, country, variant);
  }
  /**
   * Determine if a class is loadable in the current environment.
   *
   * @param className the fully-qualified name of the class
   * @return true if the class can be loaded; false otherwise
   */
  private static boolean isClassLoadable(String className) {
    try {
      Class.forName(className);
      return true;
    } catch (ClassNotFoundException ex) {
      return false;
    }
  }

  /**
   * Construct an instance of the parameter class, using the keyString as an argument to the
   * constructor. If the class has a StringConstructor instance registered, use it. If not, try to
   * find a constructor for the class with a single String argument. Otherwise, throw a
   * JDOUserException.
   *
   * @param className the name of the class
   * @param keyString the String parameter for the constructor
   * @return the result of construction
   */
  public static Object construct(String className, String keyString) {
    StringConstructor stringConstructor;
    try {
      Class<?> keyClass = Class.forName(className);
      synchronized (stringConstructorMap) {
        stringConstructor = stringConstructorMap.get(keyClass);
      }
      if (stringConstructor != null) {
        return stringConstructor.construct(keyString);
      } else {
        Constructor<?> keyConstructor = keyClass.getConstructor(new Class[] {String.class});
        return keyConstructor.newInstance(new Object[] {keyString});
      }
    } catch (JDOException ex) {
      throw ex;
    } catch (Exception ex) {
      /* ClassNotFoundException,
      NoSuchMethodException,
      InstantiationException,
      IllegalAccessException,
      InvocationTargetException */
      throw new JDOUserException(
          msg.msg(
              "EXC_ObjectIdentityStringConstruction", // NOI18N
              new Object[] {ex.toString(), className, keyString}),
          ex);
    }
  }

  /**
   * Get the DateFormat instance for the default locale from the VM. This requires the following
   * privileges for JDOImplHelper in the security permissions file: permission
   * java.util.PropertyPermission "user.country", "read"; permission java.util.PropertyPermission
   * "user.timezone", "read,write"; permission java.util.PropertyPermission "java.home", "read"; If
   * these permissions are not present, or there is some other problem getting the default date
   * format, a simple formatter is returned.
   *
   * @since 2.1
   * @return the default date-time formatter
   */
  static DateFormat getDateTimeInstance() {
    DateFormat result = null;
    try {
      result = doPrivileged(() -> DateFormat.getDateTimeInstance());
    } catch (Exception ex) {
      result = DateFormat.getInstance();
    }
    return result;
  }

  @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());
    }
  }

  /**
   * Register a DateFormat instance for use with constructing Date instances. The default is the
   * default DateFormat instance. If the new instance implements SimpleDateFormat, get its pattern
   * for error messages.
   *
   * @since 2.0
   * @param df the DateFormat instance to use
   */
  public synchronized void registerDateFormat(DateFormat df) {
    dateFormat = df;
    if (df instanceof SimpleDateFormat) {
      dateFormatPattern = ((SimpleDateFormat) df).toPattern();
    } else {
      dateFormatPattern = msg.msg("MSG_unknown"); // NOI18N
    }
  }

  /**
   * This is a helper class to manage metadata per persistence-capable class. The information is
   * used at runtime to provide field names and field types to the JDO Model.
   *
   * <p>This is the value of the <code>HashMap</code> which relates the <code>
   * PersistenceCapable Class</code> as a key to the metadata.
   */
  static class Meta {

    /**
     * Construct an instance of <code>Meta</code>.
     *
     * @param fieldNames An array of <code>String</code>
     * @param fieldTypes An array of <code>Class</code>
     * @param fieldFlags an array of <code>int</code>
     * @param persistenceCapableSuperclass the most immediate <code>PersistenceCapable</code>
     *     superclass
     * @param pc An instance of the <code>PersistenceCapable</code> class
     */
    Meta(
        String[] fieldNames,
        Class<?>[] fieldTypes,
        byte[] fieldFlags,
        Class<?> persistenceCapableSuperclass,
        PersistenceCapable pc) {
      this.fieldNames = fieldNames;
      this.fieldTypes = fieldTypes;
      this.fieldFlags = fieldFlags;
      this.persistenceCapableSuperclass = persistenceCapableSuperclass;
      this.pc = pc;
    }

    /**
     * This is an array of field names used for the Model at runtime. The field is passed by the
     * static class initialization.
     */
    final String[] fieldNames;

    /**
     * Get the field names from the metadata.
     *
     * @return the array of field names.
     */
    String[] getFieldNames() {
      return fieldNames;
    }

    /**
     * This is an array of field types used for the Model at runtime. The field is passed by the
     * static class initialization.
     */
    final Class<?>[] fieldTypes;

    /**
     * Get the field types from the metadata.
     *
     * @return the array of field types.
     */
    Class<?>[] getFieldTypes() {
      return fieldTypes;
    }

    /**
     * This is an array of field flags used for the Model at runtime. The field is passed by the
     * static class initialization.
     */
    final byte[] fieldFlags;

    /**
     * Get the field types from the metadata.
     *
     * @return the array of field types.
     */
    byte[] getFieldFlags() {
      return fieldFlags;
    }

    /**
     * This is the <code>Class</code> instance of the <code>PersistenceCapable</code> superclass.
     */
    final Class<?> persistenceCapableSuperclass;

    /**
     * Return the <code>PersistenceCapable</code> superclass.
     *
     * @return the <code>PersistenceCapable</code> superclass
     */
    Class<?> getPersistenceCapableSuperclass() {
      return persistenceCapableSuperclass;
    }
    /**
     * This is an instance of <code>PersistenceCapable</code>, used at runtime to create new
     * instances.
     */
    final PersistenceCapable pc;

    /**
     * Get an instance of the <code>PersistenceCapable</code> class.
     *
     * @return an instance of the <code>PersistenceCapable Class</code>.
     */
    PersistenceCapable getPC() {
      return pc;
    }

    /**
     * Return the string form of the metadata.
     *
     * @return the string form
     */
    public String toString() {
      return "Meta-" + pc.getClass().getName(); // NOI18N
    }
  }

  /**
   * Add a StateInterrogation to the list. Create a new list in case there is an iterator open on
   * the original list.
   *
   * @param si the StateInterrogation to add
   */
  public synchronized void addStateInterrogation(StateInterrogation si) {
    List<StateInterrogation> newList = new ArrayList<>(stateInterrogations);
    newList.add(si);
    stateInterrogations = newList;
  }

  /**
   * Remove a StateInterrogation from the list. Create a new list in case there is an iterator open
   * on the original list.
   *
   * @param si the StateInterrogation to remove
   */
  public synchronized void removeStateInterrogation(StateInterrogation si) {
    List<StateInterrogation> newList = new ArrayList<>(stateInterrogations);
    newList.remove(si);
    stateInterrogations = newList;
  }

  /**
   * Return an Iterator over all StateInterrogation instances. Synchronize to avoid
   * add/remove/iterate conflicts.
   *
   * @return an Iterator over all StateInterrogation instances.
   */
  private synchronized Iterator<StateInterrogation> getStateInterrogationIterator() {
    return stateInterrogations.iterator();
  }

  /**
   * Mark a non-binary-compatible instance dirty. Delegate to all registered StateInterrogation
   * instances until one of them handles the call.
   *
   * @param pc the instance to mark dirty
   * @param fieldName the field to mark dirty
   */
  public void nonBinaryCompatibleMakeDirty(Object pc, String fieldName) {
    Iterator<StateInterrogation> sit = getStateInterrogationIterator();
    while (sit.hasNext()) {
      StateInterrogation si = sit.next();
      try {
        if (si.makeDirty(pc, fieldName)) return;
      } catch (Throwable t) {
        continue; // ignore exceptions from errant StateInterrogations
      }
    }
  }

  /**
   * Determine the state of a non-binary-compatible instance. Delegate to all registered
   * StateInterrogation instances until one of them handles the call (returns a non-null Boolean
   * with the answer). The caller provides the stateless "method object" that does the actual call
   * to the StateInterrogation instance.
   *
   * @param pc the instance to be checked
   * @param sibr the method object that delegates to the non-binary-compatible implementation
   * @return Boolean.TRUE if the instance satisfies the state interrogation; Boolean.FALSE if the
   *     instance does not satisfy the interrogation; or null if the implementation does not manage
   *     the class of the instance
   */
  public boolean nonBinaryCompatibleIs(Object pc, StateInterrogationBooleanReturn sibr) {
    Iterator<StateInterrogation> sit = getStateInterrogationIterator();
    while (sit.hasNext()) {
      StateInterrogation si = sit.next();
      Boolean result;
      try {
        result = sibr.is(pc, si);
      } catch (Throwable t) {
        continue; // ignore exceptions from errant StateInterrogations
      }
      if (result != null) return result.booleanValue();
    }
    return false;
  }

  /**
   * Return an object associated with a non-binary-compatible instance. Delegate to all registered
   * StateInterrogation instances until one of them handles the call (returns a non-null answer).
   * The caller provides the stateless "method object" that does the actual call to the
   * StateInterrogation instance.
   *
   * @param pc the instance whose associated object is needed
   * @param sibr the method object that delegates to the non-binary-compatible implementation
   * @return the associated object or null if the implementation does not manage the class of the
   *     instance
   */
  public Object nonBinaryCompatibleGet(Object pc, StateInterrogationObjectReturn sibr) {
    Iterator<StateInterrogation> sit = getStateInterrogationIterator();
    while (sit.hasNext()) {
      StateInterrogation si = sit.next();
      Object result;
      try {
        result = sibr.get(pc, si);
      } catch (Throwable t) {
        continue; // ignore exceptions from errant StateInterrogations
      }
      if (result != null) return result;
    }
    return null;
  }

  /**
   * This is an interface used to interrogate the state of an instance that does not implement
   * PersistenceCapable. It is used for the methods that return a boolean value.
   */
  public static interface StateInterrogationBooleanReturn {
    /**
     * Interrogate the state of the instance
     *
     * @param pc the instance
     * @param si the method object
     * @return the state of the instance or null
     */
    public Boolean is(Object pc, StateInterrogation si);
  }

  /**
   * This is an interface used to interrogate the state of an instance that does not implement
   * PersistenceCapable. It is used for the methods that return an Object value.
   */
  public static interface StateInterrogationObjectReturn {
    /**
     * Return the associated instance.
     *
     * @param pc the instance
     * @param si the method object
     * @return the associated object or null
     */
    public Object get(Object pc, StateInterrogation si);
  }

  /**
   * Examines the given map for keys beginning with the JDO standard prefix, {@link
   * Constants#JAVAX_JDO_PREFIX}. If any property keys are found with that prefix but are unknown to
   * this version of the JDO standard, a JDOUserException is thrown with a message indicating the
   * unknown property. Keys that are not strings are ignored, as are string keys beginning with
   * {@link Constants#PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER} or not beginning with {@link
   * Constants#JAVAX_JDO_PREFIX}.
   *
   * @param properties The properties to examine.
   * @see Constants#JAVAX_JDO_PREFIX
   * @since 3.1
   */
  public static void assertOnlyKnownStandardProperties(Map<?, ?> properties) {
    if (properties == null || properties.isEmpty()) return;

    List<JDOUserException> exceptions = new ArrayList<>();
    StringBuilder unknowns = new StringBuilder();

    for (Object key : properties.keySet()) {
      if (!(key instanceof String)) {
        continue; // ignore keys not of type string
      }
      String s = ((String) key).toLowerCase(); // compare case-insensitively
      if (!s.startsWith(JAVAX_JDO_PREFIX_LOWER_CASED)) {
        continue; // ignore vendor-specific keys
      }
      if (s.startsWith(PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER_LOWER_CASED)) {
        continue; // ignore listener class names
      }
      if (!USER_CONFIGURABLE_STANDARD_PROPERTIES_LOWER_CASED.contains(s)) {
        exceptions.add(new JDOUserException(msg.msg("EXC_UnknownStandardProperty", s)));

        if (exceptions.size() > 1) {
          unknowns.append(",");
        }
        unknowns.append(s);
      }
    }

    if (exceptions.size() == 1) {
      throw exceptions.get(0);
    } else if (exceptions.size() > 1) {
      throw new JDOUserException(
          msg.msg("EXC_UnknownStandardProperties", unknowns.toString()),
          exceptions.toArray(new JDOUserException[] {}));
    }
  }
}
