Merge pull request #249 from stliu/HHH-6964

HHH-6964 Audit Strategy class can't be found by Thread.currentThread().getContextClassLoader() under AS7
This commit is contained in:
Adam Warski 2012-01-12 12:13:02 -08:00
commit d8003efcf6
2 changed files with 103 additions and 74 deletions

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.envers.configuration; package org.hibernate.envers.configuration;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@ -39,107 +40,134 @@ import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.synchronization.AuditProcessManager; import org.hibernate.envers.synchronization.AuditProcessManager;
import org.hibernate.envers.tools.reflection.ReflectionTools; import org.hibernate.envers.tools.reflection.ReflectionTools;
import org.hibernate.property.Getter; import org.hibernate.property.Getter;
import org.hibernate.service.classloading.spi.ClassLoaderService;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
* @author Stephanie Pau at Markit Group Plc * @author Stephanie Pau at Markit Group Plc
*/ */
public class AuditConfiguration { public class AuditConfiguration {
private final GlobalConfiguration globalCfg; private final GlobalConfiguration globalCfg;
private final AuditEntitiesConfiguration auditEntCfg; private final AuditEntitiesConfiguration auditEntCfg;
private final AuditProcessManager auditProcessManager; private final AuditProcessManager auditProcessManager;
private final AuditStrategy auditStrategy; private final AuditStrategy auditStrategy;
private final EntitiesConfigurations entCfg; private final EntitiesConfigurations entCfg;
private final RevisionInfoQueryCreator revisionInfoQueryCreator; private final RevisionInfoQueryCreator revisionInfoQueryCreator;
private final RevisionInfoNumberReader revisionInfoNumberReader; private final RevisionInfoNumberReader revisionInfoNumberReader;
private final ModifiedEntityNamesReader modifiedEntityNamesReader; private final ModifiedEntityNamesReader modifiedEntityNamesReader;
private final ClassLoaderService classLoaderService;
public AuditEntitiesConfiguration getAuditEntCfg() { public AuditEntitiesConfiguration getAuditEntCfg() {
return auditEntCfg; return auditEntCfg;
} }
public AuditProcessManager getSyncManager() { public AuditProcessManager getSyncManager() {
return auditProcessManager; return auditProcessManager;
} }
public GlobalConfiguration getGlobalCfg() { public GlobalConfiguration getGlobalCfg() {
return globalCfg; return globalCfg;
} }
public EntitiesConfigurations getEntCfg() { public EntitiesConfigurations getEntCfg() {
return entCfg; return entCfg;
} }
public RevisionInfoQueryCreator getRevisionInfoQueryCreator() { public RevisionInfoQueryCreator getRevisionInfoQueryCreator() {
return revisionInfoQueryCreator; return revisionInfoQueryCreator;
} }
public RevisionInfoNumberReader getRevisionInfoNumberReader() { public RevisionInfoNumberReader getRevisionInfoNumberReader() {
return revisionInfoNumberReader; return revisionInfoNumberReader;
} }
public ModifiedEntityNamesReader getModifiedEntityNamesReader() { public ModifiedEntityNamesReader getModifiedEntityNamesReader() {
return modifiedEntityNamesReader; return modifiedEntityNamesReader;
} }
public AuditStrategy getAuditStrategy() { public AuditStrategy getAuditStrategy() {
return auditStrategy; return auditStrategy;
} }
public AuditConfiguration(Configuration cfg) { public AuditConfiguration(Configuration cfg) {
Properties properties = cfg.getProperties(); this( cfg, null );
}
ReflectionManager reflectionManager = cfg.getReflectionManager(); public AuditConfiguration(Configuration cfg, ClassLoaderService classLoaderService) {
globalCfg = new GlobalConfiguration(properties); Properties properties = cfg.getProperties();
RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration(globalCfg);
RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager); ReflectionManager reflectionManager = cfg.getReflectionManager();
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName()); globalCfg = new GlobalConfiguration( properties );
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator()); RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration( globalCfg );
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator(); RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure( cfg, reflectionManager );
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader(); auditEntCfg = new AuditEntitiesConfiguration( properties, revInfoCfgResult.getRevisionInfoEntityName() );
modifiedEntityNamesReader = revInfoCfgResult.getModifiedEntityNamesReader(); auditProcessManager = new AuditProcessManager( revInfoCfgResult.getRevisionInfoGenerator() );
auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(), revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
revInfoCfgResult.getRevisionInfoTimestampData()); revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy, modifiedEntityNamesReader = revInfoCfgResult.getModifiedEntityNamesReader();
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping()); this.classLoaderService = classLoaderService;
} auditStrategy = initializeAuditStrategy(
revInfoCfgResult.getRevisionInfoClass(),
revInfoCfgResult.getRevisionInfoTimestampData()
);
entCfg = new EntitiesConfigurator().configure(
cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping()
);
}
private AuditStrategy initializeAuditStrategy(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) { private AuditStrategy initializeAuditStrategy(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) {
AuditStrategy strategy; AuditStrategy strategy;
try { try {
Class<?> auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
strategy = (AuditStrategy) auditStrategyClass.newInstance();
} catch (Exception e) {
throw new MappingException(
String.format("Unable to create AuditStrategy[%s] instance." , auditEntCfg.getAuditStrategyName()),
e);
}
if (strategy instanceof ValidityAuditStrategy) { Class<?> auditStrategyClass = null;
// further initialization required if ( classLoaderService != null ) {
Getter revisionTimestampGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoTimestampData); auditStrategyClass = classLoaderService.classForName( auditEntCfg.getAuditStrategyName() );
((ValidityAuditStrategy) strategy).setRevisionTimestampGetter(revisionTimestampGetter); }
} else {
auditStrategyClass = Thread.currentThread()
.getContextClassLoader()
.loadClass( auditEntCfg.getAuditStrategyName() );
}
return strategy; strategy = (AuditStrategy) auditStrategyClass.newInstance();
}
catch ( Exception e ) {
throw new MappingException(
String.format( "Unable to create AuditStrategy[%s] instance.", auditEntCfg.getAuditStrategyName() ),
e
);
}
if ( strategy instanceof ValidityAuditStrategy ) {
// further initialization required
Getter revisionTimestampGetter = ReflectionTools.getGetter( revisionInfoClass, revisionInfoTimestampData );
( (ValidityAuditStrategy) strategy ).setRevisionTimestampGetter( revisionTimestampGetter );
}
return strategy;
} }
// //
private static Map<Configuration, AuditConfiguration> cfgs private static Map<Configuration, AuditConfiguration> cfgs
= new WeakHashMap<Configuration, AuditConfiguration>(); = new WeakHashMap<Configuration, AuditConfiguration>();
public synchronized static AuditConfiguration getFor(Configuration cfg) { public synchronized static AuditConfiguration getFor(Configuration cfg) {
AuditConfiguration verCfg = cfgs.get(cfg); return getFor( cfg, null );
}
if (verCfg == null) { public synchronized static AuditConfiguration getFor(Configuration cfg, ClassLoaderService classLoaderService) {
verCfg = new AuditConfiguration(cfg); AuditConfiguration verCfg = cfgs.get( cfg );
cfgs.put(cfg, verCfg);
cfg.buildMappings(); if ( verCfg == null ) {
} verCfg = new AuditConfiguration( cfg, classLoaderService );
cfgs.put( cfg, verCfg );
return verCfg; cfg.buildMappings();
} }
return verCfg;
}
} }

View File

@ -34,6 +34,7 @@ import org.hibernate.integrator.spi.Integrator;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.metamodel.source.MetadataImplementor; import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.service.spi.SessionFactoryServiceRegistry;
/** /**
@ -60,7 +61,7 @@ public class EnversIntegrator implements Integrator {
EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
listenerRegistry.addDuplicationStrategy( EnversListenerDuplicationStrategy.INSTANCE ); listenerRegistry.addDuplicationStrategy( EnversListenerDuplicationStrategy.INSTANCE );
final AuditConfiguration enversConfiguration = AuditConfiguration.getFor( configuration ); final AuditConfiguration enversConfiguration = AuditConfiguration.getFor( configuration, serviceRegistry.getService( ClassLoaderService.class ) );
if (enversConfiguration.getEntCfg().hasAuditedEntities()) { if (enversConfiguration.getEntCfg().hasAuditedEntities()) {
listenerRegistry.appendListeners( EventType.POST_DELETE, new EnversPostDeleteEventListenerImpl( enversConfiguration ) ); listenerRegistry.appendListeners( EventType.POST_DELETE, new EnversPostDeleteEventListenerImpl( enversConfiguration ) );