diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/NamedInputStream.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/NamedInputStream.java
index 7141f55f98..733455bf7e 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/NamedInputStream.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/NamedInputStream.java
@@ -26,10 +26,12 @@ package org.hibernate.ejb.packaging;
import java.io.InputStream;
/**
- * @deprecated Use {@link org.hibernate.jpa.packaging.spi.NamedInputStream} instead
+ * @deprecated Doubly deprecated actually :) Moved to {@link org.hibernate.jpa.boot.spi.NamedInputStream}
+ * due to package renaming (org.hibernate.ejb -> org.hibernate.jpa). But also, the role fulfilled by this class
+ * was moved to the new {@link org.hibernate.jpa.boot.spi.InputStreamAccess} contract.
*/
@Deprecated
-public class NamedInputStream extends org.hibernate.jpa.packaging.spi.NamedInputStream {
+public class NamedInputStream extends org.hibernate.jpa.boot.spi.NamedInputStream {
public NamedInputStream(String name, InputStream stream) {
super( name, stream );
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java
index 3a2cd4e46a..a452e66495 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/packaging/Scanner.java
@@ -24,8 +24,8 @@
package org.hibernate.ejb.packaging;
/**
- * @deprecated Use {@link org.hibernate.jpa.packaging.spi.Scanner} instead
+ * @deprecated Use {@link org.hibernate.jpa.boot.scan.spi.Scanner} instead
*/
@Deprecated
-public interface Scanner extends org.hibernate.jpa.packaging.spi.Scanner {
+public interface Scanner extends org.hibernate.jpa.boot.scan.spi.Scanner {
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitorFactory.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/ArchiveHelper.java
similarity index 63%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitorFactory.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/ArchiveHelper.java
index 45ca7f8e1b..76caf4db9c 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitorFactory.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/ArchiveHelper.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,29 +21,26 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
+package org.hibernate.jpa.boot.archive.internal;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
-import java.net.URISyntaxException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
-import org.hibernate.internal.util.StringHelper;
-import org.hibernate.jpa.internal.EntityManagerMessageLogger;
import org.jboss.logging.Logger;
+import org.hibernate.jpa.boot.archive.spi.ArchiveException;
+
/**
* @author Emmanuel Bernard
- * @author Brett Meyer
+ * @author Steve Ebersole
*/
-public class JarVisitorFactory {
-
- private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
- JarVisitorFactory.class.getName());
+public class ArchiveHelper {
+ private static final Logger log = Logger.getLogger( ArchiveHelper.class );
/**
* Get the JAR URL of the JAR containing the given entry
@@ -51,7 +50,6 @@ public class JarVisitorFactory {
* @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;
@@ -106,7 +104,7 @@ public class JarVisitorFactory {
"Unable to determine JAR Url from " + url + ". Cause: " + e.getMessage()
);
}
- LOG.trace("JAR URL from URL Entry: " + url + " >> " + jarUrl);
+ log.trace("JAR URL from URL Entry: " + url + " >> " + jarUrl);
return jarUrl;
}
@@ -114,7 +112,6 @@ public class JarVisitorFactory {
* 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;
@@ -134,70 +131,40 @@ public class JarVisitorFactory {
return jarUrl;
}
- /**
- * Get a JarVisitor to the jar jarPath
applying the given filters
- *
- * Method used in a non-managed environment
- *
- * @throws IllegalArgumentException if the jarPath is incorrect
- */
- public static JarVisitor getVisitor(String jarPath, Filter[] filters) throws IllegalArgumentException {
- File file = new File( jarPath );
- if ( file.isFile() ) {
- return new InputStreamZippedJarVisitor( jarPath, filters );
+ public static String unqualifiedJarFileName(URL jarUrl) {
+ // todo : weak algorithm subject to AOOBE
+ String fileName = jarUrl.getFile();
+ int exclamation = fileName.lastIndexOf( "!" );
+ if (exclamation != -1) {
+ fileName = fileName.substring( 0, exclamation );
}
- else {
- return new ExplodedJarVisitor( jarPath, filters );
+
+ int slash = fileName.lastIndexOf( "/" );
+ if ( slash != -1 ) {
+ fileName = fileName.substring(
+ fileName.lastIndexOf( "/" ) + 1,
+ fileName.length()
+ );
+ }
+
+ if ( fileName.length() > 4 && fileName.endsWith( "ar" ) && fileName.charAt( fileName.length() - 4 ) == '.' ) {
+ fileName = fileName.substring( 0, fileName.length() - 4 );
+ }
+
+ return fileName;
+ }
+
+ public static byte[] getBytesFromInputStreamSafely(InputStream inputStream) {
+ try {
+ return getBytesFromInputStream( inputStream );
+ }
+ catch (IOException e) {
+ throw new ArchiveException( "Unable to extract bytes from InputStream", e );
}
}
- /**
- * Build a JarVisitor on the given JAR URL applying the given filters
- *
- * @throws IllegalArgumentException if the URL is malformed
- */
- public static JarVisitor getVisitor(URL jarUrl, Filter[] filters) throws IllegalArgumentException {
- return getVisitor( jarUrl, filters, "" );
- }
-
- public static JarVisitor getVisitor(URL jarUrl, Filter[] filters, String entry) throws IllegalArgumentException {
- String protocol = jarUrl.getProtocol();
- if ( "jar".equals( protocol ) ) {
- return new JarProtocolVisitor( jarUrl, filters, entry );
- }
- else if ( StringHelper.isEmpty( protocol ) || "file".equals( protocol ) || "vfszip".equals( protocol ) || "vfsfile".equals( protocol ) ) {
- File file;
- try {
- final String filePart = jarUrl.getFile();
- if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) {
- //unescaped (from the container), keep as is
- file = new File( jarUrl.getFile() );
- }
- else {
- file = new File( jarUrl.toURI().getSchemeSpecificPart() );
- }
- }
- catch (URISyntaxException e) {
- throw new IllegalArgumentException(
- "Unable to visit JAR " + jarUrl + ". Cause: " + e.getMessage(), e
- );
- }
-
- if ( file.isDirectory() ) {
- return new ExplodedJarVisitor( jarUrl, filters, entry );
- }
- else {
- return new FileZippedJarVisitor( jarUrl, filters, entry );
- }
- }
- else {
- //let's assume the url can return the jar as a zip stream
- return new InputStreamZippedJarVisitor( jarUrl, filters, entry );
- }
- }
-
- // Optimized by HHH-7835
public static byte[] getBytesFromInputStream(InputStream inputStream) throws IOException {
+ // Optimized by HHH-7835
int size;
List data = new LinkedList();
int bufferSize = 4096;
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/ExplodedArchiveDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/ExplodedArchiveDescriptor.java
new file mode 100644
index 0000000000..50a64a1a2f
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/ExplodedArchiveDescriptor.java
@@ -0,0 +1,212 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.jpa.boot.archive.spi.AbstractArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveException;
+import org.hibernate.jpa.boot.internal.FileInputStreamAccess;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.internal.EntityManagerMessageLogger;
+
+/**
+ * @author Steve Ebersole
+ */
+public class ExplodedArchiveDescriptor extends AbstractArchiveDescriptor {
+ private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(
+ EntityManagerMessageLogger.class,
+ ExplodedArchiveDescriptor.class.getName()
+ );
+
+ public ExplodedArchiveDescriptor(
+ ArchiveDescriptorFactory archiveDescriptorFactory,
+ URL archiveUrl,
+ String entryBasePrefix) {
+ super( archiveDescriptorFactory, archiveUrl, entryBasePrefix );
+ }
+
+ @Override
+ public void visitArchive(ArchiveContext context) {
+ final File rootDirectory = resolveRootDirectory();
+ if ( rootDirectory == null ) {
+ return;
+ }
+
+ if ( rootDirectory.isDirectory() ) {
+ processDirectory( rootDirectory, null, context );
+ }
+ else {
+ //assume zipped file
+ processZippedRoot( rootDirectory, context );
+ }
+ }
+
+ private File resolveRootDirectory() {
+ final File archiveUrlDirectory;
+ try {
+ final String filePart = getArchiveUrl().getFile();
+ if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) {
+ //unescaped (from the container), keep as is
+ archiveUrlDirectory = new File( filePart );
+ }
+ else {
+ archiveUrlDirectory = new File( getArchiveUrl().toURI().getSchemeSpecificPart() );
+ }
+ }
+ catch (URISyntaxException e) {
+ LOG.malformedUrl( getArchiveUrl(), e );
+ return null;
+ }
+
+ if ( !archiveUrlDirectory.exists() ) {
+ LOG.explodedJarDoesNotExist( getArchiveUrl() );
+ return null;
+ }
+ if ( !archiveUrlDirectory.isDirectory() ) {
+ LOG.explodedJarNotDirectory( getArchiveUrl() );
+ return null;
+ }
+
+ final String entryBase = getEntryBasePrefix();
+ if ( entryBase != null && entryBase.length() > 0 && ! "/".equals( entryBase ) ) {
+ return new File( archiveUrlDirectory, entryBase );
+ }
+ else {
+ return archiveUrlDirectory;
+ }
+ }
+
+ private void processDirectory(
+ File directory,
+ String path,
+ ArchiveContext context) {
+ if ( directory == null ) {
+ return;
+ }
+
+ final File[] files = directory.listFiles();
+ if ( files == null ) {
+ return;
+ }
+
+ path = path == null ? "" : path + "/";
+ for ( final File localFile : files ) {
+ if ( !localFile.exists() ) {
+ // should never happen conceptually, but...
+ continue;
+ }
+
+ if ( localFile.isDirectory() ) {
+ processDirectory( localFile, path + localFile.getName(), context );
+ continue;
+ }
+
+ final String name = localFile.getAbsolutePath();
+ final String relativeName = path + localFile.getName();
+ final InputStreamAccess inputStreamAccess = new FileInputStreamAccess( name, localFile );
+
+ final ArchiveEntry entry = new ArchiveEntry() {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getNameWithinArchive() {
+ return relativeName;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return inputStreamAccess;
+ }
+ };
+
+ context.obtainArchiveEntryHandler( entry ).handleEntry( entry, context );
+ }
+ }
+
+ private void processZippedRoot(File rootFile, ArchiveContext context) {
+ try {
+ final JarFile jarFile = new JarFile(rootFile);
+ final Enumeration extends ZipEntry> entries = jarFile.entries();
+ while ( entries.hasMoreElements() ) {
+ final ZipEntry zipEntry = entries.nextElement();
+ if ( zipEntry.isDirectory() ) {
+ continue;
+ }
+
+ final String name = extractName( zipEntry );
+ final String relativeName = extractRelativeName( zipEntry );
+ final InputStreamAccess inputStreamAccess;
+ try {
+ inputStreamAccess = buildByteBasedInputStreamAccess( name, jarFile.getInputStream( zipEntry ) );
+ }
+ catch (IOException e) {
+ throw new ArchiveException(
+ String.format(
+ "Unable to access stream from jar file [%s] for entry [%s]",
+ jarFile.getName(),
+ zipEntry.getName()
+ )
+ );
+ }
+
+ final ArchiveEntry entry = new ArchiveEntry() {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getNameWithinArchive() {
+ return relativeName;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return inputStreamAccess;
+ }
+ };
+ context.obtainArchiveEntryHandler( entry ).handleEntry( entry, context );
+ }
+ }
+ catch (IOException e) {
+ throw new ArchiveException( "Error accessing jar file [" + rootFile.getAbsolutePath() + "]", e );
+ }
+ }
+
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarFileBasedArchiveDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarFileBasedArchiveDescriptor.java
new file mode 100644
index 0000000000..d601d69ae2
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarFileBasedArchiveDescriptor.java
@@ -0,0 +1,193 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.internal;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.zip.ZipEntry;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.jpa.boot.archive.spi.AbstractArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
+import org.hibernate.jpa.boot.archive.spi.ArchiveException;
+import org.hibernate.jpa.internal.EntityManagerMessageLogger;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+
+/**
+ * An ArchiveDescriptor implementation leveraging the {@link JarFile} API for processing.
+ *
+ * @author Steve Ebersole
+ */
+public class JarFileBasedArchiveDescriptor extends AbstractArchiveDescriptor {
+ private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(
+ EntityManagerMessageLogger.class,
+ JarFileBasedArchiveDescriptor.class.getName()
+ );
+
+ public JarFileBasedArchiveDescriptor(
+ ArchiveDescriptorFactory archiveDescriptorFactory,
+ URL archiveUrl,
+ String entry) {
+ super( archiveDescriptorFactory, archiveUrl, entry );
+ }
+
+ @Override
+ public void visitArchive(ArchiveContext context) {
+ final JarFile jarFile = resolveJarFileReference();
+ if ( jarFile == null ) {
+ return;
+ }
+
+ final Enumeration extends ZipEntry> zipEntries = jarFile.entries();
+ while ( zipEntries.hasMoreElements() ) {
+ final ZipEntry zipEntry = zipEntries.nextElement();
+ final String entryName = extractName( zipEntry );
+
+ if ( getEntryBasePrefix() != null && ! entryName.startsWith( getEntryBasePrefix() ) ) {
+ continue;
+ }
+ if ( zipEntry.isDirectory() ) {
+ continue;
+ }
+
+ if ( entryName.equals( getEntryBasePrefix() ) ) {
+ // exact match, might be a nested jar entry (ie from jar:file:..../foo.ear!/bar.jar)
+ //
+ // This algorithm assumes that the zipped file is only the URL root (including entry), not
+ // just any random entry
+ try {
+ InputStream is = new BufferedInputStream( jarFile.getInputStream( zipEntry ) );
+ try {
+ final JarInputStream jarInputStream = new JarInputStream( is );
+ ZipEntry subZipEntry = jarInputStream.getNextEntry();
+ while ( subZipEntry != null ) {
+ if ( ! subZipEntry.isDirectory() ) {
+
+ final String name = extractName( subZipEntry );
+ final String relativeName = extractRelativeName( subZipEntry );
+ final InputStreamAccess inputStreamAccess
+ = buildByteBasedInputStreamAccess( name, jarInputStream );
+
+ final ArchiveEntry entry = new ArchiveEntry() {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getNameWithinArchive() {
+ return relativeName;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return inputStreamAccess;
+ }
+ };
+
+ final ArchiveEntryHandler entryHandler = context.obtainArchiveEntryHandler( entry );
+ entryHandler.handleEntry( entry, context );
+ }
+
+ subZipEntry = jarInputStream.getNextEntry();
+ }
+ }
+ finally {
+ is.close();
+ }
+ }
+ catch (Exception e) {
+ throw new ArchiveException( "Error accessing JarFile entry [" + zipEntry.getName() + "]", e );
+ }
+ }
+ else {
+ final String name = extractName( zipEntry );
+ final String relativeName = extractRelativeName( zipEntry );
+ final InputStreamAccess inputStreamAccess;
+ try {
+ inputStreamAccess = buildByteBasedInputStreamAccess( name, jarFile.getInputStream( zipEntry ) );
+ }
+ catch (IOException e) {
+ throw new ArchiveException(
+ String.format(
+ "Unable to access stream from jar file [%s] for entry [%s]",
+ jarFile.getName(),
+ zipEntry.getName()
+ )
+ );
+ }
+
+ final ArchiveEntry entry = new ArchiveEntry() {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getNameWithinArchive() {
+ return relativeName;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return inputStreamAccess;
+ }
+ };
+
+ final ArchiveEntryHandler entryHandler = context.obtainArchiveEntryHandler( entry );
+ entryHandler.handleEntry( entry, context );
+ }
+ }
+ }
+
+ private JarFile resolveJarFileReference() {
+ try {
+ String filePart = getArchiveUrl().getFile();
+ if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) {
+ // unescaped (from the container), keep as is
+ return new JarFile( getArchiveUrl().getFile() );
+ }
+ else {
+ return new JarFile( getArchiveUrl().toURI().getSchemeSpecificPart() );
+ }
+ }
+ catch (IOException e) {
+ LOG.unableToFindFile( getArchiveUrl(), e );
+ }
+ catch (URISyntaxException e) {
+ LOG.malformedUrlWarning( getArchiveUrl(), e );
+ }
+ return null;
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarInputStreamBasedArchiveDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarInputStreamBasedArchiveDescriptor.java
new file mode 100644
index 0000000000..3b7b338535
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarInputStreamBasedArchiveDescriptor.java
@@ -0,0 +1,168 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.internal;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.zip.ZipEntry;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.jpa.boot.archive.spi.AbstractArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveException;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.internal.EntityManagerMessageLogger;
+
+/**
+ * An ArchiveDescriptor implementation that works on archives accessible through a {@link java.util.jar.JarInputStream}.
+ * NOTE : This is less efficient implementation than {@link JarFileBasedArchiveDescriptor}
+ *
+ * @author Emmanuel Bernard
+ * @author Steve Ebersole
+ */
+public class JarInputStreamBasedArchiveDescriptor extends AbstractArchiveDescriptor {
+ private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(
+ EntityManagerMessageLogger.class,
+ JarInputStreamBasedArchiveDescriptor.class.getName()
+ );
+
+ public JarInputStreamBasedArchiveDescriptor(
+ ArchiveDescriptorFactory archiveDescriptorFactory,
+ URL url,
+ String entry) {
+ super( archiveDescriptorFactory, url, entry );
+ }
+
+ @Override
+ public void visitArchive(ArchiveContext context) {
+ final JarInputStream jarInputStream;
+ try {
+ jarInputStream = new JarInputStream( getArchiveUrl().openStream() );
+ }
+ catch (Exception e) {
+ //really should catch IOException but Eclipse is buggy and raise NPE...
+ LOG.unableToFindFile( getArchiveUrl(), e );
+ return;
+ }
+
+ try {
+ JarEntry jarEntry;
+ while ( ( jarEntry = jarInputStream.getNextJarEntry() ) != null ) {
+ String jarEntryName = jarEntry.getName();
+ if ( getEntryBasePrefix() != null && ! jarEntryName.startsWith( getEntryBasePrefix() ) ) {
+ continue;
+ }
+
+ if ( jarEntry.isDirectory() ) {
+ continue;
+ }
+
+ if ( jarEntryName.equals( getEntryBasePrefix() ) ) {
+ // exact match, might be a nested jar entry (ie from jar:file:..../foo.ear!/bar.jar)
+ //
+ // This algorithm assumes that the zipped file is only the URL root (including entry), not
+ // just any random entry
+ try {
+ final JarInputStream subJarInputStream = new JarInputStream( jarInputStream );
+ try {
+ ZipEntry subZipEntry = jarInputStream.getNextEntry();
+ while (subZipEntry != null) {
+ if ( ! subZipEntry.isDirectory() ) {
+ final String subName = extractName( subZipEntry );
+ final InputStreamAccess inputStreamAccess
+ = buildByteBasedInputStreamAccess( subName, subJarInputStream );
+
+ final ArchiveEntry entry = new ArchiveEntry() {
+ @Override
+ public String getName() {
+ return subName;
+ }
+
+ @Override
+ public String getNameWithinArchive() {
+ return subName;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return inputStreamAccess;
+ }
+ };
+
+ context.obtainArchiveEntryHandler( entry ).handleEntry( entry, context );
+ }
+ subZipEntry = jarInputStream.getNextJarEntry();
+ }
+ }
+ finally {
+ subJarInputStream.close();
+ }
+ }
+ catch (Exception e) {
+ throw new ArchiveException( "Error accessing nested jar", e );
+ }
+ }
+ else {
+ final String entryName = extractName( jarEntry );
+ final InputStreamAccess inputStreamAccess
+ = buildByteBasedInputStreamAccess( entryName, jarInputStream );
+
+ final String relativeName = extractRelativeName( jarEntry );
+
+ final ArchiveEntry entry = new ArchiveEntry() {
+ @Override
+ public String getName() {
+ return entryName;
+ }
+
+ @Override
+ public String getNameWithinArchive() {
+ return relativeName;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return inputStreamAccess;
+ }
+ };
+
+ context.obtainArchiveEntryHandler( entry ).handleEntry( entry, context );
+ }
+ }
+
+ jarInputStream.close();
+ }
+ catch (IOException ioe) {
+ throw new ArchiveException(
+ String.format( "Error accessing JarInputStream [%s]", getArchiveUrl() ),
+ ioe
+ );
+ }
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarProtocolArchiveDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarProtocolArchiveDescriptor.java
new file mode 100644
index 0000000000..4eaa7d8748
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/JarProtocolArchiveDescriptor.java
@@ -0,0 +1,71 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.internal;
+
+import java.net.URL;
+
+import org.hibernate.annotations.common.AssertionFailure;
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
+
+/**
+ * An ArchiveDescriptor implementation for handling archives whose url reported a JAR protocol (i.e., jar://).
+ *
+ * @author Steve Ebersole
+ */
+public class JarProtocolArchiveDescriptor implements ArchiveDescriptor {
+ private final ArchiveDescriptor delegateDescriptor;
+
+ public JarProtocolArchiveDescriptor(
+ ArchiveDescriptorFactory archiveDescriptorFactory,
+ URL url,
+ String incomingEntry) {
+ if ( incomingEntry != null && incomingEntry.length() > 0 ) {
+ throw new IllegalArgumentException( "jar:jar: not supported: " + url );
+ }
+
+ final String urlFile = url.getFile();
+ final int subEntryIndex = urlFile.lastIndexOf( "!" );
+ if ( subEntryIndex == -1 ) {
+ throw new AssertionFailure( "JAR URL does not contain '!/' :" + url );
+ }
+
+ final String subEntry;
+ if ( subEntryIndex + 1 >= urlFile.length() ) {
+ subEntry = "";
+ }
+ else {
+ subEntry = urlFile.substring( subEntryIndex + 1 );
+ }
+
+ URL fileUrl = archiveDescriptorFactory.getJarURLFromURLEntry( url, subEntry );
+ delegateDescriptor = archiveDescriptorFactory.buildArchiveDescriptor( fileUrl, subEntry );
+ }
+
+ @Override
+ public void visitArchive(ArchiveContext context) {
+ delegateDescriptor.visitArchive( context );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/StandardArchiveDescriptorFactory.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/StandardArchiveDescriptorFactory.java
new file mode 100644
index 0000000000..e502570140
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/internal/StandardArchiveDescriptorFactory.java
@@ -0,0 +1,105 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.internal;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.hibernate.internal.util.StringHelper;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
+
+/**
+ * @author Emmanuel Bernard
+ * @author Steve Ebersole
+ */
+public class StandardArchiveDescriptorFactory implements ArchiveDescriptorFactory {
+ public static final StandardArchiveDescriptorFactory INSTANCE = new StandardArchiveDescriptorFactory();
+
+ @Override
+ public ArchiveDescriptor buildArchiveDescriptor(URL url) {
+ return buildArchiveDescriptor( url, "" );
+ }
+
+ @Override
+ public ArchiveDescriptor buildArchiveDescriptor(URL url, String entry) {
+ final String protocol = url.getProtocol();
+ if ( "jar".equals( protocol ) ) {
+ return new JarProtocolArchiveDescriptor( this, url, entry );
+ }
+ else if ( StringHelper.isEmpty( protocol )
+ || "file".equals( protocol )
+ || "vfszip".equals( protocol )
+ || "vfsfile".equals( protocol ) ) {
+ final File file;
+ try {
+ final String filePart = url.getFile();
+ if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) {
+ //unescaped (from the container), keep as is
+ file = new File( url.getFile() );
+ }
+ else {
+ file = new File( url.toURI().getSchemeSpecificPart() );
+ }
+
+ if ( ! file.exists() ) {
+ throw new IllegalArgumentException(
+ String.format(
+ "File [%s] referenced by given URL [%s] does not exist",
+ filePart,
+ url.toExternalForm()
+ )
+ );
+ }
+ }
+ catch (URISyntaxException e) {
+ throw new IllegalArgumentException(
+ "Unable to visit JAR " + url + ". Cause: " + e.getMessage(), e
+ );
+ }
+
+ if ( file.isDirectory() ) {
+ return new ExplodedArchiveDescriptor( this, url, entry );
+ }
+ else {
+ return new JarFileBasedArchiveDescriptor( this, url, entry );
+ }
+ }
+ else {
+ //let's assume the url can return the jar as a zip stream
+ return new JarInputStreamBasedArchiveDescriptor( this, url, entry );
+ }
+ }
+
+ @Override
+ public URL getJarURLFromURLEntry(URL url, String entry) throws IllegalArgumentException {
+ return ArchiveHelper.getJarURLFromURLEntry( url, entry );
+ }
+
+ @Override
+ public URL getURLFromPath(String jarPath) {
+ return ArchiveHelper.getURLFromPath( jarPath );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java
new file mode 100644
index 0000000000..00f92c6a0b
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java
@@ -0,0 +1,92 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.spi;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.zip.ZipEntry;
+
+import org.hibernate.internal.util.StringHelper;
+import org.hibernate.jpa.boot.internal.ByteArrayInputStreamAccess;
+import org.hibernate.jpa.boot.archive.internal.ArchiveHelper;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+
+/**
+ * @author Steve Ebersole
+ */
+public abstract class AbstractArchiveDescriptor implements ArchiveDescriptor {
+ private final ArchiveDescriptorFactory archiveDescriptorFactory;
+ private final URL archiveUrl;
+ private final String entryBasePrefix;
+
+ protected AbstractArchiveDescriptor(
+ ArchiveDescriptorFactory archiveDescriptorFactory,
+ URL archiveUrl,
+ String entryBasePrefix) {
+ this.archiveDescriptorFactory = archiveDescriptorFactory;
+ this.archiveUrl = archiveUrl;
+ this.entryBasePrefix = normalizeEntryBasePrefix( entryBasePrefix );
+ }
+
+ private static String normalizeEntryBasePrefix(String entryBasePrefix) {
+ if ( StringHelper.isEmpty( entryBasePrefix ) || entryBasePrefix.length() == 1 ) {
+ return null;
+ }
+
+ return entryBasePrefix.startsWith( "/" ) ? entryBasePrefix.substring( 1 ) : entryBasePrefix;
+ }
+
+ protected ArchiveDescriptorFactory getArchiveDescriptorFactory() {
+ return archiveDescriptorFactory;
+ }
+
+ protected URL getArchiveUrl() {
+ return archiveUrl;
+ }
+
+ protected String getEntryBasePrefix() {
+ return entryBasePrefix;
+ }
+
+ protected String extractRelativeName(ZipEntry zipEntry) {
+ final String entryName = extractName( zipEntry );
+ return entryBasePrefix == null ? entryName : entryName.substring( entryBasePrefix.length() );
+ }
+
+ protected String extractName(ZipEntry zipEntry) {
+ return normalizePathName( zipEntry.getName() );
+ }
+
+ protected String normalizePathName(String pathName) {
+ return pathName.startsWith( "/" ) ? pathName.substring( 1 ) : pathName;
+ }
+
+ protected InputStreamAccess buildByteBasedInputStreamAccess(final String name, InputStream inputStream) {
+ // because of how jar InputStreams work we need to extract the bytes immediately. However, we
+ // do delay the creation of the ByteArrayInputStreams until needed
+ final byte[] bytes = ArchiveHelper.getBytesFromInputStreamSafely( inputStream );
+ return new ByteArrayInputStreamAccess( name, bytes );
+ }
+
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveContext.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveContext.java
new file mode 100644
index 0000000000..8674cc6bb5
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveContext.java
@@ -0,0 +1,37 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.spi;
+
+import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
+
+/**
+* @author Steve Ebersole
+*/
+public interface ArchiveContext {
+ public PersistenceUnitDescriptor getPersistenceUnitDescriptor();
+
+ public boolean isRootUrl();
+
+ public ArchiveEntryHandler obtainArchiveEntryHandler(ArchiveEntry entry);
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/Filter.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveDescriptor.java
similarity index 67%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/Filter.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveDescriptor.java
index 0d16548108..b9d07dee0d 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/Filter.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveDescriptor.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,22 +21,14 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
-
+package org.hibernate.jpa.boot.archive.spi;
/**
- * Filter used when searching elements in a JAR
+ * Contract for visiting an archive, which might be a jar, a zip, an exploded directory, etc.
*
+ * @author Steve Ebersole
* @author Emmanuel Bernard
*/
-public abstract class Filter {
- private boolean retrieveStream;
-
- protected Filter(boolean retrieveStream) {
- this.retrieveStream = retrieveStream;
- }
-
- public boolean getStream() {
- return retrieveStream;
- }
+public interface ArchiveDescriptor {
+ public void visitArchive(ArchiveContext archiveContext);
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveDescriptorFactory.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveDescriptorFactory.java
new file mode 100644
index 0000000000..441b531b25
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveDescriptorFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.archive.spi;
+
+import java.net.URL;
+
+/**
+ * Contract for building ArchiveDescriptor instances.
+ *
+ * @author Steve Ebersole
+ */
+public interface ArchiveDescriptorFactory {
+ public ArchiveDescriptor buildArchiveDescriptor(URL url);
+ public ArchiveDescriptor buildArchiveDescriptor(URL jarUrl, String entry);
+
+ public URL getJarURLFromURLEntry(URL url, String entry) throws IllegalArgumentException;
+ public URL getURLFromPath(String jarPath);
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveEntry.java
similarity index 55%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitor.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveEntry.java
index cbb829ee3e..7d7e9185e0 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitor.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveEntry.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,28 +21,35 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
-import java.io.IOException;
-import java.util.Set;
+package org.hibernate.jpa.boot.archive.spi;
+
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
/**
- * @author Emmanuel Bernard
+ * Represent an entry in the archive.
+ *
+ * @author Steve Ebersole
*/
-public interface JarVisitor {
+public interface ArchiveEntry {
/**
- * Get the unqualified Jar name (ie wo path and wo extension)
+ * Get the entry's name
*
- * @return the unqualified jar name.
+ * @return
*/
- String getUnqualifiedJarName();
-
- Filter[] getFilters();
+ public String getName();
/**
- * Return the matching entries for each filter in the same order the filter where passed
+ * Get the relative name of the entry within the archive. Typically what we are looking for here is
+ * the ClassLoader resource lookup name.
*
- * @return array of Set of JarVisitor.Entry
- * @throws java.io.IOException if something went wrong
+ * @return
*/
- Set[] getMatchingEntries() throws IOException;
+ public String getNameWithinArchive();
+
+ /**
+ * Get access to the stream for the entry
+ *
+ * @return
+ */
+ public InputStreamAccess getStreamAccess();
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/FileFilter.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveEntryHandler.java
similarity index 60%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/FileFilter.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveEntryHandler.java
index 8c8575be3f..3fce3402c0 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/FileFilter.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveEntryHandler.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,25 +21,13 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
-
+package org.hibernate.jpa.boot.archive.spi;
/**
- * Filter use to match a file by its name
+ * Handler for archive entries, based on the classified type of the entry
*
- * @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
-public abstract class FileFilter extends Filter {
-
- /**
- * @param retrieveStream Give back an open stream to the matching element or not
- */
- public FileFilter(boolean retrieveStream) {
- super( retrieveStream );
- }
-
- /**
- * Return true if the fully qualified file name match
- */
- public abstract boolean accept(String name);
- }
\ No newline at end of file
+public interface ArchiveEntryHandler {
+ public void handleEntry(ArchiveEntry entry, ArchiveContext context);
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/ClassFilter.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveException.java
similarity index 63%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/ClassFilter.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveException.java
index 6ea6dc08bb..1257502318 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/ClassFilter.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/ArchiveException.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,20 +21,19 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
+package org.hibernate.jpa.boot.archive.spi;
+import org.hibernate.HibernateException;
/**
- * Filter on class elements
- *
- * @author Emmanuel Bernard
- * @see JavaElementFilter
+ * @author Steve Ebersole
*/
-public abstract class ClassFilter extends JavaElementFilter {
- /**
- * @see JavaElementFilter#JavaElementFilter(boolean, Class[])
- */
- protected ClassFilter(boolean retrieveStream, Class[] annotations) {
- super( retrieveStream, annotations );
+public class ArchiveException extends HibernateException {
+ public ArchiveException(String message) {
+ super( message );
}
-}
\ No newline at end of file
+
+ public ArchiveException(String message, Throwable root) {
+ super( message, root );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/ByteArrayInputStreamAccess.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/ByteArrayInputStreamAccess.java
new file mode 100644
index 0000000000..8b949206ce
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/ByteArrayInputStreamAccess.java
@@ -0,0 +1,60 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.boot.spi.NamedInputStream;
+
+/**
+ * An InputStreamAccess implementation based on a byte array
+ *
+ * @author Steve Ebersole
+ */
+public class ByteArrayInputStreamAccess implements InputStreamAccess {
+ private final String name;
+ private final byte[] bytes;
+
+ public ByteArrayInputStreamAccess(String name, byte[] bytes) {
+ this.name = name;
+ this.bytes = bytes;
+ }
+
+ @Override
+ public String getStreamName() {
+ return name;
+ }
+
+ @Override
+ public InputStream accessInputStream() {
+ return new ByteArrayInputStream( bytes );
+ }
+
+ @Override
+ public NamedInputStream asNamedInputStream() {
+ return new NamedInputStream( getStreamName(), accessInputStream() );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/Entry.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/ClassDescriptorImpl.java
similarity index 53%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/Entry.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/ClassDescriptorImpl.java
index 584bfcb15c..f8d15c1419 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/Entry.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/ClassDescriptorImpl.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,44 +21,48 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
-import java.io.InputStream;
+package org.hibernate.jpa.boot.internal;
+
+import org.hibernate.jpa.boot.spi.ClassDescriptor;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
/**
- * Represent a JAR entry
- * Contains a name and an optional Input stream to the entry
- *
- * @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
-public class Entry {
- private String name;
- private InputStream is;
+public class ClassDescriptorImpl implements ClassDescriptor {
+ private final String name;
+ private final InputStreamAccess streamAccess;
- public Entry(String name, InputStream is) {
+ public ClassDescriptorImpl(String name, InputStreamAccess streamAccess) {
this.name = name;
- this.is = is;
+ this.streamAccess = streamAccess;
}
+ @Override
public String getName() {
return name;
}
- public InputStream getInputStream() {
- return is;
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return streamAccess;
}
+ @Override
public boolean equals(Object o) {
- if ( this == o ) return true;
- if ( o == null || getClass() != o.getClass() ) return false;
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
- final Entry entry = (Entry) o;
-
- if ( !name.equals( entry.name ) ) return false;
-
- return true;
+ ClassDescriptorImpl that = (ClassDescriptorImpl) o;
+ return name.equals( that.name );
}
+ @Override
public int hashCode() {
return name.hashCode();
}
-}
\ No newline at end of file
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
index 2098a2908e..dd47f695b0 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
@@ -23,12 +23,17 @@
*/
package org.hibernate.jpa.boot.internal;
+import javax.persistence.AttributeConverter;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityNotFoundException;
+import javax.persistence.PersistenceException;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
-import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,18 +47,17 @@ import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
-import javax.persistence.AttributeConverter;
-import javax.persistence.Converter;
-import javax.persistence.Embeddable;
-import javax.persistence.Entity;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityNotFoundException;
-import javax.persistence.MappedSuperclass;
-import javax.persistence.PersistenceException;
-import javax.persistence.spi.PersistenceUnitTransactionType;
-import javax.sql.DataSource;
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.Index;
+import org.jboss.jandex.IndexView;
+import org.jboss.jandex.Indexer;
+
+import org.jboss.logging.Logger;
import org.hibernate.Interceptor;
+import org.hibernate.InvalidMappingException;
import org.hibernate.MappingException;
import org.hibernate.MappingNotFoundException;
import org.hibernate.SessionFactory;
@@ -81,14 +85,21 @@ import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
-import org.hibernate.jpa.internal.schemagen.JpaSchemaGenerator;
import org.hibernate.jpa.internal.EntityManagerFactoryImpl;
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
+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.packaging.internal.NativeScanner;
-import org.hibernate.jpa.packaging.spi.NamedInputStream;
-import org.hibernate.jpa.packaging.spi.Scanner;
+import org.hibernate.jpa.boot.scan.internal.StandardScanOptions;
+import org.hibernate.jpa.boot.scan.internal.StandardScanner;
+import org.hibernate.jpa.boot.spi.ClassDescriptor;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+import org.hibernate.jpa.boot.spi.NamedInputStream;
+import org.hibernate.jpa.boot.spi.PackageDescriptor;
+import org.hibernate.jpa.boot.scan.spi.ScanOptions;
+import org.hibernate.jpa.boot.scan.spi.ScanResult;
+import org.hibernate.jpa.boot.scan.spi.Scanner;
import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
import org.hibernate.metamodel.source.annotations.JPADotNames;
import org.hibernate.metamodel.source.annotations.JandexHelper;
@@ -97,14 +108,6 @@ import org.hibernate.secure.internal.JACCConfiguration;
import org.hibernate.service.ConfigLoader;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor;
-import org.jboss.jandex.AnnotationInstance;
-import org.jboss.jandex.ClassInfo;
-import org.jboss.jandex.CompositeIndex;
-import org.jboss.jandex.DotName;
-import org.jboss.jandex.Index;
-import org.jboss.jandex.IndexView;
-import org.jboss.jandex.Indexer;
-import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
@@ -199,13 +202,14 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Next we do a preliminary pass at metadata processing, which involves:
// 1) scanning
- ScanResult scanResult = scan( bootstrapServiceRegistry );
+ final ScanResult scanResult = scan( bootstrapServiceRegistry );
+ final DeploymentResources deploymentResources = buildDeploymentResources( scanResult, bootstrapServiceRegistry );
// 2) building a Jandex index
- Set collectedManagedClassNames = collectManagedClassNames( scanResult );
- IndexView jandexIndex = locateOrBuildJandexIndex( collectedManagedClassNames, scanResult.getPackageNames(), bootstrapServiceRegistry );
+ final IndexView jandexIndex = locateOrBuildJandexIndex( deploymentResources );
// 3) building "metadata sources" to keep for later to use in building the SessionFactory
- metadataSources = prepareMetadataSources( jandexIndex, collectedManagedClassNames, scanResult, bootstrapServiceRegistry );
+ metadataSources = prepareMetadataSources( jandexIndex, deploymentResources, bootstrapServiceRegistry );
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
withValidatorFactory( configurationValues.get( AvailableSettings.VALIDATION_FACTORY ) );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -217,6 +221,122 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
+ private static interface DeploymentResources {
+ public Iterable getClassDescriptors();
+ public Iterable getPackageDescriptors();
+ public Iterable getMappingFileDescriptors();
+ }
+
+ private DeploymentResources buildDeploymentResources(
+ ScanResult scanResult,
+ BootstrapServiceRegistry bootstrapServiceRegistry) {
+
+ // mapping files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ final ArrayList mappingFileDescriptors = new ArrayList();
+
+ final Set nonLocatedMappingFileNames = new HashSet();
+ final List explicitMappingFileNames = persistenceUnit.getMappingFileNames();
+ 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, bootstrapServiceRegistry );
+ mappingFileDescriptors.add( descriptor );
+ }
+
+
+ // classes and packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ final HashMap classDescriptorMap = new HashMap();
+ final HashMap packageDescriptorMap = new HashMap();
+
+ for ( ClassDescriptor classDescriptor : scanResult.getLocatedClasses() ) {
+ classDescriptorMap.put( classDescriptor.getName(), classDescriptor );
+ }
+
+ for ( PackageDescriptor packageDescriptor : scanResult.getLocatedPackages() ) {
+ packageDescriptorMap.put( packageDescriptor.getName(), packageDescriptor );
+ }
+
+ final List explicitClassNames = persistenceUnit.getManagedClassNames();
+ 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 = bootstrapServiceRegistry.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 = bootstrapServiceRegistry.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,
+ persistenceUnit.getName()
+ );
+ }
+ }
+
+ return new DeploymentResources() {
+ @Override
+ public Iterable getClassDescriptors() {
+ return classDescriptorMap.values();
+ }
+
+ @Override
+ public Iterable getPackageDescriptors() {
+ return packageDescriptorMap.values();
+ }
+
+ @Override
+ public Iterable getMappingFileDescriptors() {
+ return mappingFileDescriptors;
+ }
+ };
+ }
+
+ private MappingFileDescriptor buildMappingFileDescriptor(
+ String name,
+ BootstrapServiceRegistry bootstrapServiceRegistry) {
+ final URL url = bootstrapServiceRegistry.getService( ClassLoaderService.class ).locateResource( name );
+ if ( url == null ) {
+ throw persistenceException( "Unable to resolve named mapping-file [" + name + "]" );
+ }
+
+ return new MappingFileDescriptorImpl( name, new UrlInputStreamAccess( url ) );
+ }
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// temporary!
@SuppressWarnings("unchecked")
@@ -233,13 +353,13 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
@SuppressWarnings("unchecked")
private MetadataSources prepareMetadataSources(
IndexView jandexIndex,
- Set collectedManagedClassNames,
- ScanResult scanResult,
+ DeploymentResources deploymentResources,
BootstrapServiceRegistry bootstrapServiceRegistry) {
// todo : this needs to tie into the metamodel branch...
MetadataSources metadataSources = new MetadataSources();
- for ( String className : collectedManagedClassNames ) {
+ for ( ClassDescriptor classDescriptor : deploymentResources.getClassDescriptors() ) {
+ final String className = classDescriptor.getName();
final ClassInfo classInfo = jandexIndex.getClassByName( DotName.createSimple( className ) );
if ( classInfo == null ) {
// Not really sure what this means. Most likely it is explicitly listed in the persistence unit,
@@ -266,15 +386,19 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
- metadataSources.packageNames.addAll( scanResult.getPackageNames() );
+ for ( PackageDescriptor packageDescriptor : deploymentResources.getPackageDescriptors() ) {
+ metadataSources.packageNames.add( packageDescriptor.getName() );
+ }
- metadataSources.namedMappingFileInputStreams.addAll( scanResult.getHbmFiles() );
+ for ( MappingFileDescriptor mappingFileDescriptor : deploymentResources.getMappingFileDescriptors() ) {
+ metadataSources.namedMappingFileInputStreams.add( mappingFileDescriptor.getStreamAccess().asNamedInputStream() );
+ }
- metadataSources.mappingFileResources.addAll( scanResult.getMappingFiles() );
final String explicitHbmXmls = (String) configurationValues.remove( AvailableSettings.HBXML_FILES );
if ( explicitHbmXmls != null ) {
metadataSources.mappingFileResources.addAll( Arrays.asList( StringHelper.split( ", ", explicitHbmXmls ) ) );
}
+
final List explicitOrmXml = (List) configurationValues.remove( AvailableSettings.XML_FILE_NAMES );
if ( explicitOrmXml != null ) {
metadataSources.mappingFileResources.addAll( explicitOrmXml );
@@ -283,41 +407,26 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
return metadataSources;
}
- private Set collectManagedClassNames(ScanResult scanResult) {
- Set collectedNames = new HashSet();
- if ( persistenceUnit.getManagedClassNames() != null ) {
- collectedNames.addAll( persistenceUnit.getManagedClassNames() );
- }
- collectedNames.addAll( scanResult.getManagedClassNames() );
- return collectedNames;
- }
-
- private IndexView locateOrBuildJandexIndex(
- Set collectedManagedClassNames,
- List packageNames,
- BootstrapServiceRegistry bootstrapServiceRegistry) {
+ private IndexView locateOrBuildJandexIndex(DeploymentResources deploymentResources) {
// for now create a whole new Index to work with, eventually we need to:
// 1) accept an Index as an incoming config value
// 2) pass that Index along to the metamodel code...
- //
- // (1) is mocked up here, but JBoss AS does not currently pass in any Index to use...
IndexView jandexIndex = (IndexView) configurationValues.get( JANDEX_INDEX );
if ( jandexIndex == null ) {
- jandexIndex = buildJandexIndex( collectedManagedClassNames, packageNames, bootstrapServiceRegistry );
+ jandexIndex = buildJandexIndex( deploymentResources );
}
return jandexIndex;
}
- private IndexView buildJandexIndex(Set classNamesSource, List packageNames, BootstrapServiceRegistry bootstrapServiceRegistry) {
+ private IndexView buildJandexIndex(DeploymentResources deploymentResources) {
Indexer indexer = new Indexer();
- for ( String className : classNamesSource ) {
- indexResource( className.replace( '.', '/' ) + ".class", indexer, bootstrapServiceRegistry );
+ for ( ClassDescriptor classDescriptor : deploymentResources.getClassDescriptors() ) {
+ indexStream( indexer, classDescriptor.getStreamAccess() );
}
- // add package-info from the configured packages
- for ( String packageName : packageNames ) {
- indexResource( packageName.replace( '.', '/' ) + "/package-info.class", indexer, bootstrapServiceRegistry );
+ for ( PackageDescriptor packageDescriptor : deploymentResources.getPackageDescriptors() ) {
+ indexStream( indexer, packageDescriptor.getStreamAccess() );
}
// for now we just skip entities defined in (1) orm.xml files and (2) hbm.xml files. this part really needs
@@ -325,16 +434,25 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// for now, we also need to wrap this in a CompositeIndex until Jandex is updated to use a common interface
// between the 2...
- return CompositeIndex.create( indexer.complete() );
+ return indexer.complete();
}
- private void indexResource(String resourceName, Indexer indexer, BootstrapServiceRegistry bootstrapServiceRegistry) {
- InputStream stream = bootstrapServiceRegistry.getService( ClassLoaderService.class ).locateResourceStream( resourceName );
+ private void indexStream(Indexer indexer, InputStreamAccess streamAccess) {
try {
- indexer.index( stream );
+ InputStream stream = streamAccess.accessInputStream();
+ try {
+ indexer.index( stream );
+ }
+ finally {
+ try {
+ stream.close();
+ }
+ catch (Exception ignore) {
+ }
+ }
}
catch ( IOException e ) {
- throw persistenceException( "Unable to open input stream for resource " + resourceName, e );
+ throw persistenceException( "Unable to index from stream " + streamAccess.getStreamName(), e );
}
}
@@ -586,37 +704,24 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
@SuppressWarnings("unchecked")
private ScanResult scan(BootstrapServiceRegistry bootstrapServiceRegistry) {
- Scanner scanner = locateOrBuildScanner( bootstrapServiceRegistry );
- ScanningContext scanningContext = new ScanningContext();
+ final Scanner scanner = locateOrBuildScanner( bootstrapServiceRegistry );
+ final ScanOptions scanOptions = determineScanOptions();
- final ScanResult scanResult = new ScanResult();
- if ( persistenceUnit.getMappingFileNames() != null ) {
- scanResult.getMappingFiles().addAll( persistenceUnit.getMappingFileNames() );
- }
+ return scanner.scan( persistenceUnit, scanOptions );
+ }
- // dunno, but the old code did it...
- scanningContext.setSearchOrm( ! scanResult.getMappingFiles().contains( META_INF_ORM_XML ) );
-
- if ( persistenceUnit.getJarFileUrls() != null ) {
- prepareAutoDetectionSettings( scanningContext, false );
- for ( URL jar : persistenceUnit.getJarFileUrls() ) {
- scanningContext.setUrl( jar );
- scanInContext( scanner, scanningContext, scanResult );
- }
- }
-
- prepareAutoDetectionSettings( scanningContext, persistenceUnit.isExcludeUnlistedClasses() );
- scanningContext.setUrl( persistenceUnit.getPersistenceUnitRootUrl() );
- scanInContext( scanner, scanningContext, scanResult );
-
- return scanResult;
+ private ScanOptions determineScanOptions() {
+ return new StandardScanOptions(
+ (String) configurationValues.get( AvailableSettings.AUTODETECTION ),
+ persistenceUnit.isExcludeUnlistedClasses()
+ );
}
@SuppressWarnings("unchecked")
private Scanner locateOrBuildScanner(BootstrapServiceRegistry bootstrapServiceRegistry) {
final Object value = configurationValues.remove( AvailableSettings.SCANNER );
if ( value == null ) {
- return new NativeScanner();
+ return new StandardScanner();
}
if ( Scanner.class.isInstance( value ) ) {
@@ -650,91 +755,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
- private void prepareAutoDetectionSettings(ScanningContext context, boolean excludeUnlistedClasses) {
- final String detectionSetting = (String) configurationValues.get( AvailableSettings.AUTODETECTION );
-
- if ( detectionSetting == null ) {
- if ( excludeUnlistedClasses ) {
- context.setDetectClasses( false );
- context.setDetectHbmFiles( false );
- }
- else {
- context.setDetectClasses( true );
- context.setDetectHbmFiles( true );
- }
- }
- else {
- for ( String token : StringHelper.split( ", ", detectionSetting ) ) {
- if ( "class".equalsIgnoreCase( token ) ) {
- context.setDetectClasses( true );
- }
- if ( "hbm".equalsIgnoreCase( token ) ) {
- context.setDetectClasses( true );
- }
- }
- }
- }
-
- private void scanInContext(
- Scanner scanner,
- ScanningContext scanningContext,
- ScanResult scanResult) {
- if ( scanningContext.getUrl() == null ) {
- // not sure i like just ignoring this being null, but this is exactly what the old code does...
- LOG.containerProvidingNullPersistenceUnitRootUrl();
- return;
- }
- if ( scanningContext.getUrl().getProtocol().equalsIgnoreCase( "bundle" ) ) {
- // TODO: Is there a way to scan the root bundle URL in OSGi containers?
- // Although the URL provides a stream handler that works for finding
- // resources in a specific Bundle, the root one does not work.
- return;
- }
-
- try {
- if ( scanningContext.isDetectClasses() ) {
- Set matchingPackages = scanner.getPackagesInJar( scanningContext.url, new HashSet>(0) );
- for ( Package pkg : matchingPackages ) {
- scanResult.getPackageNames().add( pkg.getName() );
- }
-
- Set> annotationsToLookFor = new HashSet>();
- annotationsToLookFor.add( Entity.class );
- annotationsToLookFor.add( MappedSuperclass.class );
- annotationsToLookFor.add( Embeddable.class );
- annotationsToLookFor.add( Converter.class );
- Set> matchingClasses = scanner.getClassesInJar( scanningContext.url, annotationsToLookFor );
- for ( Class> clazz : matchingClasses ) {
- scanResult.getManagedClassNames().add( clazz.getName() );
- }
- }
-
- Set patterns = new HashSet();
- if ( scanningContext.isSearchOrm() ) {
- patterns.add( META_INF_ORM_XML );
- }
- if ( scanningContext.isDetectHbmFiles() ) {
- patterns.add( "**/*.hbm.xml" );
- }
- if ( ! scanResult.getMappingFiles().isEmpty() ) {
- patterns.addAll( scanResult.getMappingFiles() );
- }
- if ( patterns.size() != 0 ) {
- Set files = scanner.getFilesInJar( scanningContext.getUrl(), patterns );
- for ( NamedInputStream file : files ) {
- scanResult.getHbmFiles().add( file );
- scanResult.getMappingFiles().remove( file.getName() );
- }
- }
- }
- catch (PersistenceException e ) {
- throw e;
- }
- catch ( RuntimeException e ) {
- throw persistenceException( "error trying to scan url: " + scanningContext.getUrl().toString(), e );
- }
- }
-
@Override
public EntityManagerFactoryBuilder withValidatorFactory(Object validatorFactory) {
this.validatorFactory = validatorFactory;
@@ -1094,14 +1114,28 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
//addInputStream has the responsibility to close the stream
cfg.addInputStream( new BufferedInputStream( namedInputStream.getStream() ) );
}
- catch (MappingException me) {
- //try our best to give the file name
- if ( StringHelper.isEmpty( namedInputStream.getName() ) ) {
- throw me;
+ catch ( InvalidMappingException e ) {
+ // try our best to give the file name
+ if ( StringHelper.isNotEmpty( namedInputStream.getName() ) ) {
+ throw new InvalidMappingException(
+ "Error while parsing file: " + namedInputStream.getName(),
+ e.getType(),
+ e.getPath(),
+ e
+ );
}
else {
+ throw e;
+ }
+ }
+ catch (MappingException me) {
+ // try our best to give the file name
+ if ( StringHelper.isNotEmpty( namedInputStream.getName() ) ) {
throw new MappingException("Error while parsing file: " + namedInputStream.getName(), me );
}
+ else {
+ throw me;
+ }
}
}
for ( String packageName : metadataSources.packageNames ) {
@@ -1176,68 +1210,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
- public static class ScanningContext {
- private URL url;
- private boolean detectClasses;
- private boolean detectHbmFiles;
- private boolean searchOrm;
-
- public URL getUrl() {
- return url;
- }
-
- public void setUrl(URL url) {
- this.url = url;
- }
-
- public boolean isDetectClasses() {
- return detectClasses;
- }
-
- public void setDetectClasses(boolean detectClasses) {
- this.detectClasses = detectClasses;
- }
-
- public boolean isDetectHbmFiles() {
- return detectHbmFiles;
- }
-
- public void setDetectHbmFiles(boolean detectHbmFiles) {
- this.detectHbmFiles = detectHbmFiles;
- }
-
- public boolean isSearchOrm() {
- return searchOrm;
- }
-
- public void setSearchOrm(boolean searchOrm) {
- this.searchOrm = searchOrm;
- }
- }
-
- private static class ScanResult {
- private final List managedClassNames = new ArrayList();
- private final List packageNames = new ArrayList();
- private final List hbmFiles = new ArrayList();
- private final List mappingFiles = new ArrayList();
-
- public List getManagedClassNames() {
- return managedClassNames;
- }
-
- public List getPackageNames() {
- return packageNames;
- }
-
- public List getHbmFiles() {
- return hbmFiles;
- }
-
- public List getMappingFiles() {
- return mappingFiles;
- }
- }
-
public static class MetadataSources {
private final List annotatedMappingClassNames = new ArrayList();
private final List converterDescriptors = new ArrayList();
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/FileInputStreamAccess.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/FileInputStreamAccess.java
new file mode 100644
index 0000000000..7d9294364a
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/FileInputStreamAccess.java
@@ -0,0 +1,77 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.internal;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import org.hibernate.HibernateException;
+import org.hibernate.jpa.boot.archive.spi.ArchiveException;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.boot.spi.NamedInputStream;
+
+/**
+ * An InputStreamAccess implementation based on a File reference
+ *
+ * @author Steve Ebersole
+ */
+public class FileInputStreamAccess implements InputStreamAccess {
+ private final String name;
+ private final File file;
+
+ public FileInputStreamAccess(String name, File file) {
+ this.name = name;
+ this.file = file;
+ if ( ! file.exists() ) {
+ throw new HibernateException( "File must exist : " + file.getAbsolutePath() );
+ }
+ }
+
+ @Override
+ public String getStreamName() {
+ return name;
+ }
+
+ @Override
+ public InputStream accessInputStream() {
+ try {
+ return new BufferedInputStream( new FileInputStream( file ) );
+ }
+ catch (FileNotFoundException e) {
+ // should never ever ever happen, but...
+ throw new ArchiveException(
+ "File believed to exist based on File.exists threw error when passed to FileInputStream ctor",
+ e
+ );
+ }
+ }
+
+ @Override
+ public NamedInputStream asNamedInputStream() {
+ return new NamedInputStream( getStreamName(), accessInputStream() );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/MappingFileDescriptorImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/MappingFileDescriptorImpl.java
new file mode 100644
index 0000000000..1a073c4002
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/MappingFileDescriptorImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.internal;
+
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+
+/**
+ * @author Steve Ebersole
+ */
+public class MappingFileDescriptorImpl implements MappingFileDescriptor {
+ private final String name;
+ private final InputStreamAccess streamAccess;
+
+ public MappingFileDescriptorImpl(String name, InputStreamAccess streamAccess) {
+ this.name = name;
+ this.streamAccess = streamAccess;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return streamAccess;
+ }
+
+// @Override
+// public boolean equals(Object o) {
+// if ( this == o ) {
+// return true;
+// }
+// if ( o == null || getClass() != o.getClass() ) {
+// return false;
+// }
+//
+// MappingFileDescriptorImpl that = (MappingFileDescriptorImpl) o;
+//
+// return name.equals( that.name )
+// && streamAccess.getStreamName().equals( that.streamAccess.getStreamName() );
+//
+// }
+//
+// @Override
+// public int hashCode() {
+// int result = name.hashCode();
+// result = 31 * result + streamAccess.getStreamName().hashCode();
+// return result;
+// }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PackageDescriptorImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PackageDescriptorImpl.java
new file mode 100644
index 0000000000..c40eb48786
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PackageDescriptorImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.internal;
+
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.boot.spi.PackageDescriptor;
+
+/**
+ * @author Steve Ebersole
+ */
+public class PackageDescriptorImpl implements PackageDescriptor {
+ private final String name;
+ private final InputStreamAccess streamAccess;
+
+ public PackageDescriptorImpl(String name, InputStreamAccess streamAccess) {
+ this.name = name;
+ this.streamAccess = streamAccess;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public InputStreamAccess getStreamAccess() {
+ return streamAccess;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ PackageDescriptorImpl that = (PackageDescriptorImpl) o;
+ return name.equals( that.name );
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java
index 311cc38079..e079c99c8c 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java
@@ -54,8 +54,8 @@ import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.hibernate.jpa.AvailableSettings;
+import org.hibernate.jpa.boot.archive.internal.ArchiveHelper;
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
-import org.hibernate.jpa.packaging.internal.JarVisitorFactory;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.source.XsdException;
@@ -121,7 +121,7 @@ public class PersistenceXmlParser {
final Element element = (Element) children.item( i );
final String tag = element.getTagName();
if ( tag.equals( "persistence-unit" ) ) {
- final URL puRootUrl = JarVisitorFactory.getJarURLFromURLEntry( xmlUrl, "/META-INF/persistence.xml" );
+ final URL puRootUrl = ArchiveHelper.getJarURLFromURLEntry( xmlUrl, "/META-INF/persistence.xml" );
ParsedPersistenceXmlDescriptor persistenceUnit = new ParsedPersistenceXmlDescriptor( puRootUrl );
bindPersistenceUnit( persistenceUnit, element );
@@ -214,7 +214,7 @@ public class PersistenceXmlParser {
persistenceUnit.addMappingFiles( extractContent( element ) );
}
else if ( tag.equals( "jar-file" ) ) {
- persistenceUnit.addJarFileUrl( JarVisitorFactory.getURLFromPath( extractContent( element ) ) );
+ persistenceUnit.addJarFileUrl( ArchiveHelper.getURLFromPath( extractContent( element ) ) );
}
else if ( tag.equals( "exclude-unlisted-classes" ) ) {
persistenceUnit.setExcludeUnlistedClasses( true );
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/UrlInputStreamAccess.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/UrlInputStreamAccess.java
new file mode 100644
index 0000000000..4281201381
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/UrlInputStreamAccess.java
@@ -0,0 +1,62 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.internal;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import org.hibernate.HibernateException;
+import org.hibernate.jpa.boot.spi.InputStreamAccess;
+import org.hibernate.jpa.boot.spi.NamedInputStream;
+
+/**
+ * @author Steve Ebersole
+ */
+public class UrlInputStreamAccess implements InputStreamAccess {
+ private final URL url;
+
+ public UrlInputStreamAccess(URL url) {
+ this.url = url;
+ }
+
+ @Override
+ public String getStreamName() {
+ return url.toExternalForm();
+ }
+
+ @Override
+ public InputStream accessInputStream() {
+ try {
+ return url.openStream();
+ }
+ catch (Exception e) {
+ throw new HibernateException( "Could not open url stream : " + url.toExternalForm() );
+ }
+ }
+
+ @Override
+ public NamedInputStream asNamedInputStream() {
+ return new NamedInputStream( getStreamName(), accessInputStream() );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/internal/StandardScanOptions.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/internal/StandardScanOptions.java
new file mode 100644
index 0000000000..e2dcf9e154
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/internal/StandardScanOptions.java
@@ -0,0 +1,67 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.internal;
+
+import org.hibernate.jpa.boot.scan.spi.ScanOptions;
+
+/**
+ * @author Steve Ebersole
+ */
+public class StandardScanOptions implements ScanOptions {
+ private final boolean detectClassesInRoot;
+ private final boolean detectClassesInNonRoot;
+ private final boolean detectHibernateMappingFiles;
+
+ public StandardScanOptions() {
+ this( "hbm,class", false );
+ }
+
+ public StandardScanOptions(String explicitDetectionSetting, boolean persistenceUnitExcludeUnlistedClassesValue) {
+ if ( explicitDetectionSetting == null ) {
+ detectHibernateMappingFiles = true;
+ detectClassesInRoot = ! persistenceUnitExcludeUnlistedClassesValue;
+ detectClassesInNonRoot = true;
+ }
+ else {
+ detectHibernateMappingFiles = explicitDetectionSetting.contains( "hbm" );
+ detectClassesInRoot = explicitDetectionSetting.contains( "class" );
+ detectClassesInNonRoot = detectClassesInRoot;
+ }
+ }
+
+ @Override
+ public boolean canDetectUnlistedClassesInRoot() {
+ return detectClassesInRoot;
+ }
+
+ @Override
+ public boolean canDetectUnlistedClassesInNonRoot() {
+ return detectClassesInNonRoot;
+ }
+
+ @Override
+ public boolean canDetectHibernateMappingFiles() {
+ return detectHibernateMappingFiles;
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/internal/StandardScanner.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/internal/StandardScanner.java
new file mode 100644
index 0000000000..6db4050a0e
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/internal/StandardScanner.java
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.internal;
+
+import org.hibernate.jpa.boot.archive.internal.StandardArchiveDescriptorFactory;
+import org.hibernate.jpa.boot.scan.spi.AbstractScannerImpl;
+
+/**
+ * Standard implementation of the Scanner contract, supporting typical archive walking support where
+ * the urls we are processing can be treated using normal file handling.
+ *
+ * @author Steve Ebersole
+ * @author Emmanuel Bernard
+ */
+public class StandardScanner extends AbstractScannerImpl {
+ public StandardScanner() {
+ super( StandardArchiveDescriptorFactory.INSTANCE );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/AbstractScannerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/AbstractScannerImpl.java
new file mode 100644
index 0000000000..da5af94f25
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/AbstractScannerImpl.java
@@ -0,0 +1,302 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.spi;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
+import org.hibernate.jpa.boot.internal.ClassDescriptorImpl;
+import org.hibernate.jpa.boot.internal.MappingFileDescriptorImpl;
+import org.hibernate.jpa.boot.internal.PackageDescriptorImpl;
+import org.hibernate.jpa.boot.spi.ClassDescriptor;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+import org.hibernate.jpa.boot.spi.PackageDescriptor;
+import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
+
+/**
+ * @author Steve Ebersole
+ */
+public abstract class AbstractScannerImpl implements Scanner {
+ private final ArchiveDescriptorFactory archiveDescriptorFactory;
+ private final Map archiveDescriptorCache = new HashMap();
+
+ protected AbstractScannerImpl(ArchiveDescriptorFactory archiveDescriptorFactory) {
+ this.archiveDescriptorFactory = archiveDescriptorFactory;
+ }
+
+ @Override
+ public ScanResult scan(PersistenceUnitDescriptor persistenceUnit, ScanOptions scanOptions) {
+ final ResultCollector resultCollector = new ResultCollector( scanOptions );
+
+ if ( persistenceUnit.getJarFileUrls() != null ) {
+ for ( URL url : persistenceUnit.getJarFileUrls() ) {
+ final ArchiveDescriptor descriptor = buildArchiveDescriptor( url, false, scanOptions );
+ final ArchiveContext context = buildArchiveContext( persistenceUnit, false, resultCollector );
+ descriptor.visitArchive( context );
+ }
+ }
+
+ if ( persistenceUnit.getPersistenceUnitRootUrl() != null ) {
+ final ArchiveDescriptor descriptor = buildArchiveDescriptor( persistenceUnit.getPersistenceUnitRootUrl(), true, scanOptions );
+ final ArchiveContext context = buildArchiveContext( persistenceUnit, false, resultCollector );
+ descriptor.visitArchive( context );
+ }
+
+ return ScanResultImpl.from( resultCollector );
+ }
+
+ private ArchiveContext buildArchiveContext(
+ PersistenceUnitDescriptor persistenceUnit,
+ boolean isRoot,
+ ArchiveEntryHandlers entryHandlers) {
+ return new ArchiveContextImpl( persistenceUnit, isRoot, entryHandlers );
+ }
+
+ protected static interface ArchiveEntryHandlers {
+ public ArchiveEntryHandler getClassFileHandler();
+ public ArchiveEntryHandler getPackageInfoHandler();
+ public ArchiveEntryHandler getFileHandler();
+ }
+
+ private ArchiveDescriptor buildArchiveDescriptor(URL url, boolean isRootUrl, ScanOptions scanOptions) {
+ final ArchiveDescriptor descriptor;
+ final ArchiveDescriptorInfo descriptorInfo = archiveDescriptorCache.get( url );
+ if ( descriptorInfo == null ) {
+ descriptor = archiveDescriptorFactory.buildArchiveDescriptor( url );
+ archiveDescriptorCache.put(
+ url,
+ new ArchiveDescriptorInfo( descriptor, isRootUrl, scanOptions )
+ );
+ }
+ else {
+ validateReuse( descriptorInfo, isRootUrl, scanOptions );
+ descriptor = descriptorInfo.archiveDescriptor;
+ }
+ return descriptor;
+ }
+
+ public static class ResultCollector
+ implements ArchiveEntryHandlers,
+ PackageInfoArchiveEntryHandler.Callback,
+ ClassFileArchiveEntryHandler.Callback,
+ NonClassFileArchiveEntryHandler.Callback {
+ private final ClassFileArchiveEntryHandler classFileHandler;
+ private final PackageInfoArchiveEntryHandler packageInfoHandler;
+ private final NonClassFileArchiveEntryHandler fileHandler;
+
+ private final Set packageDescriptorSet = new HashSet();
+ private final Set classDescriptorSet = new HashSet();
+ private final Set mappingFileSet = new HashSet();
+
+ public ResultCollector(ScanOptions scanOptions) {
+ this.classFileHandler = new ClassFileArchiveEntryHandler( scanOptions, this );
+ this.packageInfoHandler = new PackageInfoArchiveEntryHandler( scanOptions, this );
+ this.fileHandler = new NonClassFileArchiveEntryHandler( scanOptions, this );
+ }
+
+ @Override
+ public ArchiveEntryHandler getClassFileHandler() {
+ return classFileHandler;
+ }
+
+ @Override
+ public ArchiveEntryHandler getPackageInfoHandler() {
+ return packageInfoHandler;
+ }
+
+ @Override
+ public ArchiveEntryHandler getFileHandler() {
+ return fileHandler;
+ }
+
+ @Override
+ public void locatedPackage(PackageDescriptor packageDescriptor) {
+ if ( PackageDescriptorImpl.class.isInstance( packageDescriptor ) ) {
+ packageDescriptorSet.add( packageDescriptor );
+ }
+ else {
+ // to make sure we have proper equals/hashcode
+ packageDescriptorSet.add(
+ new PackageDescriptorImpl(
+ packageDescriptor.getName(),
+ packageDescriptor.getStreamAccess()
+ )
+ );
+ }
+ }
+
+ @Override
+ public void locatedClass(ClassDescriptor classDescriptor) {
+ if ( ClassDescriptorImpl.class.isInstance( classDescriptor ) ) {
+ classDescriptorSet.add( classDescriptor );
+ }
+ else {
+ // to make sure we have proper equals/hashcode
+ classDescriptorSet.add(
+ new ClassDescriptorImpl(
+ classDescriptor.getName(),
+ classDescriptor.getStreamAccess()
+ )
+ );
+ }
+ }
+
+ @Override
+ public void locatedMappingFile(MappingFileDescriptor mappingFileDescriptor) {
+ if ( MappingFileDescriptorImpl.class.isInstance( mappingFileDescriptor ) ) {
+ mappingFileSet.add( mappingFileDescriptor );
+ }
+ else {
+ // to make sure we have proper equals/hashcode
+ mappingFileSet.add(
+ new MappingFileDescriptorImpl(
+ mappingFileDescriptor.getName(),
+ mappingFileDescriptor.getStreamAccess()
+ )
+ );
+ }
+ }
+
+ public Set getPackageDescriptorSet() {
+ return packageDescriptorSet;
+ }
+
+ public Set getClassDescriptorSet() {
+ return classDescriptorSet;
+ }
+
+ public Set getMappingFileSet() {
+ return mappingFileSet;
+ }
+ }
+
+ private static class ArchiveDescriptorInfo {
+ private final ArchiveDescriptor archiveDescriptor;
+ private final boolean isRoot;
+ private final ScanOptions scanOptions;
+
+ private ArchiveDescriptorInfo(
+ ArchiveDescriptor archiveDescriptor,
+ boolean isRoot,
+ ScanOptions scanOptions) {
+ this.archiveDescriptor = archiveDescriptor;
+ this.isRoot = isRoot;
+ this.scanOptions = scanOptions;
+ }
+ }
+
+ protected void validateReuse(ArchiveDescriptorInfo descriptor, boolean root, ScanOptions options) {
+ // is it really reasonable that a single url be processed multiple times?
+ // for now, throw an exception, mainly because I am interested in situations where this might happen
+ throw new IllegalStateException( "ArchiveDescriptor reused; can URLs be processed multiple times?" );
+ }
+
+ public static class ArchiveContextImpl implements ArchiveContext {
+ private final PersistenceUnitDescriptor persistenceUnitDescriptor;
+ private final boolean isRootUrl;
+ private final ArchiveEntryHandlers entryHandlers;
+
+ public ArchiveContextImpl(
+ PersistenceUnitDescriptor persistenceUnitDescriptor,
+ boolean isRootUrl,
+ ArchiveEntryHandlers entryHandlers) {
+ this.persistenceUnitDescriptor = persistenceUnitDescriptor;
+ this.isRootUrl = isRootUrl;
+ this.entryHandlers = entryHandlers;
+ }
+
+ @Override
+ public PersistenceUnitDescriptor getPersistenceUnitDescriptor() {
+ return persistenceUnitDescriptor;
+ }
+
+ @Override
+ public boolean isRootUrl() {
+ return isRootUrl;
+ }
+
+ @Override
+ public ArchiveEntryHandler obtainArchiveEntryHandler(ArchiveEntry entry) {
+ final String nameWithinArchive = entry.getNameWithinArchive();
+
+ if ( nameWithinArchive.endsWith( "package-info.class" ) ) {
+ return entryHandlers.getPackageInfoHandler();
+ }
+ else if ( nameWithinArchive.endsWith( ".class" ) ) {
+ return entryHandlers.getClassFileHandler();
+ }
+ else {
+ return entryHandlers.getFileHandler();
+ }
+ }
+ }
+
+ private static class ScanResultImpl implements ScanResult {
+ private final Set packageDescriptorSet;
+ private final Set classDescriptorSet;
+ private final Set mappingFileSet;
+
+ private ScanResultImpl(
+ Set packageDescriptorSet,
+ Set classDescriptorSet,
+ Set mappingFileSet) {
+ this.packageDescriptorSet = packageDescriptorSet;
+ this.classDescriptorSet = classDescriptorSet;
+ this.mappingFileSet = mappingFileSet;
+ }
+
+ private static ScanResult from(ResultCollector resultCollector) {
+ return new ScanResultImpl(
+ Collections.unmodifiableSet( resultCollector.packageDescriptorSet ),
+ Collections.unmodifiableSet( resultCollector.classDescriptorSet ),
+ Collections.unmodifiableSet( resultCollector.mappingFileSet )
+ );
+ }
+
+ @Override
+ public Set getLocatedPackages() {
+ return packageDescriptorSet;
+ }
+
+ @Override
+ public Set getLocatedClasses() {
+ return classDescriptorSet;
+ }
+
+ @Override
+ public Set getLocatedMappingFiles() {
+ return mappingFileSet;
+ }
+ }
+
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java
new file mode 100644
index 0000000000..0bfcad0fc4
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java
@@ -0,0 +1,132 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.spi;
+
+import javax.persistence.Converter;
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.ClassFile;
+
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
+import org.hibernate.jpa.boot.archive.spi.ArchiveException;
+import org.hibernate.jpa.boot.internal.ClassDescriptorImpl;
+import org.hibernate.jpa.boot.scan.spi.ScanOptions;
+import org.hibernate.jpa.boot.spi.ClassDescriptor;
+
+/**
+* @author Steve Ebersole
+*/
+public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
+ private final ScanOptions scanOptions;
+ private final Callback callback;
+
+ public static interface Callback {
+ public void locatedClass(ClassDescriptor classDescriptor);
+ }
+
+ public ClassFileArchiveEntryHandler(ScanOptions scanOptions, Callback callback) {
+ this.scanOptions = scanOptions;
+ this.callback = callback;
+ }
+
+ @Override
+ public void handleEntry(ArchiveEntry entry, ArchiveContext context) {
+ final ClassFile classFile = toClassFile( entry );
+ final ClassDescriptor classDescriptor = toClassDescriptor( classFile, entry );
+
+ if ( ! context.getPersistenceUnitDescriptor().getManagedClassNames().contains( classDescriptor.getName() ) ) {
+ if ( context.isRootUrl() ) {
+ if ( ! scanOptions.canDetectUnlistedClassesInRoot() ) {
+ return;
+ }
+ }
+ else {
+ if ( ! scanOptions.canDetectUnlistedClassesInNonRoot() ) {
+ return;
+ }
+ }
+ }
+
+ // we are only interested in classes with certain annotations, so see if the ClassDescriptor
+ // represents a class which contains any of those annotations
+ if ( ! containsClassAnnotationsOfInterest( classFile ) ) {
+ return;
+ }
+
+ notifyMatchedClass( classDescriptor );
+ }
+
+ private ClassFile toClassFile(ArchiveEntry entry) {
+ final InputStream inputStream = entry.getStreamAccess().accessInputStream();
+ final DataInputStream dataInputStream = new DataInputStream( inputStream );
+ try {
+ return new ClassFile( dataInputStream );
+ }
+ catch (IOException e) {
+ throw new ArchiveException( "Could not build ClassFile" );
+ }
+ finally {
+ try {
+ dataInputStream.close();
+ }
+ catch (Exception ignore) {
+ }
+
+ try {
+ inputStream.close();
+ }
+ catch (IOException ignore) {
+ }
+ }
+ }
+
+ @SuppressWarnings("SimplifiableIfStatement")
+ private boolean containsClassAnnotationsOfInterest(ClassFile cf) {
+ final AnnotationsAttribute visibleAnnotations = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
+ if ( visibleAnnotations == null ) {
+ return false;
+ }
+
+ 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;
+ }
+
+ protected ClassDescriptor toClassDescriptor(ClassFile classFile, ArchiveEntry entry) {
+ return new ClassDescriptorImpl( classFile.getName(), entry.getStreamAccess() );
+ }
+
+ protected final void notifyMatchedClass(ClassDescriptor classDescriptor) {
+ callback.locatedClass( classDescriptor );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java
new file mode 100644
index 0000000000..a3aa33a437
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java
@@ -0,0 +1,82 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.spi;
+
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
+import org.hibernate.jpa.boot.internal.MappingFileDescriptorImpl;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+
+/**
+* @author Steve Ebersole
+*/
+public class NonClassFileArchiveEntryHandler implements ArchiveEntryHandler {
+ private final ScanOptions scanOptions;
+ private final Callback callback;
+
+ public static interface Callback {
+ public void locatedMappingFile(MappingFileDescriptor mappingFileDescriptor);
+ }
+
+ public NonClassFileArchiveEntryHandler(ScanOptions scanOptions, Callback callback) {
+ this.scanOptions = scanOptions;
+ this.callback = callback;
+ }
+
+ @Override
+ public void handleEntry(ArchiveEntry entry, ArchiveContext context) {
+ if ( acceptAsMappingFile( entry, context) ) {
+ notifyMatchedMappingFile( entry );
+ }
+ }
+
+ @SuppressWarnings("SimplifiableIfStatement")
+ private boolean acceptAsMappingFile(ArchiveEntry entry, ArchiveContext context) {
+ if ( entry.getName().endsWith( "hbm.xml" ) ) {
+ return scanOptions.canDetectHibernateMappingFiles();
+ }
+
+ // todo : should really do this case-insensitively
+ if ( entry.getName().endsWith( "META-INF/orm.xml" ) ) {
+ if ( context.getPersistenceUnitDescriptor().getMappingFileNames().contains( "META-INF/orm.xml" ) ) {
+ // if the user explicitly listed META-INF/orm.xml, only except the root one
+ //
+ // not sure why exactly, but this is what the old code does
+ return context.isRootUrl();
+ }
+ return true;
+ }
+
+ return context.getPersistenceUnitDescriptor().getMappingFileNames().contains( entry.getNameWithinArchive() );
+ }
+
+ protected final void notifyMatchedMappingFile(ArchiveEntry entry) {
+ callback.locatedMappingFile( toMappingFileDescriptor( entry ) );
+ }
+
+ protected MappingFileDescriptor toMappingFileDescriptor(ArchiveEntry entry) {
+ return new MappingFileDescriptorImpl( entry.getNameWithinArchive(), entry.getStreamAccess() );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/PackageInfoArchiveEntryHandler.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/PackageInfoArchiveEntryHandler.java
new file mode 100644
index 0000000000..bacd9d3f1b
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/PackageInfoArchiveEntryHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.spi;
+
+import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
+import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
+import org.hibernate.jpa.boot.internal.PackageDescriptorImpl;
+import org.hibernate.jpa.boot.spi.PackageDescriptor;
+
+import static java.io.File.separatorChar;
+
+/**
+ * @author Steve Ebersole
+ */
+public class PackageInfoArchiveEntryHandler implements ArchiveEntryHandler {
+ @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+ private final ScanOptions scanOptions;
+ private final Callback callback;
+
+ public static interface Callback {
+ public void locatedPackage(PackageDescriptor packageDescriptor);
+ }
+
+ public PackageInfoArchiveEntryHandler(ScanOptions scanOptions, Callback callback) {
+ this.scanOptions = scanOptions;
+ this.callback = callback;
+ }
+
+ @Override
+ public void handleEntry(ArchiveEntry entry, ArchiveContext context) {
+ if ( entry.getNameWithinArchive().equals( "package-info.class" ) ) {
+ // the old code skipped package-info in the root package/dir...
+ return;
+ }
+ notifyMatchedPackage( toPackageDescriptor( entry ) );
+ }
+
+ protected PackageDescriptor toPackageDescriptor(ArchiveEntry entry) {
+ final String packageInfoFilePath = entry.getNameWithinArchive();
+ final String packageName = packageInfoFilePath.substring( 0, packageInfoFilePath.lastIndexOf( '/' ) )
+ .replace( separatorChar, '.' );
+
+ return new PackageDescriptorImpl( packageName, entry.getStreamAccess() );
+ }
+
+ protected final void notifyMatchedPackage(PackageDescriptor packageDescriptor) {
+ callback.locatedPackage( packageDescriptor );
+ }
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/PackageFilter.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ScanOptions.java
similarity index 63%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/PackageFilter.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ScanOptions.java
index d8ded44656..a5ec564a8d 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/PackageFilter.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ScanOptions.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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.
+ * distributed under license by Red Hat Inc.
*
* 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
@@ -19,20 +21,14 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.internal;
-
+package org.hibernate.jpa.boot.scan.spi;
/**
- * Filter on pachage element
- *
- * @author Emmanuel Bernard
- * @see JavaElementFilter
+ * @author Steve Ebersole
*/
-public abstract class PackageFilter extends JavaElementFilter {
- /**
- * @see JavaElementFilter#JavaElementFilter(boolean, Class[])
- */
- protected PackageFilter(boolean retrieveStream, Class[] annotations) {
- super( retrieveStream, annotations );
- }
-}
\ No newline at end of file
+public interface ScanOptions {
+ public boolean canDetectUnlistedClassesInRoot();
+ public boolean canDetectUnlistedClassesInNonRoot();
+
+ public boolean canDetectHibernateMappingFiles();
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ScanResult.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ScanResult.java
new file mode 100644
index 0000000000..13e0fa02f9
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ScanResult.java
@@ -0,0 +1,41 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.spi;
+
+import java.util.Set;
+
+import org.hibernate.jpa.boot.spi.ClassDescriptor;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+import org.hibernate.jpa.boot.spi.PackageDescriptor;
+
+/**
+ * Defines the result of scanning
+ *
+ * @author Steve Ebersole
+ */
+public interface ScanResult {
+ public Set getLocatedPackages();
+ public Set getLocatedClasses();
+ public Set getLocatedMappingFiles();
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/Scanner.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/Scanner.java
new file mode 100644
index 0000000000..d57b54cb76
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/Scanner.java
@@ -0,0 +1,46 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.scan.spi;
+
+import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
+
+/**
+ * Defines the contract for Hibernate to be able to scan for classes, packages and resources inside a
+ * persistence unit.
+ *
+ * @author Emmanuel Bernard
+ * @author Steve Ebersole
+ */
+public interface Scanner {
+ /**
+ * Perform the scanning against the described persistence unit using the defined options, and return the scan
+ * results.
+ *
+ * @param persistenceUnit THe description of the persistence unit.
+ * @param options The scan options
+ *
+ * @return The scan results.
+ */
+ public ScanResult scan(PersistenceUnitDescriptor persistenceUnit, ScanOptions options);
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/ClassDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/ClassDescriptor.java
new file mode 100644
index 0000000000..c04e57d9c0
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/ClassDescriptor.java
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.spi;
+
+/**
+ * Defines the result of scanning a persistence unit for classes.
+ *
+ * @author Steve Ebersole
+ */
+public interface ClassDescriptor {
+ public String getName();
+ public InputStreamAccess getStreamAccess();
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/InputStreamAccess.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/InputStreamAccess.java
new file mode 100644
index 0000000000..cb51b1ada5
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/InputStreamAccess.java
@@ -0,0 +1,52 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.spi;
+
+import java.io.InputStream;
+
+/**
+ * Contract for building InputStreams, especially in on-demand situations
+ *
+ * @author Steve Ebersole
+ */
+public interface InputStreamAccess {
+ /**
+ * Get the name of the resource backing the stream
+ *
+ * @return The backing resource name
+ */
+ public String getStreamName();
+
+ /**
+ * Get access to the stream. Can be called multiple times, a different stream instance should be returned each time.
+ *
+ * @return The stream
+ */
+ public InputStream accessInputStream();
+
+ /**
+ * @deprecated Needed until we can remove NamedInputStream
+ */
+ public NamedInputStream asNamedInputStream();
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/MappingFileDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/MappingFileDescriptor.java
new file mode 100644
index 0000000000..5dfec7b9cb
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/MappingFileDescriptor.java
@@ -0,0 +1,32 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.spi;
+
+/**
+ * @author Steve Ebersole
+ */
+public interface MappingFileDescriptor {
+ public String getName();
+ public InputStreamAccess getStreamAccess();
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/spi/NamedInputStream.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/NamedInputStream.java
similarity index 80%
rename from hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/spi/NamedInputStream.java
rename to hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/NamedInputStream.java
index b0dfe020ac..fd6abed28f 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/spi/NamedInputStream.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/NamedInputStream.java
@@ -21,34 +21,33 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.jpa.packaging.spi;
+package org.hibernate.jpa.boot.spi;
+
import java.io.InputStream;
/**
+ * Bundles together a stream and the name that was used to locate it. The name is often useful for logging.
+ *
+ * @deprecated Use {@link org.hibernate.jpa.boot.spi.InputStreamAccess} instead.
+ *
* @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
+@Deprecated
public class NamedInputStream {
+ private final String name;
+ private final InputStream stream;
+
public NamedInputStream(String name, InputStream stream) {
this.name = name;
this.stream = stream;
}
- private String name;
- private InputStream stream;
-
public InputStream getStream() {
return stream;
}
- public void setStream(InputStream stream) {
- this.stream = stream;
- }
-
public String getName() {
return name;
}
-
- public void setName(String name) {
- this.name = name;
- }
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/PackageDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/PackageDescriptor.java
new file mode 100644
index 0000000000..101e516575
--- /dev/null
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/PackageDescriptor.java
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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.jpa.boot.spi;
+
+/**
+ * Defines the result of scanning a persistence unit for packages.
+ *
+ * @author Steve Ebersole
+ */
+public interface PackageDescriptor {
+ public String getName();
+ public InputStreamAccess getStreamAccess();
+}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/AbstractJarVisitor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/AbstractJarVisitor.java
deleted file mode 100644
index b857f9d237..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/AbstractJarVisitor.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javassist.bytecode.AnnotationsAttribute;
-import javassist.bytecode.ClassFile;
-import org.jboss.logging.Logger;
-
-import org.hibernate.jpa.internal.EntityManagerMessageLogger;
-
-/**
- * Parse a JAR of any form (zip file, exploded directory, ...)
- * apply a set of filters (File filter, Class filter, Package filter)
- * and return the appropriate matching sets of elements
- *
- * @author Emmanuel Bernard
- */
-public abstract class AbstractJarVisitor implements JarVisitor {
-
- //TODO shortcut when filters are null or empty
-
- private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
- AbstractJarVisitor.class.getName());
-
- protected String unqualifiedJarName;
- protected URL jarUrl;
- protected boolean done = false;
- private List filters = new ArrayList();
- private Set fileFilters = new HashSet();
- private Set classFilters = new HashSet();
- private Set packageFilters = new HashSet();
- private Set[] entries;
-
-
-
- /**
- * Build a jar visitor from its jar string path
- */
- private AbstractJarVisitor(String jarPath) {
- this.jarUrl = JarVisitorFactory.getURLFromPath( jarPath );
- unqualify();
- }
-
- protected AbstractJarVisitor(String fileName, Filter[] filters) {
- this( fileName );
- initFilters( filters );
- }
-
- private void initFilters(Filter[] filters) {
- for ( Filter filter : filters ) {
- if ( filter instanceof FileFilter ) {
- fileFilters.add( (FileFilter) filter );
- }
- else if ( filter instanceof ClassFilter ) {
- classFilters.add( (ClassFilter) filter );
- }
- else if ( filter instanceof PackageFilter ) {
- packageFilters.add( (PackageFilter) filter );
- }
- else {
- throw new AssertionError( "Unknown filter type: " + filter.getClass().getName() );
- }
- this.filters.add( filter );
- }
- int size = this.filters.size();
- this.entries = new Set[ size ];
- for ( int index = 0; index < size ; index++ ) {
- this.entries[index] = new HashSet();
- }
- }
-
- protected AbstractJarVisitor(URL url, Filter[] filters) {
- this( url );
- initFilters( filters );
- }
-
- private AbstractJarVisitor(URL url) {
- jarUrl = url;
- unqualify();
- }
-
- protected void unqualify() {
- //FIXME weak algorithm subject to AOOBE
- String fileName = jarUrl.getFile();
- int exclamation = fileName.lastIndexOf( "!" );
- if (exclamation != -1) fileName = fileName.substring( 0, exclamation );
- int slash = fileName.lastIndexOf( "/" );
- if ( slash != -1 ) {
- fileName = fileName.substring(
- fileName.lastIndexOf( "/" ) + 1,
- fileName.length()
- );
- }
- if ( fileName.length() > 4 && fileName.endsWith( "ar" ) && fileName.charAt( fileName.length() - 4 ) == '.' ) {
- fileName = fileName.substring( 0, fileName.length() - 4 );
- }
- unqualifiedJarName = fileName;
- LOG.debugf("Searching mapped entities in jar/par: %s", jarUrl);
- }
-
- /**
- * Get the unqualified Jar name (ie wo path and wo extension)
- */
- public String getUnqualifiedJarName() {
- return unqualifiedJarName;
- }
-
- public Filter[] getFilters() {
- return filters.toArray( new Filter[ filters.size() ] );
- }
-
- /**
- * Return the matching entries for each filter in the same order the filter where passed
- *
- * @return array of Set of JarVisitor.Entry
- * @throws IOException if something went wrong
- */
- public Set[] getMatchingEntries() throws IOException {
- if ( !done ) {
- //avoid url access and so on
- if ( filters.size() > 0 ) doProcessElements();
- done = true;
- }
- return entries;
- }
-
- protected abstract void doProcessElements() throws IOException;
-
- //TODO avoid 2 input stream when not needed
- protected final void addElement(String entryName, InputStream is, InputStream secondIs) throws IOException {
- int entryNameLength = entryName.length();
- if ( entryName.endsWith( "package-info.class" ) ) {
- String name;
- if ( entryNameLength == "package-info.class".length() ) {
- name = "";
- }
- else {
- name = entryName.substring( 0, entryNameLength - ".package-info.class".length() ).replace( '/', '.' );
- }
- executeJavaElementFilter( name, packageFilters, is, secondIs );
- }
- else if ( entryName.endsWith( ".class" ) ) {
- String name = entryName.substring( 0, entryNameLength - ".class".length() ).replace( '/', '.' );
- LOG.debugf("Filtering: %s", name);
- executeJavaElementFilter( name, classFilters, is, secondIs );
- }
- else {
- String name = entryName;
- boolean accepted = false;
- for ( FileFilter filter : fileFilters ) {
- if ( filter.accept( name ) ) {
- accepted = true;
- InputStream localIs;
- if ( filter.getStream() ) {
- localIs = secondIs;
- }
- else {
- localIs = null;
- secondIs.close();
- }
- is.close();
- LOG.debugf("File Filter matched for %s", name);
- Entry entry = new Entry( name, localIs );
- int index = this.filters.indexOf( filter );
- this.entries[index].add( entry );
- }
- }
- if (!accepted) {
- //not accepted free resources
- is.close();
- secondIs.close();
- }
- }
- }
-
- private void executeJavaElementFilter(
- String name, Set filters, InputStream is, InputStream secondIs
- ) throws IOException {
- boolean accepted = false;
- for ( JavaElementFilter filter : filters ) {
- if ( filter.accept( name ) ) {
- //FIXME cannot currently have a class filtered twice but matching once
- // need to copy the is
- boolean match = checkAnnotationMatching( is, filter );
- if ( match ) {
- accepted = true;
- InputStream localIs;
- if ( filter.getStream() ) {
- localIs = secondIs;
- }
- else {
- localIs = null;
- secondIs.close();
- }
- LOG.debugf("Java element filter matched for %s", name);
- Entry entry = new Entry( name, localIs );
- int index = this.filters.indexOf( filter );
- this.entries[index].add( entry );
- break; //we matched
- }
- }
- }
- if (!accepted) {
- is.close();
- secondIs.close();
- }
- }
-
- private boolean checkAnnotationMatching(InputStream is, JavaElementFilter filter) throws IOException {
- if ( filter.getAnnotations().length == 0 ) {
- is.close();
- return true;
- }
- DataInputStream dstream = new DataInputStream( is );
- ClassFile cf = null;
-
- try {
- cf = new ClassFile( dstream );
- }
- finally {
- dstream.close();
- is.close();
- }
- boolean match = false;
- AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
- if ( visible != null ) {
- for ( Class annotation : filter.getAnnotations() ) {
- match = visible.getAnnotation( annotation.getName() ) != null;
- if ( match ) break;
- }
- }
- return match;
- }
-}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/ExplodedJarVisitor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/ExplodedJarVisitor.java
deleted file mode 100644
index cef0a7d9aa..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/ExplodedJarVisitor.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-
-import org.jboss.logging.Logger;
-
-import org.hibernate.jpa.internal.EntityManagerMessageLogger;
-
-
-/**
- * @author Emmanuel Bernard
- */
-public class ExplodedJarVisitor extends AbstractJarVisitor {
-
- private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
- ExplodedJarVisitor.class.getName());
-
- private String entry;
-
- public ExplodedJarVisitor(URL url, Filter[] filters, String entry) {
- super( url, filters );
- this.entry = entry;
- }
-
- public ExplodedJarVisitor(String fileName, Filter[] filters) {
- super( fileName, filters );
- }
-
- @Override
- protected void doProcessElements() throws IOException {
- File jarFile;
- try {
- String filePart = jarUrl.getFile();
- if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) {
- //unescaped (from the container), keep as is
- jarFile = new File( jarUrl.getFile() );
- }
- else {
- jarFile = new File( jarUrl.toURI().getSchemeSpecificPart() );
- }
- }
- catch (URISyntaxException e) {
- LOG.malformedUrl(jarUrl, e);
- return;
- }
-
- if ( !jarFile.exists() ) {
- LOG.explodedJarDoesNotExist(jarUrl);
- return;
- }
- if ( !jarFile.isDirectory() ) {
- LOG.explodedJarNotDirectory(jarUrl);
- return;
- }
- File rootFile;
- if (entry != null && entry.length() > 0 && ! "/".equals( entry ) ) {
- rootFile = new File(jarFile, entry);
- }
- else {
- rootFile = jarFile;
- }
- if ( rootFile.isDirectory() ) {
- getClassNamesInTree( rootFile, null );
- }
- else {
- //assume zipped file
- processZippedRoot(rootFile);
- }
- }
-
- //FIXME shameful copy of FileZippedJarVisitor.doProcess()
- //TODO long term fix is to introduce a process interface (closure like) to addElements and then share the code
- private void processZippedRoot(File rootFile) throws IOException {
- JarFile jarFile = new JarFile(rootFile);
- Enumeration extends ZipEntry> entries = jarFile.entries();
- while ( entries.hasMoreElements() ) {
- ZipEntry zipEntry = entries.nextElement();
- String name = zipEntry.getName();
- if ( !zipEntry.isDirectory() ) {
- //build relative name
- if ( name.startsWith( "/" ) ) name = name.substring( 1 );
- addElement(
- name,
- new BufferedInputStream( jarFile.getInputStream( zipEntry ) ),
- new BufferedInputStream( jarFile.getInputStream( zipEntry ) )
- );
- }
- }
- }
-
- private void getClassNamesInTree(File jarFile, String header) throws IOException {
- File[] files = jarFile.listFiles();
- header = header == null ? "" : header + "/";
- for ( File localFile : files ) {
- if ( !localFile.isDirectory() ) {
- String entryName = localFile.getName();
- addElement(
- header + entryName,
- new BufferedInputStream( new FileInputStream( localFile ) ),
- new BufferedInputStream( new FileInputStream( localFile ) )
- );
-
- }
- else {
- getClassNamesInTree( localFile, header + localFile.getName() );
- }
- }
- }
-}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/FileZippedJarVisitor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/FileZippedJarVisitor.java
deleted file mode 100644
index 8dd003ce59..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/FileZippedJarVisitor.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.jar.JarFile;
-import java.util.jar.JarInputStream;
-import java.util.zip.ZipEntry;
-
-import org.jboss.logging.Logger;
-
-import org.hibernate.jpa.internal.EntityManagerMessageLogger;
-
-/**
- * Work on a JAR that can be accessed through a File
- *
- * @author Emmanuel Bernard
- */
-public class FileZippedJarVisitor extends AbstractJarVisitor {
-
- private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
- FileZippedJarVisitor.class.getName());
-
- private String entry;
-
- public FileZippedJarVisitor(String fileName, Filter[] filters) {
- super( fileName, filters );
- }
-
- public FileZippedJarVisitor(URL url, Filter[] filters, String entry) {
- super( url, filters );
- this.entry = entry;
- }
-
- @Override
- protected void doProcessElements() throws IOException {
- JarFile jarFile;
- try {
- String filePart = jarUrl.getFile();
- if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) {
- //unescaped (from the container), keep as is
- jarFile = new JarFile( jarUrl.getFile() );
- }
- else {
- jarFile = new JarFile( jarUrl.toURI().getSchemeSpecificPart() );
- }
- }
- catch (IOException ze) {
- LOG.unableToFindFile(jarUrl, ze);
- return;
- }
- catch (URISyntaxException e) {
- LOG.malformedUrlWarning(jarUrl, e);
- return;
- }
-
- if ( entry != null && entry.length() == 1 ) entry = null; //no entry
- if ( entry != null && entry.startsWith( "/" ) ) entry = entry.substring( 1 ); //remove '/' header
-
- Enumeration extends ZipEntry> entries = jarFile.entries();
- while ( entries.hasMoreElements() ) {
- ZipEntry zipEntry = entries.nextElement();
- String name = zipEntry.getName();
- if ( entry != null && ! name.startsWith( entry ) ) continue; //filter it out
- if ( !zipEntry.isDirectory() ) {
- if ( name.equals( entry ) ) {
- //exact match, might be a nested jar entry (ie from jar:file:..../foo.ear!/bar.jar)
- /*
- * This algorithm assumes that the zipped file is only the URL root (including entry), not just any random entry
- */
- InputStream is = null;
- try {
- is = new BufferedInputStream( jarFile.getInputStream( zipEntry ) );
- JarInputStream jis = new JarInputStream( is );
- ZipEntry subZipEntry = jis.getNextEntry();
- while (subZipEntry != null) {
- if ( ! subZipEntry.isDirectory() ) {
- //FIXME copy sucks
- byte[] entryBytes = JarVisitorFactory.getBytesFromInputStream( jis );
- String subname = subZipEntry.getName();
- if ( subname.startsWith( "/" ) ) subname = subname.substring( 1 );
- addElement(
- subname,
- new ByteArrayInputStream(entryBytes),
- new ByteArrayInputStream(entryBytes)
- );
- }
- subZipEntry = jis.getNextEntry();
- }
- }
- finally {
- if ( is != null) is.close();
- }
- }
- else {
- //build relative name
- if (entry != null) name = name.substring( entry.length() );
- if ( name.startsWith( "/" ) ) name = name.substring( 1 );
- addElement(
- name,
- new BufferedInputStream( jarFile.getInputStream( zipEntry ) ),
- new BufferedInputStream( jarFile.getInputStream( zipEntry ) )
- );
- }
- }
- }
- }
-}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/InputStreamZippedJarVisitor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/InputStreamZippedJarVisitor.java
deleted file mode 100644
index 27163d29ae..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/InputStreamZippedJarVisitor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.URL;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-import java.util.zip.ZipEntry;
-
-import org.jboss.logging.Logger;
-
-import org.hibernate.jpa.internal.EntityManagerMessageLogger;
-
-
-/**
- * Work on a JAR that can only be accessed through a inputstream
- * This is less efficient than the {@link FileZippedJarVisitor}
- *
- * @author Emmanuel Bernard
- */
-public class InputStreamZippedJarVisitor extends AbstractJarVisitor {
-
- private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
- InputStreamZippedJarVisitor.class.getName());
-
- private String entry;
-
- public InputStreamZippedJarVisitor(URL url, Filter[] filters, String entry) {
- super( url, filters );
- this.entry = entry;
- }
-
- public InputStreamZippedJarVisitor(String fileName, Filter[] filters) {
- super( fileName, filters );
- }
-
- @Override
- protected void doProcessElements() throws IOException {
- JarInputStream jis;
- try {
- jis = new JarInputStream( jarUrl.openStream() );
- }
- catch (Exception ze) {
- //really should catch IOException but Eclipse is buggy and raise NPE...
- LOG.unableToFindFile(jarUrl, ze);
- return;
- }
- if ( entry != null && entry.length() == 1 ) entry = null; //no entry
- if ( entry != null && entry.startsWith( "/" ) ) entry = entry.substring( 1 ); //remove '/' header
-
- JarEntry jarEntry;
- while ( ( jarEntry = jis.getNextJarEntry() ) != null ) {
- String name = jarEntry.getName();
- if ( entry != null && ! name.startsWith( entry ) ) continue; //filter it out
- if ( !jarEntry.isDirectory() ) {
- if ( name.equals( entry ) ) {
- //exact match, might be a nested jar entry (ie from jar:file:..../foo.ear!/bar.jar)
- /*
- * This algorithm assumes that the zipped file is only the URL root (including entry), not just any random entry
- */
- JarInputStream subJis = null;
- try {
- subJis = new JarInputStream( jis );
- ZipEntry subZipEntry = jis.getNextEntry();
- while (subZipEntry != null) {
- if ( ! subZipEntry.isDirectory() ) {
- //FIXME copy sucks
- byte[] entryBytes = JarVisitorFactory.getBytesFromInputStream( jis );
- String subname = subZipEntry.getName();
- if ( subname.startsWith( "/" ) ) subname = subname.substring( 1 );
- addElement(
- subname,
- new ByteArrayInputStream(entryBytes),
- new ByteArrayInputStream(entryBytes)
- );
- }
- subZipEntry = jis.getNextJarEntry();
- }
- }
- finally {
- if (subJis != null) subJis.close();
- }
- }
- else {
- byte[] entryBytes = JarVisitorFactory.getBytesFromInputStream( jis );
- //build relative name
- if (entry != null) name = name.substring( entry.length() );
- if ( name.startsWith( "/" ) ) name = name.substring( 1 );
- //this is bad cause we actually read everything instead of walking it lazily
- addElement(
- name,
- new ByteArrayInputStream( entryBytes ),
- new ByteArrayInputStream( entryBytes )
- );
- }
- }
- }
- jis.close();
- }
-}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarProtocolVisitor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarProtocolVisitor.java
deleted file mode 100644
index c1bd24a169..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarProtocolVisitor.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
-
-import org.hibernate.annotations.common.AssertionFailure;
-
-/**
- * @author Emmanuel Bernard
- */
-public class JarProtocolVisitor implements JarVisitor {
- private JarVisitor delegate;
- private URL jarUrl;
- private Filter[] filters;
-
- public JarProtocolVisitor(URL url, Filter[] filters, String entry) {
- this.jarUrl = url;
- this.filters = filters;
- if (entry != null && entry.length() > 0) throw new IllegalArgumentException( "jar:jar: not supported: " + jarUrl );
- init();
- }
-
- private void init() {
- String file = jarUrl.getFile();
- String entry;
- int subEntryIndex = file.lastIndexOf( "!" );
- if (subEntryIndex == -1) throw new AssertionFailure("JAR URL does not contain '!/' :" + jarUrl);
- if ( subEntryIndex + 1 >= file.length() ) {
- entry = "";
- }
- else {
- entry = file.substring( subEntryIndex + 1 );
- }
- URL fileUrl = JarVisitorFactory.getJarURLFromURLEntry( jarUrl, entry );
- delegate = JarVisitorFactory.getVisitor( fileUrl, filters, entry );
-
- }
-
- public String getUnqualifiedJarName() {
- return delegate.getUnqualifiedJarName();
- }
-
- public Filter[] getFilters() {
- return delegate.getFilters();
- }
-
- public Set[] getMatchingEntries() throws IOException {
- return delegate.getMatchingEntries();
- }
-
-}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JavaElementFilter.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JavaElementFilter.java
deleted file mode 100644
index ab7e42fc42..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JavaElementFilter.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-
-/**
- * Filter a Java element (class or package per fully qualified name and annotation existence)
- * At least 1 annotation has to annotate the element and the accept method must match
- * If none annotations are passed, only the accept method must pass.
- *
- * @author Emmanuel Bernard
- */
-public abstract class JavaElementFilter extends Filter {
- private Class[] annotations;
-
- /**
- * @param retrieveStream Give back an open stream to the matching element or not
- * @param annotations Array of annotations that must be present to match (1 of them should annotate the element
- */
- protected JavaElementFilter(boolean retrieveStream, Class[] annotations) {
- super( retrieveStream );
- this.annotations = annotations == null ? new Class[]{} : annotations;
- }
-
- public Class[] getAnnotations() {
- return annotations;
- }
-
- /**
- * Return true if the fully qualified name match
- */
- public abstract boolean accept(String javaElementName);
-}
\ No newline at end of file
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/NativeScanner.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/NativeScanner.java
deleted file mode 100644
index 6a568a981d..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/NativeScanner.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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.jpa.packaging.internal;
-
-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.Converter;
-import javax.persistence.Embeddable;
-import javax.persistence.Entity;
-import javax.persistence.MappedSuperclass;
-
-import org.hibernate.AssertionFailure;
-import org.hibernate.internal.util.ReflectHelper;
-import org.hibernate.jpa.packaging.spi.NamedInputStream;
-import org.hibernate.jpa.packaging.spi.Scanner;
-
-/**
- * @author Emmanuel Bernard
- */
-public class NativeScanner implements Scanner {
-
- private static final String META_INF_ORM_XML = "META-INF/orm.xml";
-
- private Map visitors = new HashMap();
- 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 getPackagesInJar(URL jarToScan, Set> annotationsToLookFor) {
- if ( annotationsToLookFor.size() > 0 ) {
- throw new AssertionFailure( "Improper use of NativeScanner: must not filter packages" );
- }
-
- JarVisitor jarVisitor = getVisitor( jarToScan );
- final Set packageEntries;
- try {
- packageEntries = ( Set ) jarVisitor.getMatchingEntries()[PACKAGE_FILTER_INDEX];
- }
- catch ( IOException e ) {
- throw new RuntimeException( "Error while reading " + jarToScan.toString(), e );
- }
- Set packages = new HashSet( 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> getClassesInJar(URL jarToScan, Set> 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 classesEntry;
- try {
- classesEntry = ( Set ) jarVisitor.getMatchingEntries()[CLASS_FILTER_INDEX];
- }
- catch ( IOException e ) {
- throw new RuntimeException( "Error while reading " + jarToScan.toString(), e );
- }
- Set> classes = new HashSet>( 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> annotationsToLookFor) {
- return annotationsToLookFor.size() != 4
- || !annotationsToLookFor.contains( Entity.class )
- || !annotationsToLookFor.contains( MappedSuperclass.class )
- || !annotationsToLookFor.contains( Embeddable.class )
- || !annotationsToLookFor.contains( Converter.class );
- }
-
- /**
- * support for patterns is primitive:
- * - **\/*.hbm.xml
- * Other patterns will not be found
- */
- public Set getFilesInJar(URL jarToScan, Set 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 endWiths = new HashSet();
- Set exacts = new HashSet();
- 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 fileEntries;
- try {
- fileEntries = ( Set ) jarVisitor.getMatchingEntries()[FILE_FILTER_INDEX];
- }
- catch ( IOException e ) {
- throw new RuntimeException( "Error while reading " + jarToScan.toString(), e );
- }
- Set files = new HashSet( fileEntries.size() );
- Set leftOver = new HashSet( 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 getFilesInClasspath(Set 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;
- }
-}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/spi/Scanner.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/spi/Scanner.java
deleted file mode 100644
index 241d233d61..0000000000
--- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/spi/Scanner.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2012, Red Hat Inc. 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 Inc.
- *
- * 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.jpa.packaging.spi;
-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 getPackagesInJar(URL jartoScan, Set> annotationsToLookFor);
-
- /**
- * return all classes in the jar matching one of these annotations
- * if annotationsToLookFor is empty, return all classes
- */
- Set> getClassesInJar(URL jartoScan, Set> 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 getFilesInJar(URL jartoScan, Set 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 getFilesInClasspath(Set filePatterns);
-
- /**
- * return the unqualified JAR name ie customer-model.jar or store.war
- */
- String getUnqualifiedJarName(URL jarUrl);
-
-}
diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/TestHelper.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/TestHelper.java
new file mode 100644
index 0000000000..90ef4d9ce8
--- /dev/null
+++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/TestHelper.java
@@ -0,0 +1,67 @@
+package org.hibernate.jpa.test;
+
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. 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 Inc.
+ *
+ * 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
+ */
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import static java.io.File.separatorChar;
+
+/**
+ * @author Steve Ebersole
+ */
+public class TestHelper {
+ private static URL RESOLVED_TEST_ROOT_URL;
+
+ public static URL determineTestRootUrl() {
+ if ( RESOLVED_TEST_ROOT_URL == null ) {
+ RESOLVED_TEST_ROOT_URL = resolveRootUrl( TestHelper.class );
+ }
+ return RESOLVED_TEST_ROOT_URL;
+ }
+
+ public static URL resolveRootUrl(Class knownClass) {
+ final String knownClassFileName = '/' + knownClass.getName().replace( '.', separatorChar ) + ".class";
+ final URL knownClassFileUrl = TestHelper.class.getResource( knownClassFileName );
+ final String knownClassFileUrlString = knownClassFileUrl.toExternalForm();
+
+ // to start, strip off the class file name
+ String rootUrlString = knownClassFileUrlString.substring( 0, knownClassFileUrlString.lastIndexOf( separatorChar ) );
+
+ // then strip off each package dir
+ final String packageName = knownClass.getPackage().getName();
+ for ( String packageNamePart : packageName.split( "\\." ) ) {
+ rootUrlString = rootUrlString.substring( 0, rootUrlString.lastIndexOf( separatorChar ) );
+ }
+
+ try {
+ return new URL( rootUrlString );
+ }
+ catch (MalformedURLException e) {
+ throw new RuntimeException( "Could not convert class base url as string to URL ref", e );
+ }
+ }
+}
diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/CustomScanner.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/CustomScanner.java
index c1ec0fdf84..71a6d5e72b 100644
--- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/CustomScanner.java
+++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/CustomScanner.java
@@ -1,19 +1,17 @@
package org.hibernate.jpa.test.packaging;
-import java.lang.annotation.Annotation;
-import java.net.URL;
-import java.util.Set;
-
-import org.hibernate.jpa.packaging.internal.NativeScanner;
-import org.hibernate.jpa.packaging.spi.NamedInputStream;
-import org.hibernate.jpa.packaging.spi.Scanner;
+import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
+import org.hibernate.jpa.boot.scan.internal.StandardScanner;
+import org.hibernate.jpa.boot.scan.spi.ScanOptions;
+import org.hibernate.jpa.boot.scan.spi.ScanResult;
+import org.hibernate.jpa.boot.scan.spi.Scanner;
/**
* @author Emmanuel Bernard
*/
public class CustomScanner implements Scanner {
public static boolean isUsed = false;
- private Scanner scanner = new NativeScanner();
+ private Scanner delegate = new StandardScanner();
public static boolean isUsed() {
return isUsed;
@@ -23,28 +21,9 @@ public class CustomScanner implements Scanner {
isUsed = false;
}
- public Set getPackagesInJar(URL jartoScan, Set> annotationsToLookFor) {
+ @Override
+ public ScanResult scan(PersistenceUnitDescriptor persistenceUnit, ScanOptions options) {
isUsed = true;
- return scanner.getPackagesInJar( jartoScan, annotationsToLookFor );
- }
-
- public Set> getClassesInJar(URL jartoScan, Set> annotationsToLookFor) {
- isUsed = true;
- return scanner.getClassesInJar( jartoScan, annotationsToLookFor );
- }
-
- public Set getFilesInJar(URL jartoScan, Set filePatterns) {
- isUsed = true;
- return scanner.getFilesInJar( jartoScan, filePatterns );
- }
-
- public Set getFilesInClasspath(Set filePatterns) {
- isUsed = true;
- return scanner.getFilesInClasspath( filePatterns );
- }
-
- public String getUnqualifiedJarName(URL jarUrl) {
- isUsed = true;
- return scanner.getUnqualifiedJarName( jarUrl );
+ return delegate.scan( persistenceUnit, options );
}
}
diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/JarVisitorTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/JarVisitorTest.java
index b1fb148cb1..e4ed5d1ef4 100644
--- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/JarVisitorTest.java
+++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/JarVisitorTest.java
@@ -23,12 +23,6 @@
*/
package org.hibernate.jpa.test.packaging;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -38,29 +32,32 @@ import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
-import java.util.Set;
-
-import javax.persistence.Embeddable;
-import javax.persistence.Entity;
-import javax.persistence.MappedSuperclass;
import org.hibernate.dialect.H2Dialect;
-import org.hibernate.jpa.packaging.internal.ClassFilter;
-import org.hibernate.jpa.packaging.internal.Entry;
-import org.hibernate.jpa.packaging.internal.ExplodedJarVisitor;
-import org.hibernate.jpa.packaging.internal.FileFilter;
-import org.hibernate.jpa.packaging.internal.FileZippedJarVisitor;
-import org.hibernate.jpa.packaging.internal.Filter;
-import org.hibernate.jpa.packaging.internal.InputStreamZippedJarVisitor;
-import org.hibernate.jpa.packaging.internal.JarProtocolVisitor;
-import org.hibernate.jpa.packaging.internal.JarVisitor;
-import org.hibernate.jpa.packaging.internal.JarVisitorFactory;
-import org.hibernate.jpa.packaging.internal.PackageFilter;
+import org.hibernate.jpa.boot.archive.internal.ArchiveHelper;
+import org.hibernate.jpa.boot.archive.internal.ExplodedArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.internal.JarFileBasedArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.internal.JarInputStreamBasedArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.internal.JarProtocolArchiveDescriptor;
+import org.hibernate.jpa.boot.archive.internal.StandardArchiveDescriptorFactory;
+import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
+import org.hibernate.jpa.boot.internal.ClassDescriptorImpl;
+import org.hibernate.jpa.boot.scan.internal.StandardScanOptions;
+import org.hibernate.jpa.boot.scan.spi.AbstractScannerImpl;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter;
import org.hibernate.jpa.test.pack.defaultpar.Version;
import org.hibernate.jpa.test.pack.explodedpar.Carpet;
+
+import org.junit.Test;
+
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
-import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author Emmanuel Bernard
@@ -72,7 +69,7 @@ import org.junit.Test;
public class JarVisitorTest extends PackagingTestCase {
@Test
public void testHttp() throws Exception {
- URL url = JarVisitorFactory.getJarURLFromURLEntry(
+ URL url = ArchiveHelper.getJarURLFromURLEntry(
new URL(
"jar:http://www.ibiblio.org/maven/hibernate/jars/hibernate-annotations-3.0beta1.jar!/META-INF/persistence.xml"
),
@@ -86,10 +83,18 @@ public class JarVisitorTest extends PackagingTestCase {
//fail silently
return;
}
- JarVisitor visitor = JarVisitorFactory.getVisitor( url, getFilters() );
- assertEquals( 0, visitor.getMatchingEntries()[0].size() );
- assertEquals( 0, visitor.getMatchingEntries()[1].size() );
- assertEquals( 0, visitor.getMatchingEntries()[2].size() );
+ ArchiveDescriptor archiveDescriptor = StandardArchiveDescriptorFactory.INSTANCE.buildArchiveDescriptor( url );
+ AbstractScannerImpl.ResultCollector resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+ assertEquals( 0, resultCollector.getClassDescriptorSet().size() );
+ assertEquals( 0, resultCollector.getPackageDescriptorSet().size() );
+ assertEquals( 0, resultCollector.getMappingFileSet().size() );
}
@Test
@@ -97,20 +102,40 @@ public class JarVisitorTest extends PackagingTestCase {
File defaultPar = buildDefaultPar();
addPackageToClasspath( defaultPar );
- Filter[] filters = getFilters();
- JarVisitor jarVisitor = new InputStreamZippedJarVisitor( defaultPar.toURL(), filters, "" );
- assertEquals( "defaultpar", jarVisitor.getUnqualifiedJarName() );
- Set entries = jarVisitor.getMatchingEntries()[1];
- assertEquals( 3, entries.size() );
- Entry entry = new Entry( org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- entry = new Entry( Version.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- assertNull( ( ( Entry ) entries.iterator().next() ).getInputStream() );
- assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
- for ( Entry localEntry : ( Set ) jarVisitor.getMatchingEntries()[2] ) {
- assertNotNull( localEntry.getInputStream() );
- localEntry.getInputStream().close();
+ ArchiveDescriptor archiveDescriptor = new JarInputStreamBasedArchiveDescriptor(
+ StandardArchiveDescriptorFactory.INSTANCE,
+ defaultPar.toURL(),
+ ""
+ );
+
+ AbstractScannerImpl.ResultCollector resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+
+ validateResults( resultCollector, org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class, Version.class );
+ }
+
+ private void validateResults(AbstractScannerImpl.ResultCollector resultCollector, Class... expectedClasses) throws IOException {
+ assertEquals( 3, resultCollector.getClassDescriptorSet().size() );
+ for ( Class expectedClass : expectedClasses ) {
+ assertTrue(
+ resultCollector.getClassDescriptorSet().contains(
+ new ClassDescriptorImpl( expectedClass.getName(), null )
+ )
+ );
+ }
+
+ assertEquals( 2, resultCollector.getMappingFileSet().size() );
+ for ( MappingFileDescriptor mappingFileDescriptor : resultCollector.getMappingFileSet() ) {
+ assertNotNull( mappingFileDescriptor.getStreamAccess() );
+ final InputStream stream = mappingFileDescriptor.getStreamAccess().accessInputStream();
+ assertNotNull( stream );
+ stream.close();
}
}
@@ -122,41 +147,39 @@ public class JarVisitorTest extends PackagingTestCase {
addPackageToClasspath( nestedEar );
String jarFileName = nestedEar.toURL().toExternalForm() + "!/defaultpar.par";
- Filter[] filters = getFilters();
- JarVisitor jarVisitor = new JarProtocolVisitor( new URL( jarFileName ), filters, "" );
- //TODO should we fix the name here to reach defaultpar rather than nestedjar ??
- //assertEquals( "defaultpar", jarVisitor.getUnqualifiedJarName() );
- Set entries = jarVisitor.getMatchingEntries()[1];
- assertEquals( 3, entries.size() );
- Entry entry = new Entry( org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- entry = new Entry( Version.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- assertNull( ( ( Entry ) entries.iterator().next() ).getInputStream() );
- assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
- for ( Entry localEntry : ( Set ) jarVisitor.getMatchingEntries()[2] ) {
- assertNotNull( localEntry.getInputStream() );
- localEntry.getInputStream().close();
- }
+
+ JarProtocolArchiveDescriptor archiveDescriptor = new JarProtocolArchiveDescriptor(
+ StandardArchiveDescriptorFactory.INSTANCE,
+ new URL( jarFileName ),
+ ""
+ );
+ AbstractScannerImpl.ResultCollector resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+
+ validateResults( resultCollector, org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class, Version.class );
jarFileName = nestedEarDir.toURL().toExternalForm() + "!/defaultpar.par";
- //JarVisitor jarVisitor = new ZippedJarVisitor( jarFileName, true, true );
- filters = getFilters();
- jarVisitor = new JarProtocolVisitor( new URL( jarFileName ), filters, "" );
- //TODO should we fix the name here to reach defaultpar rather than nestedjar ??
- //assertEquals( "defaultpar", jarVisitor.getUnqualifiedJarName() );
- entries = jarVisitor.getMatchingEntries()[1];
- assertEquals( 3, entries.size() );
- entry = new Entry( org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- entry = new Entry( Version.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- assertNull( ( ( Entry ) entries.iterator().next() ).getInputStream() );
- assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
- for ( Entry localEntry : ( Set ) jarVisitor.getMatchingEntries()[2] ) {
- assertNotNull( localEntry.getInputStream() );
- localEntry.getInputStream().close();
- }
+ archiveDescriptor = new JarProtocolArchiveDescriptor(
+ StandardArchiveDescriptorFactory.INSTANCE,
+ new URL( jarFileName ),
+ ""
+ );
+ resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+
+ validateResults( resultCollector, org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class, Version.class );
}
@Test
@@ -165,21 +188,26 @@ public class JarVisitorTest extends PackagingTestCase {
addPackageToClasspath( war );
String jarFileName = war.toURL().toExternalForm() + "!/WEB-INF/classes";
- Filter[] filters = getFilters();
- JarVisitor jarVisitor = new JarProtocolVisitor( new URL( jarFileName ), filters, "" );
- assertEquals( "war", jarVisitor.getUnqualifiedJarName() );
- Set entries = jarVisitor.getMatchingEntries()[1];
- assertEquals( 3, entries.size() );
- Entry entry = new Entry( org.hibernate.jpa.test.pack.war.ApplicationServer.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- entry = new Entry( org.hibernate.jpa.test.pack.war.Version.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- assertNull( ( ( Entry ) entries.iterator().next() ).getInputStream() );
- assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
- for ( Entry localEntry : ( Set ) jarVisitor.getMatchingEntries()[2] ) {
- assertNotNull( localEntry.getInputStream() );
- localEntry.getInputStream().close();
- }
+ JarProtocolArchiveDescriptor archiveDescriptor = new JarProtocolArchiveDescriptor(
+ StandardArchiveDescriptorFactory.INSTANCE,
+ new URL( jarFileName ),
+ ""
+ );
+
+ AbstractScannerImpl.ResultCollector resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+
+ validateResults(
+ resultCollector,
+ org.hibernate.jpa.test.pack.war.ApplicationServer.class,
+ org.hibernate.jpa.test.pack.war.Version.class
+ );
}
@Test
@@ -187,21 +215,21 @@ public class JarVisitorTest extends PackagingTestCase {
File defaultPar = buildDefaultPar();
addPackageToClasspath( defaultPar );
- Filter[] filters = getFilters();
- JarVisitor jarVisitor = new FileZippedJarVisitor( defaultPar.toURL(), filters, "" );
- assertEquals( "defaultpar", jarVisitor.getUnqualifiedJarName() );
- Set entries = jarVisitor.getMatchingEntries()[1];
- assertEquals( 3, entries.size() );
- Entry entry = new Entry( org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- entry = new Entry( Version.class.getName(), null );
- assertTrue( entries.contains( entry ) );
- assertNull( ( ( Entry ) entries.iterator().next() ).getInputStream() );
- assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
- for ( Entry localEntry : ( Set ) jarVisitor.getMatchingEntries()[2] ) {
- assertNotNull( localEntry.getInputStream() );
- localEntry.getInputStream().close();
- }
+ JarFileBasedArchiveDescriptor archiveDescriptor = new JarFileBasedArchiveDescriptor(
+ StandardArchiveDescriptorFactory.INSTANCE,
+ defaultPar.toURL(),
+ ""
+ );
+ AbstractScannerImpl.ResultCollector resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+
+ validateResults( resultCollector, org.hibernate.jpa.test.pack.defaultpar.ApplicationServer.class, Version.class );
}
@Test
@@ -209,32 +237,50 @@ public class JarVisitorTest extends PackagingTestCase {
File explodedPar = buildExplodedPar();
addPackageToClasspath( explodedPar );
- Filter[] filters = getFilters();
String dirPath = explodedPar.toURL().toExternalForm();
// TODO - shouldn't ExplodedJarVisitor take care of a trailing slash?
if ( dirPath.endsWith( "/" ) ) {
dirPath = dirPath.substring( 0, dirPath.length() - 1 );
}
- JarVisitor jarVisitor = new ExplodedJarVisitor( dirPath, filters );
- assertEquals( "explodedpar", jarVisitor.getUnqualifiedJarName() );
- Set[] entries = jarVisitor.getMatchingEntries();
- assertEquals( 1, entries[1].size() );
- assertEquals( 1, entries[0].size() );
- assertEquals( 1, entries[2].size() );
- Entry entry = new Entry( Carpet.class.getName(), null );
- assertTrue( entries[1].contains( entry ) );
- for ( Entry localEntry : ( Set ) jarVisitor.getMatchingEntries()[2] ) {
- assertNotNull( localEntry.getInputStream() );
- localEntry.getInputStream().close();
+ ExplodedArchiveDescriptor archiveDescriptor = new ExplodedArchiveDescriptor(
+ StandardArchiveDescriptorFactory.INSTANCE,
+ ArchiveHelper.getURLFromPath( dirPath ),
+ ""
+ );
+ AbstractScannerImpl.ResultCollector resultCollector = new AbstractScannerImpl.ResultCollector( new StandardScanOptions() );
+ archiveDescriptor.visitArchive(
+ new AbstractScannerImpl.ArchiveContextImpl(
+ new PersistenceUnitDescriptorAdapter(),
+ true,
+ resultCollector
+ )
+ );
+
+ assertEquals( 1, resultCollector.getClassDescriptorSet().size() );
+ assertEquals( 1, resultCollector.getPackageDescriptorSet().size() );
+ assertEquals( 1, resultCollector.getMappingFileSet().size() );
+
+ assertTrue(
+ resultCollector.getClassDescriptorSet().contains(
+ new ClassDescriptorImpl( Carpet.class.getName(), null )
+ )
+ );
+
+ for ( MappingFileDescriptor mappingFileDescriptor : resultCollector.getMappingFileSet() ) {
+ assertNotNull( mappingFileDescriptor.getStreamAccess() );
+ final InputStream stream = mappingFileDescriptor.getStreamAccess().accessInputStream();
+ assertNotNull( stream );
+ stream.close();
}
}
@Test
@TestForIssue(jiraKey = "HHH-6806")
- public void testJarVisitorFactory() throws Exception{
-
- addPackageToClasspath( buildExplodedPar(), buildDefaultPar() );
+ public void testJarVisitorFactory() throws Exception {
+ final File explodedPar = buildExplodedPar();
+ final File defaultPar = buildDefaultPar();
+ addPackageToClasspath( explodedPar, defaultPar );
//setting URL to accept vfs based protocol
URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
@@ -250,21 +296,21 @@ public class JarVisitorTest extends PackagingTestCase {
}
});
- URL jarUrl = new URL ("file:./target/packages/defaultpar.par");
- JarVisitor jarVisitor = JarVisitorFactory.getVisitor(jarUrl, getFilters(), null);
- assertEquals(FileZippedJarVisitor.class.getName(), jarVisitor.getClass().getName());
-
- jarUrl = new URL ("file:./target/packages/explodedpar");
- jarVisitor = JarVisitorFactory.getVisitor(jarUrl, getFilters(), null);
- assertEquals(ExplodedJarVisitor.class.getName(), jarVisitor.getClass().getName());
-
- jarUrl = new URL ("vfszip:./target/packages/defaultpar.par");
- jarVisitor = JarVisitorFactory.getVisitor(jarUrl, getFilters(), null);
- assertEquals(FileZippedJarVisitor.class.getName(), jarVisitor.getClass().getName());
-
- jarUrl = new URL ("vfsfile:./target/packages/explodedpar");
- jarVisitor = JarVisitorFactory.getVisitor(jarUrl, getFilters(), null);
- assertEquals(ExplodedJarVisitor.class.getName(), jarVisitor.getClass().getName());
+ URL jarUrl = defaultPar.toURL();
+ ArchiveDescriptor descriptor = StandardArchiveDescriptorFactory.INSTANCE.buildArchiveDescriptor( jarUrl );
+ assertEquals( JarFileBasedArchiveDescriptor.class.getName(), descriptor.getClass().getName() );
+
+ jarUrl = explodedPar.toURL();
+ descriptor = StandardArchiveDescriptorFactory.INSTANCE.buildArchiveDescriptor( jarUrl );
+ assertEquals( ExplodedArchiveDescriptor.class.getName(), descriptor.getClass().getName() );
+
+ jarUrl = new URL( defaultPar.toURL().toExternalForm().replace( "file:", "vfszip:" ) );
+ descriptor = StandardArchiveDescriptorFactory.INSTANCE.buildArchiveDescriptor( jarUrl );
+ assertEquals( JarFileBasedArchiveDescriptor.class.getName(), descriptor.getClass().getName());
+
+ jarUrl = new URL( explodedPar.toURL().toExternalForm().replace( "file:", "vfsfile:" ) );
+ descriptor = StandardArchiveDescriptorFactory.INSTANCE.buildArchiveDescriptor( jarUrl );
+ assertEquals( ExplodedArchiveDescriptor.class.getName(), descriptor.getClass().getName() );
}
@Test
@@ -315,36 +361,29 @@ public class JarVisitorTest extends PackagingTestCase {
@Test
@TestForIssue(jiraKey = "HHH-7835")
- public void testGetBytesFromInputStream() {
- try {
- File file = buildLargeJar();
+ public void testGetBytesFromInputStream() throws Exception {
+ File file = buildLargeJar();
- long start = System.currentTimeMillis();
- InputStream stream = new BufferedInputStream(
- new FileInputStream( file ) );
- int oldLength = getBytesFromInputStream( stream ).length;
- stream.close();
- long oldTime = System.currentTimeMillis() - start;
+ long start = System.currentTimeMillis();
+ InputStream stream = new BufferedInputStream(
+ new FileInputStream( file ) );
+ int oldLength = getBytesFromInputStream( stream ).length;
+ stream.close();
+ long oldTime = System.currentTimeMillis() - start;
- start = System.currentTimeMillis();
- stream = new BufferedInputStream( new FileInputStream( file ) );
- int newLength = JarVisitorFactory.getBytesFromInputStream(
- stream ).length;
- stream.close();
- long newTime = System.currentTimeMillis() - start;
+ start = System.currentTimeMillis();
+ stream = new BufferedInputStream( new FileInputStream( file ) );
+ int newLength = ArchiveHelper.getBytesFromInputStream( stream ).length;
+ stream.close();
+ long newTime = System.currentTimeMillis() - start;
- assertEquals( oldLength, newLength );
- assertTrue( oldTime > newTime );
- }
- catch ( Exception e ) {
- fail( e.getMessage() );
- }
+ assertEquals( oldLength, newLength );
+ assertTrue( oldTime > newTime );
}
// This is the old getBytesFromInputStream from JarVisitorFactory before
// it was changed by HHH-7835. Use it as a regression test.
- private byte[] getBytesFromInputStream(
- InputStream inputStream) throws IOException {
+ private byte[] getBytesFromInputStream(InputStream inputStream) throws IOException {
int size;
byte[] entryBytes = new byte[0];
@@ -363,46 +402,16 @@ public class JarVisitorTest extends PackagingTestCase {
@Test
@TestForIssue(jiraKey = "HHH-7835")
- public void testGetBytesFromZeroInputStream() {
- try {
- // Ensure that JarVisitorFactory#getBytesFromInputStream
- // can handle 0 length streams gracefully.
- InputStream emptyStream = new BufferedInputStream(
- new FileInputStream( new File(
- "src/test/resources/org/hibernate/jpa/test/packaging/empty.txt" ) ) );
- int length = JarVisitorFactory.getBytesFromInputStream(
- emptyStream ).length;
- assertEquals( length, 0 );
- emptyStream.close();
+ public void testGetBytesFromZeroInputStream() throws Exception {
+ // Ensure that JarVisitorFactory#getBytesFromInputStream
+ // can handle 0 length streams gracefully.
+ URL emptyTxtUrl = getClass().getResource( "/org/hibernate/jpa/test/packaging/empty.txt" );
+ if ( emptyTxtUrl == null ) {
+ throw new RuntimeException( "Bah!" );
}
- catch ( Exception e ) {
- fail( e.getMessage() );
- }
- }
-
- private Filter[] getFilters() {
- return new Filter[] {
- new PackageFilter( false, null ) {
- public boolean accept(String javaElementName) {
- return true;
- }
- },
- new ClassFilter(
- false, new Class[] {
- Entity.class,
- MappedSuperclass.class,
- Embeddable.class
- }
- ) {
- public boolean accept(String javaElementName) {
- return true;
- }
- },
- new FileFilter( true ) {
- public boolean accept(String javaElementName) {
- return javaElementName.endsWith( "hbm.xml" ) || javaElementName.endsWith( "META-INF/orm.xml" );
- }
- }
- };
+ InputStream emptyStream = new BufferedInputStream( emptyTxtUrl.openStream() );
+ int length = ArchiveHelper.getBytesFromInputStream( emptyStream ).length;
+ assertEquals( length, 0 );
+ emptyStream.close();
}
}
diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/PackagingTestCase.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/PackagingTestCase.java
index 30582808f6..af86c8aeae 100644
--- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/PackagingTestCase.java
+++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/PackagingTestCase.java
@@ -45,6 +45,7 @@ import org.hibernate.jpa.test.Cat;
import org.hibernate.jpa.test.Distributor;
import org.hibernate.jpa.test.Item;
import org.hibernate.jpa.test.Kitten;
+import org.hibernate.jpa.test.TestHelper;
import org.hibernate.jpa.test.pack.cfgxmlpar.Morito;
import org.hibernate.jpa.test.pack.defaultpar.ApplicationServer;
import org.hibernate.jpa.test.pack.defaultpar.IncrementListener;
@@ -204,6 +205,10 @@ public abstract class PackagingTestCase extends BaseCoreFunctionalTestCase {
}
protected File buildExplicitPar() {
+ // explicitpar/persistence.xml references externaljar.jar so build that from here.
+ // this is the reason for tests failing after clean at least on my (Steve) local system
+ buildExternalJar();
+
String fileName = "explicitpar.par";
JavaArchive archive = ShrinkWrap.create( JavaArchive.class, fileName );
archive.addClasses(
@@ -342,8 +347,10 @@ public abstract class PackagingTestCase extends BaseCoreFunctionalTestCase {
// Build a large jar by adding a lorem ipsum file repeatedly.
for ( int i = 0; i < 100; i++ ) {
ArchivePath path = ArchivePaths.create( "META-INF/file" + i );
- archive.addAsResource( new File( "src/test/resources/org/hibernate/jpa/test/packaging/loremipsum.txt" ),
- path );
+ archive.addAsResource(
+ "org/hibernate/jpa/test/packaging/loremipsum.txt",
+ path
+ );
}
File testPackage = new File( packageTargetDir, fileName );
diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/ScannerTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/ScannerTest.java
index ed2bc44952..28ed10ab8e 100644
--- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/ScannerTest.java
+++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/ScannerTest.java
@@ -23,31 +23,32 @@
*/
package org.hibernate.jpa.test.packaging;
-import java.io.File;
-import java.lang.annotation.Annotation;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-import javax.persistence.Converter;
-import javax.persistence.Embeddable;
-import javax.persistence.Entity;
import javax.persistence.EntityManagerFactory;
-import javax.persistence.MappedSuperclass;
import javax.persistence.Persistence;
-
-import org.junit.Test;
+import java.io.File;
+import java.io.InputStream;
+import java.util.HashMap;
import org.hibernate.jpa.AvailableSettings;
-import org.hibernate.jpa.packaging.internal.NativeScanner;
-
+import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
+import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
+import org.hibernate.jpa.boot.scan.internal.StandardScanOptions;
+import org.hibernate.jpa.boot.scan.internal.StandardScanner;
+import org.hibernate.jpa.boot.spi.ClassDescriptor;
+import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
+import org.hibernate.jpa.boot.spi.NamedInputStream;
+import org.hibernate.jpa.boot.scan.spi.ScanOptions;
+import org.hibernate.jpa.boot.scan.spi.ScanResult;
+import org.hibernate.jpa.boot.scan.spi.Scanner;
import org.hibernate.jpa.test.pack.defaultpar.ApplicationServer;
-import org.hibernate.jpa.packaging.spi.NamedInputStream;
-import org.hibernate.jpa.packaging.spi.Scanner;
import org.hibernate.jpa.test.pack.defaultpar.Version;
+import org.junit.Test;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author Emmanuel Bernard
@@ -59,32 +60,39 @@ public class ScannerTest extends PackagingTestCase {
File defaultPar = buildDefaultPar();
addPackageToClasspath( defaultPar );
- Scanner scanner = new NativeScanner();
- assertEquals( "defaultpar", scanner.getUnqualifiedJarName( defaultPar.toURL() ) );
+ PersistenceUnitDescriptor descriptor = new ParsedPersistenceXmlDescriptor( defaultPar.toURL() );
+ ScanOptions options = new StandardScanOptions( "hbm,class", descriptor.isExcludeUnlistedClasses() );
+ Scanner scanner = new StandardScanner();
+ ScanResult scanResult = scanner.scan( descriptor, options );
- Set> annotationsToLookFor = new HashSet>( 3 );
- annotationsToLookFor.add( Entity.class );
- annotationsToLookFor.add( MappedSuperclass.class );
- annotationsToLookFor.add( Embeddable.class );
- annotationsToLookFor.add( Converter.class );
- final Set> classes = scanner.getClassesInJar( defaultPar.toURL(), annotationsToLookFor );
+ assertEquals( 3, scanResult.getLocatedClasses().size() );
+ assertClassesContained( scanResult, ApplicationServer.class );
+ assertClassesContained( scanResult, Version.class );
- assertEquals( 3, classes.size() );
- assertTrue( classes.contains( ApplicationServer.class ) );
- assertTrue( classes.contains( Version.class ) );
-
- Set filePatterns = new HashSet( 2 );
- filePatterns.add( "**/*.hbm.xml" );
- filePatterns.add( "META-INF/orm.xml" );
- final Set files = scanner.getFilesInJar( defaultPar.toURL(), filePatterns );
-
- assertEquals( 2, files.size() );
- for ( NamedInputStream file : files ) {
- assertNotNull( file.getStream() );
- file.getStream().close();
+ assertEquals( 2, scanResult.getLocatedMappingFiles().size() );
+ for ( MappingFileDescriptor mappingFileDescriptor : scanResult.getLocatedMappingFiles() ) {
+ assertNotNull( mappingFileDescriptor.getName() );
+ assertNotNull( mappingFileDescriptor.getStreamAccess() );
+ InputStream stream = mappingFileDescriptor.getStreamAccess().accessInputStream();
+ assertNotNull( stream );
+ stream.close();
+ NamedInputStream namedInputStream = mappingFileDescriptor.getStreamAccess().asNamedInputStream();
+ assertNotNull( namedInputStream );
+ stream = namedInputStream.getStream();
+ assertNotNull( stream );
+ stream.close();
}
}
+ private void assertClassesContained(ScanResult scanResult, Class classToCheckFor) {
+ for ( ClassDescriptor classDescriptor : scanResult.getLocatedClasses() ) {
+ if ( classDescriptor.getName().equals( classToCheckFor.getName() ) ) {
+ return;
+ }
+ }
+ fail( "ScanResult did not contain expected Class : " + classToCheckFor.getName() );
+ }
+
@Test
public void testCustomScanner() throws Exception {
File defaultPar = buildDefaultPar();