Author: epbernard
Date: 2008-02-04 17:25:33 -0500 (Mon, 04 Feb 2008)
New Revision: 14309
Modified:
entitymanager/trunk/build.xml
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/ExplodedJarVisitor.java
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/InputStreamZippedJarVisitor.java
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/JarVisitorFactory.java
entitymanager/trunk/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java
Log:
EJB-332 handled nested jars if the root URL points to one jar:file:...foo.ear!/bar.jar
Modified: entitymanager/trunk/build.xml
===================================================================
--- entitymanager/trunk/build.xml 2008-02-03 05:57:08 UTC (rev 14308)
+++ entitymanager/trunk/build.xml 2008-02-04 22:25:33 UTC (rev 14309)
@@ -17,7 +17,7 @@
<!-- Name of project and version, used to create filenames -->
<property name="Name" value="Hibernate EntityManager"/>
<property name="name" value="hibernate-entitymanager"/>
- <property name="version" value="3.3.2.Beta2"/>
+ <property name="version" value="3.3.2.Beta3"/>
<property name="javadoc.packagenames"
value="org.hibernate.ejb.*"/>
<property name="jdbc.dir" value="jdbc"/>
<property name="copy.test" value="true"/>
@@ -203,6 +203,18 @@
<param name="jarname" value="overridenpar"/>
</antcall>
+ <!-- nested jar -->
+ <jar destfile="${build.testresources.dir}/nestedjar.ear">
+ <fileset dir="${build.testresources.dir}">
+ <include name="defaultpar.par"/>
+ </fileset>
+ </jar>
+ <copy todir="${build.testresources.dir}/nesteddir.ear">
+ <fileset dir="${build.testresources.dir}">
+ <include name="defaultpar.par"/>
+ </fileset>
+ </copy>
+
<antcall target="packjar" inheritall="true">
<param name="extension" value="war"/>
<param name="jarname" value="war"/>
Modified:
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/ExplodedJarVisitor.java
===================================================================
---
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/ExplodedJarVisitor.java 2008-02-03
05:57:08 UTC (rev 14308)
+++
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/ExplodedJarVisitor.java 2008-02-04
22:25:33 UTC (rev 14309)
@@ -5,8 +5,14 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
import java.net.URL;
import java.net.URISyntaxException;
+import java.util.zip.ZipEntry;
+import java.util.Enumeration;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarFile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -51,9 +57,35 @@
else {
rootFile = jarFile;
}
- getClassNamesInTree( rootFile, null );
+ 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 + "/";
Modified:
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java
===================================================================
---
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java 2008-02-03
05:57:08 UTC (rev 14308)
+++
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java 2008-02-04
22:25:33 UTC (rev 14309)
@@ -3,10 +3,13 @@
import java.io.BufferedInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
import java.net.URL;
import java.net.URISyntaxException;
import java.util.Enumeration;
import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;
import org.apache.commons.logging.Log;
@@ -52,14 +55,45 @@
String name = zipEntry.getName();
if ( entry != null && ! name.startsWith( entry ) ) continue; //filter it out
if ( !zipEntry.isDirectory() ) {
- //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 ) )
- );
+ 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 ) )
+ );
+ }
}
}
}
Modified:
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/InputStreamZippedJarVisitor.java
===================================================================
---
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/InputStreamZippedJarVisitor.java 2008-02-03
05:57:08 UTC (rev 14308)
+++
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/InputStreamZippedJarVisitor.java 2008-02-04
22:25:33 UTC (rev 14309)
@@ -3,9 +3,12 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.BufferedInputStream;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
+import java.util.zip.ZipEntry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -47,26 +50,46 @@
String name = jarEntry.getName();
if ( entry != null && ! name.startsWith( entry ) ) continue; //filter it out
if ( !jarEntry.isDirectory() ) {
- int size;
- byte[] tmpByte = new byte[ 4096 ];
- byte[] entryBytes = new byte[0];
- for ( ; ; ) {
- size = jis.read( tmpByte );
- if ( size == -1 ) break;
- byte[] current = new byte[ entryBytes.length + size ];
- System.arraycopy( entryBytes, 0, current, 0, entryBytes.length );
- System.arraycopy( tmpByte, 0, current, entryBytes.length, size );
- entryBytes = current;
+ 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();
+ }
}
- //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 )
- );
+ 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();
Modified: entitymanager/trunk/src/java/org/hibernate/ejb/packaging/JarVisitorFactory.java
===================================================================
---
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/JarVisitorFactory.java 2008-02-03
05:57:08 UTC (rev 14308)
+++
entitymanager/trunk/src/java/org/hibernate/ejb/packaging/JarVisitorFactory.java 2008-02-04
22:25:33 UTC (rev 14309)
@@ -5,6 +5,8 @@
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -124,4 +126,19 @@
return new InputStreamZippedJarVisitor( jarUrl, filters, entry );
}
}
+
+ public static byte[] getBytesFromInputStream(InputStream inputStream) throws IOException
{
+ int size;
+ byte[] tmpByte = new byte[ 4096 ];
+ byte[] entryBytes = new byte[0];
+ for ( ; ; ) {
+ size = inputStream.read( tmpByte );
+ if ( size == -1 ) break;
+ byte[] current = new byte[ entryBytes.length + size ];
+ System.arraycopy( entryBytes, 0, current, 0, entryBytes.length );
+ System.arraycopy( tmpByte, 0, current, entryBytes.length, size );
+ entryBytes = current;
+ }
+ return entryBytes;
+ }
}
Modified:
entitymanager/trunk/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java
===================================================================
---
entitymanager/trunk/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java 2008-02-03
05:57:08 UTC (rev 14308)
+++
entitymanager/trunk/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java 2008-02-04
22:25:33 UTC (rev 14309)
@@ -79,6 +79,52 @@
// assertTrue( classes.contains(
org.hibernate.ejb.test.pack.defaultpar.Version.class.getName() ) );
}
+ public void testNestedJarProtocol() throws Exception {
+ String jarFileName =
"jar:file:./build/testresources/nestedjar.ear!/defaultpar.par";
+ //JarVisitor jarVisitor = new ZippedJarVisitor( jarFileName, true, true );
+ 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( ApplicationServer.class.getName(), null );
+ assertTrue( entries.contains( entry ) );
+ entry = new Entry( org.hibernate.ejb.test.pack.defaultpar.Version.class.getName(), null
);
+ assertTrue( entries.contains( entry ) );
+ assertNull( ( (Entry) entries.iterator().next() ).getInputStream() );
+ assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
+ for (Entry localEntry : (Set<Entry>) jarVisitor.getMatchingEntries()[2] ) {
+ assertNotNull( localEntry.getInputStream() );
+ localEntry.getInputStream().close();
+ }
+
+ jarFileName =
"jar:file:./build/testresources/nesteddir.ear!/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( ApplicationServer.class.getName(), null );
+ assertTrue( entries.contains( entry ) );
+ entry = new Entry( org.hibernate.ejb.test.pack.defaultpar.Version.class.getName(), null
);
+ assertTrue( entries.contains( entry ) );
+ assertNull( ( (Entry) entries.iterator().next() ).getInputStream() );
+ assertEquals( 2, jarVisitor.getMatchingEntries()[2].size() );
+ for (Entry localEntry : (Set<Entry>) jarVisitor.getMatchingEntries()[2] ) {
+ assertNotNull( localEntry.getInputStream() );
+ localEntry.getInputStream().close();
+ }
+
+// Set<String> classes = jarVisitor.getClassNames();
+// assertEquals( 3, classes.size() );
+// assertTrue( classes.contains( ApplicationServer.class.getName() ) );
+// assertTrue( classes.contains( Mouse.class.getName() ) );
+// assertTrue( classes.contains(
org.hibernate.ejb.test.pack.defaultpar.Version.class.getName() ) );
+ }
+
public void testJarProtocol() throws Exception {
String jarFileName =
"jar:file:./build/testresources/war.war!/WEB-INF/classes";
//JarVisitor jarVisitor = new ZippedJarVisitor( jarFileName, true, true );
@@ -130,6 +176,7 @@
// assertTrue( classes.contains(
org.hibernate.ejb.test.pack.defaultpar.Version.class.getName() ) );
}
+
public void testExplodedJar() throws Exception {
String jarFileName = "./build/testresources/explodedpar.par";
//JarVisitor jarVisitor = new ExplodedJarVisitor( jarFileName, true, true );