Merge remote-tracking branch 'origin/jetty-7' into jetty-8

This commit is contained in:
Jan Bartel 2013-08-09 14:46:25 +10:00
commit 6a22a9f5b9
2 changed files with 178 additions and 55 deletions

View File

@ -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;
}

View File

@ -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);
}
}
}