You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by zo...@apache.org on 2011/02/27 21:35:49 UTC
svn commit: r1075139 [16/23] - in /aries/tags/blueprint-0.2-incubating: ./
blueprint-annotation-api/ blueprint-annotation-api/src/
blueprint-annotation-api/src/main/ blueprint-annotation-api/src/main/java/
blueprint-annotation-api/src/main/java/org/ bl...
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassAdapter.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassAdapter.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassAdapter.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassAdapter.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,618 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProxySubclassAdapter extends ClassAdapter implements Opcodes
+{
+
+ private static final Type STRING_TYPE = Type.getType(String.class);
+ private static final Type CLASS_TYPE = Type.getType(Class.class);
+ private static final Type OBJECT_TYPE = Type.getType(Object.class);
+ private static final Type METHOD_TYPE = Type.getType(java.lang.reflect.Method.class);
+ private static final Type IH_TYPE = Type.getType(InvocationHandler.class);
+ private static final Type[] NO_ARGS = new Type[] {};
+
+ private static final String IH_FIELD = "ih";
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ProxySubclassAdapter.class);
+
+ private String newClassName = null;
+ private String superclassBinaryName = null;
+ private Class<?> superclassClass = null;
+ private ClassLoader loader = null;
+ private Type newClassType = null;
+ private GeneratorAdapter staticAdapter = null;
+ private String currentlyAnalysedClassName = null;
+ private Class<?> currentlyAnalysedClass = null;
+ private String currentClassFieldName = null;
+
+ public ProxySubclassAdapter(ClassVisitor writer, String newClassName, ClassLoader loader)
+ {
+ // call the superclass constructor
+ super(writer);
+ // the writer is now the cv in the superclass of ClassAdapter
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "ProxySubclassAdapter", new Object[] { this, writer,
+ newClassName });
+
+ // set the newClassName field
+ this.newClassName = newClassName;
+ // set the newClassType descriptor
+ newClassType = Type.getType("L" + newClassName + ";");
+
+ // set the classloader
+ this.loader = loader;
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "ProxySubclassAdapter", this);
+ }
+
+ /*
+ * This method visits the class to generate the new subclass.
+ *
+ * The following things happen here: 1. The class is renamed to a dynamic
+ * name 2. The existing class name is changed to be the superclass name so
+ * that the generated class extends the original class. 3. A private field
+ * is added to store an invocation handler 4. A constructor is added that
+ * takes an invocation handler as an argument 5. The constructor method
+ * instantiates an instance of the superclass 6. The constructor method sets
+ * the invocation handler so the invoke method can be called from all the
+ * subsequently rewritten methods 7. Add a getInvocationHandler() method 8.
+ * store a static Class object of the superclass so we can reflectively find
+ * methods later
+ */
+ public void visit(int version, int access, String name, String signature, String superName,
+ String[] interfaces)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "visit", new Object[] { version, access, name,
+ signature, superName, interfaces });
+
+ // store the superclass binary name
+ this.superclassBinaryName = name.replaceAll("/", "\\.");
+
+ try {
+ this.superclassClass = Class.forName(superclassBinaryName, false, loader);
+ } catch (ClassNotFoundException cnfe) {
+ throw new TypeNotPresentException(superclassBinaryName, cnfe);
+ }
+
+ // move the existing class name to become the superclass
+ // modify the version of the dynamic subclass to be Java 1.6
+ int newVersion = Opcodes.V1_6;
+ // keep the same access and signature as the superclass
+ // remove all the superclass interfaces because they will be inherited
+ // from the superclass anyway
+ cv.visit(newVersion, access, newClassName, signature, name, null);
+
+ // add a private field for the invocation handler
+ // this isn't static in case we have multiple instances of the same
+ // proxy
+ cv.visitField(ACC_PRIVATE, IH_FIELD, Type.getDescriptor(InvocationHandler.class), null, null);
+
+ // create a static adapter for generating a static initialiser method in
+ // the generated subclass
+ staticAdapter = new GeneratorAdapter(ACC_STATIC,
+ new Method("<clinit>", Type.VOID_TYPE, NO_ARGS), null, null, cv);
+
+ // add a constructor method that takes an invocation handler as an
+ // argument
+ Method m = new Method("<init>", Type.VOID_TYPE, new Type[] { IH_TYPE });
+ GeneratorAdapter methodAdapter = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cv);
+ // loadthis
+ methodAdapter.loadThis();
+ // if we have java.* as a supertype call that zero args constructor
+ if (superclassBinaryName.startsWith("java.") || superclassBinaryName.startsWith("javax.")) {
+ methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>",
+ Type.VOID_TYPE, NO_ARGS));
+ }
+ // otherwise invoke the java.lang.Object no args constructor
+ else {
+ methodAdapter.invokeConstructor(OBJECT_TYPE, new Method("<init>", Type.VOID_TYPE, NO_ARGS));
+ }
+ // call from the constructor to setInvocationHandler
+ Method setter = new Method("setInvocationHandler", Type.VOID_TYPE, new Type[] { IH_TYPE });
+ // load this
+ methodAdapter.loadThis();
+ // load the supplied invocation handler arg
+ methodAdapter.loadArgs();
+ // invoke the setter method
+ methodAdapter.invokeVirtual(newClassType, setter);
+ methodAdapter.returnValue();
+ methodAdapter.endMethod();
+
+ // add a method for getting the invocation handler
+ m = new Method("getInvocationHandler", IH_TYPE, NO_ARGS);
+ methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, m, null, null, cv);
+ // load this to get the field
+ methodAdapter.loadThis();
+ // get the ih field and return
+ methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
+ methodAdapter.returnValue();
+ methodAdapter.endMethod();
+
+ // add a method for setting the invocation handler
+ methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, setter, null, null, cv);
+ // load this to put the field
+ methodAdapter.loadThis();
+ // load the method arguments (i.e. the invocation handler) to the stack
+ methodAdapter.loadArgs();
+ // set the ih field using the method argument
+ methodAdapter.putField(newClassType, IH_FIELD, IH_TYPE);
+ methodAdapter.returnValue();
+ methodAdapter.endMethod();
+
+ // loop through the class hierarchy to get any needed methods off the
+ // supertypes
+ // start by finding the methods declared on the class of interest (the
+ // superclass of our dynamic subclass)
+ java.lang.reflect.Method[] observedMethods = superclassClass.getDeclaredMethods();
+ // add the methods to a set of observedMethods
+ ProxySubclassMethodHashSet<String> setOfObservedMethods = new ProxySubclassMethodHashSet<String>(
+ observedMethods.length);
+ setOfObservedMethods.addMethodArray(observedMethods);
+ // get the next superclass in the hierarchy
+ Class<?> nextSuperClass = superclassClass.getSuperclass();
+ while (nextSuperClass != null) {
+ // set the fields for the current class
+ setCurrentAnalysisClassFields(nextSuperClass);
+
+ // add a static field and static initializer code to the generated
+ // subclass
+ // for each of the superclasses in the hierarchy
+ addClassStaticField(currentlyAnalysedClassName);
+
+ LOGGER.debug("Class currently being analysed: {} {}", currentlyAnalysedClassName,
+ currentlyAnalysedClass);
+
+ // now find the methods declared on the current class and add them
+ // to a set of foundMethods
+ java.lang.reflect.Method[] foundMethods = currentlyAnalysedClass.getDeclaredMethods();
+ ProxySubclassMethodHashSet<String> setOfFoundMethods = new ProxySubclassMethodHashSet<String>(
+ foundMethods.length);
+ setOfFoundMethods.addMethodArray(foundMethods);
+ // remove from the set of foundMethods any methods we saw on a
+ // subclass
+ // because we want to use the lowest level declaration of a method
+ setOfFoundMethods.removeAll(setOfObservedMethods);
+ try {
+ // read the current class and use a
+ // ProxySubclassHierarchyAdapter
+ // to process only methods on that class that are in the list
+ ClassReader cr = new ClassReader(loader.getResourceAsStream(currentlyAnalysedClass
+ .getName().replaceAll("\\.", "/")
+ + ".class"));
+ ClassVisitor hierarchyAdapter = new ProxySubclassHierarchyAdapter(this, setOfFoundMethods);
+ cr.accept(hierarchyAdapter, ClassReader.SKIP_DEBUG);
+ } catch (IOException e) {
+ throw new TypeNotPresentException(currentlyAnalysedClassName, e);
+ }
+ // now add the foundMethods to the overall list of observed methods
+ setOfObservedMethods.addAll(setOfFoundMethods);
+ // get the next class up in the hierarchy and go again
+ nextSuperClass = currentlyAnalysedClass.getSuperclass();
+ }
+
+ // we've finished looking at the superclass hierarchy
+ // set the fields for the immediate superclass of our dynamic subclass
+ setCurrentAnalysisClassFields(superclassClass);
+
+ // add the class static field
+ addClassStaticField(currentlyAnalysedClassName);
+ // we do the lowest class last because we are already visiting the class
+ // when in this adapter code
+ // now we are ready to visit all the methods on the lowest class
+ // which will happen by the ASM ClassVisitor implemented in this adapter
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "visit");
+ }
+
+ public void visitSource(String source, String debug)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "visitSource", new Object[] { source, debug });
+
+ // set the source to null since the class is generated on the fly and
+ // not compiled
+ cv.visitSource(null, null);
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "visitSource");
+ }
+
+ public void visitEnd()
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "visitEnd");
+
+ // this method is called when we reach the end of the class
+ // so it is time to make sure the static initialiser method is closed
+ staticAdapter.returnValue();
+ staticAdapter.endMethod();
+ // now delegate to the cv
+ cv.visitEnd();
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "visitEnd");
+ }
+
+ /*
+ * This method is called on each method of the superclass (and all parent
+ * classes up to Object) Each of these methods is visited in turn and the
+ * code here generates the byte code for the InvocationHandler to call the
+ * methods on the superclass.
+ */
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "visitMethod", new Object[] { access, name, desc,
+ signature, exceptions });
+
+ /*
+ * Check the method access and handle the method types we don't want to
+ * copy: final methods (issue warnings if these are not methods from
+ * java.* classes) static methods (initialiser and others) private
+ * methods constructors (for now we don't copy any constructors)
+ * abstract (we don't proxy/implement but we must copy the method or the
+ * subclass is invalid) everything else we process to proxy
+ */
+
+ LOGGER.debug("Method name: {} with descriptor: {}", name, desc);
+
+ MethodVisitor methodVisitorToReturn = null;
+
+ if (name.equals("<init>")) {
+ // we may need to do something extra with constructors later
+ // e.g. include bytecode for calling super with the same args
+ // since we currently rely on the super having a zero args
+ // constructor
+ // we need to issue an error if we don't find one
+
+ // for now we return null to ignore them
+ methodVisitorToReturn = null;
+ } else if (name.equals("<clinit>")) {
+ // don't copy static initialisers from the superclass into the new
+ // subclass
+ methodVisitorToReturn = null;
+ } else if ((access & ACC_FINAL) != 0) {
+ // since we check for final methods in the ProxySubclassGenerator we
+ // should never get here
+ methodVisitorToReturn = null;
+ } else if ((access & ACC_SYNTHETIC) != 0) {
+ // synthetic methods are generated by the compiler for covariance
+ // etc
+ // we shouldn't copy them or we will have duplicate methods
+ methodVisitorToReturn = null;
+ } else if ((access & ACC_PRIVATE) != 0) {
+ // don't copy private methods from the superclass
+ methodVisitorToReturn = null;
+ } else if ((access & ACC_STATIC) != 0) {
+ // don't copy static methods
+ methodVisitorToReturn = null;
+ } else if ((access & ACC_ABSTRACT) != 0) {
+ // if we find an abstract method we need to copy it as is to make
+ // the subclass valid
+ methodVisitorToReturn = cv.visitMethod(access, name, desc, signature, exceptions);
+ } else if (!(((access & ACC_PUBLIC) != 0) || ((access & ACC_PROTECTED) != 0) || ((access & ACC_PRIVATE) != 0))) {
+ // the default (package) modifier value is 0, so by using & with any
+ // of the other
+ // modifier values and getting a result of zero means that we have
+ // default accessibility
+
+ // check the package in which the method is declared against the
+ // package
+ // where the generated subclass will be
+ // if they are the same process the method otherwise ignore it
+ if (currentlyAnalysedClass.getPackage().equals(superclassClass.getPackage())) {
+ processMethod(access, name, desc, signature, exceptions);
+ methodVisitorToReturn = null;
+ } else {
+ methodVisitorToReturn = null;
+ }
+ } else {
+ processMethod(access, name, desc, signature, exceptions);
+ // return null because we don't want the original method code from
+ // the superclass
+ methodVisitorToReturn = null;
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "visitMethod", methodVisitorToReturn);
+
+ return methodVisitorToReturn;
+
+ }
+
+ private void processMethod(int access, String name, String desc, String signature,
+ String[] exceptions)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "processMethod", new Object[] { access, name, desc,
+ signature, exceptions });
+
+ LOGGER.debug("Processing method: {} with descriptor {}", name, desc);
+
+ // identify the target method parameters and return type
+ Method currentTransformMethod = new Method(name, desc);
+ Type[] targetMethodParameters = currentTransformMethod.getArgumentTypes();
+ Type returnType = currentTransformMethod.getReturnType();
+
+ // we create a static field for each method we encounter with a name
+ // like method_parm1_parm2...
+ StringBuilder methodStaticFieldNameBuilder = new StringBuilder(name);
+ // for each a parameter get the name and add it to the field removing
+ // the dots first
+ for (Type t : targetMethodParameters) {
+ methodStaticFieldNameBuilder.append("_");
+ methodStaticFieldNameBuilder.append(t.getClassName().replaceAll("\\[\\]", "Array")
+ .replaceAll("\\.", ""));
+ }
+ String methodStaticFieldName = methodStaticFieldNameBuilder.toString();
+
+ // add a private static field for the method
+ cv.visitField(ACC_PRIVATE | ACC_STATIC, methodStaticFieldName, METHOD_TYPE.getDescriptor(),
+ null, null);
+
+ // visit the method using the class writer, delegated through the method
+ // visitor and generator
+ // modify the method access so that any native methods aren't
+ // described as native
+ // since they won't be native in proxy form
+ // also stop methods being marked synchronized on the proxy as they will
+ // be sync
+ // on the real object
+ int newAccess = access & (~ACC_NATIVE) & (~ACC_SYNCHRONIZED);
+ MethodVisitor mv = cv.visitMethod(newAccess, name, desc, signature, exceptions);
+ // use a GeneratorAdapter to build the invoke call directly in byte code
+ GeneratorAdapter methodAdapter = new GeneratorAdapter(mv, newAccess, name, desc);
+
+ /*
+ * Stage 1 creates the bytecode for adding the reflected method of the
+ * superclass to a static field in the subclass: private static Method
+ * methodName_parm1_parm2... = null; static{ methodName_parm1_parm2... =
+ * superClass.getDeclaredMethod(methodName,new Class[]{method args}; }
+ *
+ * Stage 2 is to call the ih.invoke(this,methodName_parm1_parm2,args) in
+ * the new subclass methods Stage 3 is to cast the return value to the
+ * correct type
+ */
+
+ /*
+ * Stage 1 use superClass.getMethod(methodName,new Class[]{method args}
+ * from the Class object on the stack
+ */
+
+ // load the static superclass Class onto the stack
+ staticAdapter.getStatic(newClassType, currentClassFieldName, CLASS_TYPE);
+
+ // push the method name string arg onto the stack
+ staticAdapter.push(name);
+
+ // create an array of the method parm class[] arg
+ staticAdapter.push(targetMethodParameters.length);
+ staticAdapter.newArray(CLASS_TYPE);
+ int index = 0;
+ for (Type t : targetMethodParameters) {
+ staticAdapter.dup();
+ staticAdapter.push(index);
+ switch (t.getSort())
+ {
+ case Type.BOOLEAN:
+ staticAdapter.getStatic(Type.getType(java.lang.Boolean.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.BYTE:
+ staticAdapter.getStatic(Type.getType(java.lang.Byte.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.CHAR:
+ staticAdapter.getStatic(Type.getType(java.lang.Character.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.DOUBLE:
+ staticAdapter.getStatic(Type.getType(java.lang.Double.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.FLOAT:
+ staticAdapter.getStatic(Type.getType(java.lang.Float.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.INT:
+ staticAdapter.getStatic(Type.getType(java.lang.Integer.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.LONG:
+ staticAdapter.getStatic(Type.getType(java.lang.Long.class), "TYPE", CLASS_TYPE);
+ break;
+ case Type.SHORT:
+ staticAdapter.getStatic(Type.getType(java.lang.Short.class), "TYPE", CLASS_TYPE);
+ break;
+ default:
+ case Type.OBJECT:
+ staticAdapter.push(t);
+ break;
+ }
+ staticAdapter.arrayStore(CLASS_TYPE);
+ index++;
+ }
+
+ // invoke the getMethod
+ staticAdapter.invokeVirtual(CLASS_TYPE, new Method("getDeclaredMethod", METHOD_TYPE,
+ new Type[] { STRING_TYPE, Type.getType(java.lang.Class[].class) }));
+
+ // store the reflected method in the static field
+ staticAdapter.putStatic(newClassType, methodStaticFieldName, METHOD_TYPE);
+
+ /*
+ * Stage 2 call the ih.invoke(this,supermethod,parms)
+ */
+
+ // load this to get the ih field
+ methodAdapter.loadThis();
+ // load the invocation handler from the field (the location of the
+ // InvocationHandler.invoke)
+ methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
+ // loadThis (the first arg of the InvocationHandler.invoke)
+ methodAdapter.loadThis();
+ // load the method to invoke (the second arg of the
+ // InvocationHandler.invoke)
+ methodAdapter.getStatic(newClassType, methodStaticFieldName, METHOD_TYPE);
+ // load all the method arguments onto the stack as an object array (the
+ // third arg of the InvocationHandler.invoke)
+ methodAdapter.loadArgArray();
+ // generate the invoke method
+ Method invocationHandlerInvokeMethod = new Method("invoke", OBJECT_TYPE, new Type[] {
+ OBJECT_TYPE, METHOD_TYPE, Type.getType(java.lang.Object[].class) });
+ // call the invoke method of the invocation handler
+ methodAdapter.invokeInterface(IH_TYPE, invocationHandlerInvokeMethod);
+
+ /*
+ * Stage 3 the returned object is now on the top of the stack We need to
+ * check the type and cast as necessary
+ */
+ switch (returnType.getSort())
+ {
+ case Type.BOOLEAN:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Boolean.class));
+ methodAdapter.unbox(Type.BOOLEAN_TYPE);
+ break;
+ case Type.BYTE:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Byte.class));
+ methodAdapter.unbox(Type.BYTE_TYPE);
+ break;
+ case Type.CHAR:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Character.class));
+ methodAdapter.unbox(Type.CHAR_TYPE);
+ break;
+ case Type.DOUBLE:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Double.class));
+ methodAdapter.unbox(Type.DOUBLE_TYPE);
+ break;
+ case Type.FLOAT:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Float.class));
+ methodAdapter.unbox(Type.FLOAT_TYPE);
+ break;
+ case Type.INT:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Integer.class));
+ methodAdapter.unbox(Type.INT_TYPE);
+ break;
+ case Type.LONG:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Long.class));
+ methodAdapter.unbox(Type.LONG_TYPE);
+ break;
+ case Type.SHORT:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Short.class));
+ methodAdapter.unbox(Type.SHORT_TYPE);
+ break;
+ case Type.VOID:
+ methodAdapter.cast(OBJECT_TYPE, Type.getType(Void.class));
+ methodAdapter.unbox(Type.VOID_TYPE);
+ break;
+ default:
+ case Type.OBJECT:
+ // in this case check the cast and cast the object to the return
+ // type
+ methodAdapter.checkCast(returnType);
+ methodAdapter.cast(OBJECT_TYPE, returnType);
+ break;
+ }
+ // return the (appropriately cast) result of the invocation from the
+ // stack
+ methodAdapter.returnValue();
+ // end the method
+ methodAdapter.endMethod();
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "processMethod");
+ }
+
+ private void addClassStaticField(String classBinaryName)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "addClassStaticField",
+ new Object[] { classBinaryName });
+
+ currentClassFieldName = classBinaryName.replaceAll("\\.", "_");
+
+ /*
+ * use Class.forName on the superclass so we can reflectively find
+ * methods later
+ *
+ * produces bytecode for retrieving the superclass and storing in a
+ * private static field: private static Class superClass = null; static{
+ * superClass = Class.forName(superclass); }
+ */
+
+ // add a private static field for the superclass Class
+ cv.visitField(ACC_PRIVATE | ACC_STATIC, currentClassFieldName, CLASS_TYPE.getDescriptor(),
+ null, null);
+
+ // push the String arg for the Class.forName onto the stack
+ staticAdapter.push(classBinaryName);
+
+ // invoke the Class forName putting the Class on the stack
+ staticAdapter.invokeStatic(CLASS_TYPE, new Method("forName", CLASS_TYPE,
+ new Type[] { STRING_TYPE }));
+
+ // put the Class in the static field
+ staticAdapter.putStatic(newClassType, currentClassFieldName, CLASS_TYPE);
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "addClassStaticField");
+ }
+
+ private void setCurrentAnalysisClassFields(Class<?> aClass)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "setCurrentAnalysisClassFields",
+ new Object[] { aClass });
+
+ currentlyAnalysedClassName = aClass.getName();
+ currentlyAnalysedClass = aClass;
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "setCurrentAnalysisClassFields");
+ }
+
+ // we don't want to copy fields from the class into the proxy
+ public FieldVisitor visitField(int access, String name, String desc, String signature,
+ Object value)
+ {
+ return null;
+ }
+
+ // for now we don't do any processing in these methods
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible)
+ {
+ return null;
+ }
+
+ public void visitAttribute(Attribute attr)
+ {
+ // no-op
+ }
+
+ public void visitInnerClass(String name, String outerName, String innerName, int access)
+ {
+ // no-op
+ }
+
+ public void visitOuterClass(String owner, String name, String desc)
+ {
+ // no-op
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassGenerator.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassGenerator.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassGenerator.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassGenerator.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+import static java.lang.reflect.Modifier.isFinal;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProxySubclassGenerator
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(ProxySubclassGenerator.class);
+
+ // This map holds references to the names of classes created by this Class
+ // It is a weak map (so when a ClassLoader is garbage collected we remove
+ // the map of
+ // Class names to sub-Class names)
+ private static final Map<ClassLoader, ConcurrentMap<String, String>> proxyClassesByClassLoader;
+
+ private static final ClassLoader defaultClassLoader = new ClassLoader() {};
+
+ static {
+ // Ensure that this is a synchronized map as we may use it from multiple
+ // threads concurrently
+ //
+ proxyClassesByClassLoader = Collections
+ .synchronizedMap(new WeakHashMap<ClassLoader, ConcurrentMap<String, String>>());
+ }
+
+ private static final char FINAL_MODIFIER = '!';
+ private static final char UNABLE_TO_PROXY = '#';
+
+ public static Class<?> getProxySubclass(Class<?> aClass) throws UnableToProxyException
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "getProxySubclass", new Object[] { aClass });
+
+ ClassLoader loader = aClass.getClassLoader();
+ // in the special case where the loader is null we use a default classloader
+ // this is for subclassing java.* or javax.* packages, so that one will do
+ if (loader == null) loader = defaultClassLoader;
+
+ ConcurrentMap<String, String> proxyMap;
+ synchronized (loader) {
+ proxyMap = proxyClassesByClassLoader.get(loader);
+ if (proxyMap == null) {
+ proxyMap = new ConcurrentHashMap<String, String>();
+ proxyClassesByClassLoader.put(loader, proxyMap);
+ }
+ }
+
+ // check the map to see if we have already generated a subclass for this
+ // class
+ // if we have return the mapped class object
+ // if we haven't generate the subclass and return it
+ Class<?> classToReturn = null;
+ synchronized (aClass) {
+ String key = aClass.getName();
+ String className = proxyMap.get(key);
+ if (className != null) {
+
+ LOGGER.debug("Found proxy subclass with key {} and name {}.", key, className);
+
+ if (className.charAt(0) == FINAL_MODIFIER) {
+ String[] exceptionParts = className.substring(1).split(":");
+ if (exceptionParts.length == 1) {
+ throw new FinalModifierException(aClass);
+ } else {
+ throw new FinalModifierException(aClass, exceptionParts[1]);
+ }
+ } else if (className.charAt(0) == UNABLE_TO_PROXY) {
+ throw new UnableToProxyException(aClass);
+ }
+
+ try {
+ classToReturn = loader.loadClass(className);
+ } catch (ClassNotFoundException cnfe) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, cnfe);
+ throw new UnableToLoadProxyException(className, cnfe);
+ }
+ } else {
+
+ LOGGER.debug("Need to generate subclass. Using key {}.", key);
+ try {
+ scanForFinalModifiers(aClass);
+
+ classToReturn = generateAndLoadSubclass(aClass, loader);
+
+ if (classToReturn != null) {
+ proxyMap.put(key, classToReturn.getName());
+ } else {
+ proxyMap.put(key, UNABLE_TO_PROXY + aClass.getName());
+ throw new UnableToProxyException(aClass);
+ }
+ } catch (FinalModifierException e) {
+ if (e.isFinalClass()) {
+ proxyMap.put(key, FINAL_MODIFIER + e.getClassName());
+ throw e;
+ } else {
+ proxyMap.put(key, FINAL_MODIFIER + e.getClassName() + ':' + e.getFinalMethods());
+ throw e;
+ }
+ }
+
+ }
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "getProxySubclass", classToReturn);
+
+ return classToReturn;
+ }
+
+ public static Object newProxySubclassInstance(Class<?> classToProxy, InvocationHandler ih)
+ throws UnableToProxyException
+ {
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "newProxySubclassInstance", new Object[] {
+ classToProxy, ih });
+
+ Object proxySubclassInstance = null;
+ try {
+ Class<?> generatedProxySubclass = getProxySubclass(classToProxy);
+ LOGGER.debug("Getting the proxy subclass constructor");
+ Constructor<?> subclassConstructor = generatedProxySubclass
+ .getConstructor(new Class[] { InvocationHandler.class });
+ LOGGER.debug("Invoking the proxy subclass constructor");
+ proxySubclassInstance = subclassConstructor.newInstance(ih);
+ LOGGER.debug("Invoked proxy subclass constructor");
+ } catch (NoSuchMethodException nsme) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, nsme);
+ throw new ProxyClassInstantiationException(classToProxy, nsme);
+ } catch (InvocationTargetException ite) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, ite);
+ throw new ProxyClassInstantiationException(classToProxy, ite);
+ } catch (InstantiationException ie) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, ie);
+ throw new ProxyClassInstantiationException(classToProxy, ie);
+ } catch (IllegalAccessException iae) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, iae);
+ throw new ProxyClassInstantiationException(classToProxy, iae);
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "newProxySubclassInstance", proxySubclassInstance);
+
+ return proxySubclassInstance;
+ }
+
+ private static Class<?> generateAndLoadSubclass(Class<?> aClass, ClassLoader loader)
+ throws UnableToProxyException
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "generateAndLoadSubclass", new Object[] { aClass,
+ loader });
+
+ // set the newClassName
+ String newClassName = "$" + aClass.getSimpleName() + aClass.hashCode();
+ String packageName = aClass.getPackage().getName();
+ if (packageName.startsWith("java.") || packageName.startsWith("javax.")) {
+ packageName = "org.apache.aries.blueprint.proxy." + packageName;
+ }
+ String fullNewClassName = (packageName + "." + newClassName).replaceAll("\\.", "/");
+
+ LOGGER.debug("New class name: {}", newClassName);
+ LOGGER.debug("Full new class name: {}", fullNewClassName);
+
+ Class<?> clazz = null;
+ try {
+ ClassReader cReader = new ClassReader(loader.getResourceAsStream(aClass.getName().replaceAll(
+ "\\.", "/")
+ + ".class"));
+ ClassWriter cWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ ClassVisitor dynamicSubclassAdapter = new ProxySubclassAdapter(cWriter, fullNewClassName,
+ loader);
+ byte[] byteClassData = processClass(cReader, cWriter, dynamicSubclassAdapter);
+ clazz = loadClassFromBytes(loader, getBinaryName(fullNewClassName), byteClassData, aClass
+ .getName());
+ } catch (IOException ioe) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, ioe);
+ throw new ProxyClassBytecodeGenerationException(aClass.getName(), ioe);
+ } catch (TypeNotPresentException tnpe) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, tnpe);
+ throw new ProxyClassBytecodeGenerationException(tnpe.typeName(), tnpe.getCause());
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "generateAndLoadSubclass", clazz);
+
+ return clazz;
+ }
+
+ private static byte[] processClass(ClassReader cReader, ClassWriter cWriter, ClassVisitor cVisitor)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "processClass", new Object[] { cReader, cWriter,
+ cVisitor });
+
+ cReader.accept(cVisitor, ClassReader.SKIP_DEBUG);
+ byte[] byteClassData = cWriter.toByteArray();
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "processClass", byteClassData);
+
+ return byteClassData;
+ }
+
+ private static String getBinaryName(String name)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "getBinaryName", name);
+
+ String binaryName = name.replaceAll("/", "\\.");
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "getBinaryName", binaryName);
+
+ return binaryName;
+ }
+
+ private static Class<?> loadClassFromBytes(ClassLoader loader, String name, byte[] classData,
+ String classToProxyName) throws UnableToProxyException
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "loadClassFromBytes", new Object[] { loader, name,
+ classData });
+
+ Class<?> clazz = null;
+ try {
+ Method defineClassMethod = Class.forName("java.lang.ClassLoader").getDeclaredMethod(
+ "defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class);
+ defineClassMethod.setAccessible(true);
+ // define the class in the same classloader where aClass is loaded,
+ // but use the protection domain of our code
+ clazz = (Class<?>) defineClassMethod.invoke(loader, name, classData, 0, classData.length,
+ ProxySubclassGenerator.class.getProtectionDomain());
+ defineClassMethod.setAccessible(false);
+ } catch (ClassNotFoundException cnfe) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, cnfe);
+ throw new ProxyClassDefinitionException(classToProxyName, cnfe);
+ } catch (NoSuchMethodException nsme) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, nsme);
+ throw new ProxyClassDefinitionException(classToProxyName, nsme);
+ } catch (InvocationTargetException ite) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, ite);
+ throw new ProxyClassDefinitionException(classToProxyName, ite);
+ } catch (IllegalAccessException iae) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, iae);
+ throw new ProxyClassDefinitionException(classToProxyName, iae);
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "loadClassFromBytes", clazz);
+
+ return clazz;
+ }
+
+ public static boolean isProxySubclass(Class<?> aClass)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "isProxySubclass", new Object[] { aClass });
+
+ // We will always have a proxy map for the class loader of any proxy
+ // class, so if
+ // this is null we know to return false
+ Map<String, String> proxies = proxyClassesByClassLoader.get(aClass.getClassLoader());
+
+ boolean isProxySubclass = (proxies != null && proxies.containsValue(aClass.getName()));
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "isProxySubclass", isProxySubclass);
+
+ return isProxySubclass;
+ }
+
+ private static void scanForFinalModifiers(Class<?> clazz) throws FinalModifierException
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "scanForFinalModifiers", new Object[] { clazz });
+
+ if (isFinal(clazz.getModifiers())) {
+ throw new FinalModifierException(clazz);
+ }
+
+ List<String> finalMethods = new ArrayList<String>();
+
+ // we don't want to check for final methods on java.* or javax.* Class
+ // also, clazz can never be null here (we will always hit
+ // java.lang.Object first)
+ while (!clazz.getName().startsWith("java.") && !clazz.getName().startsWith("javax.")) {
+ for (Method m : clazz.getDeclaredMethods()) {
+ if (isFinal(m.getModifiers())) {
+ finalMethods.add(m.toGenericString());
+ }
+ }
+ clazz = clazz.getSuperclass();
+ }
+
+ if (!finalMethods.isEmpty()) {
+
+ String methodList = finalMethods.toString();
+ methodList = methodList.substring(1, methodList.length() - 1);
+ throw new FinalModifierException(clazz, methodList);
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "scanForFinalModifiers");
+
+ }
+
+ public static InvocationHandler getInvocationHandler(Object o)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "getInvoationHandler", new Object[] { o });
+
+ InvocationHandler ih = null;
+ if (isProxySubclass(o.getClass())) {
+ // we have to catch exceptions here, but we just log them
+ // the reason for this is that it should be impossible to get these
+ // exceptions
+ // since the Object we are dealing with is a class we generated on
+ // the fly
+ try {
+ ih = (InvocationHandler) o.getClass().getDeclaredMethod("getInvocationHandler",
+ new Class[] {}).invoke(o, new Object[] {});
+ } catch (IllegalArgumentException e) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, e);
+ } catch (SecurityException e) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, e);
+ } catch (IllegalAccessException e) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, e);
+ } catch (InvocationTargetException e) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, e);
+ } catch (NoSuchMethodException e) {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXCEPTION, e);
+ }
+ }
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "getInvoationHandler", ih);
+ return ih;
+ }
+
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassHierarchyAdapter.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassHierarchyAdapter.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassHierarchyAdapter.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassHierarchyAdapter.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+import java.util.Collection;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * Although we implement ClassVisitor we are only interested in the methods of
+ * the superclasses in the hierarchy. For this reason although visitMethod is
+ * implemented the other methods of ClassVisitor are currently no-op.
+ *
+ *
+ */
+public class ProxySubclassHierarchyAdapter implements ClassVisitor, Opcodes
+{
+
+ private ProxySubclassAdapter adapter = null;
+ private Collection<String> methodsToImplement = null;
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ProxySubclassHierarchyAdapter.class);
+
+ ProxySubclassHierarchyAdapter(ProxySubclassAdapter adapter, Collection<String> methodsToImplement)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "ProxySubclassHeirarchyAdapter", new Object[] {
+ this, adapter, methodsToImplement });
+
+ this.methodsToImplement = methodsToImplement;
+ this.adapter = adapter;
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "ProxySubclassHeirarchyAdapter", this);
+ }
+
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "visitMethod", new Object[] { access, name, desc,
+ signature, exceptions });
+
+ // if the method we find in the superclass is one that is available on
+ // the class
+ // we are dynamically subclassing then we need to implement an
+ // invocation for it
+ String argDesc = ProxySubclassMethodHashSet.typeArrayToStringArgDescriptor(Type
+ .getArgumentTypes(desc));
+ if (methodsToImplement.contains(name + argDesc)) {
+ // create the method in bytecode
+ adapter.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "visitMethod");
+
+ // always return null because we don't want to copy any method code
+ return null;
+ }
+
+ public void visit(int arg0, int arg1, String arg2, String arg3, String arg4, String[] arg5)
+ {
+ // no-op
+ }
+
+ public AnnotationVisitor visitAnnotation(String arg0, boolean arg1)
+ {
+ // don't process any annotations at this stage
+ return null;
+ }
+
+ public void visitAttribute(Attribute arg0)
+ {
+ // no-op
+ }
+
+ public void visitEnd()
+ {
+ // no-op
+ }
+
+ public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4)
+ {
+ // don't process fields
+ return null;
+ }
+
+ public void visitInnerClass(String arg0, String arg1, String arg2, int arg3)
+ {
+ // no-op
+ }
+
+ public void visitOuterClass(String arg0, String arg1, String arg2)
+ {
+ // no-op
+ }
+
+ public void visitSource(String arg0, String arg1)
+ {
+ // no-op
+ }
+
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassMethodHashSet.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassMethodHashSet.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassMethodHashSet.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/ProxySubclassMethodHashSet.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+import java.util.HashSet;
+
+import org.objectweb.asm.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProxySubclassMethodHashSet<E> extends HashSet<String>
+{
+ private static final long serialVersionUID = 7674408912532811084L;
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ProxySubclassMethodHashSet.class);
+
+ public ProxySubclassMethodHashSet(int i)
+ {
+ super(i);
+ }
+
+ public void addMethodArray(java.lang.reflect.Method[] arrayOfEntries)
+ {
+ LOGGER.debug(AsmInterceptorWrapper.LOG_ENTRY, "addMethodArray", new Object[] { arrayOfEntries });
+
+ for (java.lang.reflect.Method entry : arrayOfEntries) {
+ String methodName = entry.getName();
+
+ LOGGER.debug("Method name: {}", methodName);
+
+ Type[] methodArgTypes = Type.getArgumentTypes(entry);
+ String argDescriptor = typeArrayToStringArgDescriptor(methodArgTypes);
+
+ LOGGER.debug("Descriptor: {}", argDescriptor);
+
+ boolean added = super.add(methodName + argDescriptor);
+
+ LOGGER.debug("Added: {}", added);
+ }
+
+ LOGGER.debug(AsmInterceptorWrapper.LOG_EXIT, "addMethodArray");
+ }
+
+ static String typeArrayToStringArgDescriptor(Type[] argTypes)
+ {
+ StringBuilder descriptor = new StringBuilder();
+ for (Type t : argTypes) {
+ descriptor.append(t.toString());
+ }
+ return descriptor.toString();
+ }
+
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToLoadProxyException.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToLoadProxyException.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToLoadProxyException.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToLoadProxyException.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+public class UnableToLoadProxyException extends UnableToProxyException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 506487573157016476L;
+
+ public UnableToLoadProxyException(String className, Exception e)
+ {
+ super(className, e);
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToProxyException.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToProxyException.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToProxyException.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/UnableToProxyException.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+public class UnableToProxyException extends Exception
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -17516969014644128L;
+ String className = null;
+
+ public UnableToProxyException(Class<?> clazz)
+ {
+ className = clazz.getName();
+ }
+
+ public UnableToProxyException(Class<?> clazz, Exception e)
+ {
+ this(clazz.getName(), e);
+ }
+
+ public UnableToProxyException(String className, Throwable e)
+ {
+ super(e);
+ this.className = className;
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/WrapperedObject.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/WrapperedObject.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/WrapperedObject.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/proxy/WrapperedObject.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.proxy;
+
+/**
+ * Interface added to wrapped objects, to enable retrieval of the original object.
+ */
+public interface WrapperedObject {
+ /**
+ * Obtain the object wrapped by this wrapper.
+ * @return unwrapped object.
+ */
+ public Object unwrapObject();
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanArgumentImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanArgumentImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanArgumentImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanArgumentImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import org.apache.aries.blueprint.mutable.MutableBeanArgument;
+import org.osgi.service.blueprint.reflect.BeanArgument;
+import org.osgi.service.blueprint.reflect.Metadata;
+
+/**
+ * Implementation of BeanArgument
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class BeanArgumentImpl implements MutableBeanArgument {
+
+ private Metadata value;
+ private String valueType;
+ private int index = -1;
+
+ public BeanArgumentImpl() {
+ }
+
+ public BeanArgumentImpl(Metadata value, String valueType, int index) {
+ this.value = value;
+ this.valueType = valueType;
+ this.index = index;
+ }
+
+ public BeanArgumentImpl(BeanArgument source) {
+ value = MetadataUtil.cloneMetadata(source.getValue());
+ valueType = source.getValueType();
+ index = source.getIndex();
+ }
+
+ public Metadata getValue() {
+ return value;
+ }
+
+ public void setValue(Metadata value) {
+ this.value = value;
+ }
+
+ public String getValueType() {
+ return valueType;
+ }
+
+ public void setValueType(String valueType) {
+ this.valueType = valueType;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public String toString() {
+ return "BeanArgument[" +
+ "value=" + value +
+ ", valueType='" + valueType + '\'' +
+ ", index=" + index +
+ ']';
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanMetadataImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanMetadataImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanMetadataImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.aries.blueprint.ExtendedBeanMetadata;
+import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
+import org.osgi.service.blueprint.reflect.BeanArgument;
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+import org.osgi.service.blueprint.reflect.BeanProperty;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.osgi.service.blueprint.reflect.Target;
+
+/**
+ * Implementation of BeanMetadata
+ *
+ * @version $Rev: 910448 $, $Date: 2010-02-16 09:50:18 +0000 (Tue, 16 Feb 2010) $
+ */
+public class BeanMetadataImpl extends ComponentMetadataImpl implements MutableBeanMetadata {
+
+ private String className;
+ private String initMethod;
+ private String destroyMethod;
+ private List<BeanArgument> arguments;
+ private List<BeanProperty> properties;
+ private int initialization;
+ private String factoryMethod;
+ private Target factoryComponent;
+ private String scope;
+ private Class runtimeClass;
+ private boolean processor;
+ private boolean fieldInjection;
+
+ public BeanMetadataImpl() {
+ this.fieldInjection = false;
+ }
+
+ public BeanMetadataImpl(BeanMetadata source) {
+ super(source);
+ this.className = source.getClassName();
+ this.initMethod = source.getInitMethod();
+ this.destroyMethod = source.getDestroyMethod();
+ for (BeanArgument argument : source.getArguments()) {
+ addArgument(new BeanArgumentImpl(argument));
+ }
+ for (BeanProperty property : source.getProperties()) {
+ addProperty(new BeanPropertyImpl(property));
+ }
+ this.initialization = source.getActivation();
+ this.factoryMethod = source.getFactoryMethod();
+ this.factoryComponent = MetadataUtil.cloneTarget(source.getFactoryComponent());
+ this.scope = source.getScope();
+ this.dependsOn = new ArrayList<String>(source.getDependsOn());
+ if (source instanceof ExtendedBeanMetadata) {
+ this.runtimeClass = ((ExtendedBeanMetadata) source).getRuntimeClass();
+ this.fieldInjection = ((ExtendedBeanMetadata) source).getFieldInjection();
+ } else {
+ this.fieldInjection = false;
+ }
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
+ public String getInitMethod() {
+ return initMethod;
+ }
+
+ public void setInitMethod(String initMethodName) {
+ this.initMethod = initMethodName;
+ }
+
+ public String getDestroyMethod() {
+ return destroyMethod;
+ }
+
+ public void setDestroyMethod(String destroyMethodName) {
+ this.destroyMethod = destroyMethodName;
+ }
+
+ public List<BeanArgument> getArguments() {
+ if (this.arguments == null) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(this.arguments);
+ }
+ }
+
+ public void setArguments(List<BeanArgument> arguments) {
+ this.arguments = arguments != null ? new ArrayList<BeanArgument>(arguments) : null;
+ }
+
+ public void addArgument(BeanArgument argument) {
+ if (this.arguments == null) {
+ this.arguments = new ArrayList<BeanArgument>();
+ }
+ this.arguments.add(argument);
+ }
+
+ public BeanArgument addArgument(Metadata value, String valueType, int index) {
+ BeanArgument arg = new BeanArgumentImpl(value, valueType, index);
+ addArgument(arg);
+ return arg;
+ }
+
+ public void removeArgument(BeanArgument argument) {
+ if (this.arguments != null) {
+ this.arguments.remove(argument);
+ }
+ }
+
+ public List<BeanProperty> getProperties() {
+ if (this.properties == null) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(this.properties);
+ }
+ }
+
+ public void setProperties(List<BeanProperty> properties) {
+ this.properties = properties != null ? new ArrayList<BeanProperty>(properties) : null;
+ }
+
+ public void addProperty(BeanProperty property) {
+ if (this.properties == null) {
+ this.properties = new ArrayList<BeanProperty>();
+ }
+ this.properties.add(property);
+ }
+
+ public BeanProperty addProperty(String name, Metadata value) {
+ BeanProperty prop = new BeanPropertyImpl(name, value);
+ addProperty(prop);
+ return prop;
+ }
+
+ public void removeProperty(BeanProperty property) {
+ if (this.properties != null) {
+ this.properties.remove(property);
+ }
+ }
+
+ public String getFactoryMethod() {
+ return this.factoryMethod;
+ }
+
+ public void setFactoryMethod(String factoryMethodName) {
+ this.factoryMethod = factoryMethodName;
+ }
+
+ public Target getFactoryComponent() {
+ return this.factoryComponent;
+ }
+
+ public void setFactoryComponent(Target factoryComponent) {
+ this.factoryComponent = factoryComponent;
+ }
+
+ public String getScope() {
+ return this.scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+ public Class getRuntimeClass() {
+ return this.runtimeClass;
+ }
+
+ public void setRuntimeClass(Class runtimeClass) {
+ this.runtimeClass = runtimeClass;
+ }
+
+ public boolean isProcessor() {
+ return processor;
+ }
+
+ public void setProcessor(boolean processor) {
+ this.processor = processor;
+ }
+
+ public boolean getFieldInjection() {
+ return fieldInjection;
+ }
+
+ public void setFieldInjection(boolean fieldInjection) {
+ this.fieldInjection = fieldInjection;
+ }
+
+ @Override
+ public String toString() {
+ return "BeanMetadata[" +
+ "id='" + id + '\'' +
+ ", initialization=" + initialization +
+ ", dependsOn=" + dependsOn +
+ ", className='" + className + '\'' +
+ ", initMethodName='" + initMethod + '\'' +
+ ", destroyMethodName='" + destroyMethod + '\'' +
+ ", arguments=" + arguments +
+ ", properties=" + properties +
+ ", factoryMethodName='" + factoryMethod + '\'' +
+ ", factoryComponent=" + factoryComponent +
+ ", scope='" + scope + '\'' +
+ ", runtimeClass=" + runtimeClass +
+ ", fieldInjection=" + fieldInjection +
+ ']';
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanPropertyImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanPropertyImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanPropertyImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/BeanPropertyImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import org.apache.aries.blueprint.mutable.MutableBeanProperty;
+import org.osgi.service.blueprint.reflect.BeanProperty;
+import org.osgi.service.blueprint.reflect.Metadata;
+
+/**
+ * Implementation of BeanProperty
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class BeanPropertyImpl implements MutableBeanProperty {
+
+ private String name;
+ private Metadata value;
+
+ public BeanPropertyImpl() {
+ }
+
+ public BeanPropertyImpl(String name, Metadata value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public BeanPropertyImpl(BeanProperty source) {
+ this.name = source.getName();
+ this.value = MetadataUtil.cloneMetadata(source.getValue());
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Metadata getValue() {
+ return value;
+ }
+
+ public void setValue(Metadata value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "BeanProperty[" +
+ "name='" + name + '\'' +
+ ", value=" + value +
+ ']';
+ }
+}
\ No newline at end of file
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/CollectionMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/CollectionMetadataImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/CollectionMetadataImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/CollectionMetadataImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.aries.blueprint.mutable.MutableCollectionMetadata;
+import org.osgi.service.blueprint.reflect.CollectionMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+
+/**
+ * Implementation of CollectionMetadata
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class CollectionMetadataImpl implements MutableCollectionMetadata {
+
+ private Class collectionClass;
+ private String valueType;
+ private List<Metadata> values;
+
+ public CollectionMetadataImpl() {
+ }
+
+ public CollectionMetadataImpl(Class collectionClass, String valueType, List<Metadata> values) {
+ this.collectionClass = collectionClass;
+ this.valueType = valueType;
+ this.values = values;
+ }
+
+ public CollectionMetadataImpl(CollectionMetadata source) {
+ this.collectionClass = source.getCollectionClass();
+ this.valueType = source.getValueType();
+ for (Metadata value : source.getValues()) {
+ addValue(MetadataUtil.cloneMetadata(value));
+ }
+ }
+
+ public Class getCollectionClass() {
+ return collectionClass;
+ }
+
+ public void setCollectionClass(Class collectionClass) {
+ this.collectionClass = collectionClass;
+ }
+
+ public String getValueType() {
+ return valueType;
+ }
+
+ public void setValueType(String valueType) {
+ this.valueType = valueType;
+ }
+
+ public List<Metadata> getValues() {
+ if (this.values == null) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(this.values);
+ }
+ }
+
+ public void setValues(List<Metadata> values) {
+ this.values = values != null ? new ArrayList<Metadata>(values) : null;
+ }
+
+ public void addValue(Metadata value) {
+ if (this.values == null) {
+ this.values = new ArrayList<Metadata>();
+ }
+ this.values.add(value);
+ }
+
+ public void removeValue(Metadata value) {
+ if (this.values != null) {
+ this.values.remove(value);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CollectionMetadata[" +
+ "collectionClass=" + collectionClass +
+ ", valueType='" + valueType + '\'' +
+ ", values=" + values +
+ ']';
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/ComponentMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/ComponentMetadataImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/ComponentMetadataImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/ComponentMetadataImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.aries.blueprint.mutable.MutableComponentMetadata;
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+
+/**
+ * Implementation of ComponentMetadata
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class ComponentMetadataImpl implements MutableComponentMetadata {
+
+ protected String id;
+ protected int activation = ACTIVATION_EAGER;
+ protected List<String> dependsOn;
+
+ protected ComponentMetadataImpl() {
+ }
+
+ protected ComponentMetadataImpl(ComponentMetadata source) {
+ id = source.getId();
+ activation = source.getActivation();
+ dependsOn = new ArrayList<String>(source.getDependsOn());
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public int getActivation() {
+ return activation;
+ }
+
+ public void setActivation(int activation) {
+ this.activation = activation;
+ }
+
+ public List<String> getDependsOn() {
+ if (this.dependsOn == null) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(this.dependsOn);
+ }
+ }
+
+ public void setDependsOn(List<String> dependsOn) {
+ this.dependsOn = dependsOn != null ? new ArrayList<String>(dependsOn) : null;
+ }
+
+ public void addDependsOn(String explicitDependency) {
+ if (this.dependsOn == null) {
+ this.dependsOn = new ArrayList<String>();
+ }
+ this.dependsOn.add(explicitDependency);
+ }
+
+ public void removeDependsOn(String dependency) {
+ if (this.dependsOn != null) {
+ this.dependsOn.remove(dependency);
+ }
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/IdRefMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/IdRefMetadataImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/IdRefMetadataImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/IdRefMetadataImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import org.apache.aries.blueprint.mutable.MutableIdRefMetadata;
+import org.osgi.service.blueprint.reflect.IdRefMetadata;
+
+/**
+ * Implementation of IdRefMetadata
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class IdRefMetadataImpl implements MutableIdRefMetadata {
+
+ protected String componentId;
+
+ public IdRefMetadataImpl() {
+ }
+
+ public IdRefMetadataImpl(String componentId) {
+ this.componentId = componentId;
+ }
+
+ public IdRefMetadataImpl(IdRefMetadata source) {
+ componentId = source.getComponentId();
+ }
+
+ public String getComponentId() {
+ return componentId;
+ }
+
+ public void setComponentId(String componentId) {
+ this.componentId = componentId;
+ }
+
+ @Override
+ public String toString() {
+ return "IdRefMetadata[" +
+ "componentId='" + componentId + '\'' +
+ ']';
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapEntryImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapEntryImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapEntryImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapEntryImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import org.apache.aries.blueprint.mutable.MutableMapEntry;
+import org.osgi.service.blueprint.reflect.MapEntry;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.osgi.service.blueprint.reflect.NonNullMetadata;
+
+/**
+ * Implementation of MapEntry
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class MapEntryImpl implements MutableMapEntry {
+
+ private NonNullMetadata key;
+ private Metadata value;
+
+ public MapEntryImpl() {
+ }
+
+ public MapEntryImpl(NonNullMetadata key, Metadata value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public MapEntryImpl(MapEntry entry) {
+ this.key = (NonNullMetadata) MetadataUtil.cloneMetadata(entry.getKey());
+ this.value = MetadataUtil.cloneMetadata(entry.getValue());
+ }
+
+ public NonNullMetadata getKey() {
+ return key;
+ }
+
+ public void setKey(NonNullMetadata key) {
+ this.key = key;
+ }
+
+ public Metadata getValue() {
+ return value;
+ }
+
+ public void setValue(Metadata value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "MapEntry[" +
+ "key=" + key +
+ ", value=" + value +
+ ']';
+ }
+}
Added: aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapMetadataImpl.java?rev=1075139&view=auto
==============================================================================
--- aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapMetadataImpl.java (added)
+++ aries/tags/blueprint-0.2-incubating/blueprint-core/src/main/java/org/apache/aries/blueprint/reflect/MapMetadataImpl.java Sun Feb 27 20:35:36 2011
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.aries.blueprint.reflect;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.aries.blueprint.mutable.MutableMapMetadata;
+import org.osgi.service.blueprint.reflect.MapEntry;
+import org.osgi.service.blueprint.reflect.MapMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.osgi.service.blueprint.reflect.NonNullMetadata;
+
+/**
+ * Implementation of MapMetadata
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public class MapMetadataImpl implements MutableMapMetadata {
+
+ private String keyType;
+ private String valueType;
+ private List<MapEntry> entries;
+
+ public MapMetadataImpl() {
+ }
+
+ public MapMetadataImpl(String keyType, String valueType, List<MapEntry> entries) {
+ this.keyType = keyType;
+ this.valueType = valueType;
+ this.entries = entries;
+ }
+
+ public MapMetadataImpl(MapMetadata source) {
+ this.valueType = source.getValueType();
+ this.keyType = source.getKeyType();
+ for (MapEntry entry : source.getEntries()) {
+ addEntry(new MapEntryImpl(entry));
+ }
+ }
+
+ public String getKeyType() {
+ return this.keyType;
+ }
+
+ public void setKeyType(String keyTypeName) {
+ this.keyType = keyTypeName;
+ }
+
+ public String getValueType() {
+ return this.valueType;
+ }
+
+ public void setValueType(String valueTypeName) {
+ this.valueType = valueTypeName;
+ }
+
+ public List<MapEntry> getEntries() {
+ if (this.entries == null) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(this.entries);
+ }
+ }
+
+ public void setEntries(List<MapEntry> entries) {
+ this.entries = entries != null ? new ArrayList<MapEntry>(entries) : null;
+ }
+
+ public void addEntry(MapEntry entry) {
+ if (this.entries == null) {
+ this.entries = new ArrayList<MapEntry>();
+ }
+ this.entries.add(entry);
+ }
+
+ public MapEntry addEntry(NonNullMetadata key, Metadata value) {
+ MapEntry entry = new MapEntryImpl(key, value);
+ addEntry(entry);
+ return entry;
+ }
+
+ public void removeEntry(MapEntry entry) {
+ if (this.entries != null) {
+ this.entries.remove(entry);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "MapMetadata[" +
+ "keyType='" + keyType + '\'' +
+ ", valueType='" + valueType + '\'' +
+ ", entries=" + entries +
+ ']';
+ }
+}