diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java index 1ad8ed8a4..4cb6da5ca 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java @@ -75,6 +75,7 @@ public class Compatibility { private boolean _metaFactoriesAreStrict = false; private boolean _resetFlushFlagForCascadePersist = true;//OPENJPA-2051 private boolean _singletonLifecycleEventManager = false; + private boolean _filterPCRegistryClasses = false; // OPENJPA-2288 /** * Whether to require exact identity value types when creating object @@ -713,4 +714,18 @@ public class Compatibility { public void setSingletonLifecycleEventManager(boolean singleton) { _singletonLifecycleEventManager = singleton; } + + /** + * Whether the metadata processor should filter classes dispatched by the PCRegistry listener system. + **/ + public boolean getFilterPCRegistryClasses() { + return _filterPCRegistryClasses; + } + + /** + * Whether the metadata processor should filter classes dispatched by the PCRegistry listener system. + **/ + public void setFilterPCRegistryClasses(boolean bool) { + _filterPCRegistryClasses = bool; + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java index 4ea3a1727..56b09a126 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java @@ -162,6 +162,9 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con // Entities. private boolean _logEnhancementLevel = true; + // A boolean used to decide whether to filter Class objects submitted by the PCRegistry listener system + private boolean _filterRegisteredClasses = false; + /** * Default constructor. Configure via {@link Configurable}. */ @@ -1635,10 +1638,41 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con Collection pcNames = getPersistentTypeNames(false, envLoader); Collection> failed = null; for (int i = 0; i < reg.length; i++) { - // don't process types that aren't listed by the user; may belong - // to a different persistence unit - if (pcNames != null && !pcNames.isEmpty() && !pcNames.contains(reg[i].getName())) + // Don't process types that aren't listed by the user; it may belong to a different persistence unit. + if (pcNames != null && !pcNames.isEmpty() && !pcNames.contains(reg[i].getName())) { continue; + } + + // If the compatibility option "filterPCRegistryClasses" is enabled, then verify that the type is + // accessible to the envLoader/Thread Context ClassLoader + if (_filterRegisteredClasses) { + Log log = (_conf == null) ? null : _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); + ClassLoader loadCL = (envLoader != null) ? + envLoader : + AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()); + + try { + Class classFromAppClassLoader = Class.forName(reg[i].getName(), true, loadCL); + + if (!reg[i].equals(classFromAppClassLoader)) { + // This is a class that belongs to a ClassLoader not associated with the Application, + // so it should be processed. + if (log != null && log.isTraceEnabled()) { + log.trace( + "Metadata Repository will ignore Class " + reg[i].getName() + + ", since it originated from a ClassLoader not associated with the application."); + } + continue; + } + } catch (ClassNotFoundException cnfe) { + // Catch exception and log its occurrence, and permit MDR processing to continue to preserve + // original behavior. + if (log != null && log.isTraceEnabled()) { + log.trace("The Class " + reg[i].getName() + " was identified as a persistent class " + + "by configuration, but the Class could not be found."); + } + } + } checkEnhancementLevel(reg[i]); try { @@ -1878,6 +1912,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con public void setConfiguration(Configuration conf) { _conf = (OpenJPAConfiguration) conf; _log = _conf.getLog(OpenJPAConfiguration.LOG_METADATA); + _filterRegisteredClasses = _conf.getCompatibilityInstance().getFilterPCRegistryClasses(); } public void startConfiguration() {