Merge remote-tracking branch 'origin/jetty-7' into jetty-8
This commit is contained in:
commit
6a22a9f5b9
|
@ -733,7 +733,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++)
|
||||
{
|
||||
|
@ -742,15 +742,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)
|
||||
|
@ -790,8 +795,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)
|
||||
|
@ -840,9 +845,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);
|
||||
|
||||
|
@ -907,23 +910,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(path.charAt(c0)))
|
||||
if (!Character.isJavaIdentifierStart(name.charAt(c0)))
|
||||
{
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Not a java identifier: {}"+name);
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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,56 @@ import static org.junit.Assert.fail;
|
|||
|
||||
public class TestAnnotationParser
|
||||
{
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
|
||||
|
||||
public static class TrackingAnnotationHandler implements DiscoverableAnnotationHandler
|
||||
{
|
||||
|
||||
private final String annotationName;
|
||||
public final Set<String> foundClasses;
|
||||
|
||||
public TrackingAnnotationHandler(String annotationName)
|
||||
{
|
||||
this.annotationName = annotationName;
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAnnotationName()
|
||||
{
|
||||
return this.annotationName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSampleAnnotation() throws Exception
|
||||
{
|
||||
|
@ -53,35 +115,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);
|
||||
|
@ -111,8 +158,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
|
||||
|
@ -127,11 +173,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,
|
||||
|
@ -146,10 +187,6 @@ public class TestAnnotationParser
|
|||
{
|
||||
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className));
|
||||
assertTrue("a".equals(methodName));
|
||||
for (Value anv: values)
|
||||
{
|
||||
System.err.println(anv.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -164,8 +201,8 @@ public class TestAnnotationParser
|
|||
parser.registerHandler(new MultiAnnotationHandler());
|
||||
parser.parse(classNames, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testHiddenFilesInJar () throws Exception
|
||||
{
|
||||
|
@ -174,4 +211,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(Sample.class.getName());
|
||||
|
||||
// Setup annotation scanning
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
parser.registerHandler(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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue