blob: 53622f3b076ed277937485535053e05d8a14b736 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.annotations;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
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.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
public class TestAnnotationParser
{
public static class TrackingAnnotationHandler extends AnnotationParser.AbstractHandler
{
private final String annotationName;
public final Set<String> foundClasses;
public TrackingAnnotationHandler(String annotationName)
{
this.annotationName = annotationName;
this.foundClasses = new HashSet<>();
}
@Override
public void handle(ClassInfo info, String annotation)
{
if (annotation == null || !annotationName.equals(annotation))
return;
foundClasses.add(info.getClassName());
}
}
@Rule
public TestingDir testdir = new TestingDir();
@Test
public void testSampleAnnotation() throws Exception
{
String[] classNames = new String[]
{ "org.eclipse.jetty.annotations.ClassA" };
AnnotationParser parser = new AnnotationParser();
class SampleAnnotationHandler extends AnnotationParser.AbstractHandler
{
private List<String> methods = Arrays.asList("a","b","c","d","l");
public void handle(ClassInfo info, String annotation)
{
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
assertEquals("org.eclipse.jetty.annotations.ClassA",info.getClassName());
}
public void handle(FieldInfo info, String annotation)
{
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
assertEquals("m",info.getFieldName());
assertEquals(org.objectweb.asm.Type.OBJECT,org.objectweb.asm.Type.getType(info.getFieldType()).getSort());
}
public void handle(MethodInfo info, String annotation)
{
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
assertEquals("org.eclipse.jetty.annotations.ClassA",info.getClassInfo().getClassName());
assertTrue(methods.contains(info.getMethodName()));
assertEquals("org.eclipse.jetty.annotations.Sample",annotation);
}
}
//long start = System.currentTimeMillis();
parser.parse(Collections.singleton(new SampleAnnotationHandler()), classNames,new ClassNameResolver()
{
public boolean isExcluded(String name)
{
return false;
}
public boolean shouldOverride(String name)
{
return false;
}
});
//long end = System.currentTimeMillis();
//System.err.println("Time to parse class: " + ((end - start)));
}
@Test
public void testMultiAnnotation() throws Exception
{
String[] classNames = new String[]
{ "org.eclipse.jetty.annotations.ClassB" };
AnnotationParser parser = new AnnotationParser();
class MultiAnnotationHandler extends AnnotationParser.AbstractHandler
{
public void handle(ClassInfo info, String annotation)
{
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
return;
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(info.getClassName()));
}
public void handle(FieldInfo info, String annotation)
{
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
return;
// there should not be any
fail();
}
public void handle(MethodInfo info, String annotation)
{
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
return;
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(info.getClassInfo().getClassName()));
assertTrue("a".equals(info.getMethodName()));
}
}
parser.parse(Collections.singleton(new MultiAnnotationHandler()), classNames,null);
}
@Test
public void testHiddenFilesInJar() throws Exception
{
File badClassesJar = MavenTestingUtils.getTestResourceFile("bad-classes.jar");
AnnotationParser parser = new AnnotationParser();
Set<Handler> emptySet = Collections.emptySet();
parser.parse(emptySet, 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.getPathFile(".base/workspace/classes").toFile();
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();
// Parse
parser.parse(Collections.singleton(tracker), basedir.toURI(),null);
// Validate
Assert.assertThat("Found Class", 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);
Assert.assertThat("URL for: " + classname,url,notNullValue());
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);
}
}
}