Author: epbernard
Date: 2009-04-18 10:35:58 -0400 (Sat, 18 Apr 2009)
New Revision: 16358
Added:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/packaging/NativeScannerTest.java
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/AbstractJarVisitor.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java
Log:
EJB-428 move scanning facility under the Scanner interface and implement NativeScanner
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java 2009-04-17
20:48:26 UTC (rev 16357)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java 2009-04-18
14:35:58 UTC (rev 16358)
@@ -21,6 +21,8 @@
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.HashSet;
+import java.lang.annotation.Annotation;
import javax.naming.BinaryRefAddr;
import javax.naming.NamingException;
import javax.naming.Reference;
@@ -52,16 +54,12 @@
import org.hibernate.cfg.annotations.reflection.XMLContext;
import org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider;
import org.hibernate.ejb.instrument.InterceptFieldClassFileTransformer;
-import org.hibernate.ejb.packaging.JarVisitor;
import org.hibernate.ejb.packaging.NamedInputStream;
import org.hibernate.ejb.packaging.PersistenceMetadata;
import org.hibernate.ejb.packaging.PersistenceXmlLoader;
-import org.hibernate.ejb.packaging.Filter;
import org.hibernate.ejb.packaging.JarVisitorFactory;
-import org.hibernate.ejb.packaging.Entry;
-import org.hibernate.ejb.packaging.FileFilter;
-import org.hibernate.ejb.packaging.PackageFilter;
-import org.hibernate.ejb.packaging.ClassFilter;
+import org.hibernate.ejb.packaging.Scanner;
+import org.hibernate.ejb.packaging.NativeScanner;
import org.hibernate.ejb.transaction.JoinableCMTTransactionFactory;
import org.hibernate.ejb.util.ConfigurationHelper;
import org.hibernate.ejb.util.LogHelper;
@@ -232,23 +230,41 @@
) ) {
//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();
+ 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();
+ 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 );
}
@@ -267,40 +283,90 @@
}
}
- //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 NativeScanner buildScanner() {
+ return new NativeScanner();
}
- private static void addMetadataFromVisitor(JarVisitor visitor, PersistenceMetadata
metadata) throws IOException {
+ 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 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() );
+ }
+ }
}
/**
@@ -352,13 +418,23 @@
//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();
+ context.scanner( buildScanner() )
+ .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 );
+
Properties properties = info.getProperties() != null ?
info.getProperties() :
new Properties();
@@ -536,88 +612,54 @@
return this;
}
- private boolean[] getDetectedArtifacts(Properties properties, Map overridenProperties,
boolean excludeIfNotOverriden) {
- boolean[] result = new boolean[2];
- result[0] = false; //detect classes
- result[1] = false; //detect hbm
- String detect = overridenProperties != null ?
+ /**
+ * Set ScanningContext detectClasses and detectHbmFiles according to context
+ */
+ private void setDetectedArtifactsOnScanningContext(ScanningContext context,
+ Properties properties,
+ Map overridenProperties,
+ boolean excludeIfNotOverriden) {
+
+ boolean detectClasses = false;
+ boolean detectHbm = false;
+ String detectSetting = overridenProperties != null ?
(String) overridenProperties.get( HibernatePersistence.AUTODETECTION ) :
null;
- detect = detect == null ?
+ detectSetting = detectSetting == null ?
properties.getProperty( HibernatePersistence.AUTODETECTION) :
- detect;
- if (detect == null && excludeIfNotOverriden) {
+ detectSetting;
+ if ( detectSetting == null && excludeIfNotOverriden) {
//not overriden through HibernatePersistence.AUTODETECTION so we comply with the spec
excludeUnlistedClasses
- return result;
+ context.detectClasses( false ).detectHbmFiles( false );
+ return;
}
- else if (detect == null){
- detect = "class,hbm";
+
+ if ( detectSetting == null){
+ detectSetting = "class,hbm";
}
- StringTokenizer st = new StringTokenizer( detect, ", ", false );
+ StringTokenizer st = new StringTokenizer( detectSetting, ", ", false );
while ( st.hasMoreElements() ) {
String element = (String) st.nextElement();
- if ( "class".equalsIgnoreCase( element ) ) result[0] = true;
- if ( "hbm".equalsIgnoreCase( element ) ) result[1] = true;
+ if ( "class".equalsIgnoreCase( element ) ) detectClasses = true;
+ if ( "hbm".equalsIgnoreCase( element ) ) detectHbm = true;
}
- log.debug( "Detect class: {}; detect hbm: {}", result[0], result[1] );
- return result;
+ log.debug( "Detect class: {}; detect hbm: {}", detectClasses, detectHbm );
+ context.detectClasses( detectClasses ).detectHbmFiles( detectHbm );
}
- private Filter[] getFilters(PersistenceMetadata metadata, Map overridenProperties,
boolean excludeIfNotOverriden) {
- Properties properties = metadata.getProps();
- final List<String> mappingFiles = metadata.getMappingFiles();
- boolean[] detectedArtifacts = getDetectedArtifacts( properties, overridenProperties,
excludeIfNotOverriden );
-
- return getFilters( detectedArtifacts, true, mappingFiles );
- }
-
- private Filter[] getFilters(final boolean[] detectedArtifacts, final boolean searchORM,
final List<String> mappingFiles) {
- final int mappingFilesSize = mappingFiles != null ? mappingFiles.size() : 0;
- int size = ( detectedArtifacts[0] ? 2 : 0 ) + ( (searchORM || detectedArtifacts[1] ||
mappingFilesSize > 0 ) ? 1 : 0);
- Filter[] filters = new Filter[size];
- if ( detectedArtifacts[0] ) {
- filters[0] = new PackageFilter( false, null ) {
- public boolean accept(String javaElementName) {
- return true;
- }
- };
- filters[1] = new ClassFilter(
- false, new Class[]{
- Entity.class,
- MappedSuperclass.class,
- Embeddable.class}
- ) {
- public boolean accept(String javaElementName) {
- return true;
- }
- };
- }
- if ( detectedArtifacts[1] || searchORM || mappingFilesSize > 0) {
- filters[size - 1] = new FileFilter( true ) {
- public boolean accept(String javaElementName) {
- return ( detectedArtifacts[1] && javaElementName.endsWith(
"hbm.xml" ) )
- || ( searchORM && javaElementName.endsWith( META_INF_ORM_XML ) )
- || ( mappingFilesSize > 0 && mappingFiles.contains( javaElementName )
);
- }
- };
- }
- return filters;
- }
-
- private void scanForClasses(URL jar, List<String> packages, List<String>
entities, List<NamedInputStream> hbmFiles, boolean[] detectedArtifacts, boolean
searchORM) {
- if (jar == null) {
+ 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 );
}
}
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/AbstractJarVisitor.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/AbstractJarVisitor.java 2009-04-17
20:48:26 UTC (rev 16357)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/AbstractJarVisitor.java 2009-04-18
14:35:58 UTC (rev 16358)
@@ -41,21 +41,7 @@
* Build a jar visitor from its jar string path
*/
private AbstractJarVisitor(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 );
- }
- }
- this.jarUrl = jarUrl;
+ this.jarUrl = JarVisitorFactory.getURLFromPath( jarPath );
unqualify();
}
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java 2009-04-17
20:48:26 UTC (rev 16357)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/JarVisitorFactory.java 2009-04-18
14:35:58 UTC (rev 16358)
@@ -26,6 +26,7 @@
* @param entry file known to be in the JAR
* @return the JAR URL
* @throws IllegalArgumentException if none URL is found
+ * TODO move to a ScannerHelper service?
*/
public static URL getJarURLFromURLEntry(URL url, String entry) throws
IllegalArgumentException {
URL jarUrl;
@@ -75,6 +76,30 @@
}
/**
+ * get the URL from a given path string
+ *
+ * @throws IllegalArgumentException is something goes wrong
+ * TODO move to a ScannerHelper service?
+ */
+ 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 a JarVisitor to the jar <code>jarPath</code> applying the given
filters
*
* Method used in a non-managed environment
Added:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java
(rev 0)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/NativeScanner.java 2009-04-18
14:35:58 UTC (rev 16358)
@@ -0,0 +1,227 @@
+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" );
+ }
+ System.err.println(sb.toString());
+ 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;
+ continue;
+ }
+ }
+ if (done) continue;
+ for ( String endWithPattern : endWiths ) {
+ if ( entry.getName().endsWith( endWithPattern ) ) {
+ files.add( new NamedInputStream( entry.getName(), entry.getInputStream() ) );
+ leftOver.remove( entry );
+ continue;
+ }
+ }
+
+ }
+ 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(URL jartoScan, 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: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java
(rev 0)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java 2009-04-18
14:35:58 UTC (rev 16358)
@@ -0,0 +1,45 @@
+package org.hibernate.ejb.packaging;
+
+import java.util.Set;
+import java.util.List;
+import java.net.URL;
+import java.lang.annotation.Annotation;
+import java.io.InputStream;
+
+/**
+ * @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.
+ */
+ Set<NamedInputStream> getFilesInClasspath(URL jartoScan, Set<String>
filePatterns);
+
+ /**
+ * return the unqualified JAR name ie customer-model.jar or store.war
+ */
+ String getUnqualifiedJarName(URL jarUrl);
+
+}
Added:
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/packaging/NativeScannerTest.java
===================================================================
---
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/packaging/NativeScannerTest.java
(rev 0)
+++
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/packaging/NativeScannerTest.java 2009-04-18
14:35:58 UTC (rev 16358)
@@ -0,0 +1,53 @@
+package org.hibernate.ejb.test.packaging;
+
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+
+import junit.framework.TestCase;
+
+import org.hibernate.ejb.packaging.NamedInputStream;
+import org.hibernate.ejb.packaging.NativeScanner;
+import org.hibernate.ejb.packaging.Scanner;
+import org.hibernate.ejb.test.pack.defaultpar.ApplicationServer;
+
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class NativeScannerTest extends TestCase {
+ private static final String jarFileBase = "file:./target/test-packages";
+
+ public void testNativeScanner() throws Exception {
+ String jarFileName = jarFileBase + "/defaultpar.par";
+ Scanner scanner = new NativeScanner();
+
+ final URL jarUrl = new URL( jarFileName );
+ assertEquals( "defaultpar", scanner.getUnqualifiedJarName( jarUrl ) );
+
+ Set<Class<? extends Annotation>> annotationsToLookFor = new
HashSet<Class<? extends Annotation>>(3);
+ annotationsToLookFor.add( Entity.class );
+ annotationsToLookFor.add( MappedSuperclass.class );
+ annotationsToLookFor.add( Embeddable.class );
+ final Set<Class<?>> classes = scanner.getClassesInJar( jarUrl,
annotationsToLookFor );
+
+ assertEquals( 3, classes.size() );
+ assertTrue( classes.contains( ApplicationServer.class ) );
+ assertTrue( classes.contains( org.hibernate.ejb.test.pack.defaultpar.Version.class )
);
+
+ Set<String> filePatterns = new HashSet<String>(2);
+ filePatterns.add("**/*.hbm.xml");
+ filePatterns.add("META-INF/orm.xml");
+ final Set<NamedInputStream> files = scanner.getFilesInJar( jarUrl, filePatterns
);
+
+ assertEquals( 2, files.size() );
+ for (NamedInputStream file : files ) {
+ assertNotNull( file.getStream() );
+ file.getStream().close();
+ }
+ }
+}