HHH-7835 Inefficient implementation of
JarVisitorFactory.getBytesFromInputStream
This commit is contained in:
parent
da32690828
commit
2fad160bd6
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in New Issue