blob: 99752666b1967a97a64e0b3740aacfccda9e2039 [file] [log] [blame]
package org.testng.internal.annotations;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.testng.TestRunner;
import org.testng.internal.Utils;
import org.testng.log4testng.Logger;
import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.directorywalker.DirectoryScanner;
import com.thoughtworks.qdox.directorywalker.FileVisitor;
import com.thoughtworks.qdox.directorywalker.SuffixFilter;
import com.thoughtworks.qdox.model.AbstractInheritableJavaEntity;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
/**
* This class implements IAnnotationFinder with QDox for JDK 1.4
*
* @author <a href="mailto:cedric@beust.com">Cedric Beust</a>
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
*/
public class JDK14AnnotationFinder implements IAnnotationFinder {
/** This class' loge4testng Logger. */
private static final Logger LOGGER = Logger.getLogger(JDK14AnnotationFinder.class);
private Map<String, List<File>> m_sourceFiles= new HashMap<String, List<File>>();
private Map<String, String> m_parsedClasses= new HashMap<String, String>();
private Map<String, String> m_parsedFiles= new HashMap<String, String>();
private JDK14TagFactory m_tagFactory = new JDK14TagFactory();
private JavaDocBuilder m_docBuilder;
private String[] m_dirPaths;
private IAnnotationTransformer m_transformer;
public JDK14AnnotationFinder(IAnnotationTransformer transformer) {
m_docBuilder = new JavaDocBuilder();
m_transformer = transformer;
}
public void addSourceDirs(String[] dirPaths) {
if(dirPaths == null) {
Utils.log(getClass().getName(), 1, "[WARNING] Array of source directory paths is null");
return;
}
m_dirPaths = dirPaths;
for (int i = 0; i < m_dirPaths.length; i++) {
File dir = new File(m_dirPaths[i]);
if(!dir.exists() || !dir.isDirectory()) {
Utils.log(getClass().getName(), 1, "[WARNING] Invalid source directory " + m_dirPaths[i] + " ignored");
continue;
}
DirectoryScanner scanner = new DirectoryScanner(dir);
scanner.addFilter(new SuffixFilter(".java"));
scanner.scan(new FileVisitor() {
public void visitFile(File currentFile) {
registerSourceFile(currentFile);
}
});
}
}
/**
* Record in an internal map the existence of a source file.
* @param sourcefile the source file
*/
private void registerSourceFile(File sourcefile) {
List<File> files= m_sourceFiles.get(sourcefile.getName());
if(null == files) {
files= new ArrayList<File>();
m_sourceFiles.put(sourcefile.getName(), files);
}
files.add(sourcefile);
}
private boolean addSource(String filePath) {
if(m_parsedFiles.containsKey(filePath)) {
return true;
}
try {
m_docBuilder.addSource(new FileReader(filePath));
m_parsedFiles.put(filePath, filePath);
return true;
}
catch(FileNotFoundException fnfe) {
Utils.log(getClass().getName(), 1, "[WARNING] source file not found: " + filePath + "\n " + fnfe.getMessage());
}
catch(Throwable t) {
Utils.log(getClass().getName(), 1, "[WARNING] cannot parse source: " + filePath + "\n " + t.getMessage());
}
return false;
}
/**
* Must be synch to be assured that a file is not parsed twice
*/
private synchronized JavaClass getClassByName(Class clazz) {
if(m_parsedClasses.containsKey(clazz.getName())) {
JavaClass jc= m_docBuilder.getClassByName(clazz.getName());
return jc;
}
else {
parseSource(clazz);
return getClassByName(clazz);
}
}
/**
* Must be synch to be assured that a file is not parsed twice
*/
private synchronized void parseSource(Class clazz) {
final String className= clazz.getName();
int innerSignPos= className.indexOf('$');
final String fileName = innerSignPos == -1
? className.substring(className.lastIndexOf('.') + 1)
: clazz.getName().substring(className.lastIndexOf('.') + 1, innerSignPos);
List<File> sourcefiles= m_sourceFiles.get(fileName + ".java");
if(null != sourcefiles) {
for(File f: sourcefiles) {
addSource(f.getAbsolutePath());
}
}
m_parsedClasses.put(className, className);
Class superClass= clazz.getSuperclass();
if(null != superClass && !Object.class.equals(superClass)) {
parseSource(superClass);
}
}
public IAnnotation findAnnotation(Class cls, Class annotationClass) {
if(Object.class.equals(cls)) {
return null;
}
IAnnotation result = m_tagFactory.createTag(annotationClass, getClassByName(cls), m_transformer);
transform(result, cls, null, null);
return result;
}
public IAnnotation findAnnotation(Method m, Class annotationClass) {
IAnnotation result = findMethodAnnotation(m.getName(), m.getParameterTypes(),
m.getDeclaringClass(), annotationClass, m_transformer);
transform(result, null, null, m);
return result;
}
public IAnnotation findAnnotation(Constructor m, Class annotationClass) {
String name = stripPackage(m.getName());
IAnnotation result = findMethodAnnotation(name, m.getParameterTypes(), m.getDeclaringClass(),
annotationClass, m_transformer);
transform(result, null, m, null);
return result;
}
private void transform (IAnnotation a, Class testClass, Constructor testConstructor, Method testMethod) {
if (a instanceof ITest) {
m_transformer.transform((ITest) a, testClass, testConstructor, testMethod);
}
}
private String stripPackage(String name) {
return name.substring(name.lastIndexOf('.') + 1);
// String result = name;
// int index = result.lastIndexOf(".");
// if (index > 0) {
// result = result.substring(index + 1);
// }
//
// return result;
}
private IAnnotation findMethodAnnotation(String methodName, Class[] parameterTypes,
Class methodClass, Class annotationClass, IAnnotationTransformer transformer)
{
if(Object.class.equals(methodClass)) {
return null;
}
IAnnotation result = null;
JavaClass jc = getClassByName(methodClass);
if (jc != null) {
List<JavaMethod> methods = new ArrayList<JavaMethod>();
JavaMethod[] allMethods = jc.getMethods();
for (int i = 0; i < allMethods.length; i++) {
JavaMethod jm = allMethods[i];
if (methodsAreEqual(jm, methodName, parameterTypes)) {
methods.add(jm);
}
}
JavaMethod method = null;
// if (methods.size() > 1) {
// ppp("WARNING: method " + methodName + " is overloaded, only considering the first one");
// }
if (methods.size() > 0) {
method = methods.get(0);
result = findTag(annotationClass, result, method, transformer);
}
}
else {
Utils.log(getClass().getName(), 1, "[WARNING] cannot resolve class: " + methodClass.getName());
}
return result;
}
private boolean methodsAreEqual(JavaMethod jm, String methodName, Class[] parameterTypes) {
boolean result = jm.getName().equals(methodName) &&
jm.getParameters().length == parameterTypes.length;
return result;
}
private IAnnotation findTag(Class annotationClass, IAnnotation result,
AbstractInheritableJavaEntity entity, IAnnotationTransformer transformer)
{
return m_tagFactory.createTag(annotationClass, entity, transformer);
}
private static void ppp(String s) {
System.out.println("[JDK14AnnotationFinder] " + s);
}
}