Author: stliu
Date: 2011-12-19 03:43:31 -0500 (Mon, 19 Dec 2011)
New Revision: 20997
Added:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/Scanner.java
Modified:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/HibernatePersistence.java
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java
Log:
JBPAPP-7729 Hibernate 3.3.x Auto scan for JPA entities does not work with AS 7.1
Modified:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
===================================================================
---
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/Ejb3Configuration.java 2011-12-14
03:02:55 UTC (rev 20996)
+++
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/Ejb3Configuration.java 2011-12-19
08:43:31 UTC (rev 20997)
@@ -9,12 +9,14 @@
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
+import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -54,15 +56,15 @@
import org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider;
import org.hibernate.ejb.instrument.InterceptFieldClassFileTransformer;
import org.hibernate.ejb.packaging.ClassFilter;
-import org.hibernate.ejb.packaging.Entry;
import org.hibernate.ejb.packaging.FileFilter;
import org.hibernate.ejb.packaging.Filter;
-import org.hibernate.ejb.packaging.JarVisitor;
import org.hibernate.ejb.packaging.JarVisitorFactory;
import org.hibernate.ejb.packaging.NamedInputStream;
+import org.hibernate.ejb.packaging.NativeScanner;
import org.hibernate.ejb.packaging.PackageFilter;
import org.hibernate.ejb.packaging.PersistenceMetadata;
import org.hibernate.ejb.packaging.PersistenceXmlLoader;
+import org.hibernate.ejb.packaging.Scanner;
import org.hibernate.ejb.transaction.JoinableCMTTransactionFactory;
import org.hibernate.ejb.util.ConfigurationHelper;
import org.hibernate.ejb.util.LogHelper;
@@ -78,6 +80,7 @@
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;
import org.hibernate.util.XMLHelper;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.EntityResolver;
@@ -232,24 +235,45 @@
metadata.getProvider()
) ) {
//correct provider
-
- //lazy compute the visitor if possible to avoid useless exceptions if an unexpected
state happens
- JarVisitor visitor = null;
-
+ //lazy load the scanner to avoid unnecessary IOExceptions
+ Scanner scanner = null;
+ URL jarURL = null;
if ( metadata.getName() == null ) {
- visitor = getMainJarVisitor( url, metadata, integration );
- metadata.setName( visitor.getUnqualifiedJarName() );
+ scanner = buildScanner( metadata.getProps(), integration );
+ jarURL = JarVisitorFactory.getJarURLFromURLEntry( url,
"/META-INF/persistence.xml" );
+ metadata.setName( scanner.getUnqualifiedJarName( jarURL ) );
}
if ( persistenceUnitName == null && xmls.hasMoreElements() ) {
throw new PersistenceException( "No name provided and several persistence
units found" );
}
else if ( persistenceUnitName == null || metadata.getName().equals(
persistenceUnitName ) ) {
- if (visitor == null) visitor = getMainJarVisitor( url, metadata, integration );
- addMetadataFromVisitor( visitor, metadata );
- Filter[] otherXmlFilter = getFilters( metadata, integration, false );
+ if ( scanner == null ) {
+ scanner = buildScanner( metadata.getProps(), integration );
+ jarURL = JarVisitorFactory.getJarURLFromURLEntry( url,
"/META-INF/persistence.xml" );
+ }
+ //scan main JAR
+ ScanningContext mainJarScanCtx = new ScanningContext()
+ .scanner( scanner )
+ .url( jarURL )
+ .explicitMappingFiles( metadata.getMappingFiles() )
+ .searchOrm( true );
+ setDetectedArtifactsOnScanningContext(
+ mainJarScanCtx, metadata.getProps(), integration,
+ metadata.getExcludeUnlistedClasses()
+ );
+ addMetadataFromScan( mainJarScanCtx, metadata );
+
+ ScanningContext otherJarScanCtx = new ScanningContext()
+ .scanner( scanner )
+ .explicitMappingFiles( metadata.getMappingFiles() )
+ .searchOrm( true );
+ setDetectedArtifactsOnScanningContext(
+ otherJarScanCtx, metadata.getProps(), integration,
+ false
+ );
for ( String jarFile : metadata.getJarFiles() ) {
- visitor = JarVisitorFactory.getVisitor( jarFile, otherXmlFilter );
- addMetadataFromVisitor( visitor, metadata );
+ otherJarScanCtx.url( JarVisitorFactory.getURLFromPath( jarFile ) );
+ addMetadataFromScan( otherJarScanCtx, metadata );
}
return configure( metadata, integration );
}
@@ -268,40 +292,129 @@
}
}
- //method used in a non managed environment
- private JarVisitor getMainJarVisitor(URL url, PersistenceMetadata metadata, Map
integration) {
- URL jarURL = JarVisitorFactory.getJarURLFromURLEntry( url,
"/META-INF/persistence.xml" );
- Filter[] persistenceXmlFilter = getFilters( metadata, integration,
metadata.getExcludeUnlistedClasses() );
- return JarVisitorFactory.getVisitor( jarURL, persistenceXmlFilter );
+ private Scanner buildScanner(Properties properties, Map<?, ?> integration) {
+ //read the String or Instance from the integration map first and use the properties as
a backup.
+ Object scanner = integration.get( HibernatePersistence.SCANNER );
+ if ( scanner == null ) {
+ scanner = properties.getProperty( HibernatePersistence.SCANNER );
+ }
+ if ( scanner != null ) {
+ Class<?> scannerClass;
+ if ( scanner instanceof String ) {
+ try {
+ scannerClass = ReflectHelper.classForName( (String) scanner, this.getClass() );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new PersistenceException(
+ "Cannot find scanner class. " + HibernatePersistence.SCANNER +
"=" + scanner,
+ e
+ );
+ }
+ }
+ else if ( scanner instanceof Class ) {
+ scannerClass = (Class<? extends Scanner>) scanner;
+ }
+ else if ( scanner instanceof Scanner ) {
+ return (Scanner) scanner;
+ }
+ else {
+ throw new PersistenceException( "Scanner class configuration error: unknown type
on the property. " + HibernatePersistence.SCANNER );
+ }
+ try {
+ return (Scanner) scannerClass.newInstance();
+ }
+ catch ( InstantiationException e ) {
+ throw new PersistenceException( "Unable to load Scanner class: " +
scannerClass, e );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new PersistenceException( "Unable to load Scanner class: " +
scannerClass, e );
+ }
+ }
+ else {
+ return new NativeScanner();
+ }
+}
+
+ private static class ScanningContext {
+ //boolean excludeUnlistedClasses;
+ private Scanner scanner;
+ private URL url;
+ private List<String> explicitMappingFiles;
+ private boolean detectClasses;
+ private boolean detectHbmFiles;
+ private boolean searchOrm;
+
+ public ScanningContext scanner(Scanner scanner) {
+ this.scanner = scanner;
+ return this;
+ }
+
+ public ScanningContext url(URL url) {
+ this.url = url;
+ return this;
+ }
+
+ public ScanningContext explicitMappingFiles(List<String> explicitMappingFiles) {
+ this.explicitMappingFiles = explicitMappingFiles;
+ return this;
+ }
+
+ public ScanningContext detectClasses(boolean detectClasses) {
+ this.detectClasses = detectClasses;
+ return this;
+ }
+
+ public ScanningContext detectHbmFiles(boolean detectHbmFiles) {
+ this.detectHbmFiles = detectHbmFiles;
+ return this;
+ }
+
+ public ScanningContext searchOrm(boolean searchOrm) {
+ this.searchOrm = searchOrm;
+ return this;
+ }
}
- private static void addMetadataFromVisitor(JarVisitor visitor, PersistenceMetadata
metadata) throws IOException {
+ private static void addMetadataFromScan(ScanningContext scanningContext,
PersistenceMetadata metadata) throws IOException {
List<String> classes = metadata.getClasses();
List<String> packages = metadata.getPackages();
List<NamedInputStream> hbmFiles = metadata.getHbmfiles();
List<String> mappingFiles = metadata.getMappingFiles();
- addScannedEntries( visitor, classes, packages, hbmFiles, mappingFiles );
+ addScannedEntries( scanningContext, classes, packages, hbmFiles, mappingFiles );
}
- private static void addScannedEntries(JarVisitor visitor, List<String> classes,
List<String> packages, List<NamedInputStream> hbmFiles, List<String>
mappingFiles) throws IOException {
- Filter[] filters = visitor.getFilters();
- Set[] entries = visitor.getMatchingEntries();
- int size = filters.length;
- for ( int index = 0; index < size ; index++ ) {
- for (Object o : entries[index]) {
- Entry entry = (Entry) o;
- if ( filters[index] instanceof ClassFilter ) {
- classes.add( entry.getName() );
- }
- else if ( filters[index] instanceof PackageFilter ) {
- packages.add( entry.getName() );
- }
- else if ( filters[index] instanceof FileFilter ) {
- hbmFiles.add( new NamedInputStream( entry.getName(), entry.getInputStream() ) );
- if (mappingFiles != null) mappingFiles.remove( entry.getName() );
- }
+ private static void addScannedEntries(ScanningContext scanningContext,
List<String> classes, List<String> packages, List<NamedInputStream>
hbmFiles, List<String> mappingFiles) throws IOException {
+ Scanner scanner = scanningContext.scanner;
+ if (scanningContext.detectClasses) {
+ Set<Class<? extends Annotation>> annotationsToExclude = new
HashSet<Class<? extends Annotation>>(3);
+ annotationsToExclude.add( Entity.class );
+ annotationsToExclude.add( MappedSuperclass.class );
+ annotationsToExclude.add( Embeddable.class );
+ Set<Class<?>> matchingClasses = scanner.getClassesInJar(
scanningContext.url, annotationsToExclude );
+ for (Class<?> clazz : matchingClasses) {
+ classes.add( clazz.getName() );
}
+
+ Set<Package> matchingPackages = scanner.getPackagesInJar( scanningContext.url,
new HashSet<Class<? extends Annotation>>(0) );
+ for (Package pkg : matchingPackages) {
+ packages.add( pkg.getName() );
+ }
}
+ Set<String> patterns = new HashSet<String>();
+ if (scanningContext.searchOrm) {
+ patterns.add( META_INF_ORM_XML );
+ }
+ if (scanningContext.detectHbmFiles) {
+ patterns.add( "**/*.hbm.xml" );
+ }
+ if ( mappingFiles != null) patterns.addAll( mappingFiles );
+ if (patterns.size() !=0) {
+ Set<NamedInputStream> files = scanner.getFilesInJar( scanningContext.url,
patterns );
+ for (NamedInputStream file : files) {
+ hbmFiles.add( file );
+ if (mappingFiles != null) mappingFiles.remove( file.getName() );
+ }
+ }
}
/**
@@ -353,13 +466,31 @@
//Should always be true if the container is not dump
boolean searchForORMFiles = ! xmlFiles.contains( META_INF_ORM_XML );
- boolean[] detectArtifactForOtherJars = getDetectedArtifacts( info.getProperties(),
null, false );
- boolean[] detectArtifactForMainJar = getDetectedArtifacts( info.getProperties(), null,
info.excludeUnlistedClasses() );
+ ScanningContext context = new ScanningContext();
+ final Properties copyOfProperties = (Properties) info.getProperties().clone();
+ ConfigurationHelper.overrideProperties( copyOfProperties, integration );
+ context.scanner( buildScanner( copyOfProperties, integration ) )
+ .searchOrm( searchForORMFiles )
+ .explicitMappingFiles( null ); //URLs provided by the container already
+
+ //context for other JARs
+ setDetectedArtifactsOnScanningContext(context, info.getProperties(), null, false );
for ( URL jar : info.getJarFileUrls() ) {
- scanForClasses( jar, packages, entities, hbmFiles, detectArtifactForOtherJars,
searchForORMFiles );
+ context.url(jar);
+ scanForClasses( context, packages, entities, hbmFiles );
}
- scanForClasses( info.getPersistenceUnitRootUrl(), packages, entities, hbmFiles,
detectArtifactForMainJar, searchForORMFiles );
+ //main jar
+ context.url( info.getPersistenceUnitRootUrl() );
+ setDetectedArtifactsOnScanningContext( context, info.getProperties(), null,
info.excludeUnlistedClasses() );
+ scanForClasses( context, packages, entities, hbmFiles );
+// boolean[] detectArtifactForOtherJars = getDetectedArtifacts( info.getProperties(),
null, false );
+// boolean[] detectArtifactForMainJar = getDetectedArtifacts( info.getProperties(),
null, info.excludeUnlistedClasses() );
+// for ( URL jar : info.getJarFileUrls() ) {
+// scanForClasses( jar, packages, entities, hbmFiles, detectArtifactForOtherJars,
searchForORMFiles );
+// }
+// scanForClasses( info.getPersistenceUnitRootUrl(), packages, entities, hbmFiles,
detectArtifactForMainJar, searchForORMFiles );
+
Properties properties = info.getProperties() != null ?
info.getProperties() :
new Properties();
@@ -604,24 +735,56 @@
}
return filters;
}
+ /**
+ * Set ScanningContext detectClasses and detectHbmFiles according to context
+ */
+ private void setDetectedArtifactsOnScanningContext(ScanningContext context,
+ Properties properties,
+ Map overridenProperties,
+ boolean excludeIfNotOverriden) {
- private void scanForClasses(URL jar, List<String> packages, List<String>
entities, List<NamedInputStream> hbmFiles, boolean[] detectedArtifacts, boolean
searchORM) {
- if (jar == null) {
+ boolean detectClasses = false;
+ boolean detectHbm = false;
+ String detectSetting = overridenProperties != null ?
+ (String) overridenProperties.get( HibernatePersistence.AUTODETECTION ) :
+ null;
+ detectSetting = detectSetting == null ?
+ properties.getProperty( HibernatePersistence.AUTODETECTION) :
+ detectSetting;
+ if ( detectSetting == null && excludeIfNotOverriden) {
+ //not overriden through HibernatePersistence.AUTODETECTION so we comply with the spec
excludeUnlistedClasses
+ context.detectClasses( false ).detectHbmFiles( false );
+ return;
+ }
+
+ if ( detectSetting == null){
+ detectSetting = "class,hbm";
+ }
+ StringTokenizer st = new StringTokenizer( detectSetting, ", ", false );
+ while ( st.hasMoreElements() ) {
+ String element = (String) st.nextElement();
+ if ( "class".equalsIgnoreCase( element ) ) detectClasses = true;
+ if ( "hbm".equalsIgnoreCase( element ) ) detectHbm = true;
+ }
+ log.debug( "Detect class: {}; detect hbm: {}", detectClasses, detectHbm );
+ context.detectClasses( detectClasses ).detectHbmFiles( detectHbm );
+ }
+
+ private void scanForClasses(ScanningContext scanningContext, List<String>
packages, List<String> entities, List<NamedInputStream> hbmFiles) {
+ if (scanningContext.url == null) {
log.error( "Container is providing a null PersistenceUnitRootUrl: discovery
impossible");
return;
}
try {
- JarVisitor visitor = JarVisitorFactory.getVisitor( jar, getFilters( detectedArtifacts,
searchORM, null ) );
- addScannedEntries( visitor, entities, packages, hbmFiles, null );
+ addScannedEntries( scanningContext, entities, packages, hbmFiles, null );
}
catch (RuntimeException e) {
- throw new RuntimeException( "error trying to scan <jar-file>: " +
jar.toString(), e );
+ throw new RuntimeException( "error trying to scan <jar-file>: " +
scanningContext.url.toString(), e );
}
catch( IOException e ) {
- throw new RuntimeException( "Error while reading " + jar.toString(), e );
+ throw new RuntimeException( "Error while reading " +
scanningContext.url.toString(), e );
}
}
-
/**
* create a factory from a list of properties and
* HibernatePersistence.CLASS_NAMES -> Collection<String> (use to list the
classes from config files
Modified:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/HibernatePersistence.java
===================================================================
---
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/HibernatePersistence.java 2011-12-14
03:02:55 UTC (rev 20996)
+++
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/HibernatePersistence.java 2011-12-19
08:43:31 UTC (rev 20997)
@@ -83,7 +83,12 @@
* in the JNDI in a serialized form
*/
public static final String CONFIGURATION_JNDI_NAME =
"hibernate.ejb.configuration_jndi_name";
-
+ /**
+ * Pass an implementation of {@link org.hibernate.ejb.packaging.Scanner}:
+ * - preferably an actual instance
+ * - or a class name with a no-arg constructor
+ */
+ public static final String SCANNER = "hibernate.ejb.resource_scanner";
//The following properties are for Internal use only
/**
* link to the alternative Hibernate configuration file
Modified:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java
===================================================================
---
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java 2011-12-14
03:02:55 UTC (rev 20996)
+++
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java 2011-12-19
08:43:31 UTC (rev 20997)
@@ -17,7 +17,23 @@
*/
public class JarVisitorFactory {
private static final Logger log = LoggerFactory.getLogger( JarVisitorFactory.class );
-
+ public static URL getURLFromPath(String jarPath) {
+ URL jarUrl;
+ try {
+ //is it an url
+ jarUrl = new URL( jarPath );
+ }
+ catch ( MalformedURLException e) {
+ try {
+ //consider it as a file path
+ jarUrl = new URL( "file:" + jarPath );
+ }
+ catch (MalformedURLException ee) {
+ throw new IllegalArgumentException( "Unable to find jar:" + jarPath, ee );
+ }
+ }
+ return jarUrl;
+ }
/**
* Get the JAR URL of the JAR containing the given entry
* Method used in a non managed environment
Added:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java
===================================================================
---
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java
(rev 0)
+++
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java 2011-12-19
08:43:31 UTC (rev 20997)
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.ejb.packaging;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+import org.hibernate.AssertionFailure;
+import org.hibernate.util.ReflectHelper;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class NativeScanner implements Scanner {
+
+ private static final String META_INF_ORM_XML = "META-INF/orm.xml";
+
+ private Map<URL, StateJarVisitor> visitors = new HashMap<URL,
StateJarVisitor>();
+ private static final int PACKAGE_FILTER_INDEX = 0;
+ private static final int CLASS_FILTER_INDEX = 1;
+ private static final int FILE_FILTER_INDEX = 2;
+
+ /**
+ * This implementation does not honor the list of annotations and return everything.
+ * Must strictly be used by HEM
+ */
+ public Set<Package> getPackagesInJar(URL jarToScan, Set<Class<? extends
Annotation>> annotationsToLookFor) {
+ if ( annotationsToLookFor.size() > 0 ) {
+ throw new AssertionFailure( "Improper use of NativeScanner: must not filter
packages" );
+ }
+
+ JarVisitor jarVisitor = getVisitor( jarToScan );
+ final Set<Entry> packageEntries;
+ try {
+ packageEntries = ( Set<Entry> )
jarVisitor.getMatchingEntries()[PACKAGE_FILTER_INDEX];
+ }
+ catch ( IOException e ) {
+ throw new RuntimeException( "Error while reading " + jarToScan.toString(), e
);
+ }
+ Set<Package> packages = new HashSet<Package>( packageEntries.size() );
+ for ( Entry entry : packageEntries ) {
+ try {
+ packages.add( ReflectHelper.classForName( entry.getName() + ".package-info"
).getPackage() );
+ }
+ catch ( ClassNotFoundException e ) {
+ //should never happen, if it happens, simply ignore the flawed package
+ }
+ }
+ return packages;
+ }
+
+ /**
+ * Build a JarVisitor with some assumptions wrt the scanning
+ * This helps do one scan instead of several
+ */
+ private JarVisitor getVisitor(URL jar) {
+ StateJarVisitor stateJarVisitor = visitors.get( jar );
+
+ if ( stateJarVisitor == null ) {
+
+ Filter[] filters = new Filter[3];
+ filters[PACKAGE_FILTER_INDEX] = new PackageFilter( false, null ) {
+ public boolean accept(String javaElementName) {
+ return true;
+ }
+ };
+ filters[CLASS_FILTER_INDEX] = new ClassFilter(
+ false, new Class[] {
+ Entity.class,
+ MappedSuperclass.class,
+ Embeddable.class
+ }
+ ) {
+ public boolean accept(String javaElementName) {
+ return true;
+ }
+ };
+ filters[FILE_FILTER_INDEX] = new FileFilter( true ) {
+ public boolean accept(String javaElementName) {
+ return javaElementName.endsWith( "hbm.xml" )
+ || javaElementName.endsWith( META_INF_ORM_XML );
+ }
+ };
+
+ stateJarVisitor = new StateJarVisitor( JarVisitorFactory.getVisitor( jar, filters )
);
+ visitors.put( jar, stateJarVisitor );
+ }
+ return stateJarVisitor.visitor;
+ }
+
+ public Set<Class<?>> getClassesInJar(URL jarToScan, Set<Class<?
extends Annotation>> annotationsToLookFor) {
+ if ( isValidForClasses( annotationsToLookFor ) ) {
+ throw new AssertionFailure(
+ "Improper use of NativeScanner: "
+ + "must not filter classes by other annotations than Entity,
MappedSuperclass, embeddable"
+ );
+ }
+ JarVisitor jarVisitor = getVisitor( jarToScan );
+ final Set<Entry> classesEntry;
+ try {
+ classesEntry = ( Set<Entry> )
jarVisitor.getMatchingEntries()[CLASS_FILTER_INDEX];
+ }
+ catch ( IOException e ) {
+ throw new RuntimeException( "Error while reading " + jarToScan.toString(), e
);
+ }
+ Set<Class<?>> classes = new HashSet<Class<?>>(
classesEntry.size() );
+ for ( Entry entry : classesEntry ) {
+ try {
+ classes.add( ReflectHelper.classForName( entry.getName() ) );
+ }
+ catch ( ClassNotFoundException e ) {
+ //should never happen, if it happens, simply ignore the flawed package
+ }
+ }
+ return classes;
+ }
+
+ private boolean isValidForClasses(Set<Class<? extends Annotation>>
annotationsToLookFor) {
+ return annotationsToLookFor.size() != 3
+ || !annotationsToLookFor.contains( Entity.class )
+ || !annotationsToLookFor.contains( MappedSuperclass.class )
+ || !annotationsToLookFor.contains( Embeddable.class );
+ }
+
+ /**
+ * support for patterns is primitive:
+ * - **\/*.hbm.xml
+ * Other patterns will not be found
+ */
+ public Set<NamedInputStream> getFilesInJar(URL jarToScan, Set<String>
filePatterns) {
+ StringBuilder sb = new StringBuilder("URL: ").append( jarToScan )
+ .append( "\n" );
+ for (String pattern : filePatterns) {
+ sb.append( " " ).append( pattern ).append( "\n" );
+ }
+ JarVisitor jarVisitor = getVisitor( jarToScan );
+
+ //state visitor available
+ final StateJarVisitor stateVisitor = visitors.get( jarToScan );
+ if ( stateVisitor.hasReadFiles ) {
+ throw new AssertionFailure( "Cannot read files twice on NativeScanner" );
+ }
+ stateVisitor.hasReadFiles = true;
+
+ Set<String> endWiths = new HashSet<String>();
+ Set<String> exacts = new HashSet<String>();
+ for ( String pattern : filePatterns ) {
+ if ( pattern.startsWith( "**/*" ) ) {
+ final String patternTail = pattern.substring( 4, pattern.length() );
+ if ( !patternTail.equals( ".hbm.xml" ) ) {
+ throw new AssertionFailure(
+ "Improper use of NativeScanner: "
+ + "must not filter files via pattern other than .hbm.xml"
+ );
+ }
+ endWiths.add( patternTail );
+ }
+ else {
+ exacts.add( pattern );
+ }
+ }
+
+ final Set<Entry> fileEntries;
+ try {
+ fileEntries = ( Set<Entry> )
jarVisitor.getMatchingEntries()[FILE_FILTER_INDEX];
+ }
+ catch ( IOException e ) {
+ throw new RuntimeException( "Error while reading " + jarToScan.toString(), e
);
+ }
+ Set<NamedInputStream> files = new HashSet<NamedInputStream>(
fileEntries.size() );
+ Set<Entry> leftOver = new HashSet<Entry>( fileEntries );
+ for ( Entry entry : fileEntries ) {
+ boolean done = false;
+ for ( String exact : exacts ) {
+ if ( entry.getName().equals( exact ) ) {
+ files.add( new NamedInputStream( entry.getName(), entry.getInputStream() ) );
+ leftOver.remove( entry );
+ done = true;
+ }
+ }
+ if (done) continue;
+ for ( String endWithPattern : endWiths ) {
+ if ( entry.getName().endsWith( endWithPattern ) ) {
+ files.add( new NamedInputStream( entry.getName(), entry.getInputStream() ) );
+ leftOver.remove( entry );
+ }
+ }
+
+ }
+ for ( Entry entry : leftOver ) {
+ try {
+ entry.getInputStream().close();
+ }
+ catch ( IOException e ) {
+ //swallow as we don't care about these files
+ }
+ }
+ return files;
+ }
+
+ public Set<NamedInputStream> getFilesInClasspath(Set<String> filePatterns)
{
+ throw new AssertionFailure( "Not implemented" );
+ }
+
+ public String getUnqualifiedJarName(URL jarToScan) {
+ JarVisitor jarVisitor = getVisitor( jarToScan );
+ return jarVisitor.getUnqualifiedJarName();
+ }
+
+ private static class StateJarVisitor {
+ StateJarVisitor(JarVisitor visitor) {
+ this.visitor = visitor;
+ }
+ JarVisitor visitor;
+ boolean hasReadFiles = false;
+ }
+}
Added:
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/Scanner.java
===================================================================
---
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/Scanner.java
(rev 0)
+++
entitymanager/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/ejb/packaging/Scanner.java 2011-12-19
08:43:31 UTC (rev 20997)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.ejb.packaging;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.Set;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public interface Scanner {
+ /**
+ * return all packages in the jar matching one of these annotations
+ * if annotationsToLookFor is empty, return all packages
+ */
+ Set<Package> getPackagesInJar(URL jartoScan, Set<Class<? extends
Annotation>> annotationsToLookFor);
+
+ /**
+ * return all classes in the jar matching one of these annotations
+ * if annotationsToLookFor is empty, return all classes
+ */
+ Set<Class<?>> getClassesInJar(URL jartoScan, Set<Class<? extends
Annotation>> annotationsToLookFor);
+
+ /**
+ * return all files in the jar matching one of these file names
+ * if filePatterns is empty, return all files
+ * eg **\/*.hbm.xml, META-INF/orm.xml
+ */
+ Set<NamedInputStream> getFilesInJar(URL jartoScan, Set<String>
filePatterns);
+
+
+ /**
+ * Return all files in the classpath (ie PU visibility) matching one of these file
names
+ * if filePatterns is empty, return all files
+ * the use case is really exact file name.
+ *
+ * NOT USED by HEM at the moment. We use exact file search via getResourceAsStream for
now.
+ */
+ Set<NamedInputStream> getFilesInClasspath(Set<String> filePatterns);
+
+ /**
+ * return the unqualified JAR name ie customer-model.jar or store.war
+ */
+ String getUnqualifiedJarName(URL jarUrl);
+
+}