HHH-9887 - Make sure the JPA temp ClassLoader is not used to load Class definitions that are then held on to

This commit is contained in:
Steve Ebersole 2015-07-02 02:49:09 -05:00
parent abd0461d34
commit 0d6393a8b1
35 changed files with 882 additions and 675 deletions

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.boot;
import java.sql.DatabaseMetaData;
import javax.persistence.AttributeConverter;
import javax.persistence.SharedCacheMode;
@ -24,7 +23,6 @@ import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.AttributeConverterDefinition;
import org.hibernate.cfg.MetadataSourceType;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.type.BasicType;
import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.UserType;

View File

@ -26,18 +26,13 @@ import org.hibernate.boot.internal.MetadataBuilderImpl;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.boot.jaxb.internal.CacheableFileXmlSource;
import org.hibernate.boot.jaxb.internal.FileXmlSource;
import org.hibernate.boot.jaxb.internal.InputStreamXmlSource;
import org.hibernate.boot.jaxb.internal.JarFileEntryXmlSource;
import org.hibernate.boot.jaxb.internal.JaxpSourceXmlSource;
import org.hibernate.boot.jaxb.internal.MappingBinder;
import org.hibernate.boot.jaxb.internal.UrlXmlSource;
import org.hibernate.boot.jaxb.spi.Binder;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.XmlMappingBinderAccess;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.service.ServiceRegistry;
@ -59,7 +54,7 @@ public class MetadataSources implements Serializable {
private final ServiceRegistry serviceRegistry;
private Binder mappingsBinder;
private XmlMappingBinderAccess xmlMappingBinderAccess;
private List<Binding> xmlBindings = new ArrayList<Binding>();
private LinkedHashSet<Class<?>> annotatedClasses = new LinkedHashSet<Class<?>>();
@ -85,11 +80,7 @@ public class MetadataSources implements Serializable {
);
}
this.serviceRegistry = serviceRegistry;
// NOTE : The boolean here indicates whether or not to perform validation as we load XML documents.
// Should we expose this setting? Disabling would speed up JAXP and JAXB at runtime, but potentially
// at the cost of less obvious errors when a document is not valid.
this.mappingsBinder = new MappingBinder( serviceRegistry.getService( ClassLoaderService.class ), true );
this.xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry );
}
protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRegistry) {
@ -97,6 +88,10 @@ public class MetadataSources implements Serializable {
|| StandardServiceRegistry.class.isInstance( serviceRegistry );
}
public XmlMappingBinderAccess getXmlMappingBinderAccess() {
return xmlMappingBinderAccess;
}
public List<Binding> getXmlBindings() {
return xmlBindings;
}
@ -209,31 +204,6 @@ public class MetadataSources implements Serializable {
return this;
}
/**
* Read mappings as a application resourceName (i.e. classpath lookup).
*
* @param name The resource name
*
* @return this (for method chaining purposes)
*/
public MetadataSources addResource(String name) {
LOG.tracef( "reading mappings from resource : %s", name );
final Origin origin = new Origin( SourceType.RESOURCE, name );
final URL url = classLoaderService().locateResource( name );
if ( url == null ) {
throw new MappingNotFoundException( origin );
}
xmlBindings.add( new UrlXmlSource( origin, url ).doBind( mappingsBinder ) );
return this;
}
private ClassLoaderService classLoaderService() {
return serviceRegistry.getService( ClassLoaderService.class );
}
/**
* Read a mapping as an application resource using the convention that a class named {@code foo.bar.Foo} is
* mapped by a file named {@code foo/bar/Foo.hbm.xml} which can be resolved as a classpath resource.
@ -255,6 +225,18 @@ public class MetadataSources implements Serializable {
return this;
}
/**
* Read mappings as a application resourceName (i.e. classpath lookup).
*
* @param name The resource name
*
* @return this (for method chaining purposes)
*/
public MetadataSources addResource(String name) {
xmlBindings.add( getXmlMappingBinderAccess().bind( name ) );
return this;
}
/**
* Read mappings from a particular XML file
*
@ -265,23 +247,10 @@ public class MetadataSources implements Serializable {
* @see #addFile(java.io.File)
*/
public MetadataSources addFile(String path) {
addFile(
new Origin( SourceType.FILE, path ),
new File( path )
);
addFile( new File( path ) );
return this;
}
private void addFile(Origin origin, File file) {
LOG.tracef( "reading mappings from file : %s", origin.getName() );
if ( !file.exists() ) {
throw new MappingNotFoundException( origin );
}
xmlBindings.add( new FileXmlSource( origin, file ).doBind( mappingsBinder ) );
}
/**
* Read mappings from a particular XML file
*
@ -290,10 +259,7 @@ public class MetadataSources implements Serializable {
* @return this (for method chaining purposes)
*/
public MetadataSources addFile(File file) {
addFile(
new Origin( SourceType.FILE, file.getPath() ),
file
);
xmlBindings.add( getXmlMappingBinderAccess().bind( file ) );
return this;
}
@ -313,7 +279,7 @@ public class MetadataSources implements Serializable {
}
private void addCacheableFile(Origin origin, File file) {
xmlBindings.add( new CacheableFileXmlSource( origin, file, false ).doBind( mappingsBinder ) );
xmlBindings.add( new CacheableFileXmlSource( origin, file, false ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
}
/**
@ -350,7 +316,7 @@ public class MetadataSources implements Serializable {
*/
public MetadataSources addCacheableFileStrictly(File file) throws SerializationException, FileNotFoundException {
final Origin origin = new Origin( SourceType.FILE, file.getAbsolutePath() );
xmlBindings.add( new CacheableFileXmlSource( origin, file, true ).doBind( mappingsBinder ) );
xmlBindings.add( new CacheableFileXmlSource( origin, file, true ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
return this;
}
@ -362,19 +328,7 @@ public class MetadataSources implements Serializable {
* @return this (for method chaining purposes)
*/
public MetadataSources addInputStream(InputStreamAccess xmlInputStreamAccess) {
final Origin origin = new Origin( SourceType.INPUT_STREAM, xmlInputStreamAccess.getStreamName() );
InputStream xmlInputStream = xmlInputStreamAccess.accessInputStream();
try {
xmlBindings.add( new InputStreamXmlSource( origin, xmlInputStream, false ).doBind( mappingsBinder ) );
}
finally {
try {
xmlInputStream.close();
}
catch (IOException e) {
LOG.debugf( "Unable to close InputStream obtained from InputStreamAccess : " + xmlInputStreamAccess.getStreamName() );
}
}
xmlBindings.add( getXmlMappingBinderAccess().bind( xmlInputStreamAccess ) );
return this;
}
@ -386,8 +340,7 @@ public class MetadataSources implements Serializable {
* @return this (for method chaining purposes)
*/
public MetadataSources addInputStream(InputStream xmlInputStream) {
final Origin origin = new Origin( SourceType.INPUT_STREAM, null );
xmlBindings.add( new InputStreamXmlSource( origin, xmlInputStream, false ).doBind( mappingsBinder ) );
xmlBindings.add( getXmlMappingBinderAccess().bind( xmlInputStream ) );
return this;
}
@ -399,11 +352,7 @@ public class MetadataSources implements Serializable {
* @return this (for method chaining purposes)
*/
public MetadataSources addURL(URL url) {
final String urlExternalForm = url.toExternalForm();
LOG.debugf( "Reading mapping document from URL : %s", urlExternalForm );
final Origin origin = new Origin( SourceType.URL, urlExternalForm );
xmlBindings.add( new UrlXmlSource( origin, url ).doBind( mappingsBinder ) );
xmlBindings.add( getXmlMappingBinderAccess().bind( url ) );
return this;
}
@ -419,7 +368,7 @@ public class MetadataSources implements Serializable {
@Deprecated
public MetadataSources addDocument(Document document) {
final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH );
xmlBindings.add( new JaxpSourceXmlSource( origin, new DOMSource( document ) ).doBind( mappingsBinder ) );
xmlBindings.add( new JaxpSourceXmlSource( origin, new DOMSource( document ) ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
return this;
}
@ -444,7 +393,7 @@ public class MetadataSources implements Serializable {
if ( zipEntry.getName().endsWith( ".hbm.xml" ) ) {
LOG.tracef( "found mapping document : %s", zipEntry.getName() );
xmlBindings.add(
new JarFileEntryXmlSource( origin, jarFile, zipEntry ).doBind( mappingsBinder )
new JarFileEntryXmlSource( origin, jarFile, zipEntry ).doBind( getXmlMappingBinderAccess().getMappingBinder() )
);
}
}
@ -489,4 +438,5 @@ public class MetadataSources implements Serializable {
}
return this;
}
}

View File

@ -14,10 +14,12 @@ import org.hibernate.boot.archive.spi.InputStreamAccess;
*/
public class ClassDescriptorImpl implements ClassDescriptor {
private final String name;
private final Categorization categorization;
private final InputStreamAccess streamAccess;
public ClassDescriptorImpl(String name, InputStreamAccess streamAccess) {
public ClassDescriptorImpl(String name, Categorization categorization, InputStreamAccess streamAccess) {
this.name = name;
this.categorization = categorization;
this.streamAccess = streamAccess;
}
@ -26,6 +28,10 @@ public class ClassDescriptorImpl implements ClassDescriptor {
return name;
}
public Categorization getCategorization() {
return categorization;
}
@Override
public InputStreamAccess getStreamAccess() {
return streamAccess;

View File

@ -29,8 +29,6 @@ public class ScanResultCollector {
private final ScanEnvironment environment;
private final ScanOptions options;
private final ScanParameters scanParameters;
private final Set<ClassDescriptor> discoveredClasses;
private final Set<PackageDescriptor> discoveredPackages;
private final Set<MappingFileDescriptor> discoveredMappingFiles;
@ -39,8 +37,6 @@ public class ScanResultCollector {
this.environment = environment;
this.options = options;
this.scanParameters = parameters;
if ( environment.getExplicitlyListedClassNames() == null ) {
throw new IllegalArgumentException( "ScanEnvironment#getExplicitlyListedClassNames should not return null" );
}
@ -55,19 +51,6 @@ public class ScanResultCollector {
}
public void handleClass(ClassDescriptor classDescriptor, boolean rootUrl) {
// see if "discovery" of this entry is allowed
// final ClassInfo classInfo = scanParameters.getJandexInitializer().handle( classDescriptor );
//
// if ( !isListedOrDetectable( classInfo.name().toString(), rootUrl ) ) {
// return;
// }
//
// if ( !containsClassAnnotationsOfInterest( classInfo ) ) {
// // not strictly needed, but helps cut down on the size of discoveredClasses
// return;
// }
if ( !isListedOrDetectable( classDescriptor.getName(), rootUrl ) ) {
return;
}
@ -95,21 +78,7 @@ public class ScanResultCollector {
}
}
// @SuppressWarnings("SimplifiableIfStatement")
// private boolean containsClassAnnotationsOfInterest(ClassInfo classInfo) {
// if ( classInfo.annotations() == null ) {
// return false;
// }
//
// return classInfo.annotations().containsKey( JPADotNames.ENTITY )
// || classInfo.annotations().containsKey( JPADotNames.MAPPED_SUPERCLASS )
// || classInfo.annotations().containsKey( JPADotNames.EMBEDDABLE )
// || classInfo.annotations().containsKey( JPADotNames.CONVERTER );
// }
public void handlePackage(PackageDescriptor packageDescriptor, boolean rootUrl) {
// final ClassInfo classInfo = scanParameters.getJandexInitializer().handle( packageDescriptor );
if ( !isListedOrDetectable( packageDescriptor.getName(), rootUrl ) ) {
// not strictly needed, but helps cut down on the size of discoveredPackages
return;

View File

@ -0,0 +1,22 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.archive.scan.internal;
import org.hibernate.boot.archive.scan.spi.ScanParameters;
/**
* @author Steve Ebersole
*/
public class StandardScanParameters implements ScanParameters {
/**
* Singleton access
*/
public static final StandardScanParameters INSTANCE = new StandardScanParameters();
private StandardScanParameters() {
}
}

View File

@ -14,17 +14,25 @@ import org.hibernate.boot.archive.spi.InputStreamAccess;
* @author Steve Ebersole
*/
public interface ClassDescriptor {
enum Categorization {
MODEL,
CONVERTER,
OTHER
}
/**
* Retrieves the class name, not the file name.
*
* @return The name (FQN) of the class
*/
public String getName();
String getName();
Categorization getCategorization();
/**
* Retrieves access to the InputStream for the class file.
*
* @return Access to the InputStream for the class file.
*/
public InputStreamAccess getStreamAccess();
InputStreamAccess getStreamAccess();
}

View File

@ -38,17 +38,20 @@ public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
@Override
public void handleEntry(ArchiveEntry entry, ArchiveContext context) {
// Ultimately we'd like to leverage Jandex here as long term we want to move to
// using Jandex for annotation processing. But even then, Jandex atm does not have
// any facility for passing a stream and conditionally indexing it into an Index or
// returning existing ClassInfo objects.
//
// So not sure we can ever not do this unconditional input stream read :(
final ClassFile classFile = toClassFile( entry );
final ClassDescriptor classDescriptor = toClassDescriptor( classFile, entry );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// temporary until HHH-9489 is addressed
if ( ! containsClassAnnotationsOfInterest( classFile ) ) {
if ( classDescriptor.getCategorization() == ClassDescriptor.Categorization.OTHER ) {
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
resultCollector.handleClass( toClassDescriptor( toClassFile( entry ), entry ), context.isRootUrl() );
resultCollector.handleClass( classDescriptor, context.isRootUrl() );
}
private ClassFile toClassFile(ArchiveEntry entry) {
@ -75,21 +78,21 @@ public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
}
}
private ClassDescriptor toClassDescriptor(ClassFile classFile, ArchiveEntry entry) {
ClassDescriptor.Categorization categorization = ClassDescriptor.Categorization.OTHER;;
@SuppressWarnings("SimplifiableIfStatement")
private boolean containsClassAnnotationsOfInterest(ClassFile cf) {
final AnnotationsAttribute visibleAnnotations = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
if ( visibleAnnotations == null ) {
return false;
final AnnotationsAttribute visibleAnnotations = (AnnotationsAttribute) classFile.getAttribute( AnnotationsAttribute.visibleTag );
if ( visibleAnnotations != null ) {
if ( visibleAnnotations.getAnnotation( Entity.class.getName() ) != null
|| visibleAnnotations.getAnnotation( MappedSuperclass.class.getName() ) != null
|| visibleAnnotations.getAnnotation( Embeddable.class.getName() ) != null ) {
categorization = ClassDescriptor.Categorization.MODEL;
}
else if ( visibleAnnotations.getAnnotation( Converter.class.getName() ) != null ) {
categorization = ClassDescriptor.Categorization.CONVERTER;
}
}
return visibleAnnotations.getAnnotation( Entity.class.getName() ) != null
|| visibleAnnotations.getAnnotation( MappedSuperclass.class.getName() ) != null
|| visibleAnnotations.getAnnotation( Embeddable.class.getName() ) != null
|| visibleAnnotations.getAnnotation( Converter.class.getName() ) != null;
}
private ClassDescriptor toClassDescriptor(ClassFile classFile, ArchiveEntry entry) {
return new ClassDescriptorImpl( classFile.getName(), entry.getStreamAccess() );
return new ClassDescriptorImpl( classFile.getName(), categorization, entry.getStreamAccess() );
}
}

View File

@ -1,22 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.archive.scan.spi;
import org.jboss.jandex.ClassInfo;
/**
* Helper for preparing Jandex for later use..
*
* Not currently used. See https://hibernate.atlassian.net/browse/HHH-9489
*
* @author Steve Ebersole
*/
public interface JandexInitializer {
ClassInfo handle(PackageDescriptor packageDescriptor);
ClassInfo handle(ClassDescriptor classDescriptor);
}

View File

@ -13,5 +13,4 @@ package org.hibernate.boot.archive.scan.spi;
* @author Steve Ebersole
*/
public interface ScanParameters {
public JandexInitializer getJandexInitializer();
}

View File

@ -1,163 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.internal;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.archive.internal.UrlInputStreamAccess;
import org.hibernate.boot.archive.scan.internal.ClassDescriptorImpl;
import org.hibernate.boot.archive.scan.internal.MappingFileDescriptorImpl;
import org.hibernate.boot.archive.scan.internal.PackageDescriptorImpl;
import org.hibernate.boot.archive.scan.spi.ClassDescriptor;
import org.hibernate.boot.archive.scan.spi.MappingFileDescriptor;
import org.hibernate.boot.archive.scan.spi.PackageDescriptor;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanResult;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class DeploymentResourcesInterpreter {
/**
* Singleton access
*/
public static final DeploymentResourcesInterpreter INSTANCE = new DeploymentResourcesInterpreter();
public static interface DeploymentResources {
public Iterable<ClassDescriptor> getClassDescriptors();
public Iterable<PackageDescriptor> getPackageDescriptors();
public Iterable<MappingFileDescriptor> getMappingFileDescriptors();
}
private static final Logger log = Logger.getLogger( DeploymentResourcesInterpreter.class );
public DeploymentResources buildDeploymentResources(
ScanEnvironment scanEnvironment,
ScanResult scanResult,
ServiceRegistry serviceRegistry) {
// mapping files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final ArrayList<MappingFileDescriptor> mappingFileDescriptors = new ArrayList<MappingFileDescriptor>();
final Set<String> nonLocatedMappingFileNames = new HashSet<String>();
final List<String> explicitMappingFileNames = scanEnvironment.getExplicitlyListedMappingFiles();
if ( explicitMappingFileNames != null ) {
nonLocatedMappingFileNames.addAll( explicitMappingFileNames );
}
for ( MappingFileDescriptor mappingFileDescriptor : scanResult.getLocatedMappingFiles() ) {
mappingFileDescriptors.add( mappingFileDescriptor );
nonLocatedMappingFileNames.remove( mappingFileDescriptor.getName() );
}
for ( String name : nonLocatedMappingFileNames ) {
MappingFileDescriptor descriptor = buildMappingFileDescriptor( name, serviceRegistry );
mappingFileDescriptors.add( descriptor );
}
// classes and packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final HashMap<String, ClassDescriptor> classDescriptorMap = new HashMap<String, ClassDescriptor>();
final HashMap<String, PackageDescriptor> packageDescriptorMap = new HashMap<String, PackageDescriptor>();
for ( ClassDescriptor classDescriptor : scanResult.getLocatedClasses() ) {
classDescriptorMap.put( classDescriptor.getName(), classDescriptor );
}
for ( PackageDescriptor packageDescriptor : scanResult.getLocatedPackages() ) {
packageDescriptorMap.put( packageDescriptor.getName(), packageDescriptor );
}
final List<String> explicitClassNames = scanEnvironment.getExplicitlyListedClassNames();
if ( explicitClassNames != null ) {
for ( String explicitClassName : explicitClassNames ) {
// IMPL NOTE : explicitClassNames can contain class or package names!!!
if ( classDescriptorMap.containsKey( explicitClassName ) ) {
continue;
}
if ( packageDescriptorMap.containsKey( explicitClassName ) ) {
continue;
}
// try it as a class name first...
final String classFileName = explicitClassName.replace( '.', '/' ) + ".class";
final URL classFileUrl = serviceRegistry.getService( ClassLoaderService.class )
.locateResource( classFileName );
if ( classFileUrl != null ) {
classDescriptorMap.put(
explicitClassName,
new ClassDescriptorImpl( explicitClassName, new UrlInputStreamAccess( classFileUrl ) )
);
continue;
}
// otherwise, try it as a package name
final String packageInfoFileName = explicitClassName.replace( '.', '/' ) + "/package-info.class";
final URL packageInfoFileUrl = serviceRegistry.getService( ClassLoaderService.class )
.locateResource( packageInfoFileName );
if ( packageInfoFileUrl != null ) {
packageDescriptorMap.put(
explicitClassName,
new PackageDescriptorImpl( explicitClassName, new UrlInputStreamAccess( packageInfoFileUrl ) )
);
continue;
}
log.debugf(
"Unable to resolve class [%s] named in persistence unit [%s]",
explicitClassName,
scanEnvironment.getRootUrl().toExternalForm()
);
}
}
return new DeploymentResources() {
@Override
public Iterable<ClassDescriptor> getClassDescriptors() {
return classDescriptorMap.values();
}
@Override
public Iterable<PackageDescriptor> getPackageDescriptors() {
return packageDescriptorMap.values();
}
@Override
public Iterable<MappingFileDescriptor> getMappingFileDescriptors() {
return mappingFileDescriptors;
}
};
}
private MappingFileDescriptor buildMappingFileDescriptor(
String name,
ServiceRegistry serviceRegistry) {
final URL url = serviceRegistry.getService( ClassLoaderService.class ).locateResource( name );
if ( url == null ) {
throw new MappingException(
"Unable to resolve explicitly named mapping-file : " + name,
new Origin( SourceType.RESOURCE, name )
);
}
return new MappingFileDescriptorImpl( name, new UrlInputStreamAccess( url ) );
}
}

View File

@ -34,7 +34,6 @@ import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.util.StringHelper;
import org.hibernate.boot.CacheRegionDefinition;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
@ -160,7 +159,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
public InFlightMetadataCollectorImpl(
MetadataBuildingOptions options,
MetadataSources sources,
TypeResolver typeResolver) {
this.uuid = UUID.randomUUID();
this.options = options;
@ -168,10 +166,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
this.identifierGeneratorFactory = options.getServiceRegistry().getService( MutableIdentifierGeneratorFactory.class );
for ( AttributeConverterDefinition attributeConverterDefinition : options.getAttributeConverters() ) {
addAttributeConverter( attributeConverterDefinition );
}
for ( Map.Entry<String, SQLFunction> sqlFunctionEntry : options.getSqlFunctions().entrySet() ) {
if ( sqlFunctionMap == null ) {
// we need this to be a ConcurrentHashMap for the one we ultimately pass along to the SF

View File

@ -42,6 +42,7 @@ import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.boot.model.process.spi.MetadataBuildingProcess;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistry;
@ -49,6 +50,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.boot.spi.MappingDefaults;
import org.hibernate.boot.spi.MetadataBuilderImplementor;
import org.hibernate.boot.spi.MetadataBuilderInitializer;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.MetadataSourcesContributor;
@ -79,7 +81,7 @@ import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
/**
* @author Steve Ebersole
*/
public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeContributions {
private static final CoreMessageLogger log = CoreLogging.messageLogger( MetadataBuilderImpl.class );
private final MetadataSources sources;
@ -396,6 +398,11 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
return MetadataBuildingProcess.build( sources, options );
}
@Override
public MetadataBuildingOptions getMetadataBuildingOptions() {
return options;
}
public static class MappingDefaultsImpl implements MappingDefaults {
private String implicitSchemaName;
private String implicitCatalogName;

View File

@ -0,0 +1,38 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.model.process.internal;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.spi.MetadataBuildingOptions;
/**
* @author Steve Ebersole
*/
public class ManagedResourcesBuilder {
/**
* Singleton access
*/
public static final ManagedResourcesBuilder INSTANCE = new ManagedResourcesBuilder();
private ManagedResourcesBuilder() {
}
public ManagedResources buildCompleteManagedResources(
final MetadataSources sources,
final MetadataBuildingOptions options) {
// Instantiate ManagedResourcesImpl, and build its baseline from MetadataSources
final ManagedResourcesImpl managedResources = ManagedResourcesImpl.baseline( sources, options );
ScanningCoordinator.INSTANCE.coordinateScan( managedResources, options, sources.getXmlMappingBinderAccess() );
return managedResources;
}
}

View File

@ -0,0 +1,100 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.model.process.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.cfg.AttributeConverterDefinition;
/**
* @author Steve Ebersole
*/
public class ManagedResourcesImpl implements ManagedResources {
private Map<Class, AttributeConverterDefinition> attributeConverterDefinitionMap = new HashMap<Class,AttributeConverterDefinition>();
private Set<Class> annotatedClassReferences = new HashSet<Class>();
private Set<String> annotatedClassNames = new HashSet<String>();
private Set<String> annotatedPackageNames = new HashSet<String>();
private List<Binding> mappingFileBindings = new ArrayList<Binding>();
public static ManagedResourcesImpl baseline(MetadataSources sources, MetadataBuildingOptions metadataBuildingOptions) {
final ManagedResourcesImpl impl = new ManagedResourcesImpl();
for ( AttributeConverterDefinition attributeConverterDefinition : metadataBuildingOptions.getAttributeConverters() ) {
impl.addAttributeConverterDefinition( attributeConverterDefinition );
}
impl.annotatedClassReferences.addAll( sources.getAnnotatedClasses() );
impl.annotatedClassNames.addAll( sources.getAnnotatedClassNames() );
impl.annotatedPackageNames.addAll( sources.getAnnotatedPackages() );
impl.mappingFileBindings.addAll( sources.getXmlBindings() );
return impl;
}
private ManagedResourcesImpl() {
}
@Override
public Collection<AttributeConverterDefinition> getAttributeConverterDefinitions() {
return Collections.unmodifiableCollection( attributeConverterDefinitionMap.values() );
}
@Override
public Collection<Class> getAnnotatedClassReferences() {
return Collections.unmodifiableSet( annotatedClassReferences );
}
@Override
public Collection<String> getAnnotatedClassNames() {
return Collections.unmodifiableSet( annotatedClassNames );
}
@Override
public Collection<String> getAnnotatedPackageNames() {
return Collections.unmodifiableSet( annotatedPackageNames );
}
@Override
public Collection<Binding> getXmlMappingBindings() {
return Collections.unmodifiableList( mappingFileBindings );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// package private
void addAttributeConverterDefinition(AttributeConverterDefinition attributeConverterDefinition) {
attributeConverterDefinitionMap.put(
attributeConverterDefinition.getAttributeConverter().getClass(),
attributeConverterDefinition
);
}
void addAnnotatedClassReference(Class annotatedClassReference) {
annotatedClassReferences.add( annotatedClassReference );
}
void addAnnotatedClassName(String annotatedClassName) {
annotatedClassNames.add( annotatedClassName );
}
void addAnnotatedPackageName(String annotatedPackageName) {
annotatedPackageNames.add( annotatedPackageName );
}
void addXmlBinding(Binding binding) {
mappingFileBindings.add( binding );
}
}

View File

@ -0,0 +1,278 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.model.process.internal;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.AttributeConverter;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.archive.internal.StandardArchiveDescriptorFactory;
import org.hibernate.boot.archive.internal.UrlInputStreamAccess;
import org.hibernate.boot.archive.scan.internal.StandardScanParameters;
import org.hibernate.boot.archive.scan.internal.StandardScanner;
import org.hibernate.boot.archive.scan.spi.ClassDescriptor;
import org.hibernate.boot.archive.scan.spi.MappingFileDescriptor;
import org.hibernate.boot.archive.scan.spi.PackageDescriptor;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanResult;
import org.hibernate.boot.archive.scan.spi.Scanner;
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.XmlMappingBinderAccess;
import org.hibernate.cfg.AttributeConverterDefinition;
import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;
/**
* Coordinates the process of executing {@link org.hibernate.boot.archive.scan.spi.Scanner} (if enabled)
* and applying the resources (classes, packages and mappings) discovered.
*
* @author Steve Ebersole
*/
public class ScanningCoordinator {
private static final Logger log = Logger.getLogger( ScanningCoordinator.class );
/**
* Singleton access
*/
public static final ScanningCoordinator INSTANCE = new ScanningCoordinator();
private ScanningCoordinator() {
}
public void coordinateScan(
ManagedResourcesImpl managedResources,
MetadataBuildingOptions options,
XmlMappingBinderAccess xmlMappingBinderAccess) {
if ( options.getScanEnvironment() == null ) {
return;
}
final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class );
final ClassLoaderAccess classLoaderAccess = new ClassLoaderAccessImpl(
options.getTempClassLoader(),
classLoaderService
);
// NOTE : the idea with JandexInitializer/JandexInitManager was to allow adding classes
// to the index as we discovered them via scanning and . Currently
final Scanner scanner = buildScanner( options, classLoaderAccess );
final ScanResult scanResult = scanner.scan(
options.getScanEnvironment(),
options.getScanOptions(),
StandardScanParameters.INSTANCE
);
applyScanResultsToManagedResources( managedResources, scanResult, options, xmlMappingBinderAccess );
}
private static final Class[] SINGLE_ARG = new Class[] { ArchiveDescriptorFactory.class };
@SuppressWarnings("unchecked")
private static Scanner buildScanner(MetadataBuildingOptions options, ClassLoaderAccess classLoaderAccess) {
final Object scannerSetting = options.getScanner();
final ArchiveDescriptorFactory archiveDescriptorFactory = options.getArchiveDescriptorFactory();
if ( scannerSetting == null ) {
// No custom Scanner specified, use the StandardScanner
if ( archiveDescriptorFactory == null ) {
return new StandardScanner();
}
else {
return new StandardScanner( archiveDescriptorFactory );
}
}
else {
if ( Scanner.class.isInstance( scannerSetting ) ) {
if ( archiveDescriptorFactory != null ) {
throw new IllegalStateException(
"A Scanner instance and an ArchiveDescriptorFactory were both specified; please " +
"specify one or the other, or if you need to supply both, Scanner class to use " +
"(assuming it has a constructor accepting a ArchiveDescriptorFactory). " +
"Alternatively, just pass the ArchiveDescriptorFactory during your own " +
"Scanner constructor assuming it is statically known."
);
}
return (Scanner) scannerSetting;
}
final Class<? extends Scanner> scannerImplClass;
if ( Class.class.isInstance( scannerSetting ) ) {
scannerImplClass = (Class<? extends Scanner>) scannerSetting;
}
else {
scannerImplClass = classLoaderAccess.classForName( scannerSetting.toString() );
}
if ( archiveDescriptorFactory != null ) {
// find the single-arg constructor - its an error if none exists
try {
final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor( SINGLE_ARG );
try {
return constructor.newInstance( archiveDescriptorFactory );
}
catch (Exception e) {
throw new IllegalStateException(
"Error trying to instantiate custom specified Scanner [" +
scannerImplClass.getName() + "]",
e
);
}
}
catch (NoSuchMethodException e) {
throw new IllegalArgumentException(
"Configuration named a custom Scanner and a custom ArchiveDescriptorFactory, but " +
"Scanner impl did not define a constructor accepting ArchiveDescriptorFactory"
);
}
}
else {
// could be either ctor form...
// find the single-arg constructor - its an error if none exists
try {
final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor( SINGLE_ARG );
try {
return constructor.newInstance( StandardArchiveDescriptorFactory.INSTANCE );
}
catch (Exception e) {
throw new IllegalStateException(
"Error trying to instantiate custom specified Scanner [" +
scannerImplClass.getName() + "]",
e
);
}
}
catch (NoSuchMethodException e) {
try {
final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor();
try {
return constructor.newInstance();
}
catch (Exception e2) {
throw new IllegalStateException(
"Error trying to instantiate custom specified Scanner [" +
scannerImplClass.getName() + "]",
e2
);
}
}
catch (NoSuchMethodException ignore) {
throw new IllegalArgumentException(
"Configuration named a custom Scanner, but we were unable to locate " +
"an appropriate constructor"
);
}
}
}
}
}
public void applyScanResultsToManagedResources(
ManagedResourcesImpl managedResources,
ScanResult scanResult,
MetadataBuildingOptions options,
XmlMappingBinderAccess xmlMappingBinderAccess) {
final ScanEnvironment scanEnvironment = options.getScanEnvironment();
final ServiceRegistry serviceRegistry = options.getServiceRegistry();
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
// mapping files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final Set<String> nonLocatedMappingFileNames = new HashSet<String>();
final List<String> explicitMappingFileNames = scanEnvironment.getExplicitlyListedMappingFiles();
if ( explicitMappingFileNames != null ) {
nonLocatedMappingFileNames.addAll( explicitMappingFileNames );
}
for ( MappingFileDescriptor mappingFileDescriptor : scanResult.getLocatedMappingFiles() ) {
managedResources.addXmlBinding( xmlMappingBinderAccess.bind( mappingFileDescriptor.getStreamAccess() ) );
nonLocatedMappingFileNames.remove( mappingFileDescriptor.getName() );
}
for ( String name : nonLocatedMappingFileNames ) {
final URL url = classLoaderService.locateResource( name );
if ( url == null ) {
throw new MappingException(
"Unable to resolve explicitly named mapping-file : " + name,
new Origin( SourceType.RESOURCE, name )
);
}
final UrlInputStreamAccess inputStreamAccess = new UrlInputStreamAccess( url );
managedResources.addXmlBinding( xmlMappingBinderAccess.bind( inputStreamAccess ) );
}
// classes and packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final List<String> unresolvedListedClassNames = scanEnvironment.getExplicitlyListedClassNames() == null
? new ArrayList<String>()
: new ArrayList<String>( scanEnvironment.getExplicitlyListedClassNames() );
for ( ClassDescriptor classDescriptor : scanResult.getLocatedClasses() ) {
if ( classDescriptor.getCategorization() == ClassDescriptor.Categorization.CONVERTER ) {
// converter classes are safe to load because we never enhance them,
// and notice we use the ClassLoaderService specifically, not the temp ClassLoader (if any)
managedResources.addAttributeConverterDefinition(
AttributeConverterDefinition.from(
classLoaderService.<AttributeConverter>classForName( classDescriptor.getName() )
)
);
}
else if ( classDescriptor.getCategorization() == ClassDescriptor.Categorization.MODEL ) {
managedResources.addAnnotatedClassName( classDescriptor.getName() );
}
unresolvedListedClassNames.remove( classDescriptor.getName() );
}
// IMPL NOTE : "explicitlyListedClassNames" can contain class or package names...
for ( PackageDescriptor packageDescriptor : scanResult.getLocatedPackages() ) {
managedResources.addAnnotatedPackageName( packageDescriptor.getName() );
unresolvedListedClassNames.remove( packageDescriptor.getName() );
}
for ( String unresolvedListedClassName : unresolvedListedClassNames ) {
// because the explicit list can contain either class names or package names
// we need to check for both here...
// First, try it as a class name
final String classFileName = unresolvedListedClassName.replace( '.', '/' ) + ".class";
final URL classFileUrl = classLoaderService.locateResource( classFileName );
if ( classFileUrl != null ) {
managedResources.addAnnotatedClassName( unresolvedListedClassName );
continue;
}
// Then, try it as a package name
final String packageInfoFileName = unresolvedListedClassName.replace( '.', '/' ) + "/package-info.class";
final URL packageInfoFileUrl = classLoaderService.locateResource( packageInfoFileName );
if ( packageInfoFileUrl != null ) {
managedResources.addAnnotatedPackageName( unresolvedListedClassName );
continue;
}
log.debugf(
"Unable to resolve class [%s] named in persistence unit [%s]",
unresolvedListedClassName,
scanEnvironment.getRootUrl().toExternalForm()
);
}
}
}

View File

@ -0,0 +1,13 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Defines the contracts used to perform the process of transforming a {@link org.hibernate.boot.MetadataSources}
* references into a {@link org.hibernate.boot.Metadata} reference. This process is mainly defined by
* {@link org.hibernate.boot.model.process.spi.MetadataBuildingProcess}.
*/
package org.hibernate.boot.model.process;

View File

@ -0,0 +1,67 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.model.process.spi;
import java.util.Collection;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.cfg.AttributeConverterDefinition;
/**
* Represents the result of the first step of the process of building {@link org.hibernate.boot.MetadataSources}
* reference into a {@link org.hibernate.boot.Metadata} reference.
* <p/>
* Essentially it represents thecombination of:<ol>
* <li>domain classes, packages and mapping files defined via MetadataSources</li>
* <li>attribute converters defined via MetadataBuildingOptions</li>
* <li>classes, converters, packages and mapping files auto-discovered as part of scanning</li>
* </ol>
*
* @author Steve Ebersole
*/
public interface ManagedResources {
/**
* Informational access to the AttributeConverter definitions known about. Changes to made to
* the returned list have no effect.
*
* @return The AttributeConverter definitions.
*/
Collection<AttributeConverterDefinition> getAttributeConverterDefinitions();
/**
* Informational access to any entity and component classes in the user domain model known by Class
* reference . Changes to made to the returned list have no effect.
*
* @return The list of entity/component classes known by Class reference.
*/
Collection<Class> getAnnotatedClassReferences();
/**
* Informational access to any entity and component classes in the user domain model known by name.
* Changes to made to the returned list have no effect.
*
* @return The list of entity/component classes known by name.
*/
Collection<String> getAnnotatedClassNames();
/**
* Informational access to any known annotated package names (packages with a {@code package-info.class}
* file that Hibernate has been told about). Changes to made to the returned list have no effect.
*
* @return The list of known annotated package names.
*/
Collection<String> getAnnotatedPackageNames();
/**
* Informational access to binding for all known XML mapping files. Changes to made to the returned
* list have no effect.
*
* @return The list of bindings for all known XML mapping files.
*/
Collection<Binding> getXmlMappingBindings();
}

View File

@ -4,30 +4,22 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.internal;
package org.hibernate.boot.model.process.spi;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Converter;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.archive.internal.StandardArchiveDescriptorFactory;
import org.hibernate.boot.archive.scan.internal.StandardScanner;
import org.hibernate.boot.archive.scan.spi.ClassDescriptor;
import org.hibernate.boot.archive.scan.spi.JandexInitializer;
import org.hibernate.boot.archive.scan.spi.MappingFileDescriptor;
import org.hibernate.boot.archive.scan.spi.PackageDescriptor;
import org.hibernate.boot.archive.scan.spi.ScanParameters;
import org.hibernate.boot.archive.scan.spi.ScanResult;
import org.hibernate.boot.archive.scan.spi.Scanner;
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
import org.hibernate.boot.internal.DeploymentResourcesInterpreter.DeploymentResources;
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
import org.hibernate.boot.internal.InFlightMetadataCollectorImpl;
import org.hibernate.boot.internal.MetadataBuilderImpl.MetadataBuildingOptionsImpl;
import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
import org.hibernate.boot.internal.MetadataImpl;
import org.hibernate.boot.jaxb.internal.MappingBinder;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.boot.model.process.internal.ManagedResourcesBuilder;
import org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl;
import org.hibernate.boot.model.source.internal.hbm.EntityHierarchyBuilder;
import org.hibernate.boot.model.source.internal.hbm.EntityHierarchySourceImpl;
@ -36,7 +28,6 @@ import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
import org.hibernate.boot.model.source.internal.hbm.ModelBinder;
import org.hibernate.boot.model.source.spi.MetadataSourceProcessor;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.AdditionalJaxbMappingProducer;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.MetadataBuildingOptions;
@ -55,8 +46,21 @@ import org.jboss.jandex.IndexView;
import org.jboss.logging.Logger;
/**
* Represents the process of building a Metadata object. The main entry point is the
* static {@link #build}
* Represents the process of of transforming a {@link org.hibernate.boot.MetadataSources}
* reference into a {@link org.hibernate.boot.Metadata} reference. Allows for 2 different process paradigms:<ul>
* <li>
* Single step : as defined by the {@link #build} method; internally leverages the 2-step paradigm
* </li>
* <li>
* Two step : a first step coordinates resource scanning and some other preparation work; a second step
* builds the {@link org.hibernate.boot.Metadata}. A hugely important distinction in the need for the
* steps is that the first phase should strive to not load user entity/component classes so that we can still
* perform enhancement on them later. This approach caters to the 2-phase bootstrap we use in regards
* to WildFly Hibernate-JPA integration. The first step is defined by {@link #prepare} which returns
* a {@link ManagedResources} instance. The second step is defined by calling
* {@link #complete}
* </li>
* </ul>
*
* @author Steve Ebersole
*/
@ -65,7 +69,27 @@ public class MetadataBuildingProcess {
public static MetadataImpl build(
final MetadataSources sources,
final MetadataBuildingOptionsImpl options) {
final MetadataBuildingOptions options) {
return complete( prepare( sources, options ), options );
}
public static ManagedResources prepare(
final MetadataSources sources,
final MetadataBuildingOptions options) {
return ManagedResourcesBuilder.INSTANCE.buildCompleteManagedResources( sources, options );
}
public static MetadataImpl complete(final ManagedResources managedResources, final MetadataBuildingOptions options) {
final BasicTypeRegistry basicTypeRegistry = handleTypes( options );
final InFlightMetadataCollectorImpl metadataCollector = new InFlightMetadataCollectorImpl(
options,
new TypeResolver( basicTypeRegistry, new TypeFactory() )
);
for ( AttributeConverterDefinition attributeConverterDefinition : managedResources.getAttributeConverterDefinitions() ) {
metadataCollector.addAttributeConverter( attributeConverterDefinition );
}
final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class );
final ClassLoaderAccess classLoaderAccess = new ClassLoaderAccessImpl(
@ -73,70 +97,14 @@ public class MetadataBuildingProcess {
classLoaderService
);
// final JandexInitManager jandexInitializer = buildJandexInitializer( options, classLoaderAccess );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// scanning - Jandex initialization and source discovery
if ( options.getScanEnvironment() != null ) {
final Scanner scanner = buildScanner( options, classLoaderAccess );
final ScanResult scanResult = scanner.scan(
options.getScanEnvironment(),
options.getScanOptions(),
new ScanParameters() {
@Override
public JandexInitializer getJandexInitializer() {
// return jandexInitializer;
return null;
}
}
);
// Add to the MetadataSources any classes/packages/mappings discovered during scanning
addScanResultsToSources( sources, options, scanResult );
}
// // todo : add options.getScanEnvironment().getExplicitlyListedClassNames() to jandex?
// // ^^ - another option is to make sure that they are added to sources
//
// if ( !jandexInitializer.wasIndexSupplied() ) {
// // If the Jandex Index(View) was supplied, we consider that supplied
// // one "complete".
// // Here though we were NOT supplied an index; in this case we want to
// // additionally ensure that any-and-all "known" classes are added to
// // the index we are building
// sources.indexKnownClasses( jandexInitializer );
// }
// It's necessary to delay the binding of XML resources until now. ClassLoaderAccess is needed for
// reflection, etc.
// sources.buildBindResults( classLoaderAccess );
// final IndexView jandexView = augmentJandexFromMappings( jandexInitializer.buildIndex(), sources, options );
final IndexView jandexView = options.getJandexView();
final BasicTypeRegistry basicTypeRegistry = handleTypes( options );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// prep to start handling binding in earnest
// final JandexAccessImpl jandexAccess = new JandexAccessImpl(
// jandexView,
// classLoaderAccess
//
// );
final InFlightMetadataCollectorImpl metadataCollector = new InFlightMetadataCollectorImpl(
options,
sources,
new TypeResolver( basicTypeRegistry, new TypeFactory() )
);
final MetadataBuildingContextRootImpl rootMetadataBuildingContext = new MetadataBuildingContextRootImpl(
options,
classLoaderAccess,
metadataCollector
);
final IndexView jandexView = options.getJandexView();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Set up the processors and start binding
// NOTE : this becomes even more simplified after we move purely
@ -144,12 +112,12 @@ public class MetadataBuildingProcess {
final MetadataSourceProcessor processor = new MetadataSourceProcessor() {
private final HbmMetadataSourceProcessorImpl hbmProcessor = new HbmMetadataSourceProcessorImpl(
sources,
managedResources,
rootMetadataBuildingContext
);
private final AnnotationMetadataSourceProcessorImpl annotationProcessor = new AnnotationMetadataSourceProcessorImpl(
sources,
managedResources,
rootMetadataBuildingContext,
jandexView
);
@ -321,152 +289,7 @@ public class MetadataBuildingProcess {
// return new JandexInitManager( options.getJandexView(), classLoaderAccess, autoIndexMembers );
// }
private static final Class[] SINGLE_ARG = new Class[] { ArchiveDescriptorFactory.class };
private static Scanner buildScanner(MetadataBuildingOptions options, ClassLoaderAccess classLoaderAccess) {
final Object scannerSetting = options.getScanner();
final ArchiveDescriptorFactory archiveDescriptorFactory = options.getArchiveDescriptorFactory();
if ( scannerSetting == null ) {
// No custom Scanner specified, use the StandardScanner
if ( archiveDescriptorFactory == null ) {
return new StandardScanner();
}
else {
return new StandardScanner( archiveDescriptorFactory );
}
}
else {
if ( Scanner.class.isInstance( scannerSetting ) ) {
if ( archiveDescriptorFactory != null ) {
throw new IllegalStateException(
"A Scanner instance and an ArchiveDescriptorFactory were both specified; please " +
"specify one or the other, or if you need to supply both, Scanner class to use " +
"(assuming it has a constructor accepting a ArchiveDescriptorFactory). " +
"Alternatively, just pass the ArchiveDescriptorFactory during your own " +
"Scanner constructor assuming it is statically known."
);
}
return (Scanner) scannerSetting;
}
final Class<? extends Scanner> scannerImplClass;
if ( Class.class.isInstance( scannerSetting ) ) {
scannerImplClass = (Class<? extends Scanner>) scannerSetting;
}
else {
scannerImplClass = classLoaderAccess.classForName( scannerSetting.toString() );
}
if ( archiveDescriptorFactory != null ) {
// find the single-arg constructor - its an error if none exists
try {
final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor( SINGLE_ARG );
try {
return constructor.newInstance( archiveDescriptorFactory );
}
catch (Exception e) {
throw new IllegalStateException(
"Error trying to instantiate custom specified Scanner [" +
scannerImplClass.getName() + "]",
e
);
}
}
catch (NoSuchMethodException e) {
throw new IllegalArgumentException(
"Configuration named a custom Scanner and a custom ArchiveDescriptorFactory, but " +
"Scanner impl did not define a constructor accepting ArchiveDescriptorFactory"
);
}
}
else {
// could be either ctor form...
// find the single-arg constructor - its an error if none exists
try {
final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor( SINGLE_ARG );
try {
return constructor.newInstance( StandardArchiveDescriptorFactory.INSTANCE );
}
catch (Exception e) {
throw new IllegalStateException(
"Error trying to instantiate custom specified Scanner [" +
scannerImplClass.getName() + "]",
e
);
}
}
catch (NoSuchMethodException e) {
try {
final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor();
try {
return constructor.newInstance();
}
catch (Exception e2) {
throw new IllegalStateException(
"Error trying to instantiate custom specified Scanner [" +
scannerImplClass.getName() + "]",
e2
);
}
}
catch (NoSuchMethodException ignore) {
throw new IllegalArgumentException(
"Configuration named a custom Scanner, but we were unable to locate " +
"an appropriate constructor"
);
}
}
}
}
}
private static void addScanResultsToSources(
MetadataSources sources,
MetadataBuildingOptionsImpl options,
ScanResult scanResult) {
final ClassLoaderService cls = options.getServiceRegistry().getService( ClassLoaderService.class );
DeploymentResources deploymentResources = DeploymentResourcesInterpreter.INSTANCE.buildDeploymentResources(
options.getScanEnvironment(),
scanResult,
options.getServiceRegistry()
);
for ( ClassDescriptor classDescriptor : deploymentResources.getClassDescriptors() ) {
final String className = classDescriptor.getName();
// todo : leverage Jandex calls after we fully integrate Jandex...
try {
final Class classRef = cls.classForName( className );
// logic here assumes an entity is not also a converter...
final Converter converter = (Converter) classRef.getAnnotation( Converter.class );
if ( converter != null ) {
//noinspection unchecked
options.addAttributeConverterDefinition(
AttributeConverterDefinition.from( classRef, converter.autoApply() )
);
}
else {
sources.addAnnotatedClass( classRef );
}
}
catch (ClassLoadingException e) {
// Not really sure what this means...
sources.addAnnotatedClassName( className );
}
}
for ( PackageDescriptor packageDescriptor : deploymentResources.getPackageDescriptors() ) {
sources.addPackage( packageDescriptor.getName() );
}
for ( MappingFileDescriptor mappingFileDescriptor : deploymentResources.getMappingFileDescriptors() ) {
sources.addInputStream( mappingFileDescriptor.getStreamAccess() );
}
}
private static BasicTypeRegistry handleTypes(MetadataBuildingOptions options) {

View File

@ -6,17 +6,26 @@
*/
package org.hibernate.boot.model.source.internal.annotations;
import org.dom4j.Document;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.common.reflection.ClassLoadingException;
import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.internal.MetadataBuilderImpl.MetadataBuildingOptionsImpl;
import org.hibernate.boot.internal.MetadataBuilderImpl.MetadataBuildingOptionsImpl.JpaOrmXmlPersistenceUnitDefaults;
import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.model.source.spi.MetadataSourceProcessor;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.AnnotationBinder;
@ -26,18 +35,11 @@ import org.hibernate.cfg.annotations.reflection.AttributeConverterDefinitionColl
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.jboss.jandex.IndexView;
import org.jboss.logging.Logger;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dom4j.Document;
/**
* @author Steve Ebersole
@ -57,7 +59,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
private final List<XClass> xClasses = new ArrayList<XClass>();
public AnnotationMetadataSourceProcessorImpl(
MetadataSources sources,
ManagedResources managedResources,
final MetadataBuildingContextRootImpl rootMetadataBuildingContext,
IndexView jandexView) {
this.rootMetadataBuildingContext = rootMetadataBuildingContext;
@ -65,8 +67,8 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
this.reflectionManager = rootMetadataBuildingContext.getBuildingOptions().getReflectionManager();
if ( CollectionHelper.isNotEmpty( sources.getAnnotatedPackages() ) ) {
annotatedPackages.addAll( sources.getAnnotatedPackages() );
if ( CollectionHelper.isNotEmpty( managedResources.getAnnotatedPackageNames() ) ) {
annotatedPackages.addAll( managedResources.getAnnotatedPackageNames() );
}
final AttributeConverterManager attributeConverterManager = new AttributeConverterManager( rootMetadataBuildingContext );
@ -75,7 +77,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
// Ewww. This is temporary until we migrate to Jandex + StAX for annotation binding
final JPAMetadataProvider jpaMetadataProvider = (JPAMetadataProvider) ( (MetadataProviderInjector) reflectionManager ).getMetadataProvider();
for ( Binding xmlBinding : sources.getXmlBindings() ) {
for ( Binding xmlBinding : managedResources.getXmlMappingBindings() ) {
// if ( !MappingBinder.DelayedOrmXmlData.class.isInstance( xmlBinding.getRoot() ) ) {
// continue;
// }
@ -97,12 +99,12 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final ClassLoaderService cls = rootMetadataBuildingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class );
for ( String className : sources.getAnnotatedClassNames() ) {
for ( String className : managedResources.getAnnotatedClassNames() ) {
final Class annotatedClass = cls.classForName( className );
categorizeAnnotatedClass( annotatedClass, attributeConverterManager );
}
for ( Class annotatedClass : sources.getAnnotatedClasses() ) {
for ( Class annotatedClass : managedResources.getAnnotatedClassReferences() ) {
categorizeAnnotatedClass( annotatedClass, attributeConverterManager );
}
}

View File

@ -7,18 +7,18 @@
package org.hibernate.boot.model.source.internal.hbm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.model.source.spi.MetadataSourceProcessor;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.jboss.logging.Logger;
/**
* MetadataSourceProcessor implementation for processing {@code hbm.xml} mapping documents.
*
@ -28,24 +28,21 @@ public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor {
private static final Logger log = Logger.getLogger( HbmMetadataSourceProcessorImpl.class );
private final MetadataBuildingContext rootBuildingContext;
private List<MappingDocument> mappingDocuments;
private Collection<MappingDocument> mappingDocuments;
private final ModelBinder modelBinder;
private List<EntityHierarchySourceImpl> entityHierarchies;
public HbmMetadataSourceProcessorImpl(
MetadataSources metadataSources,
ManagedResources managedResources,
MetadataBuildingContext rootBuildingContext) {
this(
metadataSources.getXmlBindings(),
rootBuildingContext
);
this( managedResources.getXmlMappingBindings(), rootBuildingContext );
}
@SuppressWarnings("unchecked")
public HbmMetadataSourceProcessorImpl(
List<Binding> xmlBindings,
Collection<Binding> xmlBindings,
MetadataBuildingContext rootBuildingContext) {
this.rootBuildingContext = rootBuildingContext;
final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder();

View File

@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.spi;
import org.hibernate.boot.MetadataBuilder;
/**
* Internal API for MetadataBuilder exposing the building options being collected.
*
* @author Steve Ebersole
*/
public interface MetadataBuilderImplementor extends MetadataBuilder {
/**
* Get the options being collected on this MetadataBuilder that will ultimately be used in
* building the Metadata.
*
* @return The current building options
*/
MetadataBuildingOptions getMetadataBuildingOptions();
}

View File

@ -0,0 +1,104 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.spi;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.hibernate.boot.MappingNotFoundException;
import org.hibernate.boot.archive.spi.InputStreamAccess;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.boot.jaxb.internal.FileXmlSource;
import org.hibernate.boot.jaxb.internal.InputStreamXmlSource;
import org.hibernate.boot.jaxb.internal.MappingBinder;
import org.hibernate.boot.jaxb.internal.UrlXmlSource;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class XmlMappingBinderAccess {
private static final Logger LOG = Logger.getLogger( XmlMappingBinderAccess.class );
private final ClassLoaderService classLoaderService;
private final MappingBinder mappingBinder;
public XmlMappingBinderAccess(ServiceRegistry serviceRegistry) {
this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
// NOTE : The boolean here indicates whether or not to perform validation as we load XML documents.
// Should we expose this setting? Disabling would speed up JAXP and JAXB at runtime, but potentially
// at the cost of less obvious errors when a document is not valid.
this.mappingBinder = new MappingBinder( serviceRegistry.getService( ClassLoaderService.class ), true );
}
public MappingBinder getMappingBinder() {
return mappingBinder;
}
public Binding bind(String resource) {
LOG.tracef( "reading mappings from resource : %s", resource );
final Origin origin = new Origin( SourceType.RESOURCE, resource );
final URL url = classLoaderService.locateResource( resource );
if ( url == null ) {
throw new MappingNotFoundException( origin );
}
return new UrlXmlSource( origin, url ).doBind( getMappingBinder() );
}
public Binding bind(File file) {
final Origin origin = new Origin( SourceType.FILE, file.getPath() );
LOG.tracef( "reading mappings from file : %s", origin.getName() );
if ( !file.exists() ) {
throw new MappingNotFoundException( origin );
}
return new FileXmlSource( origin, file ).doBind( getMappingBinder() );
}
public Binding bind(InputStreamAccess xmlInputStreamAccess) {
LOG.tracef( "reading mappings from InputStreamAccess : %s", xmlInputStreamAccess.getStreamName() );
final Origin origin = new Origin( SourceType.INPUT_STREAM, xmlInputStreamAccess.getStreamName() );
InputStream xmlInputStream = xmlInputStreamAccess.accessInputStream();
try {
return new InputStreamXmlSource( origin, xmlInputStream, false ).doBind( mappingBinder );
}
finally {
try {
xmlInputStream.close();
}
catch (IOException e) {
LOG.debugf( "Unable to close InputStream obtained from InputStreamAccess : " + xmlInputStreamAccess.getStreamName() );
}
}
}
public Binding bind(InputStream xmlInputStream) {
LOG.tracef( "reading mappings from InputStream" );
final Origin origin = new Origin( SourceType.INPUT_STREAM, null );
return new InputStreamXmlSource( origin, xmlInputStream, false ).doBind( getMappingBinder() );
}
public Binding bind(URL url) {
final String urlExternalForm = url.toExternalForm();
LOG.debugf( "Reading mapping document from URL : %s", urlExternalForm );
final Origin origin = new Origin( SourceType.URL, urlExternalForm );
return new UrlXmlSource( origin, url ).doBind( getMappingBinder() );
}
}

View File

@ -31,14 +31,19 @@ import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.archive.scan.internal.StandardScanOptions;
import org.hibernate.boot.cfgxml.internal.ConfigLoader;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.cfgxml.spi.LoadedConfig;
import org.hibernate.boot.cfgxml.spi.MappingReference;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.model.process.spi.MetadataBuildingProcess;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.boot.spi.MetadataBuilderImplementor;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AttributeConverterDefinition;
import org.hibernate.cfg.Environment;
@ -61,7 +66,6 @@ import org.hibernate.jpa.internal.schemagen.JpaSchemaGenerator;
import org.hibernate.jpa.internal.util.LogHelper;
import org.hibernate.jpa.internal.util.PersistenceUnitTransactionTypeHelper;
import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
@ -121,16 +125,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// things built in first phase, needed for second phase..
private final Map configurationValues;
private final StandardServiceRegistry standardServiceRegistry;
private final MetadataImplementor metadata;
private final ManagedResources managedResources;
private final MetadataBuilderImplementor metamodelBuilder;
private final SettingsImpl settings;
/**
* Intended for internal testing only...
*/
public MetadataImplementor getMetadata() {
return metadata;
}
private static class JpaEntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable {
/**
* Singleton access
@ -174,10 +172,29 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
configure( standardServiceRegistry, mergedSettings );
final MetadataSources metadataSources = new MetadataSources( bsr );
List<AttributeConverterDefinition> attributeConverterDefinitions = populate( metadataSources, mergedSettings, standardServiceRegistry );
final MetadataBuilder metamodelBuilder = metadataSources.getMetadataBuilder( standardServiceRegistry );
List<AttributeConverterDefinition> attributeConverterDefinitions = populate(
metadataSources,
mergedSettings,
standardServiceRegistry
);
this.metamodelBuilder = (MetadataBuilderImplementor) metadataSources.getMetadataBuilder( standardServiceRegistry );
populate( metamodelBuilder, mergedSettings, standardServiceRegistry, attributeConverterDefinitions );
this.metadata = (MetadataImplementor) metamodelBuilder.build();
// todo : would be nice to have MetadataBuilder still do the handling of CfgXmlAccessService here
// another option is to immediately handle them here (probably in mergeSettings?) as we encounter them...
final CfgXmlAccessService cfgXmlAccessService = standardServiceRegistry.getService( CfgXmlAccessService.class );
if ( cfgXmlAccessService.getAggregatedConfig() != null ) {
if ( cfgXmlAccessService.getAggregatedConfig().getMappingReferences() != null ) {
for ( MappingReference mappingReference : cfgXmlAccessService.getAggregatedConfig().getMappingReferences() ) {
mappingReference.apply( metadataSources );
}
}
}
this.managedResources = MetadataBuildingProcess.prepare(
metadataSources,
metamodelBuilder.getMetadataBuildingOptions()
);
withValidatorFactory( configurationValues.get( AvailableSettings.VALIDATION_FACTORY ) );
@ -186,7 +203,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// container situations, calling back into PersistenceUnitInfo#addClassTransformer
final boolean useClassTransformer = "true".equals( configurationValues.remove( AvailableSettings.USE_CLASS_ENHANCER ) );
if ( useClassTransformer ) {
persistenceUnit.pushClassTransformer( collectNamesOfClassesToEnhance( metadata ) );
persistenceUnit.pushClassTransformer( managedResources.getAnnotatedClassNames() );
}
}
@ -708,24 +725,20 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
private List<String> collectNamesOfClassesToEnhance(MetadataImplementor metadata) {
final List<String> entityClassNames = new ArrayList<String>();
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
if ( persistentClass.getClassName() != null ) {
entityClassNames.add( persistentClass.getClassName() );
}
}
return entityClassNames;
}
// Phase 2 concerns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private Object validatorFactory;
private Object cdiBeanManager;
private DataSource dataSource;
private MetadataImplementor metadata;
/**
* Intended for internal testing only...
*/
public MetadataImplementor getMetadata() {
return metadata;
}
@Override
public EntityManagerFactoryBuilder withValidatorFactory(Object validatorFactory) {
@ -749,16 +762,23 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// todo : close the bootstrap registry (not critical, but nice to do)
}
private MetadataImplementor metadata() {
if ( this.metadata == null ) {
this.metadata = MetadataBuildingProcess.complete( managedResources, metamodelBuilder.getMetadataBuildingOptions() );
}
return metadata;
}
@Override
public void generateSchema() {
// This seems overkill, but building the SF is necessary to get the Integrators to kick in.
// Metamodel will clean this up...
try {
SessionFactoryBuilder sfBuilder = metadata.getSessionFactoryBuilder();
SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
populate( sfBuilder, standardServiceRegistry );
sfBuilder.build();
JpaSchemaGenerator.performGeneration( metadata, configurationValues, standardServiceRegistry );
JpaSchemaGenerator.performGeneration( metadata(), configurationValues, standardServiceRegistry );
}
catch (Exception e) {
throw persistenceException( "Unable to build Hibernate SessionFactory", e );
@ -771,7 +791,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
@SuppressWarnings("unchecked")
public EntityManagerFactory build() {
SessionFactoryBuilder sfBuilder = metadata.getSessionFactoryBuilder();
SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
populate( sfBuilder, standardServiceRegistry );
SessionFactoryImplementor sessionFactory;
@ -782,12 +802,12 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
throw persistenceException( "Unable to build Hibernate SessionFactory", e );
}
JpaSchemaGenerator.performGeneration( metadata, configurationValues, standardServiceRegistry );
JpaSchemaGenerator.performGeneration( metadata(), configurationValues, standardServiceRegistry );
return new EntityManagerFactoryImpl(
persistenceUnit.getName(),
sessionFactory,
metadata,
metadata(),
settings,
configurationValues
);

View File

@ -9,6 +9,7 @@ package org.hibernate.jpa.boot.internal;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import javax.persistence.SharedCacheMode;
@ -184,7 +185,7 @@ public class ParsedPersistenceXmlDescriptor implements org.hibernate.jpa.boot.sp
}
@Override
public void pushClassTransformer(List<String> entityClassNames) {
public void pushClassTransformer(Collection<String> entityClassNames) {
// todo : log a message that this is currently not supported...
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.jpa.boot.internal;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import javax.persistence.SharedCacheMode;
@ -108,7 +109,7 @@ public class PersistenceUnitInfoDescriptor implements PersistenceUnitDescriptor
}
@Override
public void pushClassTransformer(List<String> entityClassNames) {
public void pushClassTransformer(Collection<String> entityClassNames) {
persistenceUnitInfo.addTransformer( new InterceptFieldClassFileTransformer( entityClassNames ) );
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.jpa.boot.spi;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import javax.persistence.SharedCacheMode;
@ -81,5 +82,5 @@ public interface PersistenceUnitDescriptor {
public ClassLoader getClassLoader();
public ClassLoader getTempClassLoader();
public void pushClassTransformer(List<String> entityClassNames);
public void pushClassTransformer(Collection<String> entityClassNames);
}

View File

@ -8,6 +8,7 @@ package org.hibernate.jpa.internal.instrument;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.bytecode.buildtime.spi.ClassFilter;
@ -24,7 +25,7 @@ import org.hibernate.cfg.Environment;
public class InterceptFieldClassFileTransformer implements javax.persistence.spi.ClassTransformer {
private ClassTransformer classTransformer;
public InterceptFieldClassFileTransformer(List<String> entities) {
public InterceptFieldClassFileTransformer(Collection<String> entities) {
final List<String> copyEntities = new ArrayList<String>( entities.size() );
copyEntities.addAll( entities );
classTransformer = Environment.getBytecodeProvider().getTransformer(

View File

@ -6,34 +6,34 @@
*/
package org.hibernate.jpa.test;
import javax.persistence.EntityManager;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.PersistenceUnitTransactionType;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.PersistenceUnitTransactionType;
import org.jboss.logging.Logger;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.HibernateEntityManagerFactory;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.After;
import org.junit.Before;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.jboss.logging.Logger;
/**
* A base class for all ejb tests.
@ -176,7 +176,7 @@ public abstract class BaseEntityManagerFunctionalTestCase extends BaseUnitTestCa
}
@Override
public void pushClassTransformer(List<String> entityClassNames) {
public void pushClassTransformer(Collection<String> entityClassNames) {
}
}

View File

@ -6,14 +6,15 @@
*/
package org.hibernate.jpa.test;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
@ -109,6 +110,6 @@ public class PersistenceUnitDescriptorAdapter implements PersistenceUnitDescript
}
@Override
public void pushClassTransformer(List<String> entityClassNames) {
public void pushClassTransformer(Collection<String> entityClassNames) {
}
}

View File

@ -21,6 +21,7 @@ import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.test.PersistenceUnitInfoAdapter;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.testing.cache.CachingRegionFactory;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
@ -123,11 +124,11 @@ public class ConfigurationTest extends BaseUnitTestCase {
adapter,
settings
);
emfb.build();
return emfb.getMetadata();
}
public static class CustomRegionFactory extends NoCachingRegionFactory {
public static class CustomRegionFactory extends CachingRegionFactory {
public CustomRegionFactory() {
}

View File

@ -36,6 +36,7 @@ public class NamingStrategyConfigurationTest extends BaseUnitTestCase {
adapter,
Collections.singletonMap( AvailableSettings.PHYSICAL_NAMING_STRATEGY, MyNamingStrategy.class.getName() )
);
builder.build();
assertEquals(
MyNamingStrategy.class.getName(),
builder.getConfigurationValues().get( AvailableSettings.PHYSICAL_NAMING_STRATEGY )

View File

@ -26,12 +26,12 @@ import org.hibernate.boot.archive.internal.StandardArchiveDescriptorFactory;
import org.hibernate.boot.archive.scan.internal.ClassDescriptorImpl;
import org.hibernate.boot.archive.scan.internal.ScanResultCollector;
import org.hibernate.boot.archive.scan.internal.StandardScanOptions;
import org.hibernate.boot.archive.scan.internal.StandardScanParameters;
import org.hibernate.boot.archive.scan.internal.StandardScanner;
import org.hibernate.boot.archive.scan.spi.AbstractScannerImpl;
import org.hibernate.boot.archive.scan.spi.JandexInitializer;
import org.hibernate.boot.archive.scan.spi.ClassDescriptor;
import org.hibernate.boot.archive.scan.spi.MappingFileDescriptor;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanParameters;
import org.hibernate.boot.archive.scan.spi.ScanResult;
import org.hibernate.boot.archive.spi.ArchiveDescriptor;
import org.hibernate.dialect.H2Dialect;
@ -82,14 +82,7 @@ public class JarVisitorTest extends PackagingTestCase {
return new StandardScanner().scan(
env,
new StandardScanOptions(),
new ScanParameters() {
// private final JandexInitManager jandexInitManager = new JandexInitManager();
@Override
public JandexInitializer getJandexInitializer() {
// return jandexInitManager;
return null;
}
}
StandardScanParameters.INSTANCE
);
}
@ -135,7 +128,7 @@ public class JarVisitorTest extends PackagingTestCase {
for ( Class expectedClass : expectedClasses ) {
assertTrue(
scanResult.getLocatedClasses().contains(
new ClassDescriptorImpl( expectedClass.getName(), null )
new ClassDescriptorImpl( expectedClass.getName(), ClassDescriptor.Categorization.MODEL, null )
)
);
}
@ -169,14 +162,7 @@ public class JarVisitorTest extends PackagingTestCase {
ScanResultCollector collector = new ScanResultCollector(
environment,
new StandardScanOptions(),
new ScanParameters() {
// private final JandexInitManager jandexInitManager = new JandexInitManager();
@Override
public JandexInitializer getJandexInitializer() {
// return jandexInitManager;
return null;
}
}
StandardScanParameters.INSTANCE
);
archiveDescriptor.visitArchive(
@ -201,14 +187,7 @@ public class JarVisitorTest extends PackagingTestCase {
collector = new ScanResultCollector(
environment,
new StandardScanOptions(),
new ScanParameters() {
// private final JandexInitManager jandexInitManager = new JandexInitManager();
@Override
public JandexInitializer getJandexInitializer() {
// return jandexInitManager;
return null;
}
}
StandardScanParameters.INSTANCE
);
archiveDescriptor.visitArchive(
@ -239,14 +218,7 @@ public class JarVisitorTest extends PackagingTestCase {
final ScanResultCollector collector = new ScanResultCollector(
environment,
new StandardScanOptions(),
new ScanParameters() {
// private final JandexInitManager jandexInitManager = new JandexInitManager();
@Override
public JandexInitializer getJandexInitializer() {
// return jandexInitManager;
return null;
}
}
StandardScanParameters.INSTANCE
);
archiveDescriptor.visitArchive(
@ -291,7 +263,7 @@ public class JarVisitorTest extends PackagingTestCase {
assertTrue(
result.getLocatedClasses().contains(
new ClassDescriptorImpl( Carpet.class.getName(), null )
new ClassDescriptorImpl( Carpet.class.getName(), ClassDescriptor.Categorization.MODEL, null )
)
);

View File

@ -13,13 +13,12 @@ import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.hibernate.boot.archive.scan.internal.StandardScanOptions;
import org.hibernate.boot.archive.scan.internal.StandardScanParameters;
import org.hibernate.boot.archive.scan.internal.StandardScanner;
import org.hibernate.boot.archive.scan.spi.ClassDescriptor;
import org.hibernate.boot.archive.scan.spi.JandexInitializer;
import org.hibernate.boot.archive.scan.spi.MappingFileDescriptor;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanOptions;
import org.hibernate.boot.archive.scan.spi.ScanParameters;
import org.hibernate.boot.archive.scan.spi.ScanResult;
import org.hibernate.boot.archive.scan.spi.Scanner;
import org.hibernate.cfg.AvailableSettings;
@ -53,14 +52,7 @@ public class ScannerTest extends PackagingTestCase {
ScanResult scanResult = scanner.scan(
env,
options,
new ScanParameters() {
// private final JandexInitManager jandexInitManager = new JandexInitManager();
@Override
public JandexInitializer getJandexInitializer() {
// return jandexInitManager;
return null;
}
}
StandardScanParameters.INSTANCE
);
assertEquals( 3, scanResult.getLocatedClasses().size() );

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.testing.boot;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
import org.hibernate.boot.internal.InFlightMetadataCollectorImpl;
import org.hibernate.boot.internal.MetadataBuilderImpl;
@ -38,7 +37,7 @@ public class MetadataBuildingContextTestingImpl implements MetadataBuildingConte
public MetadataBuildingContextTestingImpl(StandardServiceRegistry serviceRegistry) {
buildingOptions = new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry );
mappingDefaults = new MetadataBuilderImpl.MappingDefaultsImpl( serviceRegistry );
metadataCollector = new InFlightMetadataCollectorImpl( buildingOptions, new MetadataSources( serviceRegistry ), new TypeResolver() );
metadataCollector = new InFlightMetadataCollectorImpl( buildingOptions, new TypeResolver() );
classLoaderAccess = new ClassLoaderAccessImpl( null, serviceRegistry );
objectNameNormalizer = new ObjectNameNormalizer() {

View File

@ -25,7 +25,7 @@ ext {
// Annotations
commons_annotations: 'org.hibernate.common:hibernate-commons-annotations:5.0.0.Final',
jandex: 'org.jboss:jandex:1.1.0.Final',
jandex: 'org.jboss:jandex:1.2.2.Final',
classmate: 'com.fasterxml:classmate:0.8.0',
// Woodstox