001: package com.bm.ejb3metadata;
002:
003: import java.io.IOException;
004: import java.io.InputStream;
005: import java.util.List;
006: import java.util.Map;
007:
008: import org.ejb3unit.asm.ClassReader;
009:
010: import com.bm.ejb3metadata.annotations.analyzer.ScanClassVisitor;
011: import com.bm.ejb3metadata.annotations.exceptions.ResolverException;
012: import com.bm.ejb3metadata.annotations.helper.ResolverHelper;
013: import com.bm.ejb3metadata.annotations.metadata.ClassAnnotationMetadata;
014: import com.bm.ejb3metadata.annotations.metadata.EjbJarAnnotationMetadata;
015: import com.bm.ejb3metadata.finder.ClassFinder;
016:
017: /**
018: * Analyse the matadate for ejb 3.
019: *
020: * @author Daniel Wiese
021: */
022: public final class MetadataAnalyzer {
023:
024: /**
025: * Defines java.lang.Object class.
026: */
027: public static final String JAVA_LANG_OBJECT = "java/lang/Object";
028:
029: private MetadataAnalyzer() {
030:
031: }
032:
033: public static EjbJarAnnotationMetadata initialize(Class<?> toInspect) {
034: final ClassFinder finder = new ClassFinder();
035: final List<String> classes = finder.getListOfClasses(toInspect);
036: return analyzeClasses(classes, toInspect.getName());
037: }
038:
039: public static EjbJarAnnotationMetadata initialize(String className) {
040: final ClassFinder finder = new ClassFinder();
041: final List<String> classes = finder.getListOfClasses(className);
042: return analyzeClasses(classes, className);
043: }
044:
045: private static synchronized EjbJarAnnotationMetadata analyzeClasses(
046: List<String> classes, String className) {
047: EjbJarAnnotationMetadata toReturn = null;
048: try {
049: toReturn = MetadataAnalyzer.analyze(Thread.currentThread()
050: .getContextClassLoader(), classes, null);
051: } catch (ResolverException e) {
052: throw new RuntimeException("Class (" + className
053: + ") canīt be resolved");
054: }
055: return toReturn;
056: }
057:
058: /**
059: * Allow to analyze a given set of classes.
060: *
061: * @param loader
062: * the classloader that will be used to load the classes.
063: * @param classesToAnalyze
064: * the set of classes to analyze.
065: * @param map
066: * a map allowing to give some objects to the enhancer.
067: * @return die metadaten
068: * @throws ResolverException
069: * in error case
070: */
071: private static EjbJarAnnotationMetadata analyze(
072: final ClassLoader loader,
073: final List<String> classesToAnalyze,
074: final Map<String, Object> map) throws ResolverException {
075: EjbJarAnnotationMetadata ejbJarAnnotationMetadata = new EjbJarAnnotationMetadata();
076: ScanClassVisitor scanVisitor = new ScanClassVisitor(
077: ejbJarAnnotationMetadata);
078: // logger.info("ClassLoader used = (" + loader + ")");
079: for (String clazz : classesToAnalyze) {
080: read(clazz, loader, scanVisitor, ejbJarAnnotationMetadata);
081: }
082:
083: ResolverHelper.resolve(ejbJarAnnotationMetadata);
084: return ejbJarAnnotationMetadata;
085:
086: }
087:
088: /**
089: * Visits the given class and all available parent classes.
090: *
091: * @param className
092: * the class to visit.
093: * @param loader
094: * the classloader to use.
095: * @param scanVisitor
096: * the ASM visitor.
097: * @param ejbJarAnnotationMetadata
098: * the structure containing class metadata
099: */
100: private static void read(final String className,
101: final ClassLoader loader,
102: final ScanClassVisitor scanVisitor,
103: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata) {
104: String readingClass = className;
105: if (!className.toLowerCase().endsWith(".class")) {
106: readingClass = className + ".class";
107: }
108:
109: InputStream is = loader.getResourceAsStream(readingClass);
110:
111: try {
112: new ClassReader(is).accept(scanVisitor,
113: ClassReader.SKIP_CODE);
114: } catch (IOException e) {
115: throw new RuntimeException("Cannot read the given class '"
116: + className + "'.", e);
117: }
118:
119: // get the class parsed
120: ClassAnnotationMetadata classMetadata = ejbJarAnnotationMetadata
121: .getClassAnnotationMetadata(className);
122: String super ClassName = classMetadata.getSuperName();
123: if (!super ClassName.equals(JAVA_LANG_OBJECT)) {
124: read(super ClassName, loader, scanVisitor,
125: ejbJarAnnotationMetadata);
126: }
127: try {
128: is.close();
129: } catch (IOException e) {
130: throw new RuntimeException(
131: "Cannot close the input stream for class '"
132: + className + "'.", e);
133: }
134:
135: }
136:
137: }
|