Repository: tapestry-5 Updated Branches: refs/heads/master 925e84bb4 -> 5f8deb1fc
TAP5-2096: correctly scan for classes in nested directories most of the changes such as making the inner Job class static were necessary just to make the class testable Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/5f8deb1f Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/5f8deb1f Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/5f8deb1f Branch: refs/heads/master Commit: 5f8deb1fc109af839e670b2d8dd5342ba94a1833 Parents: 925e84b Author: Jochen Kemnade <jochen.kemn...@eddyson.de> Authored: Tue May 20 10:55:30 2014 +0200 Committer: Jochen Kemnade <jochen.kemn...@eddyson.de> Committed: Tue May 20 17:59:09 2014 +0200 ---------------------------------------------------------------------- .../internal/services/ClasspathScannerImpl.java | 22 ++++++---- .../ioc/specs/ClasspathScannerImplSpec.groovy | 44 ++++++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5f8deb1f/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathScannerImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathScannerImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathScannerImpl.java index 27e3777..775bf97 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathScannerImpl.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathScannerImpl.java @@ -37,7 +37,7 @@ public class ClasspathScannerImpl implements ClasspathScanner private final ClasspathURLConverter converter; - private final Pattern FOLDER_NAME_PATTERN = Pattern.compile("^\\p{javaJavaIdentifierStart}[\\p{javaJavaIdentifierPart}]*$", Pattern.CASE_INSENSITIVE); + private static final Pattern FOLDER_NAME_PATTERN = Pattern.compile("^\\p{javaJavaIdentifierStart}[\\p{javaJavaIdentifierPart}]*$", Pattern.CASE_INSENSITIVE); public ClasspathScannerImpl(ClasspathURLConverter converter) @@ -61,13 +61,13 @@ public class ClasspathScannerImpl implements ClasspathScanner assert packagePath != null && packagePath.endsWith("/"); assert matcher != null; - return new Job(matcher).findMatches(packagePath); + return new Job(matcher, contextClassLoader, converter).findMatches(packagePath); } /** * Check whether container supports opening a stream on a dir/package to get a list of its contents. */ - private boolean supportsDirStream(URL packageURL) + private static boolean supportsDirStream(URL packageURL) { InputStream is = null; @@ -99,7 +99,7 @@ public class ClasspathScannerImpl implements ClasspathScanner * @throws java.io.IOException * If error occurs creating jar file */ - private JarFile getAlternativeJarFile(URL url) throws IOException + private static JarFile getAlternativeJarFile(URL url) throws IOException { String urlFile = url.getFile(); // Trim off any suffix - which is prefixed by "!/" on Weblogic @@ -137,10 +137,14 @@ public class ClasspathScannerImpl implements ClasspathScanner /** * Encapsulates the data, result, and queue of deferred operations for performing the scan. */ - class Job + static class Job { final ClasspathMatcher matcher; + final ClasspathURLConverter converter; + + final ClassLoader classloader; + final Set<String> matches = CollectionFactory.newSet(); /** @@ -149,15 +153,17 @@ public class ClasspathScannerImpl implements ClasspathScanner final Stack<IOWork> queue = CollectionFactory.newStack(); - Job(ClasspathMatcher matcher) + Job(ClasspathMatcher matcher, ClassLoader classloader, ClasspathURLConverter converter) { this.matcher = matcher; + this.classloader = classloader; + this.converter = converter; } Set<String> findMatches(String packagePath) throws IOException { - Enumeration<URL> urls = contextClassLoader.getResources(packagePath); + Enumeration<URL> urls = classloader.getResources(packagePath); while (urls.hasMoreElements()) { @@ -231,7 +237,7 @@ public class ClasspathScannerImpl implements ClasspathScanner if (file.isDirectory()) { - final String nestedPackagePath = fileName + "/"; + final String nestedPackagePath = packagePath + fileName + "/"; queue.push(new IOWork() { http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5f8deb1f/tapestry-ioc/src/test/groovy/ioc/specs/ClasspathScannerImplSpec.groovy ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ClasspathScannerImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ClasspathScannerImplSpec.groovy new file mode 100644 index 0000000..72e6eaf --- /dev/null +++ b/tapestry-ioc/src/test/groovy/ioc/specs/ClasspathScannerImplSpec.groovy @@ -0,0 +1,44 @@ +package ioc.specs + +import java.io.File; +import java.net.URL; + +import org.apache.tapestry5.ioc.Locatable; +import org.apache.tapestry5.ioc.internal.services.ClasspathScannerImpl; +import org.apache.tapestry5.ioc.internal.services.ClasspathURLConverterImpl +import org.apache.tapestry5.ioc.internal.util.InternalUtils; +import org.apache.tapestry5.ioc.services.ClasspathMatcher; +import org.apache.tapestry5.ioc.services.ClasspathURLConverter; + +import spock.lang.Specification; + +class ClasspathScannerImplSpec extends Specification { + + // TAP5-2096 + def "can locate classes inside a subpackage, inside an extracted JAR file"() { + setup: + + ClasspathMatcher matchAll = new ClasspathMatcher(){ + boolean matches(String arg0, String arg1) { + true + }; + } + def scannerJob = new ClasspathScannerImpl.Job(matchAll, Thread.currentThread().getContextClassLoader(), new ClasspathURLConverterImpl()) + + when: + URL url = Locatable.class.getResource('Locatable.class'); + scannerJob.scanDir("org/apache/tapestry5/ioc/", new File(url.getPath()).parentFile) + while (!scannerJob.queue.isEmpty()) + { + def queued = scannerJob.queue.pop(); + + queued.run(); + } + def classes = scannerJob.matches + + then: + classes.contains(InternalUtils.class.getName().replaceAll(/\./, "/")+'.class') + } + + +}