4040package org .glassfish .jersey .server .internal .scanning ;
4141
4242import java .io .FileInputStream ;
43+ import java .io .IOException ;
4344import java .io .InputStream ;
4445import java .util .Enumeration ;
4546import java .util .jar .JarEntry ;
4647import java .util .jar .JarFile ;
48+ import java .util .regex .Pattern ;
4749
4850import org .junit .Before ;
4951import org .junit .Test ;
52+ import org .junit .experimental .theories .DataPoint ;
53+ import org .junit .experimental .theories .Theories ;
54+ import org .junit .experimental .theories .Theory ;
55+ import org .junit .runner .RunWith ;
5056import static org .hamcrest .CoreMatchers .equalTo ;
57+ import static org .junit .Assert .assertFalse ;
5158import static org .junit .Assert .assertThat ;
5259import static org .junit .Assert .fail ;
5360
5461/**
5562 * @author Martin Snyder
5663 */
64+ @ RunWith (Theories .class )
5765public class JarFileScannerTest {
66+ @ DataPoint
67+ public static final boolean RECURSIVE = true ;
68+ @ DataPoint
69+ public static final boolean NON_RECURSIVE = false ;
5870
5971 private String jaxRsApiPath ;
6072
@@ -75,55 +87,78 @@ public void setUp() throws Exception {
7587 }
7688 }
7789
78- /**
79- * Test case for JERSEY-2197, JERSEY-2175.
80- */
8190 @ Test
82- public void testClassEnumeration () throws Exception {
83- // Count actual entries.
84- final JarFile jarFile = new JarFile (jaxRsApiPath );
91+ public void testRecursiveResourceEnumerationOfAllPackages () throws IOException {
92+ final int actualEntries = countJarEntriesByPattern (Pattern .compile (".*\\ .(class|properties|xml)" ));
93+ final int scannedEntries = countJarEntriesUsingScanner ("" , true );
94+ assertThat ("Failed to enumerate all contents of javax.ws.rs-api" , scannedEntries , equalTo (actualEntries ));
95+ }
8596
86- int actualEntries = 0 ;
87- try {
88- final Enumeration <JarEntry > entries = jarFile .entries ();
97+ @ Test
98+ public void testRecursiveClassEnumerationWithExistantPackage () throws IOException {
99+ final int actualEntries = countJarEntriesByPattern (Pattern .compile ("javax/ws/rs/.*\\ .class" ));
100+ final int scannedEntries = countJarEntriesUsingScanner ("javax/ws/rs" , true );
101+ assertThat ("Failed to enumerate all contents of javax.ws.rs-api" , scannedEntries , equalTo (actualEntries ));
102+ }
89103
104+ @ Test
105+ public void testNonRecursiveClassEnumerationWithExistantPackage () throws IOException {
106+ final int actualEntries = countJarEntriesByPattern (Pattern .compile ("javax/ws/rs/[^/]*\\ .class" ));
107+ final int scannedEntries = countJarEntriesUsingScanner ("javax/ws/rs" , false );
108+ assertThat ("Failed to enumerate package 'javax.ws.rs' of javax.ws.rs-api" , scannedEntries , equalTo (actualEntries ));
109+ }
110+
111+ private int countJarEntriesByPattern (final Pattern pattern ) throws IOException {
112+ int matchingEntries = 0 ;
113+
114+ try (final JarFile jarFile = new JarFile (this .jaxRsApiPath )) {
115+ final Enumeration <JarEntry > entries = jarFile .entries ();
90116 while (entries .hasMoreElements ()) {
91117 final JarEntry entry = entries .nextElement ();
92-
93- if (entry .getName ().endsWith (".class" )) {
94- actualEntries ++;
118+ if (pattern .matcher (entry .getName ()).matches ()) {
119+ matchingEntries ++;
95120 }
96121 }
97- } finally {
98- jarFile .close ();
99122 }
100123
101- // Scan entries using Jersey scanner.
102- final InputStream jaxRsApi = new FileInputStream ( jaxRsApiPath );
124+ return matchingEntries ;
125+ }
103126
104- try {
105- final JarFileScanner jarFileScanner = new JarFileScanner ( jaxRsApi , "javax/ws/rs" , true ) ;
127+ private int countJarEntriesUsingScanner ( final String parent , final boolean recursive ) throws IOException {
128+ int scannedEntryCount = 0 ;
106129
107- int scannedEntryCount = 0 ;
130+ try (final InputStream jaxRsApi = new FileInputStream (this .jaxRsApiPath )) {
131+ final JarFileScanner jarFileScanner = new JarFileScanner (jaxRsApi , parent , recursive );
108132 while (jarFileScanner .hasNext ()) {
109133 // Fetch next entry.
110134 jarFileScanner .next ();
111135
136+ // JERSEY-2175 and JERSEY-2197:
112137 // This test doesn't actually do anything with the input stream, but it is important that it
113138 // open/close the stream to simulate actual usage. The reported defect is only exposed if you
114139 // call open/close in some fashion.
115- final InputStream classStream = jarFileScanner .open ();
116-
117- try {
140+ try (final InputStream classStream = jarFileScanner .open ()) {
118141 scannedEntryCount ++;
119- } finally {
120- classStream .close ();
121142 }
122143 }
144+ }
145+
146+ return scannedEntryCount ;
147+ }
148+
149+ @ Theory
150+ public void testClassEnumerationWithNonexistentPackage (final boolean recursive ) throws IOException {
151+ try (final InputStream jaxRsApi = new FileInputStream (this .jaxRsApiPath )) {
152+ final JarFileScanner jarFileScanner = new JarFileScanner (jaxRsApi , "javax/ws/r" , recursive );
153+ assertFalse ("Unexpectedly found package 'javax.ws.r' in javax.ws.rs-api" , jarFileScanner .hasNext ());
154+ }
155+ }
123156
124- assertThat ("Failed to enumerate all contents of javax.ws.rs-api." , scannedEntryCount , equalTo (actualEntries ));
125- } finally {
126- jaxRsApi .close ();
157+ @ Theory
158+ public void testClassEnumerationWithClassPrefix (final boolean recursive ) throws IOException {
159+ try (final InputStream jaxRsApi = new FileInputStream (this .jaxRsApiPath )) {
160+ final JarFileScanner jarFileScanner = new JarFileScanner (jaxRsApi , "javax/ws/rs/GE" , recursive );
161+ assertFalse ("Unexpectedly found package 'javax.ws.rs.GE' in javax.ws.rs-api" , jarFileScanner .hasNext ());
127162 }
128163 }
129164}
0 commit comments