From 694b5ecaadb4f09df765a201b99ae3e382358e7c Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Fri, 3 Jul 2020 13:01:18 +0100 Subject: [PATCH] HHH-14096 Adapt the Hibernate Envers module to use its private copy of XMLHelper --- .../envers/boot/internal/EnversService.java | 3 - .../boot/internal/EnversServiceImpl.java | 9 --- .../internal/RevisionInfoConfiguration.java | 13 ++- .../configuration/internal/XMLHelper.java | 79 +++++++++++++++++++ 4 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/XMLHelper.java diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversService.java b/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversService.java index 55ba23e1bed9..bdac75af98ec 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversService.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversService.java @@ -17,7 +17,6 @@ import org.hibernate.envers.internal.revisioninfo.RevisionInfoQueryCreator; import org.hibernate.envers.internal.synchronization.AuditProcessManager; import org.hibernate.envers.strategy.AuditStrategy; -import org.hibernate.internal.util.xml.XMLHelper; import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; @@ -56,8 +55,6 @@ public interface EnversService extends Service { void initialize(MetadataImplementor metadata, MappingCollector mappingCollector); - XMLHelper getXmlHelper(); - GlobalConfiguration getGlobalConfiguration(); AuditEntitiesConfiguration getAuditEntitiesConfiguration(); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversServiceImpl.java b/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversServiceImpl.java index 7a9cf02bd8f2..8f68358a81f3 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversServiceImpl.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/boot/internal/EnversServiceImpl.java @@ -30,7 +30,6 @@ import org.hibernate.envers.strategy.AuditStrategy; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.internal.util.xml.XMLHelper; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.Stoppable; @@ -74,8 +73,6 @@ public class EnversServiceImpl implements EnversService, Configurable, Stoppable private RevisionInfoNumberReader revisionInfoNumberReader; private ModifiedEntityNamesReader modifiedEntityNamesReader; - private XMLHelper xmlHelper; - @Override public void configure(Map configurationValues) { if ( configurationValues.containsKey( LEGACY_AUTO_REGISTER ) ) { @@ -111,7 +108,6 @@ public void initialize(final MetadataImplementor metadata, final MappingCollecto this.serviceRegistry = metadata.getMetadataBuildingOptions().getServiceRegistry(); this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - this.xmlHelper = new XMLHelper(); doInitialize( metadata, mappingCollector, serviceRegistry ); } @@ -186,11 +182,6 @@ private static AuditStrategy initializeAuditStrategy( return strategy; } - @Override - public XMLHelper getXmlHelper() { - return xmlHelper; - } - /** * Load a class by name, preferring our ClassLoader and then the ClassLoaderService. * diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java index e8b089ec2988..97a7c0c35d1c 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java @@ -55,6 +55,8 @@ public class RevisionInfoConfiguration { private Type revisionInfoTimestampType; private GlobalConfiguration globalCfg; + private XMLHelper xmlHelper; + private String revisionPropType; private String revisionPropSqlType; @@ -75,7 +77,7 @@ public RevisionInfoConfiguration(GlobalConfiguration globalCfg) { } private Document generateDefaultRevisionInfoXmlMapping() { - final Document document = globalCfg.getEnversService().getXmlHelper().getDocumentFactory().createDocument(); + final Document document = getXmlHelper().getDocumentFactory().createDocument(); final Element classMapping = MetadataTools.createEntity( document, @@ -120,6 +122,13 @@ private Document generateDefaultRevisionInfoXmlMapping() { return document; } + private XMLHelper getXmlHelper() { + if ( this.xmlHelper == null ) { + this.xmlHelper = new XMLHelper(); + } + return this.xmlHelper; + } + /** * Generates mapping that represents a set of primitive types.
* @@ -158,7 +167,7 @@ private void generateEntityNamesTrackingTableMapping( } private Element generateRevisionInfoRelationMapping() { - final Document document = globalCfg.getEnversService().getXmlHelper().getDocumentFactory().createDocument(); + final Document document = getXmlHelper().getDocumentFactory().createDocument(); final Element revRelMapping = document.addElement( "key-many-to-one" ); revRelMapping.addAttribute( "type", revisionPropType ); revRelMapping.addAttribute( "class", revisionInfoEntityName ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/XMLHelper.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/XMLHelper.java new file mode 100644 index 000000000000..655d73602de8 --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/XMLHelper.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.envers.configuration.internal; + +import org.dom4j.DocumentFactory; +import org.dom4j.io.SAXReader; +import org.hibernate.internal.util.xml.ErrorLogger; +import org.xml.sax.EntityResolver; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Small helper class that lazily loads DOM and SAX reader and keep them for fast use afterwards. + * + * This was part of Hibernate ORM core, but moved into the testsuite helpers to not expose + * access to the dom4j types. It's also used by Hibernate Envers, so we will need two copies + * until Envers is able to remove its reliance on dom4j. + * The rest of Hibernate uses StAX now for XML processing. See {@link org.hibernate.boot.jaxb.internal.stax} + */ +public final class XMLHelper { + private final DocumentFactory documentFactory; + + public XMLHelper() { + PrivilegedAction action = new PrivilegedAction() { + public DocumentFactory run() { + final ClassLoader originalTccl = Thread.currentThread().getContextClassLoader(); + try { + // We need to make sure we get DocumentFactory + // loaded from the same ClassLoader that loads + // Hibernate classes, to make sure we get the + // proper version of DocumentFactory, This class + // is "internal", and should only be used for XML + // files generated by Envers. + + // Using the (Hibernate) ClassLoader that loads + // this Class will avoid collisions in the case + // that DocumentFactory can be loaded from, + // for example, the application ClassLoader. + Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); + return DocumentFactory.getInstance(); + } + finally { + Thread.currentThread().setContextClassLoader( originalTccl ); + } + } + }; + + this.documentFactory = System.getSecurityManager() != null + ? AccessController.doPrivileged( action ) + : action.run(); + } + + public DocumentFactory getDocumentFactory() { + return documentFactory; + } + + public SAXReader createSAXReader(ErrorLogger errorLogger, EntityResolver entityResolver) { + SAXReader saxReader = new SAXReader(); + try { + saxReader.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false ); + saxReader.setFeature( "http://xml.org/sax/features/external-general-entities", false ); + saxReader.setFeature( "http://xml.org/sax/features/external-parameter-entities", false ); + } + catch (Exception e) { + throw new RuntimeException( e ); + } + saxReader.setMergeAdjacentText( true ); + saxReader.setValidation( true ); + saxReader.setErrorHandler( errorLogger ); + saxReader.setEntityResolver( entityResolver ); + + return saxReader; + } +}