Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2fad160

Browse files
committed
HHH-7835 Inefficient implementation of
JarVisitorFactory.getBytesFromInputStream
1 parent da32690 commit 2fad160

File tree

4 files changed

+99
-15
lines changed

4 files changed

+99
-15
lines changed

hibernate-entitymanager/src/main/java/org/hibernate/jpa/packaging/internal/JarVisitorFactory.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,21 @@
2121
*/
2222
package org.hibernate.jpa.packaging.internal;
2323

24+
import java.io.ByteArrayOutputStream;
2425
import java.io.File;
2526
import java.io.IOException;
2627
import java.io.InputStream;
2728
import java.net.MalformedURLException;
2829
import java.net.URISyntaxException;
2930
import java.net.URL;
3031

31-
import org.jboss.logging.Logger;
32-
33-
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
3432
import org.hibernate.internal.util.StringHelper;
33+
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
34+
import org.jboss.logging.Logger;
3535

3636
/**
3737
* @author Emmanuel Bernard
38+
* @author Brett Meyer
3839
*/
3940
public class JarVisitorFactory {
4041

@@ -194,18 +195,16 @@ else if ( StringHelper.isEmpty( protocol ) || "file".equals( protocol ) || "vfsz
194195
}
195196
}
196197

197-
public static byte[] getBytesFromInputStream(InputStream inputStream) throws IOException {
198-
int size;
199-
byte[] tmpByte = new byte[ 4096 ];
200-
byte[] entryBytes = new byte[0];
201-
for ( ; ; ) {
202-
size = inputStream.read( tmpByte );
203-
if ( size == -1 ) break;
204-
byte[] current = new byte[ entryBytes.length + size ];
205-
System.arraycopy( entryBytes, 0, current, 0, entryBytes.length );
206-
System.arraycopy( tmpByte, 0, current, entryBytes.length, size );
207-
entryBytes = current;
198+
public static byte[] getBytesFromInputStream(
199+
InputStream inputStream) throws IOException {
200+
201+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
202+
int numBytes;
203+
byte[] data = new byte[4096];
204+
while ( ( numBytes = inputStream.read( data, 0, data.length ) ) != -1 ) {
205+
buffer.write( data, 0, numBytes );
208206
}
209-
return entryBytes;
207+
buffer.flush();
208+
return buffer.toByteArray();
210209
}
211210
}

hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/JarVisitorTest.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@
2727
import static org.junit.Assert.assertNotNull;
2828
import static org.junit.Assert.assertNull;
2929
import static org.junit.Assert.assertTrue;
30+
import static org.junit.Assert.fail;
3031

32+
import java.io.BufferedInputStream;
3133
import java.io.File;
34+
import java.io.FileInputStream;
3235
import java.io.IOException;
36+
import java.io.InputStream;
3337
import java.net.URL;
3438
import java.net.URLConnection;
3539
import java.net.URLStreamHandler;
@@ -61,6 +65,7 @@
6165
/**
6266
* @author Emmanuel Bernard
6367
* @author Hardy Ferentschik
68+
* @author Brett Meyer
6469
*/
6570
@RequiresDialect( H2Dialect.class ) // Nothing dialect-specific -- no need to run in matrix.
6671
@SuppressWarnings("unchecked")
@@ -307,6 +312,73 @@ public void testDuplicateFilterExplodedJarExpected() throws Exception {
307312
// Entry entry = new Entry( Carpet.class.getName(), null );
308313
// assertTrue( entries[1].contains( entry ) );
309314
}
315+
316+
@Test
317+
@TestForIssue(jiraKey = "HHH-7835")
318+
public void testGetBytesFromInputStream() {
319+
try {
320+
File file = buildLargeJar();
321+
322+
long start = System.currentTimeMillis();
323+
InputStream stream = new BufferedInputStream(
324+
new FileInputStream( file ) );
325+
int oldLength = getBytesFromInputStream( stream ).length;
326+
stream.close();
327+
long oldTime = System.currentTimeMillis() - start;
328+
329+
start = System.currentTimeMillis();
330+
stream = new BufferedInputStream( new FileInputStream( file ) );
331+
int newLength = JarVisitorFactory.getBytesFromInputStream(
332+
stream ).length;
333+
stream.close();
334+
long newTime = System.currentTimeMillis() - start;
335+
336+
assertEquals( oldLength, newLength );
337+
assertTrue( oldTime > newTime );
338+
}
339+
catch ( Exception e ) {
340+
fail( e.getMessage() );
341+
}
342+
}
343+
344+
// This is the old getBytesFromInputStream from JarVisitorFactory before
345+
// it was changed by HHH-7835. Use it as a regression test.
346+
private byte[] getBytesFromInputStream(
347+
InputStream inputStream) throws IOException {
348+
int size;
349+
350+
byte[] entryBytes = new byte[0];
351+
for ( ;; ) {
352+
byte[] tmpByte = new byte[4096];
353+
size = inputStream.read( tmpByte );
354+
if ( size == -1 )
355+
break;
356+
byte[] current = new byte[entryBytes.length + size];
357+
System.arraycopy( entryBytes, 0, current, 0, entryBytes.length );
358+
System.arraycopy( tmpByte, 0, current, entryBytes.length, size );
359+
entryBytes = current;
360+
}
361+
return entryBytes;
362+
}
363+
364+
@Test
365+
@TestForIssue(jiraKey = "HHH-7835")
366+
public void testGetBytesFromZeroInputStream() {
367+
try {
368+
// Ensure that JarVisitorFactory#getBytesFromInputStream
369+
// can handle 0 length streams gracefully.
370+
InputStream emptyStream = new BufferedInputStream(
371+
new FileInputStream( new File(
372+
"src/test/resources/org/hibernate/jpa/test/packaging/empty.txt" ) ) );
373+
int length = JarVisitorFactory.getBytesFromInputStream(
374+
emptyStream ).length;
375+
assertEquals( length, 0 );
376+
emptyStream.close();
377+
}
378+
catch ( Exception e ) {
379+
fail( e.getMessage() );
380+
}
381+
}
310382

311383
private Filter[] getFilters() {
312384
return new Filter[] {

hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/packaging/PackagingTestCase.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373

7474
/**
7575
* @author Hardy Ferentschik
76+
* @author Brett Meyer
7677
*/
7778
public abstract class PackagingTestCase extends BaseCoreFunctionalTestCase {
7879
protected static ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
@@ -335,6 +336,18 @@ protected File buildExternalJar() {
335336
return testPackage;
336337
}
337338

339+
protected File buildLargeJar() {
340+
String fileName = "large.jar";
341+
JavaArchive archive = ShrinkWrap.create( JavaArchive.class, fileName );
342+
// Build a large jar by adding all EntityManager packages and
343+
// subpackages on the classpath.
344+
archive.addPackages(true, "org.hibernate.ejb", "org.hibernate.jpa" );
345+
346+
File testPackage = new File( packageTargetDir, fileName );
347+
archive.as( ZipExporter.class ).exportTo( testPackage, true );
348+
return testPackage;
349+
}
350+
338351
protected File buildWar() {
339352
String fileName = "war.war";
340353
WebArchive archive = ShrinkWrap.create( WebArchive.class, fileName );

hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/packaging/empty.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)