diff options
author | Jan Bartel | 2013-08-09 04:19:04 +0000 |
---|---|---|
committer | Jan Bartel | 2013-08-09 04:19:04 +0000 |
commit | 66620b77b8b524bbeaae1d1516df2994997d1853 (patch) | |
tree | 6f7f7d7708c5cafbeb711b07bc2afbe4a16bca7f | |
parent | 4ce461559739c4280914c806ada4b32dd0f169ee (diff) | |
download | org.eclipse.jetty.project-66620b77b8b524bbeaae1d1516df2994997d1853.tar.gz org.eclipse.jetty.project-66620b77b8b524bbeaae1d1516df2994997d1853.tar.xz org.eclipse.jetty.project-66620b77b8b524bbeaae1d1516df2994997d1853.zip |
414507 Ensure AnnotationParser ignores parent dir hierarchy when checking for hidden dirnames
-rw-r--r-- | jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java | 71 | ||||
-rw-r--r-- | jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java | 150 |
2 files changed, 167 insertions, 54 deletions
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java index 8f2bd36161..8ae4267034 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java @@ -529,7 +529,7 @@ public class AnnotationParser if (!dir.isDirectory() || !dir.exists() || dir.getName().startsWith(".")) return; - + String[] files=dir.list(); for (int f=0;files!=null && f<files.length;f++) { @@ -538,15 +538,20 @@ public class AnnotationParser Resource res = dir.addPath(files[f]); if (res.isDirectory()) parse(res, resolver); - String name = res.getName(); - if (isValidClassFileName(name)) + else { - if ((resolver == null)|| (!resolver.isExcluded(name) && (!isParsed(name) || resolver.shouldOverride(name)))) + String fullname = res.getName(); + String filename = res.getFile().getName(); + + if (isValidClassFileName(filename)) { - Resource r = Resource.newResource(res.getURL()); - scanClass(r.getInputStream()); - } + if ((resolver == null)|| (!resolver.isExcluded(fullname) && (!isParsed(fullname) || resolver.shouldOverride(fullname)))) + { + Resource r = Resource.newResource(res.getURL()); + scanClass(r.getInputStream()); + } + } } } catch (Exception ex) @@ -585,8 +590,8 @@ public class AnnotationParser if (entry.isDirectory()) return; - String name = entry.getName(); - if (isValidClassFileName(name)) + String name = entry.getName(); + if (isValidClassFilePath(name) && isValidClassFileName(name)) { String shortName = name.replace('/', '.').substring(0,name.length()-6); if ((resolver == null) @@ -634,9 +639,7 @@ public class AnnotationParser return; String name = entry.getName(); - - //skip any class files that are in a hidden directory (ie dirname starts with .) - if (isValidClassFileName(name)) + if (isValidClassFilePath(name) && isValidClassFileName(name)) { String shortName = name.replace('/', '.').substring(0,name.length()-6); @@ -702,23 +705,53 @@ public class AnnotationParser * @param path * @return */ - private boolean isValidClassFileName (String path) + private boolean isValidClassFileName (String name) { + //no name cannot be valid + if (name == null || name.length()==0) + return false; + //skip anything that is not a class file - if (!path.toLowerCase(Locale.ENGLISH).endsWith(".class")) + if (!name.toLowerCase(Locale.ENGLISH).endsWith(".class")) + { + if (LOG.isDebugEnabled()) LOG.debug("Not a class: {}",name); return false; - - //skip any classfiles that are not a valid name - int c0 = 0; - int ldir = path.lastIndexOf('/', path.length()-6); + } + + //skip any classfiles that are not a valid java identifier + int c0 = 0; + int ldir = name.lastIndexOf('/', name.length()-6); c0 = (ldir > -1 ? ldir+1 : c0); + if (!Character.isJavaIdentifierStart(name.charAt(c0))) + { + if (LOG.isDebugEnabled()) LOG.debug("Not a java identifier: {}"+name); + return false; + } - if (!Character.isJavaIdentifierStart(path.charAt(c0))) + return true; + } + + + + /** + * Check that the given path does not contain hidden directories + * + * @param path + * @return + */ + private boolean isValidClassFilePath (String path) + { + //no path is not valid + if (path == null || path.length()==0) return false; + //skip any classfiles that are in a hidden directory if (path.startsWith(".") || path.contains("/.")) + { + if (LOG.isDebugEnabled()) LOG.debug("Contains hidden dirs: {}"+path); return false; + } return true; } diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java index 9b22174911..7822095565 100644 --- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java +++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java @@ -19,12 +19,24 @@ package org.eclipse.jetty.annotations; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.annotations.AnnotationParser.Value; +import org.eclipse.jetty.toolchain.test.FS; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.toolchain.test.TestingDir; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.Resource; +import org.junit.Rule; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -33,6 +45,46 @@ import static org.junit.Assert.fail; public class TestAnnotationParser { + + @Rule + public TestingDir testdir = new TestingDir(); + + + + public static class TrackingAnnotationHandler implements DiscoverableAnnotationHandler + { + public final Set<String> foundClasses; + + public TrackingAnnotationHandler() + { + this.foundClasses = new HashSet<String>(); + } + + + public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, + List<Value> values) + { + foundClasses.add(className); + } + + + public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation, + List<Value> values) + { + /* ignore */ + } + + + public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, + List<Value> values) + { + /* ignore */ + } + } + + + + @Test public void testSampleAnnotation() throws Exception { @@ -50,35 +102,20 @@ public class TestAnnotationParser } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, - List<Value> values) + List<Value> values) { - assertEquals ("m", fieldName); - assertEquals (org.objectweb.asm.Type.OBJECT, org.objectweb.asm.Type.getType(fieldType).getSort()); - assertEquals (1, values.size()); - Value anv1 = values.get(0); - assertEquals ("value", anv1.getName()); - assertEquals (7, anv1.getValue()); + assertEquals ("m", fieldName); + assertEquals (org.objectweb.asm.Type.OBJECT, org.objectweb.asm.Type.getType(fieldType).getSort()); + assertEquals (1, values.size()); + Value anv1 = values.get(0); + assertEquals ("value", anv1.getName()); + assertEquals (7, anv1.getValue()); } public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation, List<Value> values) { - System.err.println("Sample annotated method : classname="+className+" methodName="+methodName+" access="+access+" desc="+desc+" signature="+signature); - - org.objectweb.asm.Type retType = org.objectweb.asm.Type.getReturnType(desc); - System.err.println("REturn type = "+retType); - org.objectweb.asm.Type[] params = org.objectweb.asm.Type.getArgumentTypes(desc); - if (params == null) - System.err.println("No params"); - else - System.err.println(params.length+" params"); - - if (exceptions == null) - System.err.println("No exceptions"); - else - System.err.println(exceptions.length+" exceptions"); - assertEquals("org.eclipse.jetty.annotations.ClassA", className); assertTrue(methods.contains(methodName)); assertEquals("org.eclipse.jetty.annotations.Sample", annotation); @@ -102,8 +139,7 @@ public class TestAnnotationParser }); long end = System.currentTimeMillis(); - - System.err.println("Time to parse class: "+((end-start))); + //System.err.println("Time to parse class: "+((end-start))); } @Test @@ -118,11 +154,6 @@ public class TestAnnotationParser List<Value> values) { assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className)); - - for (Value anv: values) - { - System.err.println(anv.toString()); - } } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, @@ -137,18 +168,14 @@ public class TestAnnotationParser { assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className)); assertTrue("a".equals(methodName)); - for (Value anv: values) - { - System.err.println(anv.toString()); - } } } parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Multi", new MultiAnnotationHandler()); parser.parse(classNames, null); } - - + + @Test public void testHiddenFilesInJar () throws Exception { @@ -157,4 +184,57 @@ public class TestAnnotationParser parser.parse(badClassesJar.toURI(), null); //only the valid classes inside bad-classes.jar should be parsed. If any invalid classes are parsed and exception would be thrown here } + + @Test + public void testBasedirExclusion() throws Exception + { + // Build up basedir, which itself has a path segment that violates java package and classnaming. + // The basedir should have no effect on annotation scanning. + // Intentionally using a base director name that starts with a "." + // This mimics what you see in jenkins, hudson, hadoop, solr, camel, and selenium for their + // installed and/or managed webapps + File basedir = testdir.getFile(".base/workspace/classes"); + FS.ensureEmpty(basedir); + + // Copy in class that is known to have annotations. + copyClass(ClassA.class,basedir); + + // Setup Tracker + TrackingAnnotationHandler tracker = new TrackingAnnotationHandler(); + + // Setup annotation scanning + AnnotationParser parser = new AnnotationParser(); + parser.registerAnnotationHandler(Sample.class.getName(), tracker); + + // Parse + parser.parse(Resource.newResource(basedir),null); + + // Validate + assertTrue(tracker.foundClasses.contains(ClassA.class.getName())); + } + + private void copyClass(Class<?> clazz, File basedir) throws IOException + { + String classname = clazz.getName().replace('.',File.separatorChar) + ".class"; + URL url = this.getClass().getResource('/'+classname); + assertTrue(url != null); + + String classpath = classname.substring(0,classname.lastIndexOf(File.separatorChar)); + FS.ensureDirExists(new File(basedir,classpath)); + + InputStream in = null; + OutputStream out = null; + try + { + in = url.openStream(); + out = new FileOutputStream(new File(basedir,classname)); + IO.copy(in,out); + } + finally + { + IO.close(out); + IO.close(in); + } + } + } |