HHH-7835 Inefficient implementation of

JarVisitorFactory.getBytesFromInputStream
This commit is contained in:
brmeyer 2012-12-06 14:26:13 -05:00
parent da32690828
commit 2fad160bd6
4 changed files with 99 additions and 15 deletions

View File

@ -21,6 +21,7 @@
*/ */
package org.hibernate.jpa.packaging.internal; package org.hibernate.jpa.packaging.internal;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -28,13 +29,13 @@ import java.net.MalformedURLException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import org.jboss.logging.Logger;
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
import org.jboss.logging.Logger;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard
* @author Brett Meyer
*/ */
public class JarVisitorFactory { public class JarVisitorFactory {
@ -194,18 +195,16 @@ public class JarVisitorFactory {
} }
} }
public static byte[] getBytesFromInputStream(InputStream inputStream) throws IOException { public static byte[] getBytesFromInputStream(
int size; InputStream inputStream) throws IOException {
byte[] tmpByte = new byte[ 4096 ];
byte[] entryBytes = new byte[0]; ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for ( ; ; ) { int numBytes;
size = inputStream.read( tmpByte ); byte[] data = new byte[4096];
if ( size == -1 ) break; while ( ( numBytes = inputStream.read( data, 0, data.length ) ) != -1 ) {
byte[] current = new byte[ entryBytes.length + size ]; buffer.write( data, 0, numBytes );
System.arraycopy( entryBytes, 0, current, 0, entryBytes.length );
System.arraycopy( tmpByte, 0, current, entryBytes.length, size );
entryBytes = current;
} }
return entryBytes; buffer.flush();
return buffer.toByteArray();
} }
} }

View File

@ -27,9 +27,13 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLStreamHandler; import java.net.URLStreamHandler;
@ -61,6 +65,7 @@ import org.junit.Test;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard
* @author Hardy Ferentschik * @author Hardy Ferentschik
* @author Brett Meyer
*/ */
@RequiresDialect( H2Dialect.class ) // Nothing dialect-specific -- no need to run in matrix. @RequiresDialect( H2Dialect.class ) // Nothing dialect-specific -- no need to run in matrix.
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -308,6 +313,73 @@ public class JarVisitorTest extends PackagingTestCase {
// assertTrue( entries[1].contains( entry ) ); // assertTrue( entries[1].contains( entry ) );
} }
@Test
@TestForIssue(jiraKey = "HHH-7835")
public void testGetBytesFromInputStream() {
try {
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;
start = System.currentTimeMillis();
stream = new BufferedInputStream( new FileInputStream( file ) );
int newLength = JarVisitorFactory.getBytesFromInputStream(
stream ).length;
stream.close();
long newTime = System.currentTimeMillis() - start;
assertEquals( oldLength, newLength );
assertTrue( oldTime > newTime );
}
catch ( Exception e ) {
fail( e.getMessage() );
}
}
// 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 {
int size;
byte[] entryBytes = new byte[0];
for ( ;; ) {
byte[] tmpByte = new byte[4096];
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;
}
@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();
}
catch ( Exception e ) {
fail( e.getMessage() );
}
}
private Filter[] getFilters() { private Filter[] getFilters() {
return new Filter[] { return new Filter[] {
new PackageFilter( false, null ) { new PackageFilter( false, null ) {

View File

@ -73,6 +73,7 @@ import static org.junit.Assert.fail;
/** /**
* @author Hardy Ferentschik * @author Hardy Ferentschik
* @author Brett Meyer
*/ */
public abstract class PackagingTestCase extends BaseCoreFunctionalTestCase { public abstract class PackagingTestCase extends BaseCoreFunctionalTestCase {
protected static ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); protected static ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
@ -335,6 +336,18 @@ public abstract class PackagingTestCase extends BaseCoreFunctionalTestCase {
return testPackage; return testPackage;
} }
protected File buildLargeJar() {
String fileName = "large.jar";
JavaArchive archive = ShrinkWrap.create( JavaArchive.class, fileName );
// Build a large jar by adding all EntityManager packages and
// subpackages on the classpath.
archive.addPackages(true, "org.hibernate.ejb", "org.hibernate.jpa" );
File testPackage = new File( packageTargetDir, fileName );
archive.as( ZipExporter.class ).exportTo( testPackage, true );
return testPackage;
}
protected File buildWar() { protected File buildWar() {
String fileName = "war.war"; String fileName = "war.war";
WebArchive archive = ShrinkWrap.create( WebArchive.class, fileName ); WebArchive archive = ShrinkWrap.create( WebArchive.class, fileName );