Author: scabanovich
Date: 2007-07-11 08:07:52 -0400 (Wed, 11 Jul 2007)
New Revision: 2382
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/TypeScanner.java
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java
Log:
EXIN-217 ClassFileReader used to scan classes in jars for seam components.
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java 2007-07-11
11:51:04 UTC (rev 2381)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java 2007-07-11
12:07:52 UTC (rev 2382)
@@ -10,6 +10,7 @@
******************************************************************************/
package org.jboss.tools.seam.internal.core.scanner.lib;
+import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;
@@ -25,6 +26,8 @@
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.filesystems.impl.FileSystemsImpl;
import org.jboss.tools.common.model.plugin.ModelPlugin;
@@ -155,36 +158,77 @@
process((IPackageFragment)es[i], ds);
} else if(es[i] instanceof IClassFile) {
IClassFile typeRoot = (IClassFile)es[i];
- IType type = typeRoot.getType();
- String className = type.getFullyQualifiedName();
- if(className.equals("org.jboss.seam.core.TransactionListener")) {
-// System.out.println("!!");
- }
-
- Class<?> cls = null;
- try {
- cls = classPath.getClassLoader().loadClass(className);
- } catch (NoClassDefFoundError e) {
- //ignore
- } catch (ClassNotFoundException e) {
- //ignore
- }
- if(cls == null) continue;
- if(!CLASS_SCANNER.isLikelyComponentSource(cls)) continue;
- LoadedDeclarations ds1 = null;
- try {
- ds1 = CLASS_SCANNER.parse(type, cls, sourcePath);
- } catch (Exception e) {
- SeamCorePlugin.getPluginLog().logError(e);
- }
- if(ds1 != null) {
- ds.add(ds1);
- }
-// System.out.println(className);
+ processWithClassReader(typeRoot, ds);
+// processWithClassLoader(typeRoot, ds);
}
}
}
+ void processWithClassReader(IClassFile typeRoot, LoadedDeclarations ds) {
+ IType type = typeRoot.getType();
+
+ String className = type.getFullyQualifiedName();
+
+ byte[] bs = null;
+
+ try {
+ bs = typeRoot.getBytes();
+ } catch (JavaModelException e) {
+ return;
+ }
+
+ ClassFileReader reader = null;
+
+ try {
+ reader = ClassFileReader.read(new ByteArrayInputStream(bs), className, false);
+ } catch (Throwable t) {
+ //ignore
+ }
+
+ if(reader == null) return;
+ LoadedDeclarations ds1 = null;
+
+ TypeScanner scanner = new TypeScanner();
+ try {
+ if(!scanner.isLikelyComponentSource(reader)) return;
+ ds1 = scanner.parse(type, reader, sourcePath);
+ } catch (Throwable t) {
+ System.out.println("failed " + className);
+// SeamCorePlugin.getPluginLog().logError(t);
+ }
+
+ if(ds1 != null) {
+// System.out.println("declarations found in " + className);
+ ds.add(ds1);
+ }
+ }
+ void processWithClassLoader(IClassFile typeRoot, LoadedDeclarations ds) {
+ IType type = typeRoot.getType();
+ String className = type.getFullyQualifiedName();
+
+ Class<?> cls = null;
+ try {
+ cls = classPath.getClassLoader().loadClass(className);
+ } catch (NoClassDefFoundError e) {
+ //ignore
+ } catch (ClassNotFoundException e) {
+ //ignore
+ }
+ if(cls == null) return;
+ if(!CLASS_SCANNER.isLikelyComponentSource(cls)) return;
+ LoadedDeclarations ds1 = null;
+ try {
+ ds1 = CLASS_SCANNER.parse(type, cls, sourcePath);
+ } catch (Exception e) {
+ SeamCorePlugin.getPluginLog().logError(e);
+ }
+ if(ds1 != null) {
+ ds.add(ds1);
+ }
+// System.out.println(className);
+ }
+
+
}
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/TypeScanner.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/TypeScanner.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/TypeScanner.java 2007-07-11
12:07:52 UTC (rev 2382)
@@ -0,0 +1,274 @@
+package org.jboss.tools.seam.internal.core.scanner.lib;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
+import org.eclipse.jdt.internal.compiler.env.IBinaryField;
+import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.IntConstant;
+import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.jboss.tools.seam.core.BijectedAttributeType;
+import org.jboss.tools.seam.core.SeamCorePlugin;
+import org.jboss.tools.seam.internal.core.AbstractContextVariable;
+import org.jboss.tools.seam.internal.core.BijectedAttribute;
+import org.jboss.tools.seam.internal.core.SeamAnnotatedFactory;
+import org.jboss.tools.seam.internal.core.SeamJavaComponentDeclaration;
+import org.jboss.tools.seam.internal.core.scanner.LoadedDeclarations;
+import org.jboss.tools.seam.internal.core.scanner.java.SeamAnnotations;
+
+public class TypeScanner implements SeamAnnotations {
+
+ /**
+ * Checks if class may be a source of seam components.
+ * @param f
+ * @return
+ */
+ public boolean isLikelyComponentSource(ClassFileReader cls) {
+ return cls != null && isSeamAnnotatedClass(cls);
+ }
+
+ /**
+ * Loads seam components from class.
+ * Returns object that contains loaded components or null;
+ * @param type
+ * @param cls
+ * @param path
+ * @return
+ */
+ public LoadedDeclarations parse(IType type, ClassFileReader cls, IPath path) {
+ if(!isLikelyComponentSource(cls)) return null;
+ LoadedDeclarations ds = new LoadedDeclarations();
+
+ SeamJavaComponentDeclaration component = new SeamJavaComponentDeclaration();
+ component.setSourcePath(path);
+ component.setId(type);
+ component.setType(type);
+ component.setClassName(type.getFullyQualifiedName());
+ process(cls, component, ds);
+
+ ds.getComponents().add(component);
+ for (int i = 0; i < ds.getFactories().size(); i++) {
+ AbstractContextVariable f = (AbstractContextVariable)ds.getFactories().get(i);
+ f.setSourcePath(path);
+ f.getId();
+ }
+ return ds;
+ }
+
+ /**
+ * Check if class has at least one seam annotation.
+ * @param cls
+ * @return
+ */
+ boolean isSeamAnnotatedClass(ClassFileReader cls) {
+ if(cls == null || ((cls.getModifiers() & ClassFileConstants.AccInterface) > 0))
return false;
+ IBinaryAnnotation[] as = cls.getAnnotations();
+ if(as != null) for (int i = 0; i < as.length; i++) {
+ String type = getTypeName(as[i]);
+ if(type.startsWith(SEAM_ANNOTATION_TYPE_PREFIX)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected String getTypeName(IBinaryAnnotation a) {
+ if(a.getTypeName() == null) return "";
+ String t = new String(a.getTypeName());
+ if(t.startsWith("L") && t.endsWith(";")) {
+ t = t.substring(1, t.length() - 1);
+ }
+ t = t.replace('/', '.');
+
+ return t;
+ }
+
+ Map<String,IBinaryAnnotation> getSeamAnnotations(IBinaryAnnotation[] as) {
+ if(as == null || as.length == 0) return null;
+ Map<String,IBinaryAnnotation> map = null;
+ for (int i = 0; i < as.length; i++) {
+ String type = getTypeName(as[i]);
+ if(type.startsWith(SEAM_ANNOTATION_TYPE_PREFIX) ||
+ //TODO put all non-seam relevant annotations to set
+ type.equals(STATEFUL_ANNOTATION_TYPE)) {
+ if(map == null) map = new HashMap<String, IBinaryAnnotation>();
+ map.put(type, as[i]);
+ }
+ }
+ return map;
+ }
+
+ private void process(ClassFileReader cls, SeamJavaComponentDeclaration component,
LoadedDeclarations ds) {
+ Map<String, IBinaryAnnotation> map = getSeamAnnotations(cls.getAnnotations());
+ if(map != null) {
+ IBinaryAnnotation a = map.get(NAME_ANNOTATION_TYPE);
+ if(a != null) {
+ String name = (String)getValue(a, "value");
+ if(name != null) component.setName(name);
+ }
+ a = map.get(SCOPE_ANNOTATION_TYPE);
+ if(a != null) {
+ Object scope = getValue(a, "value");
+ if(scope != null) component.setScope(scope.toString());
+ }
+ a = map.get(INSTALL_ANNOTATION_TYPE);
+ if(a != null) {
+ Object precedence = getValue(a, "precedence");
+ if(precedence instanceof Integer) component.setPrecedence((Integer)precedence);
+ }
+ a = map.get(STATEFUL_ANNOTATION_TYPE);
+ if(a != null) {
+ component.setStateful(true);
+ }
+ }
+ IBinaryMethod[] ms = null;
+ try {
+ ms = cls.getMethods();
+ } catch (NoClassDefFoundError e) {
+ //ignore
+ }
+ if(ms != null) for (int i = 0; i < ms.length; i++) {
+ process(ms[i], component, ds);
+ }
+
+ IBinaryField[] fs = null;
+ try {
+ fs = cls.getFields();
+ } catch (NoClassDefFoundError e) {
+ //ignore
+ }
+ if(fs != null) for (int i = 0; i < fs.length; i++) {
+ //TODO
+ }
+ }
+
+ private void process(IBinaryMethod m, SeamJavaComponentDeclaration component,
LoadedDeclarations ds) {
+ Map<String,IBinaryAnnotation> map = getSeamAnnotations(m.getAnnotations());
+ if(map == null || map.isEmpty()) return;
+ IBinaryAnnotation a = map.get(FACTORY_ANNOTATION_TYPE);
+ if(a != null) {
+ processFactory(m, a, component, ds);
+ }
+ IBinaryAnnotation in = map.get(IN_ANNOTATION_TYPE);
+ IBinaryAnnotation out = map.get(OUT_ANNOTATION_TYPE);
+ if(in != null || out != null) {
+ processBijection(m, in, out, component, ds);
+ }
+ }
+
+ private void processFactory(IBinaryMethod m, IBinaryAnnotation a,
SeamJavaComponentDeclaration component, LoadedDeclarations ds) {
+ if(a == null) return;
+ String name = (String)getValue(a, "value");
+ if(name == null || name.length() == 0) {
+ name = new String(m.getSelector());
+ }
+ SeamAnnotatedFactory factory = new SeamAnnotatedFactory();
+ ds.getFactories().add(factory);
+ IMethod im = findIMethod(component, m);
+
+ factory.setId(im);
+ factory.setSourceMember(im);
+ factory.setName(name);
+
+ Object scope = getValue(a, "scope");
+ if(scope != null) factory.setScopeAsString(scope.toString());
+ Object autoCreate = getValue(a, "autoCreate");
+ if(autoCreate instanceof Boolean) {
+ factory.setAutoCreate((Boolean)autoCreate);
+ }
+ }
+
+ private void processBijection(IBinaryMethod m, IBinaryAnnotation in, IBinaryAnnotation
out, SeamJavaComponentDeclaration component, LoadedDeclarations ds) {
+ if(in == null && out == null) return;
+ BijectedAttribute att = new BijectedAttribute();
+ component.addBijectedAttribute(att);
+
+ BijectedAttributeType[] types = (in == null) ? new
BijectedAttributeType[]{BijectedAttributeType.OUT}
+ : (out == null) ? new BijectedAttributeType[]{BijectedAttributeType.IN}
+ : new BijectedAttributeType[]{BijectedAttributeType.IN, BijectedAttributeType.OUT};
+ att.setTypes(types);
+
+ String name = (String)getValue(in != null ? in : out, "value");
+ if(name == null || name.length() == 0) {
+ name = new String(m.getSelector());
+ }
+ att.setName(name);
+ Object scope = getValue(in != null ? in : out, "scope");
+ if(scope != null) att.setScopeAsString(scope.toString());
+
+ IMember im = findIMethod(component, m);
+ att.setSourceMember(im);
+
+ }
+
+ private String getValue(IBinaryAnnotation a, String method) {
+ try {
+ IBinaryElementValuePair[] ps = a.getElementValuePairs();
+ if(ps != null) for (int i = 0; i < ps.length; i++) {
+ if(method.equals(new String(ps[i].getName()))) {
+ Object v = ps[i].getValue();
+ if(v == null) return null;
+ if(v instanceof EnumConstantSignature) {
+ EnumConstantSignature cs = (EnumConstantSignature)v;
+ char[] cv = cs.getEnumConstantName();
+ return cv == null ? null : new String(cv);
+ } else if(v instanceof Constant) {
+ Constant ic = (Constant)v;
+ return ic.stringValue();
+ }
+ v = v.toString();
+ return (String)v;
+ }
+ }
+ } catch (Throwable e) {
+ SeamCorePlugin.getPluginLog().logError(e);
+ }
+ return null;
+ }
+
+ private IMethod findIMethod(SeamJavaComponentDeclaration component, IBinaryMethod m) {
+ String name = new String(m.getSelector());
+ IType type = (IType)component.getSourceMember();
+ String signature = new String(m.getMethodDescriptor());
+ IMethod im = null;
+ IMethod[] ms = null;
+ try {
+ ms = type.getMethods();
+ } catch (Exception e) {
+ //ignore
+ }
+ if(ms != null) for (int i = 0; i < ms.length; i++) {
+ if(!ms[i].getElementName().equals(name)) continue;
+ //check parameters
+ try {
+ if(ms[i].getParameterNames().length != m.getArgumentNames().length) continue;
+ } catch (Exception e) {
+ continue;
+ }
+ //compare
+ return ms[i];
+ }
+ return null;
+ }
+
+ private IField findIField(SeamJavaComponentDeclaration component, Field m) {
+ IType type = (IType)component.getSourceMember();
+ return type.getField(m.getName());
+ }
+
+}