You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by mc...@apache.org on 2011/10/17 12:31:51 UTC
svn commit: r1185095 [3/15] - in /felix/trunk/bundleplugin: ./
src/main/java/aQute/ src/main/java/aQute/bnd/
src/main/java/aQute/bnd/annotation/
src/main/java/aQute/bnd/annotation/component/
src/main/java/aQute/bnd/annotation/metatype/ src/main/java/aQ...
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/ParseSignatureBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/ParseSignatureBuilder.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/ParseSignatureBuilder.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/ParseSignatureBuilder.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,109 @@
+package aQute.bnd.compatibility;
+
+import java.io.*;
+
+import aQute.lib.osgi.*;
+
+public class ParseSignatureBuilder {
+ final Scope root;
+
+ public ParseSignatureBuilder(Scope root) {
+ this.root = root;
+ }
+
+ public void add( Jar jar ) throws Exception {
+ for ( Resource r : jar.getResources().values()) {
+ InputStream in = r.openInputStream();
+ try {
+ parse(in);
+ } finally {
+ in.close();
+ }
+ }
+ }
+
+ public Scope getRoot() { return root; }
+
+
+ public void parse(InputStream in) throws IOException {
+ Clazz clazz = new Clazz("", null);
+
+ clazz.parseClassFile(in, new ClassDataCollector() {
+ Scope s;
+ Scope enclosing;
+ Scope declaring;
+
+ public void classBegin(int access, String name) {
+ s = root.getScope(Scope.classIdentity(name));
+ s.access = Access.modifier(access);
+ s.kind = Kind.CLASS;
+ }
+
+ public void extendsClass(String name) {
+// s.setBase(new GenericType(name));
+ }
+
+ public void implementsInterfaces(String names[]) {
+ s.setParameterTypes(convert(names));
+ }
+
+ GenericType[] convert(String names[]) {
+ GenericType tss[] = new GenericType[names.length];
+ for (int i = 0; i < names.length; i++) {
+// tss[i] = new GenericType(names[i]);
+ }
+ return tss;
+ }
+
+ public void method(Clazz.MethodDef defined) {
+ String descriptor;
+ Kind kind;
+ if (defined.isConstructor()) {
+ descriptor = ":" + defined.descriptor;
+ kind = Kind.CONSTRUCTOR;
+ } else {
+ descriptor = defined.name + ":" + defined.descriptor;
+ kind = Kind.METHOD;
+ }
+ Scope m = s.getScope(descriptor);
+ m.access = Access.modifier(defined.access);
+ m.kind = kind;
+ m.declaring = s;
+ s.add(m);
+ }
+
+ public void field(Clazz.FieldDef defined) {
+ String descriptor = defined.name + ":" + defined.descriptor;
+ Kind kind = Kind.FIELD;
+ Scope m = s.getScope(descriptor);
+ m.access = Access.modifier(defined.access);
+ m.kind = kind;
+ m.declaring = s;
+ s.add(m);
+ }
+
+ public void classEnd() {
+ if (enclosing != null)
+ s.setEnclosing( enclosing );
+ if (declaring != null)
+ s.setDeclaring( declaring );
+ }
+
+ public void enclosingMethod(String cName, String mName, String mDescriptor) {
+ enclosing = root.getScope(Scope.classIdentity(cName));
+ if (mName != null) {
+ enclosing = enclosing.getScope(Scope.methodIdentity(mName, mDescriptor));
+ }
+ }
+
+ public void innerClass(String innerClass, String outerClass, String innerName,
+ int innerClassAccessFlags) {
+ if (outerClass != null && innerClass != null && innerClass.equals(s.name))
+ declaring = root.getScope(Scope.classIdentity(outerClass));
+ }
+ });
+
+
+ }
+}
+
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/ParseSignatureBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/ParseSignatureBuilder.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,220 @@
+package aQute.bnd.compatibility;
+
+import java.lang.reflect.*;
+
+public class RuntimeSignatureBuilder {
+ final Scope root;
+
+ public RuntimeSignatureBuilder(Scope root) {
+ this.root = root;
+ }
+
+ static public String identity(Class<?> c) {
+ return Scope.classIdentity(c.getName());
+ }
+
+ static public String identity(Method m) {
+ return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m
+ .getParameterTypes()));
+ }
+
+ static public String identity(Constructor m) {
+ return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes()));
+ }
+
+ static public String identity(Field m) {
+ return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null));
+ }
+
+ static public String getDescriptor(Class<?> base, Class<?>[] parameters) {
+ StringBuilder sb = new StringBuilder();
+ if (parameters != null) {
+ sb.append("(");
+ for (Class<?> parameter : parameters) {
+ sb.append(getDescriptor(parameter));
+ }
+ sb.append(")");
+ }
+ sb.append(getDescriptor(base));
+ return sb.toString();
+ }
+
+ public Scope add(Class<?> c) {
+ Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(),
+ Kind.CLASS, identity(c), c.getGenericSuperclass(), c.getGenericInterfaces(), null);
+
+ for (Field f : c.getDeclaredFields()) {
+ add(local, // declaring scope
+ local, // enclosing
+ f.getModifiers(), // access modifiers
+ null, // fields have no type vars
+ Kind.FIELD, // field
+ identity(f), // the name of the field
+ f.getGenericType(), // the type of the field
+ null, // fields have no parameters
+ null // fields have no exceptions
+ );
+ }
+
+ for (Constructor constr : c.getConstructors()) {
+ add(local, // class scope
+ local, // enclosing
+ constr.getModifiers(), // access modifiers
+ constr.getTypeParameters(), // Type vars
+ Kind.CONSTRUCTOR, // constructor
+ identity(constr), // <init>(type*)
+ void.class, // Always void
+ constr.getGenericParameterTypes(), // parameters types
+ constr.getGenericExceptionTypes() // exception types
+ );
+ }
+
+ for (Method m : c.getDeclaredMethods()) {
+ if (m.getDeclaringClass() != Object.class) {
+ add(local, // class scope
+ local, // enclosing
+ m.getModifiers(), // access modifiers
+ m.getTypeParameters(), Kind.METHOD, // method
+ identity(m), // <name>(type*)return
+ m.getGenericReturnType(), // return type
+ m.getGenericParameterTypes(), // parameter types
+ m.getGenericExceptionTypes() // exception types
+ );
+ }
+ }
+
+ return local;
+ }
+
+ private Scope getEnclosingScope(Class<?> c) {
+ Method m = c.getEnclosingMethod();
+ if (m != null) {
+ Scope s = getGlobalScope(m.getDeclaringClass());
+ return s.getScope(identity(m));
+ }
+// TODO
+// Constructor cnstr = c.getEnclosingConstructor();
+// if (m != null) {
+// Scope s = getGlobalScope(cnstr.getDeclaringClass());
+// return s.getScope(identity(cnstr));
+//
+// }
+ Class<?> enclosingClass = c.getEnclosingClass();
+ if (enclosingClass != null) {
+ return getGlobalScope(enclosingClass);
+ }
+
+ return null;
+ }
+
+ private Scope getGlobalScope(Class<?> c) {
+ if (c == null)
+ return null;
+ String id = identity(c);
+ return root.getScope(id);
+ }
+
+ private Scope add(Scope declaring, Scope enclosing, int modifiers,
+ TypeVariable<?>[] typeVariables, Kind kind, String id, Type mainType,
+ Type[] parameterTypes, Type exceptionTypes[]) {
+
+ Scope scope = declaring.getScope(id);
+ assert scope.access == Access.UNKNOWN;
+ scope.setAccess(Access.modifier(modifiers));
+ scope.setKind(kind);
+ scope.setGenericParameter(convert(typeVariables));
+ scope.setBase(convert(scope,mainType));
+ scope.setParameterTypes(convert(parameterTypes));
+ scope.setExceptionTypes(convert(exceptionTypes));
+ scope.setDeclaring(declaring);
+ scope.setEnclosing(enclosing);
+ return scope;
+ }
+
+ private GenericType convert(Scope source, Type t) {
+ if (t instanceof ParameterizedType) {
+ // C<P..>
+ ParameterizedType pt = (ParameterizedType) t;
+ /*Scope reference =*/ root.getScope(identity((Class<?>)pt.getRawType()));
+ Type args[] = pt.getActualTypeArguments();
+ GenericType[] arguments = new GenericType[args.length];
+ int n = 0;
+ for (Type arg : args)
+ arguments[n++] = convert(source,arg);
+// return new GenericType(reference,null,arguments);
+
+ } else if (t instanceof TypeVariable) {
+// TypeVariable tv = (TypeVariable) t;
+// return new GenericType(source,tv.getName(), null);
+ } else if (t instanceof WildcardType) {
+// WildcardType wc = (WildcardType) t;
+// wc.
+ } else if (t instanceof GenericArrayType) {
+
+ }
+ if (t instanceof Class<?>) {
+// raw = ((Class<?>) t).getName() + ";";
+ } else
+ throw new IllegalArgumentException(t.toString());
+
+ return null;
+ }
+
+ private GenericParameter[] convert(TypeVariable vars[]) {
+ if (vars == null)
+ return null;
+
+ GenericParameter out[] = new GenericParameter[vars.length];
+ for (int i = 0; i < vars.length; i++) {
+ GenericType gss[] = convert(vars[i].getBounds());
+ out[i] = new GenericParameter(vars[i].getName(), gss);
+ }
+ return out;
+ }
+
+ private GenericType[] convert(Type[] parameterTypes) {
+ if (parameterTypes == null || parameterTypes.length == 0)
+ return GenericType.EMPTY;
+
+ GenericType tss[] = new GenericType[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ //tss[i] = new GenericType(parameterTypes[i]);
+ }
+ return tss;
+ }
+
+ private static String getDescriptor(Class<?> c) {
+ StringBuilder sb = new StringBuilder();
+ if (c.isPrimitive()) {
+ if (c == boolean.class)
+ sb.append("Z");
+ else if (c == byte.class)
+ sb.append("Z");
+ else if (c == char.class)
+ sb.append("C");
+ else if (c == short.class)
+ sb.append("S");
+ else if (c == int.class)
+ sb.append("I");
+ else if (c == long.class)
+ sb.append("J");
+ else if (c == float.class)
+ sb.append("F");
+ else if (c == double.class)
+ sb.append("D");
+ else if (c == void.class)
+ sb.append("V");
+ else
+ throw new IllegalArgumentException("unknown primitive type: " + c);
+ } else if (c.isArray()) {
+ sb.append("[");
+ sb.append(getDescriptor(c));
+ } else {
+ sb.append("L");
+ sb.append(c.getName().replace('.', '/'));
+ sb.append(";");
+ }
+ return sb.toString();
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Scope.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Scope.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Scope.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Scope.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,166 @@
+package aQute.bnd.compatibility;
+
+import java.io.*;
+import java.util.*;
+
+public class Scope {
+ final Map<String, Scope> children = new LinkedHashMap<String, Scope>();
+
+ // class: slashed name
+ // field: name ":" typed
+ // constructor: ":(" typed* ")" typed
+ // method: name ":(" typed* ")" typed
+ final String name;
+
+ Access access;
+ Kind kind;
+ Scope enclosing;
+ Scope declaring;
+ GenericParameter typeVars[];
+ Map<String, String[]> name2bounds;
+
+ // class: super
+ // field: type
+ // constructor: void
+ // method: return
+ GenericType base;
+
+ // class: interfaces
+ // constructor: args
+ // method: args
+ GenericType[] parameters;
+
+ // constructor: exceptions
+ // method: exceptions
+ GenericType[] exceptions;
+
+ // class: super interfaces*
+ // field: type
+ // constructor: void arguments*
+ // method: return arguments*
+
+ public Scope(Access access, Kind kind, String name) {
+ this.access = access;
+ this.kind = kind;
+ this.name = name;
+ }
+
+ Scope getScope(String name) {
+ Scope s = children.get(name);
+ if (s != null)
+ return s;
+
+ s = new Scope(Access.UNKNOWN, Kind.UNKNOWN, name);
+ children.put(name, s);
+ s.declaring = this;
+ return s;
+ }
+
+ public void setParameterTypes(GenericType[] convert) {
+ this.parameters = convert;
+ }
+
+ public void setExceptionTypes(GenericType[] convert) {
+ this.exceptions = convert;
+ }
+
+ public void setBase(GenericType typeSignature) {
+ base = typeSignature;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ if ( typeVars != null && typeVars.length !=0) {
+ sb.append("<");
+ for ( GenericParameter v : typeVars) {
+ sb.append(v);
+ }
+ sb.append(">");
+ }
+ sb.append(access.toString());
+ sb.append(" ");
+ sb.append(kind.toString());
+ sb.append( " ");
+ sb.append( name );
+ return sb.toString();
+ }
+
+ public void report(Appendable a, int indent) throws IOException {
+ for (int i = 0; i < indent; i++)
+ a.append(" ");
+ a.append(toString());
+ a.append("\n");
+ for (Scope s : children.values())
+ s.report(a, indent + 1);
+ }
+
+ public void add(Scope m) {
+ children.put(m.name, m);
+
+ }
+
+ public void setDeclaring(Scope declaring) {
+ this.declaring = declaring;
+ }
+
+ public void setAccess(Access access) {
+ this.access = access;
+ }
+
+ public void setEnclosing(Scope enclosing) {
+ this.enclosing = enclosing;
+ if (this.enclosing != null) {
+ this.enclosing.add(this);
+ }
+ }
+
+ public boolean isTop() {
+ return enclosing == null;
+ }
+
+ public void setKind(Kind kind) {
+ this.kind = kind;
+ }
+
+ static public String classIdentity(String name) {
+ return name.replace('.', '/');
+ }
+
+ static public String methodIdentity(String name, String descriptor) {
+ return name + ":" + descriptor;
+ }
+
+ static public String constructorIdentity(String descriptor) {
+ return ":" + descriptor;
+ }
+
+ static public String fieldIdentity(String name, String descriptor) {
+ return name + ":" + descriptor;
+ }
+
+ public void cleanRoot() {
+ Iterator<Map.Entry<String, Scope>> i = children.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry<String, Scope> entry = i.next();
+ if (!entry.getValue().isTop())
+ i.remove();
+ }
+ }
+
+ public void prune(EnumSet<Access> level) {
+ Iterator<Map.Entry<String, Scope>> i = children.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry<String, Scope> entry = i.next();
+ if (!level.contains(entry.getValue().access))
+ i.remove();
+ else
+ entry.getValue().prune(level);
+ }
+ }
+
+ public void setGenericParameter(GenericParameter[] typeVars) {
+ this.typeVars = typeVars;
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Scope.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Scope.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/SignatureGenerator.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/SignatureGenerator.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/SignatureGenerator.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/SignatureGenerator.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,125 @@
+package aQute.bnd.compatibility;
+
+
+public class SignatureGenerator {
+// enum ACCESS {
+//// PUBLIC("+"), PROTECTED("|"), PACKAGE_PRIVATE(""), PRIVATE("-");
+//// final String repr;
+////
+//// ACCESS(String s) {
+//// repr = s;
+//// }
+////
+//// public String toString() {
+//// return repr;
+//// }
+// }
+//
+// public static void main(String args[]) throws Exception {
+// final PrintStream out = System.out;
+//
+// Clazz c = new Clazz("x", new FileResource(new File(
+// "src/aQute/bnd/compatibility/SignatureGenerator.class")));
+// c.parseClassFileWithCollector(new ClassDataCollector() {
+// public void classBegin(int access, String name) {
+// out.print(name);
+// out.println(access(access));
+// }
+//
+// private ACCESS access(int access) {
+// if (Modifier.isPublic(access))
+// return ACCESS.PUBLIC;
+//
+// throw new IllegalArgumentException();
+// }
+//
+// public void extendsClass(String name) {
+// }
+//
+// public void implementsInterfaces(String name[]) {
+// }
+//
+// public void addReference(String token) {
+// }
+//
+// public void annotation(Annotation annotation) {
+// }
+//
+// public void parameter(int p) {
+// }
+//
+// public void method(Clazz.MethodDef defined) {
+// if (defined.isConstructor())
+// constructor(defined.access, defined.descriptor);
+// else
+// method(defined.access, defined.name, defined.descriptor);
+// }
+//
+// public void field(Clazz.FieldDef defined) {
+// field(defined.access, defined.name, defined.descriptor);
+// }
+//
+// public void reference(Clazz.MethodDef referenced) {
+// }
+//
+// public void reference(Clazz.FieldDef referenced) {
+// }
+//
+// public void classEnd() {
+// }
+//
+// @Deprecated// Will really be removed!
+// public void field(int access, String name, String descriptor) {
+// }
+//
+// @Deprecated// Will really be removed!
+// public void constructor(int access, String descriptor) {
+// }
+//
+// @Deprecated// Will really be removed!
+// public void method(int access, String name, String descriptor) {
+// }
+//
+// /**
+// * The EnclosingMethod attribute
+// *
+// * @param cName
+// * The name of the enclosing class, never null. Name is
+// * with slashes.
+// * @param mName
+// * The name of the enclosing method in the class with
+// * cName or null
+// * @param mDescriptor
+// * The descriptor of this type
+// */
+// public void enclosingMethod(String cName, String mName, String mDescriptor) {
+//
+// }
+//
+// /**
+// * The InnerClass attribute
+// *
+// * @param innerClass
+// * The name of the inner class (with slashes). Can be
+// * null.
+// * @param outerClass
+// * The name of the outer class (with slashes) Can be
+// * null.
+// * @param innerName
+// * The name inside the outer class, can be null.
+// * @param modifiers
+// * The access flags
+// */
+// public void innerClass(String innerClass, String outerClass, String innerName,
+// int innerClassAccessFlags) {
+// }
+//
+// public void signature(String signature) {
+// }
+//
+// public void constant(Object object) {
+// }
+//
+// });
+// }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/SignatureGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/SignatureGenerator.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Signatures.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Signatures.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Signatures.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Signatures.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) OSGi Alliance (2009, 2010). All Rights Reserved.
+ *
+ * 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 aQute.bnd.compatibility;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * This class is compiled against 1.5 or later to provide access to the generic
+ * signatures. It can convert a Class, Field, Method or constructor to a generic
+ * signature and it can normalize a signature. Both are methods. Normalized
+ * signatures can be string compared and match even if the type variable names
+ * differ.
+ *
+ * @version $Id$
+ */
+public class Signatures {
+
+
+ /**
+ * Check if the environment has generics, i.e. later than
+ * Java 5 VM.
+ *
+ * @return true if generics are supported
+ * @throws Exception
+ */
+ public boolean hasGenerics() throws Exception {
+ try {
+ call( Signatures.class, "getGenericSuperClass");
+ return true;
+ } catch( NoSuchMethodException mnfe ) {
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Helper class to track an index in a string.
+ */
+ class Rover {
+ final String s;
+ int i;
+
+ public Rover(String s) {
+ this.s = s;
+ i = 0;
+ }
+
+ char peek() {
+ return s.charAt(i);
+ }
+
+ char take() {
+ return s.charAt(i++);
+ }
+
+ char take(char c) {
+ char x = s.charAt(i++);
+ if (c != x)
+ throw new IllegalStateException("get() expected " + c
+ + " but got + " + x);
+ return x;
+ }
+
+ public String upTo(String except) {
+ int start = i;
+ while (except.indexOf(peek()) < 0)
+ take();
+ return s.substring(start, i);
+ }
+
+ public boolean isEOF() {
+ return i >= s.length();
+ }
+
+ }
+
+ /**
+ * Calculate the generic signature of a Class,Method,Field, or Constructor.
+ * @param f
+ * @return
+ * @throws Exception
+ */
+ public String getSignature(Object c) throws Exception {
+ if( c instanceof Class<?>)
+ return getSignature((Class<?>)c);
+ if( c instanceof Constructor<?>)
+ return getSignature((Constructor<?>)c);
+ if( c instanceof Method)
+ return getSignature((Method)c);
+ if( c instanceof Field)
+ return getSignature((Field)c);
+
+ throw new IllegalArgumentException(c.toString());
+ }
+
+ /**
+ * Calculate the generic signature of a Class. A Class consists of:
+ *
+ * <pre>
+ * class ::= declaration? reference reference*
+ * </pre>
+ *
+ *
+ * @param f
+ * @return
+ * @throws Exception
+ */
+ public String getSignature(Class< ? > c) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ declaration(sb, c);
+ reference(sb, call(c, "getGenericSuperclass"));
+ for (Object type : (Object[]) call(c,"getGenericInterfaces")) {
+ reference(sb, type);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Calculate the generic signature of a Method. A Method consists of:
+ *
+ * <pre>
+ * method ::= declaration? '(' reference* ')' reference
+ * </pre>
+ *
+ * @param c
+ * @return
+ * @throws Exception
+ */
+ public String getSignature(Method m) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ declaration(sb, m);
+ sb.append('(');
+ for (Object type : (Object[]) call(m,"getGenericParameterTypes")) {
+ reference(sb, type);
+ }
+ sb.append(')');
+ reference(sb, call(m,"getGenericReturnType"));
+ return sb.toString();
+ }
+
+ /**
+ * Calculate the generic signature of a Constructor. A Constructor consists
+ * of:
+ *
+ * <pre>
+ * constructor ::= declaration? '(' reference* ')V'
+ * </pre>
+ *
+ * @param c
+ * @return
+ * @throws Exception
+ */
+ public String getSignature(Constructor< ? > c) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ declaration(sb, c);
+ sb.append('(');
+ for (Object type : (Object[]) call(c,"getGenericParameterTypes")) {
+ reference(sb, type);
+ }
+ sb.append(')');
+ reference(sb, void.class);
+ return sb.toString();
+ }
+
+ /**
+ * Calculate the generic signature of a Field. A Field consists of:
+ *
+ * <pre>
+ * constructor ::= reference
+ * </pre>
+ *
+ * @param c
+ * @return
+ * @throws Exception
+ */
+ public String getSignature(Field f) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ Object t = call(f,"getGenericType");
+ reference(sb, t);
+ return sb.toString();
+ }
+
+/**
+ * Classes, Methods, or Constructors can have a declaration that provides
+ * nested a scope for type variables. A Method/Constructor inherits
+ * the type variables from its class and a class inherits its type variables
+ * from its outer class. The declaration consists of the following
+ * syntax:
+ * <pre>
+ * declarations ::= '<' declaration ( ',' declaration )* '>'
+ * declaration ::= identifier ':' declare
+ * declare ::= types | variable
+ * types ::= ( 'L' class ';' )? ( ':' 'L' interface ';' )*
+ * variable ::= 'T' id ';'
+ * </pre>
+ *
+ * @param sb
+ * @param gd
+ * @throws Exception
+ */
+ private void declaration(StringBuffer sb, Object gd) throws Exception {
+ Object[] typeParameters = (Object[]) call(gd,"getTypeParameters");
+ if (typeParameters.length > 0) {
+ sb.append('<');
+ for (Object tv : typeParameters) {
+ sb.append( call(tv,"getName"));
+
+ Object[] bounds = (Object[]) call(tv,"getBounds");
+ if (bounds.length > 0 && isInterface(bounds[0])) {
+ sb.append(':');
+ }
+ for (int i = 0; i < bounds.length; i++) {
+ sb.append(':');
+ reference(sb, bounds[i]);
+ }
+ }
+ sb.append('>');
+ }
+ }
+
+ /**
+ * Verify that the type is an interface.
+ *
+ * @param type the type to check.
+ * @return true if this is a class that is an interface or a Parameterized
+ * Type that is an interface
+ * @throws Exception
+ */
+ private boolean isInterface(Object type) throws Exception {
+ if (type instanceof Class)
+ return (((Class< ? >) type).isInterface());
+
+ if ( isInstance(type.getClass(), "java.lang.reflect.ParameterizedType"))
+ return isInterface(call(type,"getRawType"));
+
+ return false;
+ }
+
+
+/**
+ * This is the heart of the signature builder. A reference is used
+ * in a lot of places. It referes to another type.
+ * <pre>
+ * reference ::= array | class | primitive | variable
+ * array ::= '[' reference
+ * class ::= 'L' body ( '.' body )* ';'
+ * body ::= id ( '<' ( wildcard | reference )* '>' )?
+ * variable ::= 'T' id ';'
+ * primitive ::= PRIMITIVE
+ * </pre>
+ *
+ * @param sb
+ * @param t
+ * @throws Exception
+ */
+ private void reference(StringBuffer sb, Object t) throws Exception {
+
+ if ( isInstance(t.getClass(),"java.lang.reflect.ParameterizedType")) {
+ sb.append('L');
+ parameterizedType(sb, t);
+ sb.append(';');
+ return;
+ }
+ else
+ if ( isInstance(t.getClass(), "java.lang.reflect.GenericArrayType")) {
+ sb.append('[');
+ reference(sb, call(t,"getGenericComponentType"));
+ }
+ else
+ if ( isInstance(t.getClass(), "java.lang.reflect.WildcardType")) {
+ Object[] lowerBounds = (Object[]) call(t, "getLowerBounds");
+ Object[] upperBounds = (Object[]) call(t, "getUpperBounds");
+
+ if (upperBounds.length == 1
+ && upperBounds[0] == Object.class)
+ upperBounds = new Object[0];
+
+ if (upperBounds.length != 0) {
+ // extend
+ for (Object upper : upperBounds) {
+ sb.append('+');
+ reference(sb, upper);
+ }
+ }
+ else
+ if (lowerBounds.length != 0) {
+ // super, can only be one by the language
+ for (Object lower : lowerBounds) {
+ sb.append('-');
+ reference(sb, lower);
+ }
+ }
+ else
+ sb.append('*');
+ }
+ else
+ if ( isInstance(t.getClass(),"java.lang.reflect.TypeVariable")) {
+ sb.append('T');
+ sb.append( call(t,"getName"));
+ sb.append(';');
+ }
+ else
+ if (t instanceof Class< ? >) {
+ Class< ? > c = (Class< ? >) t;
+ if (c.isPrimitive()) {
+ sb.append(primitive(c));
+ }
+ else {
+ sb.append('L');
+ String name = c.getName().replace('.', '/');
+ sb.append(name);
+ sb.append(';');
+ }
+ }
+ }
+
+ /**
+ * Creates the signature for a Parameterized Type.
+ *
+ * A Parameterized Type has a raw class and a set of type variables.
+ *
+ * @param sb
+ * @param pt
+ * @throws Exception
+ */
+ private void parameterizedType(StringBuffer sb, Object pt) throws Exception {
+ Object owner = call(pt,"getOwnerType");
+ String name = ((Class< ? >) call(pt,"getRawType")).getName()
+ .replace('.', '/');
+ if (owner != null) {
+ if ( isInstance(owner.getClass(), "java.lang.reflect.ParameterizedType"))
+ parameterizedType(sb, owner);
+ else
+ sb.append(((Class< ? >) owner).getName().replace('.', '/'));
+ sb.append('.');
+ int n = name.lastIndexOf('$');
+ name = name.substring(n + 1);
+ }
+ sb.append(name);
+
+ sb.append('<');
+ for (Object parameterType : (Object[]) call(pt,"getActualTypeArguments")) {
+ reference(sb, parameterType);
+ }
+ sb.append('>');
+
+ }
+
+ /**
+ * Handle primitives, these need to be translated to a single char.
+ *
+ * @param type the primitive class
+ * @return the single char associated with the primitive
+ */
+ private char primitive(Class< ? > type) {
+ if (type == byte.class)
+ return 'B';
+ else
+ if (type == char.class)
+ return 'C';
+ else
+ if (type == double.class)
+ return 'D';
+ else
+ if (type == float.class)
+ return 'F';
+ else
+ if (type == int.class)
+ return 'I';
+ else
+ if (type == long.class)
+ return 'J';
+ else
+ if (type == short.class)
+ return 'S';
+ else
+ if (type == boolean.class)
+ return 'Z';
+ else
+ if (type == void.class)
+ return 'V';
+ else
+ throw new IllegalArgumentException(
+ "Unknown primitive type "
+ + type);
+ }
+
+ /**
+ * Normalize a signature to make sure the name of the variables are always
+ * the same. We change the names of the type variables to _n, where n is an
+ * integer. n is incremented for every new name and already used names are
+ * replaced with the _n name.
+ *
+ * @return a normalized signature
+ */
+
+ public String normalize(String signature) {
+ StringBuffer sb = new StringBuffer();
+ Map<String, String> map = new HashMap<String, String>();
+ Rover rover = new Rover(signature);
+ declare(sb, map, rover);
+
+ if (rover.peek() == '(') {
+ // method or constructor
+ sb.append(rover.take('('));
+ while (rover.peek() != ')') {
+ reference(sb, map, rover, true);
+ }
+ sb.append(rover.take(')'));
+ reference(sb, map, rover, true); // return type
+ }
+ else {
+ // field or class
+ reference(sb, map, rover, true); // field type or super class
+ while (!rover.isEOF()) {
+ reference(sb, map, rover, true); // interfaces
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * The heart of the routine. Handle a reference to a type. Can be
+ * an array, a class, a type variable, or a primitive.
+ *
+ * @param sb
+ * @param map
+ * @param rover
+ * @param primitivesAllowed
+ */
+ private void reference(StringBuffer sb, Map<String, String> map,
+ Rover rover, boolean primitivesAllowed) {
+
+ char type = rover.take();
+ sb.append(type);
+
+ if (type == '[') {
+ reference(sb, map, rover, true);
+ }
+ else
+ if (type == 'L') {
+ String fqnb = rover.upTo("<;.");
+ sb.append(fqnb);
+ body(sb, map, rover);
+ while (rover.peek() == '.') {
+ sb.append(rover.take('.'));
+ sb.append(rover.upTo("<;."));
+ body(sb, map, rover);
+ }
+ sb.append(rover.take(';'));
+ }
+ else
+ if (type == 'T') {
+ String name = rover.upTo(";");
+ name = assign(map, name);
+ sb.append(name);
+ sb.append(rover.take(';'));
+ }
+ else {
+ if (!primitivesAllowed)
+ throw new IllegalStateException(
+ "Primitives are not allowed without an array");
+ }
+ }
+
+ /**
+ * Because classes can be nested the body handles the part that can
+ * be nested, the reference handles the enclosing L ... ;
+ *
+ * @param sb
+ * @param map
+ * @param rover
+ */
+ private void body(StringBuffer sb, Map<String, String> map, Rover rover) {
+ if (rover.peek() == '<') {
+ sb.append(rover.take('<'));
+ while (rover.peek() != '>') {
+ switch (rover.peek()) {
+ case 'L' :
+ case '[' :
+ reference(sb, map, rover, false);
+ break;
+
+ case 'T' :
+ String name;
+ sb.append(rover.take('T')); // 'T'
+ name = rover.upTo(";");
+ sb.append(assign(map, name));
+ sb.append(rover.take(';'));
+ break;
+
+ case '+' : // extends
+ case '-' : // super
+ sb.append(rover.take());
+ reference(sb, map, rover, false);
+ break;
+
+ case '*' : // wildcard
+ sb.append(rover.take());
+ break;
+
+ }
+ }
+ sb.append(rover.take('>'));
+ }
+ }
+
+ /**
+ * Handle the declaration part.
+ *
+ * @param sb
+ * @param map
+ * @param rover
+ */
+ private void declare(StringBuffer sb, Map<String, String> map, Rover rover) {
+ char c = rover.peek();
+ if (c == '<') {
+ sb.append(rover.take('<'));
+
+ while (rover.peek() != '>') {
+ String name = rover.upTo(":");
+ name = assign(map, name);
+ sb.append(name);
+ typeVar: while (rover.peek() == ':') {
+ sb.append(rover.take(':'));
+ switch (rover.peek()) {
+ case ':' : // empty class cases
+ continue typeVar;
+
+ default :
+ reference(sb, map, rover, false);
+ break;
+ }
+ }
+ }
+ sb.append(rover.take('>'));
+ }
+ }
+
+ /**
+ * Handles the assignment of type variables to index names so that
+ * we have a normalized name for each type var.
+ *
+ * @param map the map with variables.
+ * @param name The name of the variable
+ * @return the index name, like _1
+ */
+ private String assign(Map<String, String> map, String name) {
+ if (map.containsKey(name))
+ return map.get(name);
+ else {
+ int n = map.size();
+ map.put(name, "_" + n);
+ return "_" + n;
+ }
+ }
+
+ private boolean isInstance(Class<?> type, String string) {
+ if ( type == null)
+ return false;
+
+ if ( type.getName().equals(string))
+ return true;
+
+ if ( isInstance( type.getSuperclass(), string))
+ return true;
+
+ for ( Class<?> intf : type.getInterfaces()) {
+ if ( isInstance(intf,string))
+ return true;
+ }
+ return false;
+ }
+
+ private Object call(Object gd, String string) throws Exception {
+ Method m = gd.getClass().getMethod(string);
+ return m.invoke(gd);
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Signatures.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/compatibility/Signatures.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/AnnotationReader.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/AnnotationReader.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/AnnotationReader.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/AnnotationReader.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,344 @@
+package aQute.bnd.component;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import org.osgi.service.component.annotations.*;
+
+import aQute.lib.collections.*;
+import aQute.lib.osgi.*;
+import aQute.libg.version.*;
+
+public class AnnotationReader extends ClassDataCollector {
+ final static String[] EMPTY = new String[0];
+ final static Pattern PROPERTY_PATTERN = Pattern
+ .compile("([^=]+(:(Boolean|Byte|Char|Short|Integer|Long|Float|Double|String))?)\\s*=(.*)");
+
+ public static final Version V1_1 = new Version("1.1.0"); // "1.1.0"
+ public static final Version V1_2 = new Version("1.2.0"); // "1.1.0"
+ static Pattern BINDDESCRIPTOR = Pattern
+ .compile("\\(((L([^;]+);)(Ljava/util/Map;)?|Lorg/osgi/framework/ServiceReference;)\\)V");
+ static Pattern BINDMETHOD = Pattern
+ .compile("(set|bind|add)?(.*)");
+
+ static Pattern ACTIVATEDESCRIPTOR = Pattern
+ .compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)V");
+ static Pattern REFERENCEBINDDESCRIPTOR = Pattern
+ .compile("\\(Lorg/osgi/framework/ServiceReference;\\)V");
+
+ ComponentDef component = new ComponentDef();
+
+ Clazz clazz;
+ String interfaces[];
+ String methodDescriptor;
+ String method;
+ String className;
+ int methodAccess;
+ Analyzer analyzer;
+ MultiMap<String, String> methods = new MultiMap<String, String>();
+ String extendsClass;
+
+ AnnotationReader(Analyzer analyzer, Clazz clazz) {
+ this.analyzer = analyzer;
+ this.clazz = clazz;
+ }
+
+ public static ComponentDef getDefinition(Clazz c, Analyzer analyzer) throws Exception {
+ AnnotationReader r = new AnnotationReader(analyzer, c);
+
+ return r.getDef(c, analyzer);
+ }
+
+ /**
+ * fixup any unbind methods To declare no unbind method, the value "-" must
+ * be used. If not specified, the name of the unbind method is derived from
+ * the name of the annotated bind method. If the annotated method name
+ * begins with set, that is replaced with unset to derive the unbind method
+ * name. If the annotated method name begins with add, that is replaced with
+ * remove to derive the unbind method name. Otherwise, un is prefixed to the
+ * annotated method name to derive the unbind method name.
+ *
+ * @return
+ * @throws Exception
+ */
+ private ComponentDef getDef(Clazz c, Analyzer analyzer) throws Exception {
+ c.parseClassFileWithCollector(this);
+ if (component.implementation == null)
+ return null;
+
+ while (extendsClass != null) {
+ if (extendsClass.startsWith("java/"))
+ break;
+
+ Clazz ec = analyzer.findClass(extendsClass);
+ if (ec == null) {
+ analyzer.error("Missing super class for DS annotations: "
+ + Clazz.pathToFqn(extendsClass) + " from " + c.getFQN());
+ } else {
+ c.parseClassFileWithCollector(this);
+ }
+ }
+
+ if (component.implementation != null) {
+ for (ReferenceDef rdef : component.references.values()) {
+ rdef.unbind = referredMethod(analyzer, rdef, rdef.unbind, "add(.*)", "remove$1", "(.*)",
+ "un$1");
+ rdef.modified = referredMethod(analyzer, rdef, rdef.modified, "(add|set)(.*)", "modified$2",
+ "(.*)", "modified$1");
+ }
+ return component;
+ } else
+ return null;
+ }
+
+ /**
+ *
+ * @param analyzer
+ * @param rdef
+ */
+ protected String referredMethod(Analyzer analyzer, ReferenceDef rdef, String value,
+ String... matches) {
+ if (value == null) {
+ String bind = rdef.bind;
+ for (int i = 0; i < matches.length; i += 2) {
+ Matcher m = Pattern.compile(matches[i]).matcher(bind);
+ if (m.matches()) {
+ value = m.replaceFirst(matches[i+1]);
+ break;
+ }
+ }
+ } else if (value.equals("-"))
+ return null;
+
+ if (methods.containsKey(value)) {
+ for (String descriptor : methods.get(value)) {
+ Matcher matcher = BINDDESCRIPTOR.matcher(descriptor);
+ if (matcher.matches()) {
+ String type = matcher.group(2);
+ if (rdef.interfce.equals(Clazz.objectDescriptorToFQN(type))
+ || type.equals("Ljava/util/Map;")
+ || type.equals("Lorg/osgi/framework/ServiceReference;")) {
+
+ return value;
+ }
+ }
+ }
+ analyzer.error(
+ "A related method to %s from the reference %s has no proper prototype for class %s. Expected void %s(%s s [,Map m] | ServiceReference r)",
+ rdef.bind, value, component.implementation, value, rdef.interfce);
+ }
+ return null;
+ }
+
+ public void annotation(Annotation annotation) {
+ try {
+ java.lang.annotation.Annotation a = annotation.getAnnotation();
+
+ if (a instanceof Component)
+ doComponent((Component) a, annotation);
+ else if (a instanceof Activate)
+ doActivate();
+ else if (a instanceof Deactivate)
+ doDeactivate();
+ else if (a instanceof Modified)
+ doModified();
+ else if (a instanceof Reference)
+ doReference((Reference) a, annotation);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ analyzer.error("During generation of a component on class %s, exception %s", clazz, e);
+ }
+ }
+
+ /**
+ *
+ */
+ protected void doDeactivate() {
+ if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+ analyzer.error(
+ "Deactivate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
+ clazz, methodDescriptor);
+ else {
+ component.deactivate = method;
+ }
+ }
+
+ /**
+ *
+ */
+ protected void doModified() {
+ if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+ analyzer.error(
+ "Modified method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
+ clazz, methodDescriptor);
+ else {
+ component.modified = method;
+ }
+ }
+ /**
+ * @param annotation
+ * @throws Exception
+ */
+ protected void doReference(Reference reference, Annotation raw) throws Exception {
+ ReferenceDef def = new ReferenceDef();
+ def.name = reference.name();
+
+ if (def.name == null) {
+ Matcher m = BINDMETHOD.matcher(method);
+ if (m.matches()) {
+ def.name = m.group(2);
+ } else {
+ def.name = method;
+ }
+ }
+
+ def.unbind = reference.unbind();
+ def.bind = method;
+
+ def.interfce = raw.get("service");
+ if (def.interfce != null) {
+ def.interfce = Clazz.objectDescriptorToFQN(def.interfce);
+ } else {
+ // We have to find the type of the current method to
+ // link it to the referenced service.
+ Matcher m = BINDDESCRIPTOR.matcher(methodDescriptor);
+ if (m.matches()) {
+ def.interfce = Clazz.internalToFqn(m.group(3));
+ } else
+ throw new IllegalArgumentException(
+ "Cannot detect the type of a Component Reference from the descriptor: "
+ + methodDescriptor);
+ }
+
+ // Check if we have a target, this must be a filter
+ def.target = reference.target();
+ if (def.target != null) {
+ Verifier.verifyFilter(def.target, 0);
+ }
+
+ if (component.references.containsKey(def.name))
+ analyzer.error(
+ "In component %s, multiple references with the same name: %s. Previous def: %s, this def: %s",
+ component.implementation, component.references.get(def.name), def.interfce, "");
+ else
+ component.references.put(def.name, def);
+
+ def.cardinality = reference.cardinality();
+ def.policy = reference.policy();
+ }
+
+ /**
+ *
+ */
+ protected void doActivate() {
+ if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+ analyzer.error(
+ "Activate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
+ clazz, methodDescriptor);
+ else {
+ component.activate = method;
+ }
+ }
+
+ /**
+ * @param annotation
+ * @throws Exception
+ */
+ protected void doComponent(Component comp, Annotation annotation) throws Exception {
+
+ // Check if we are doing a super class
+ if (component.implementation != null)
+ return;
+
+ component.version = V1_1;
+ component.implementation = clazz.getFQN();
+ component.name = comp.name();
+ component.factory = comp.factory();
+ component.configurationPolicy = comp.configurationPolicy();
+ if (annotation.get("enabled") != null)
+ component.enabled = comp.enabled();
+ if (annotation.get("factory") != null)
+ component.factory = comp.factory();
+ if (annotation.get("immediate") != null)
+ component.immediate = comp.immediate();
+ if (annotation.get("servicefactory") != null)
+ component.servicefactory = comp.servicefactory();
+
+ String properties[] = comp.properties();
+ if (properties != null)
+ for (String entry : properties)
+ component.properties.add(entry);
+
+ doProperties(comp.property());
+ Object [] x = annotation.get("service");
+
+ if (x == null) {
+ // Use the found interfaces, but convert from internal to
+ // fqn.
+ if (interfaces != null) {
+ List<String> result = new ArrayList<String>();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (!interfaces[i].equals("scala/ScalaObject"))
+ result.add(Clazz.internalToFqn(interfaces[i]));
+ }
+ component.service = result.toArray(EMPTY);
+ }
+ } else {
+ // We have explicit interfaces set
+ component.service= new String[x.length];
+ for (int i = 0; i < x.length; i++) {
+ component.service[i] = Clazz.objectDescriptorToFQN(x[i].toString());
+ }
+ }
+
+ }
+
+ /**
+ * Parse the properties
+ */
+
+ private void doProperties(String[] properties) {
+ if (properties != null) {
+ for (String p : properties) {
+ Matcher m = PROPERTY_PATTERN.matcher(p);
+
+ if (m.matches()) {
+ String key = m.group(1);
+ String value = m.group(4);
+ component.property.add(key, value);
+ } else
+ throw new IllegalArgumentException("Malformed property '" + p
+ + "' on component: " + className);
+ }
+ }
+ }
+
+ /**
+ * Are called during class parsing
+ */
+
+ @Override public void classBegin(int access, String name) {
+ className = name;
+ }
+
+ @Override public void implementsInterfaces(String[] interfaces) {
+ this.interfaces = interfaces;
+ }
+
+ @Override public void method(int access, String name, String descriptor) {
+ if (Modifier.isPrivate(access) || Modifier.isAbstract(access) || Modifier.isStatic(access))
+ return;
+
+ this.method = name;
+ this.methodDescriptor = descriptor;
+ this.methodAccess = access;
+ methods.add(name, descriptor);
+ }
+
+ @Override public void extendsClass(String name) {
+ this.extendsClass = name;
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/AnnotationReader.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/AnnotationReader.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,132 @@
+package aQute.bnd.component;
+
+import java.util.*;
+
+import org.osgi.service.component.annotations.*;
+
+import aQute.lib.collections.*;
+import aQute.lib.osgi.*;
+import aQute.lib.tag.*;
+import aQute.libg.version.*;
+
+class ComponentDef {
+ final static String NAMESPACE_STEM = "http://www.osgi.org/xmlns/scr";
+ Version version = new Version("1.1.0");
+ String name;
+ String factory;
+ Boolean immediate;
+ Boolean servicefactory;
+ ConfigurationPolicy configurationPolicy;
+ String implementation;
+ String service[];
+ String activate;
+ String deactivate;
+ String modified;
+ Boolean enabled;
+ final List<String> properties = new ArrayList<String>();
+ final MultiMap<String, String> property = new MultiMap<String, String>();
+ final Map<String, ReferenceDef> references = new TreeMap<String, ReferenceDef>();
+
+ void prepare(Analyzer analyzer) {
+
+ for (ReferenceDef ref : references.values()) {
+ ref.prepare(analyzer);
+ if (ref.version.compareTo(version) > 0)
+ version = ref.version;
+ }
+
+ if (implementation == null)
+ analyzer.error("No Implementation defined for component " + name);
+ else
+ analyzer.referTo(implementation);
+
+ name = implementation;
+
+ if (service != null && service.length > 0) {
+ for (String interfaceName : service)
+ analyzer.referTo(interfaceName);
+ } else if (servicefactory != null && servicefactory)
+ analyzer.warning("The servicefactory:=true directive is set but no service is provided, ignoring it");
+ }
+
+ Tag getTag() {
+ Tag component = new Tag("scr:component");
+ component.addAttribute("xmlns:scr", NAMESPACE_STEM + "/" + version);
+ component.addAttribute("name", name);
+
+ if (servicefactory != null)
+ component.addAttribute("servicefactory", servicefactory);
+
+ if (configurationPolicy != null)
+ component.addAttribute("configuration-policy", configurationPolicy.toString()
+ .toLowerCase());
+ if (enabled != null)
+ component.addAttribute("enabled", enabled);
+ if (immediate != null)
+ component.addAttribute("immediate", immediate);
+
+ if (factory != null)
+ component.addAttribute("factory", factory);
+
+ if (activate != null)
+ component.addAttribute("activate", activate);
+
+ if (deactivate != null)
+ component.addAttribute("deactivate", deactivate);
+
+ if (modified != null)
+ component.addAttribute("modified", modified);
+
+ Tag impl = new Tag(component, "implementation");
+ impl.addAttribute("class", implementation);
+
+ if (service != null && service.length != 0) {
+ Tag s = new Tag(component, "service");
+ if (servicefactory != null && servicefactory)
+ s.addAttribute("servicefactory", true);
+
+ for (String ss : service) {
+ Tag provide = new Tag(s, "provide");
+ provide.addAttribute("interface", ss);
+ }
+ }
+
+ for (ReferenceDef ref : references.values()) {
+ Tag refTag = ref.getTag();
+ component.addContent(refTag);
+
+ }
+
+ for (Map.Entry<String, Set<String>> kvs : property.entrySet()) {
+ Tag property = new Tag(component, "property");
+ String name = kvs.getKey();
+ String type = null;
+ int n = name.indexOf(':');
+ if (n > 0) {
+ type = name.substring(n + 1);
+ name = name.substring(0, n);
+ }
+
+ property.addAttribute("name", name);
+ if (type != null) {
+ property.addAttribute("type", type);
+ }
+ StringBuffer sb = new StringBuffer();
+
+ String del = "";
+ for (String v : kvs.getValue()) {
+ sb.append(del);
+ sb.append(v);
+ del = "\n";
+ }
+ property.addContent(sb.toString());
+ }
+
+ for (String entry : properties) {
+ Tag properties = new Tag(component, "properties");
+ properties.addAttribute("entry", entry);
+ }
+ return component;
+ }
+
+}
\ No newline at end of file
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/DSAnnotations.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/DSAnnotations.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/DSAnnotations.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/DSAnnotations.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,25 @@
+package aQute.bnd.component;
+
+import aQute.bnd.service.*;
+import aQute.lib.osgi.*;
+
+/**
+ * Analyze the class space for any classes that have an OSGi annotation for DS.
+ *
+ */
+public class DSAnnotations implements AnalyzerPlugin {
+
+ public boolean analyzeJar(Analyzer analyzer) throws Exception {
+
+ for (Clazz c : analyzer.getClassspace().values()) {
+ ComponentDef definition = AnnotationReader.getDefinition(c, analyzer);
+ if (definition != null) {
+ definition.prepare(analyzer);
+ analyzer.getJar().putResource("OSGI-INF/" + definition.name + ".xml",
+ new TagResource(definition.getTag()));
+ }
+ }
+ return false;
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/DSAnnotations.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/DSAnnotations.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ReferenceDef.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ReferenceDef.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ReferenceDef.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ReferenceDef.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,98 @@
+package aQute.bnd.component;
+
+import org.osgi.service.component.annotations.*;
+
+import aQute.lib.osgi.*;
+import aQute.lib.tag.*;
+import aQute.libg.version.*;
+
+class ReferenceDef {
+ Version version;
+ String name;
+ String interfce;
+ ReferenceCardinality cardinality;
+ ReferencePolicy policy;
+ String target;
+ String bind;
+ String unbind;
+ String modified;
+
+ public void prepare(Analyzer analyzer) {
+ if (name == null)
+ analyzer.error("No name for a reference");
+
+ if (version == null)
+ version = AnnotationReader.V1_1;
+
+ }
+
+ public Tag getTag() {
+ Tag ref = new Tag("reference");
+ ref.addAttribute("name", name);
+ if (cardinality != null)
+ ref.addAttribute("cardinality", p(cardinality));
+ if (policy != null)
+ ref.addAttribute("policy", p(policy));
+
+ if (interfce != null)
+ ref.addAttribute("interface", interfce);
+
+ if (target != null)
+ ref.addAttribute("target", target);
+
+ if (bind != null)
+ ref.addAttribute("bind", bind);
+
+ if (unbind != null)
+ ref.addAttribute("unbind", unbind);
+
+ if (modified != null) {
+ ref.addAttribute("modified", modified);
+ version = max(version, AnnotationReader.V1_2);
+ }
+
+ return ref;
+ }
+
+ private String p(ReferencePolicy policy) {
+ switch(policy) {
+ case DYNAMIC:
+ return "dynamic";
+
+ case STATIC:
+ return "static";
+ }
+ return policy.toString();
+ }
+
+ private String p(ReferenceCardinality crd) {
+ switch (crd) {
+ case AT_LEAST_ONE:
+ return "1..n";
+
+ case MANDATORY:
+ return "1..1";
+
+ case MULTIPLE:
+ return "0..n";
+
+ case OPTIONAL:
+ return "0..1";
+
+ }
+ return crd.toString();
+ }
+
+ private <T extends Comparable<T>> T max(T a, T b) {
+ int n = a.compareTo(b);
+ if (n >= 0)
+ return a;
+ else
+ return b;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ReferenceDef.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ReferenceDef.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/concurrent/MultiBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/concurrent/MultiBuilder.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/concurrent/MultiBuilder.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/concurrent/MultiBuilder.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,141 @@
+package aQute.bnd.concurrent;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.bnd.build.*;
+import aQute.lib.osgi.*;
+import aQute.libg.forker.*;
+
+/**
+ * This class implements a concurrent builder. It manages the build process in
+ * an environment where many threads can initiate builds. Users should call
+ * changed(Project,boolean)
+ *
+ */
+public class MultiBuilder {
+ Workspace workspace;
+ Forker<Project> forker;
+ boolean building = false;
+ final Set<File> filesChanged = Collections.synchronizedSet(new HashSet<File>());
+
+ /**
+ * Constructor
+ *
+ * @param workspace
+ * the workspace this MultiBuilder works for.
+ *
+ */
+ public MultiBuilder(Workspace workspace) {
+ this.workspace = workspace;
+ }
+
+ /**
+ * Return the build result of a project.
+ *
+ * @param p
+ * the project
+ * @return the files build by the project
+ *
+ * @throws Exception
+ */
+ public File[] build(Project p) throws Exception {
+ if (p.isStale()) {
+ startBuild();
+ }
+ syncBuild();
+ return p.build();
+ }
+
+ /**
+ * Indicate that the project has changed. This will start a build.
+ *
+ * @param p
+ * the project that is changed
+ * @throws Exception
+ */
+ public void changed(Project p) throws Exception {
+ p.setChanged();
+ cancel();
+ startBuild();
+ }
+
+ /**
+ * Cancel the current build or do nothing if no build is active.
+ *
+ * @throws InterruptedException
+ */
+ public synchronized void cancel() throws InterruptedException {
+ if (building) {
+ forker.cancel();
+ }
+ }
+
+ /**
+ * Synchronize with a current build or return immediately.
+ *
+ * @throws InterruptedException
+ */
+ public synchronized void syncBuild() throws InterruptedException {
+ if (building) {
+ forker.join();
+ }
+ }
+
+ /**
+ * Schedule a new build if no build is running otherwise return.
+ *
+ * @throws Exception
+ */
+ public void startBuild() throws Exception {
+ synchronized (this) {
+ if (building)
+ return;
+
+ forker = new Forker<Project>(Processor.getExecutor());
+ building = true;
+ }
+
+ Processor.getExecutor().execute(new Runnable() {
+ public void run() {
+ try {
+ build();
+ synchronized (MultiBuilder.this) {
+ building = false;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Do the whole build using a forker.
+ *
+ * @throws Exception
+ */
+ private void build() throws Exception {
+ // handle multiple requests
+ Thread.sleep(100);
+ workspace.bracket(true);
+ try {
+ for (final Project p : workspace.getAllProjects()) {
+ forker.doWhen(p.getDependson(), p, new Runnable() {
+
+ public void run() {
+ try {
+ p.build();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ forker.join();
+ } finally {
+ workspace.bracket(false);
+ }
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/concurrent/MultiBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/concurrent/MultiBuilder.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Errors.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Errors.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Errors.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Errors.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,5 @@
+package aQute.bnd.help;
+
+public interface Errors {
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Errors.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Errors.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision