/*
* Copyright 2011 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ocpsoft.rewrite.annotation.scan;
import static org.junit.Assert.assertNotNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import javax.servlet.ServletContext;
import org.junit.Test;
import org.mockito.Mockito;
import org.ocpsoft.rewrite.annotation.api.ClassVisitor;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class WebLibFinderTest
{
@Test
public void testWebLibFinder() throws Exception
{
// URLs of simulated directories and files
URL libUrl = new URL("file:/somewhere/WEB-INF/lib/");
URL jarUrl = new URL("file", null, 0, "/somewhere/WEB-INF/lib/mylib.jar", new TestURLStreamHandler());
// Contents of the lib directory
Set<String> libDirectory = new HashSet<String>(Arrays.asList("/WEB-INF/lib/mylib.jar"));
// Create filter accepting all packages
PackageFilter filter = new PackageFilter(null);
// Mock of ServletContext that knows our directories and files
ServletContext servletContext = Mockito.mock(ServletContext.class);
Mockito.when(servletContext.getResource("/WEB-INF/lib/")).thenReturn(libUrl);
Mockito.when(servletContext.getResourcePaths("/WEB-INF/lib/")).thenReturn(libDirectory);
Mockito.when(servletContext.getResource("/WEB-INF/lib/mylib.jar")).thenReturn(jarUrl);
// ClassLoader that knows the test class
ClassLoader classLoader = Mockito.mock(ClassLoader.class);
Mockito.when(classLoader.loadClass(ClassFinderTestBean.class.getName()))
.thenReturn((Class) ClassFinderTestBean.class);
// We will need the ByteCodeFilter
Set<Class<? extends Annotation>> types = new HashSet<Class<? extends Annotation>>();
types.add(TestAnnotation.class);
ByteCodeFilter byteCodeFilter = new ByteCodeFilter(types);
// Mock the visitor for verification
ClassVisitor classVisitor = Mockito.mock(ClassVisitor.class);
// Run finder
WebLibFinder finder = new WebLibFinder(servletContext, classLoader, filter, byteCodeFilter);
finder.findClasses(classVisitor);
// Verify that the PrettyAnnotationHandler has been notified
Mockito.verify(classVisitor).visit(ClassFinderTestBean.class);
}
/**
* A custom {@link URLStreamHandler} that will always return an in-memory JAR archive containing only the
* {@link ClassFinderTestBean} class.
*/
private final class TestURLStreamHandler extends URLStreamHandler
{
protected URLConnection openConnection(URL u) throws IOException
{
return new URLConnection(u)
{
@Override
public void connect() throws IOException
{
// nothing to do
}
@Override
public InputStream getInputStream() throws IOException
{
try
{
// location of the class on the classpath and in the archive
final String classLocation = ClassFinderTestBean.class.getName().replace('.', '/') + ".class";
// read the original class file from the classpath
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream classStream = classLoader.getResourceAsStream(classLocation);
assertNotNull("Cannot find test class", classStream);
// prepare the in-memory JAR file
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
JarOutputStream jarOutput = new JarOutputStream(byteArrayStream);
// write the class file to the archive
jarOutput.putNextEntry(new ZipEntry(classLocation));
byte[] buffer = new byte[255];
for (int len; (len = classStream.read(buffer)) != -1;)
{
jarOutput.write(buffer, 0, len);
}
jarOutput.closeEntry();
// close the JAR archive and return the InputStream
jarOutput.close();
return new ByteArrayInputStream(byteArrayStream.toByteArray());
}
catch (IOException e)
{
throw new IllegalStateException(e);
}
}
};
}
}
}