You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2007/12/21 20:28:13 UTC
svn commit: r606280 [3/6] - in /felix/sandbox/clement/ipojo: composite/
composite/src/ composite/src/main/ composite/src/main/java/
composite/src/main/java/org/ composite/src/main/java/org/apache/
composite/src/main/java/org/apache/felix/ composite/src...
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,362 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.manipulation.Manipulator;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Check and build a composition, i.e. a POJO containing the composition.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class CompositionMetadata {
+
+ /**
+ * Implemented composition.
+ */
+ private SpecificationMetadata m_specification;
+
+ /**
+ * Name of the composition.
+ */
+ private String m_name;
+
+ /**
+ * Bundle Context.
+ */
+ private BundleContext m_context;
+
+ /**
+ * Manipulation Metadata.
+ */
+ private Element m_manipulationMetadata;
+
+ /**
+ * Reference on the handler.
+ */
+ private ProvidedServiceHandler m_handler;
+
+ /**
+ * List of Mappings.
+ */
+ private List m_mappings = new ArrayList();
+
+ /**
+ * Constructor.
+ * @param bc : bundle context
+ * @param description : 'provides' element
+ * @param psh : parent handler
+ * @param name : name of the composition.
+ */
+ public CompositionMetadata(BundleContext bc, Element description, ProvidedServiceHandler psh, String name) {
+ m_context = bc;
+ m_handler = psh;
+ // Get the composition name
+ m_name = description.getAttribute("specification") + name;
+
+ // Get implemented service specification
+ String spec = description.getAttribute("specification");
+ m_specification = new SpecificationMetadata(spec, m_context, false, false, m_handler);
+
+ Element[] mappings = description.getElements("delegation");
+ for (int i = 0; i < mappings.length; i++) {
+ String methodName = mappings[i].getAttribute("method");
+ MethodMetadata method = m_specification.getMethodByName(methodName);
+ if (method == null) {
+ m_handler.error( "The method " + methodName + " does not exist in the specicifation " + spec);
+ return;
+ }
+
+ if (mappings[i].getAttribute("policy").equalsIgnoreCase("All")) {
+ method.setAllPolicy();
+ }
+ }
+ }
+
+ protected BundleContext getBundleContext() {
+ return m_context;
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public SpecificationMetadata getSpecificationMetadata() {
+ return m_specification;
+ }
+
+ /**
+ * Build Available Mappings.
+ * @throws CompositionException : a factory is not available, the composition cannot be checked.
+ */
+ private void buildAvailableMappingList() throws CompositionException {
+ int index = 0;
+
+ for (int i = 0; i < m_handler.getInstanceType().size(); i++) {
+ String type = (String) m_handler.getInstanceType().get(i);
+ try {
+ ServiceReference[] refs = m_context.getServiceReferences(Factory.class.getName(), "(factory.name=" + type + ")");
+ if (refs == null) {
+ m_handler.error( "The factory " + type + " is not available, cannot check the composition");
+ throw new CompositionException("The factory " + type + " needs to be available to check the composition");
+ } else {
+ String className = (String) refs[0].getProperty("component.class"); //TODO !!!!
+ Class impl = m_context.getBundle().loadClass(className);
+ SpecificationMetadata spec = new SpecificationMetadata(impl, type, m_handler);
+ FieldMetadata field = new FieldMetadata(spec);
+ field.setName("_field" + index);
+ Mapping map = new Mapping(spec, field);
+ m_mappings.add(map);
+ index++;
+ }
+ } catch (InvalidSyntaxException e) {
+ m_handler.error( "A LDAP filter is not valid : " + e.getMessage());
+ } catch (ClassNotFoundException e) {
+ m_handler.error( "The implementation class of a component cannot be loaded : " + e.getMessage());
+ }
+ }
+
+ for (int i = 0; i < m_handler.getSpecifications().size(); i++) {
+ SpecificationMetadata spec = (SpecificationMetadata) m_handler.getSpecifications().get(i);
+ FieldMetadata field = new FieldMetadata(spec);
+ field.setName("_field" + index);
+ if (spec.isOptional()) {
+ field.setOptional(true);
+ }
+ if (spec.isAggregate()) {
+ field.setAggregate(true);
+ }
+ Mapping map = new Mapping(spec, field);
+ m_mappings.add(map);
+ index++;
+ }
+ }
+
+
+ /**
+ * Build the delegation mapping.
+ * @throws CompositionException : occurs when the mapping cannot be inferred correctly
+ */
+ protected void buildMapping() throws CompositionException {
+ buildAvailableMappingList();
+
+ // Dependency closure is OK, now look for method delegation
+ Map/* <MethodMetadata, Mapping> */availableSvcMethods = new HashMap();
+ Map/* <MethodMetadata, Mapping> */availableInstMethods = new HashMap();
+
+ for (int i = 0; i < m_mappings.size(); i++) {
+ Mapping map = (Mapping) m_mappings.get(i);
+ SpecificationMetadata spec = map.getSpecification();
+ for (int j = 0; j < spec.getMethods().size(); j++) {
+ MethodMetadata method = (MethodMetadata) spec.getMethods().get(j);
+ if (spec.isInterface()) {
+ availableSvcMethods.put(method, map);
+ } else {
+ availableInstMethods.put(method, map);
+ }
+ }
+ }
+
+ // For each needed method, search if available and store the mapping
+ for (int j = 0; j < m_specification.getMethods().size(); j++) {
+ MethodMetadata method = (MethodMetadata) m_specification.getMethods().get(j);
+ Set keys = availableInstMethods.keySet(); // Look first in methods contained in the glue code.
+ Iterator it = keys.iterator();
+ boolean found = false;
+ while (it.hasNext() & !found) {
+ MethodMetadata met = (MethodMetadata) it.next();
+ if (met.equals(method)) {
+ found = true;
+ FieldMetadata field = ((Mapping) availableInstMethods.get(met)).getField();
+ field.setUseful(true);
+ method.setDelegation(field);
+ }
+ }
+ if (!found) { // If not found looks inside method contained in services.
+ keys = availableSvcMethods.keySet(); // Look first in methods contained in the glue code
+ it = keys.iterator();
+ while (!found && it.hasNext()) {
+ MethodMetadata met = (MethodMetadata) it.next();
+ if (met.equals(method)) {
+ found = true;
+ FieldMetadata field = ((Mapping) availableSvcMethods.get(met)).getField();
+ field.setUseful(true);
+ method.setDelegation(field);
+ // Test optional
+ if (field.isOptional() && !method.throwsUnsupportedOperationException()) {
+ m_handler.warn("The method " + method.getMethod().getName() + " could not be provided correctly : the specification " + field.getSpecification().getName() + " is optional");
+ }
+ }
+ }
+ }
+ if (!found) {
+ throw new CompositionException("Inconsistent composition - the method " + method.getMethod() + " could not be delegated");
+ }
+ }
+ }
+
+ /**
+ * Build a service implementation.
+ * @return the byte[] of the POJO.
+ */
+ protected byte[] buildPOJO() {
+ Class clazz = null;
+ try {
+ clazz = getBundleContext().getBundle().loadClass(m_specification.getName());
+ } catch (ClassNotFoundException e1) {
+ //TODO
+ e1.printStackTrace();
+ }
+ byte[] pojo = POJOWriter.dump(clazz, m_name, getFieldList(), getMethodList());
+ Manipulator m = new Manipulator();
+ try {
+ byte[] ff = m.manipulate(pojo);
+ m_manipulationMetadata = m.getManipulationMetadata();
+ return ff;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Build service implementation metadata.
+ * @param in : name of the future instance (used to avoid cycle)
+ * @return Component Type metadata.
+ */
+ protected Element buildMetadata(String in) {
+ Element elem = new Element("component", "");
+ Attribute className = new Attribute("className", m_name);
+ Attribute factory = new Attribute("factory", "false");
+ elem.addAttribute(className);
+ elem.addAttribute(factory);
+
+ // Add architecture for debug
+ elem.addAttribute(new Attribute("architecture", "true"));
+
+ // Provides
+ Element provides = new Element("provides", "");
+ provides.addAttribute(new Attribute("specification", m_specification.getName()));
+ elem.addElement(provides);
+
+ // Dependencies
+ List fields = getFieldList();
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMetadata field = (FieldMetadata) fields.get(i);
+ if (field.isUseful() && field.getSpecification().isInterface()) {
+ Element dep = new Element("requires", "");
+ dep.addAttribute(new Attribute("field", field.getName()));
+ dep.addAttribute(new Attribute("scope", "composite"));
+ if (field.getSpecification().isOptional()) {
+ dep.addAttribute(new Attribute("optional", "true"));
+ }
+ dep.addAttribute(new Attribute("filter", "(!(instance.name=" + in + "))"));
+ elem.addElement(dep);
+ }
+ }
+
+ Element properties = new Element("properties", "");
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMetadata field = (FieldMetadata) fields.get(i);
+ if (field.isUseful() && ! field.getSpecification().isInterface()) {
+ Element prop = new Element("Property", "");
+ prop.addAttribute(new Attribute("field", field.getName()));
+ properties.addElement(prop);
+ }
+ }
+ if (properties.getElements().length != 0) {
+ elem.addElement(properties);
+ }
+
+ // Insert information to metadata
+ elem.addElement(m_manipulationMetadata);
+
+ return elem;
+ }
+
+ /**
+ * Get the field list to use for the delegation.
+ * @return the field list.
+ */
+ public List getFieldList() {
+ List list = new ArrayList();
+ for (int i = 0; i < m_mappings.size(); i++) {
+ Mapping map = (Mapping) m_mappings.get(i);
+ list.add(map.getField());
+ }
+ return list;
+ }
+
+ /**
+ * Get the method list contained in the implemented specification.
+ * @return the List of implemented method.
+ */
+ private List getMethodList() {
+ return m_specification.getMethods();
+ }
+
+ /**
+ * Store links between Field and pointed Specification.
+ */
+ private class Mapping {
+
+ /**
+ * Specification.
+ */
+ private SpecificationMetadata m_spec;
+
+ /**
+ * Field.
+ */
+ private FieldMetadata m_field;
+
+ /**
+ * Constructor.
+ * @param spec : specification metadata.
+ * @param field : the field.
+ */
+ public Mapping(SpecificationMetadata spec, FieldMetadata field) {
+ m_spec = spec;
+ m_field = field;
+ }
+
+ public SpecificationMetadata getSpecification() {
+ return m_spec;
+ }
+
+ public FieldMetadata getField() {
+ return m_field;
+ }
+
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,105 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+/**
+ * Field used inside a composition.
+ * This class contains all information useful for the generation.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FieldMetadata {
+
+ /**
+ * Name of the field.
+ */
+ private String m_name;
+
+ /**
+ * Is the field an array?
+ */
+ private boolean m_isAggregate = false;
+
+ /**
+ * Interface of the field.
+ */
+ private SpecificationMetadata m_specification;
+
+ /**
+ * Is the field useful in this composition.
+ */
+ private boolean m_isUseful;
+
+ /**
+ * Is the dependency for this field optional.
+ */
+ private boolean m_isOptional = false;
+
+ /**
+ * Constructor.
+ * @param specification : interface of the field.
+ */
+ public FieldMetadata(SpecificationMetadata specification) {
+ super();
+ this.m_specification = specification;
+ if (m_specification.isAggregate()) {
+ m_isAggregate = true;
+ }
+ }
+
+ public boolean isAggregate() {
+ return m_isAggregate;
+ }
+
+ public void setAggregate(boolean aggregate) {
+ m_isAggregate = aggregate;
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public void setName(String name) {
+ this.m_name = name;
+ }
+
+ public SpecificationMetadata getSpecification() {
+ return m_specification;
+ }
+
+ public void setSpecification(SpecificationMetadata specification) {
+ this.m_specification = specification;
+ }
+
+ public boolean isUseful() {
+ return m_isUseful;
+ }
+
+ public void setUseful(boolean useful) {
+ m_isUseful = useful;
+ }
+
+ public boolean isOptional() {
+ return m_isOptional;
+ }
+
+ public void setOptional(boolean opt) {
+ m_isOptional = opt;
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,127 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.lang.reflect.Method;
+
+/**
+ * Information on Method for the composition.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodMetadata {
+
+ /**
+ * ONE POLICY.
+ */
+ public static final int ONE_POLICY = 1;
+
+ /**
+ * ALL POLICY.
+ */
+ public static final int ALL_POLICY = 2;
+
+ /**
+ * Method Object.
+ */
+ private Method m_method;
+
+ /**
+ * Delegation field.
+ */
+ private FieldMetadata m_delegation;
+
+ /**
+ * Delegation policy (default = ONE).
+ */
+ private int m_policy = ONE_POLICY;
+
+ /**
+ * Constructor.
+ * @param method : method object.
+ */
+ public MethodMetadata(Method method) {
+ m_method = method;
+ }
+
+ public Method getMethod() {
+ return m_method;
+ }
+
+ public void setDelegation(FieldMetadata dm) {
+ m_delegation = dm;
+ }
+
+ public FieldMetadata getDelegation() {
+ return m_delegation;
+ }
+
+ /**
+ * Check if two method metadata are equals.
+ * @param mm : the method metadata to compare with the current method metadata.
+ * @return true if the two method are equals
+ */
+ public boolean equals(MethodMetadata mm) {
+ Method met = mm.getMethod();
+ return equals(met);
+ }
+
+ /**
+ * Equals method for Method object.
+ * @param met : the method object to compare.
+ * @return true if the given method signature is equals to the current method metadata.
+ */
+ public boolean equals(Method met) {
+ if (! met.getName().equals(m_method.getName()) || met.getParameterTypes().length != m_method.getParameterTypes().length) {
+ return false;
+ }
+
+ for (int i = 0; i < m_method.getParameterTypes().length; i++) {
+ if (!m_method.getParameterTypes()[i].getName().equals(met.getParameterTypes()[i].getName())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int getPolicy() {
+ return m_policy;
+ }
+
+ /**
+ * Activate the all policy for this method.
+ */
+ public void setAllPolicy() {
+ m_policy = ALL_POLICY;
+ }
+
+ /**
+ * Check if the method can throw UnsupportedOperationException.
+ * @return true if the method has declared the UnsupportedOperationException.
+ */
+ boolean throwsUnsupportedOperationException() {
+ for (int i = 0; i < m_method.getExceptionTypes().length; i++) {
+ if (m_method.getExceptionTypes()[i].getName().equals(UnsupportedOperationException.class.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,371 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * Create the Proxy class.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class POJOWriter implements Opcodes {
+
+ /**
+ * Create a class.
+ * @param cw : class writer
+ * @param className : class name
+ * @param spec : implemented specification
+ */
+ private static void createClass(ClassWriter cw, String className, String spec) {
+ // Create the class
+ cw.visit(V1_2, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[] { spec.replace('.', '/') });
+ }
+
+ /**
+ * Inject field in the current class.
+ * @param cw : class writer.
+ * @param fields : list of field to inject.
+ */
+ private static void injectFields(ClassWriter cw, List fields) {
+ // Inject fields
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMetadata field = (FieldMetadata) fields.get(i);
+ if (field.isUseful()) {
+ SpecificationMetadata spec = field.getSpecification();
+ String fieldName = field.getName();
+ String desc = "";
+ if (field.isAggregate()) {
+ desc = "[L" + spec.getName().replace('.', '/') + ";";
+ } else {
+ desc = "L" + spec.getName().replace('.', '/') + ";";
+ }
+
+ cw.visitField(Opcodes.ACC_PRIVATE, fieldName, desc, null, null);
+ }
+ }
+ }
+
+ /**
+ * Return the proxy 'classname' for the contract 'contractname' by delegating on available service.
+ * @param clazz : Specification class
+ * @param className : The class name to create
+ * @param fields : the list of fields on which delegate
+ * @param methods : the list of method on which delegate
+ * @return byte[] : the build class
+ */
+ public static byte[] dump(Class clazz, String className, List fields, List methods) {
+ Method[] itfmethods = clazz.getMethods();
+
+ // Create the class
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ className = className.replace('.', '/');
+ createClass(cw, className, clazz.getName());
+
+ // Inject fields inside the POJO
+ injectFields(cw, fields);
+
+ // Inject a constructor <INIT>()V
+ MethodVisitor cst = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ cst.visitVarInsn(ALOAD, 0);
+ cst.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ cst.visitInsn(RETURN);
+ cst.visitMaxs(0, 0);
+ cst.visitEnd();
+
+ for (int i = 0; i < itfmethods.length; ++i) {
+ Method method = itfmethods[i];
+
+ // Get the field for this method
+ // 1) find the MethodMetadata
+ FieldMetadata delegator = null; // field to delegate
+ MethodMetadata methodDelegator = null; // field to delegate
+ for (int j = 0; j < methods.size(); j++) {
+ MethodMetadata methodMeta = (MethodMetadata) methods.get(j);
+ if (methodMeta.equals(method)) {
+ delegator = methodMeta.getDelegation();
+ methodDelegator = methodMeta;
+ }
+ }
+
+ generateOneMethod(cw, className, methodDelegator, method, delegator);
+
+ }
+
+ // End process
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ /**
+ * Generate on method.
+ * @param cw : class writer
+ * @param className : the current class name
+ * @param method : the method to generate
+ * @param sign : method signature to generate
+ * @param delegator : the field on which delegate
+ */
+ private static void generateOneMethod(ClassWriter cw, String className, MethodMetadata method, Method sign, FieldMetadata delegator) {
+ String desc = Type.getMethodDescriptor(sign);
+ String name = sign.getName();
+ String[] exc = new String[sign.getExceptionTypes().length];
+ for (int i = 0; i < sign.getExceptionTypes().length; i++) {
+ exc[i] = Type.getType(sign.getExceptionTypes()[i]).getInternalName();
+ }
+
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, name, desc, null, exc);
+
+ if (delegator.isOptional()) {
+ if (!delegator.isAggregate()) {
+ generateOptionalCase(mv, delegator, className);
+ }
+ if (delegator.isAggregate() /*&& method.getPolicy() == MethodMetadata.ONE_POLICY*/) {
+ generateOptionalAggregateCase(mv, delegator, className);
+ }
+ }
+
+ if (delegator.isAggregate()) {
+ if (method.getPolicy() == MethodMetadata.ONE_POLICY) {
+ // Aggregate and One Policy
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");
+ mv.visitInsn(ICONST_0); // Take the first one
+ mv.visitInsn(AALOAD);
+
+ // Loads args
+ Type[] args = Type.getArgumentTypes(desc);
+ for (int i = 0; i < args.length; i++) {
+ writeLoad(args[i], i + 1, mv);
+ }
+
+ // Invoke
+ mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+
+ // Return
+ writeReturn(Type.getReturnType(desc), mv);
+ } else { // All policy
+ if (Type.getReturnType(desc).getSort() != Type.VOID) {
+ System.err.println("All policy cannot be used on method which does not return void");
+ }
+
+ Type[] args = Type.getArgumentTypes(desc);
+ int index = args.length + 1;
+
+ // Init
+ mv.visitInsn(ICONST_0);
+ mv.visitVarInsn(ISTORE, index);
+ Label l1b = new Label();
+ mv.visitLabel(l1b);
+ Label l2b = new Label();
+ mv.visitJumpInsn(GOTO, l2b);
+
+ // Loop
+ Label l3b = new Label();
+ mv.visitLabel(l3b);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");
+ mv.visitVarInsn(ILOAD, index);
+ mv.visitInsn(AALOAD);
+
+ // Loads args
+ for (int i = 0; i < args.length; i++) {
+ writeLoad(args[i], i + 1, mv);
+ }
+
+ mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+
+ Label l4b = new Label();
+ mv.visitLabel(l4b);
+ mv.visitIincInsn(index, 1); // i++;
+
+ // Condition
+ mv.visitLabel(l2b);
+ mv.visitVarInsn(ILOAD, index);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");
+ mv.visitInsn(ARRAYLENGTH);
+ mv.visitJumpInsn(IF_ICMPLT, l3b);
+
+ Label l5b = new Label();
+ mv.visitLabel(l5b);
+ mv.visitInsn(RETURN);
+ }
+ } else {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "L" + delegator.getSpecification().getName().replace('.', '/') + ";");
+
+ // Loads args
+ Type[] args = Type.getArgumentTypes(desc);
+ for (int i = 0; i < args.length; i++) {
+ writeLoad(args[i], i + 1, mv);
+ }
+
+ // Invoke
+ if (delegator.getSpecification().isInterface()) {
+ mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+ } else {
+ mv.visitMethodInsn(INVOKEVIRTUAL, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+ }
+
+ // Return
+ writeReturn(Type.getReturnType(desc), mv);
+ }
+
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ /**
+ * Generate Optional Case for aggregate field.
+ * @param mv : method visitor
+ * @param delegator : Field on which delegate
+ * @param className : current class name
+ */
+ private static void generateOptionalAggregateCase(MethodVisitor mv, FieldMetadata delegator, String className) {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");
+ mv.visitInsn(ARRAYLENGTH);
+ Label l1a = new Label();
+ mv.visitJumpInsn(IFNE, l1a);
+ Label l2a = new Label();
+ mv.visitLabel(l2a);
+ mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException");
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn("Operation not supported");
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "(Ljava/lang/String;)V");
+ mv.visitInsn(ATHROW);
+ mv.visitLabel(l1a);
+ }
+
+ /**
+ * Generate Optional case for non aggregate fields.
+ *
+ * @param mv : the method visitor
+ * @param delegator : the field on which delegate.
+ * @param className : the name of the current class.
+ */
+ private static void generateOptionalCase(MethodVisitor mv, FieldMetadata delegator, String className) {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "L" + delegator.getSpecification().getName().replace('.', '/') + ";");
+ mv.visitTypeInsn(INSTANCEOF, "org/apache/felix/ipojo/Nullable");
+ Label end = new Label();
+ mv.visitJumpInsn(IFEQ, end);
+ Label begin = new Label();
+ mv.visitLabel(begin);
+ mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException");
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn("Operation not supported");
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "(Ljava/lang/String;)V");
+ mv.visitInsn(ATHROW);
+ mv.visitLabel(end);
+ }
+
+ /**
+ * Write a return instruction according to the given type.
+ * @param t : the type
+ * @param mv : the method visitor
+ */
+ private static void writeReturn(Type t, MethodVisitor mv) {
+ switch (t.getSort()) {
+ case Type.BOOLEAN:
+ case Type.INT:
+ case Type.BYTE:
+ case Type.CHAR:
+ case Type.SHORT:
+ // Integer or Boolean : return 0 ( false)
+ mv.visitInsn(IRETURN);
+ break;
+ case Type.LONG:
+ // mv.visitInsn(LCONST_0);
+ mv.visitInsn(LRETURN);
+ break;
+ case Type.DOUBLE:
+ // Double : return 0.0
+ // mv.visitInsn(DCONST_0);
+ mv.visitInsn(DRETURN);
+ break;
+ case Type.FLOAT:
+ // Double : return 0.0
+ // mv.visitInsn(DCONST_0);
+ mv.visitInsn(FRETURN);
+ break;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ // Return always null for array and object
+ // mv.visitInsn(ACONST_NULL);
+ mv.visitInsn(ARETURN);
+ break;
+ case Type.VOID:
+ mv.visitInsn(RETURN);
+ break;
+ default:
+ System.err.println("Type not yet managed : " + t);
+ break;
+ }
+ }
+
+ /**
+ * Write a load instruction according to the given type.
+ * @param t : the type
+ * @param mv : the method visitor
+ * @param index : variable name (index)
+ */
+ private static void writeLoad(Type t, int index, MethodVisitor mv) {
+ switch (t.getSort()) {
+ case Type.BOOLEAN:
+ case Type.INT:
+ case Type.BYTE:
+ case Type.CHAR:
+ case Type.SHORT:
+ // Integer or Boolean : return 0 ( false)
+ mv.visitVarInsn(ILOAD, index);
+ break;
+ case Type.LONG:
+ // mv.visitInsn(LCONST_0);
+ mv.visitVarInsn(LLOAD, index);
+ break;
+ case Type.FLOAT:
+ // mv.visitInsn(LCONST_0);
+ mv.visitVarInsn(FLOAD, index);
+ break;
+ case Type.DOUBLE:
+ // Double : return 0.0
+ // mv.visitInsn(DCONST_0);
+ mv.visitVarInsn(DLOAD, index);
+ break;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ // Return always null for array and object
+ // mv.visitInsn(ACONST_NULL);
+ mv.visitVarInsn(ALOAD, index);
+ break;
+ default:
+ System.err.println("Type not yet managed : " + t);
+ break;
+ }
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,234 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.MissingHandlerException;
+import org.apache.felix.ipojo.ServiceContext;
+import org.apache.felix.ipojo.UnacceptableConfiguration;
+import org.apache.felix.ipojo.composite.CompositeManager;
+import org.apache.felix.ipojo.composite.instance.InstanceHandler;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Composite Provided Service.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProvidedService {
+
+ /**
+ * Composite Manager.
+ */
+ private CompositeManager m_manager;
+
+ /**
+ * Composition Model.
+ */
+ private CompositionMetadata m_composition;
+
+ /**
+ * generated POJO class.
+ */
+ private byte[] m_clazz;
+
+ /**
+ * Metadata of the POJO.
+ */
+ private Element m_metadata;
+
+ /**
+ * Internal context.
+ */
+ private ServiceContext m_scope;
+
+ /**
+ * External context.
+ */
+ private BundleContext m_context;
+
+ /**
+ * Created Factory.
+ */
+ private ComponentFactory m_factory;
+
+ /**
+ * Created Instance.
+ */
+ private ComponentInstance m_instance;
+
+ /**
+ * Exporter.
+ */
+ private ServiceExporter m_exports;
+
+ /**
+ * Created instance name.
+ */
+ private String m_instanceName;
+
+ /**
+ * Constructor.
+ * The delegation mapping is infers in this method.
+ * @param handler : the handler.
+ * @param element : 'provides' element.
+ * @param name : name of this provided service.
+ */
+ public ProvidedService(ProvidedServiceHandler handler, Element element, String name) {
+ m_manager = handler.getCompositeManager();
+ m_scope = m_manager.getServiceContext();
+ m_context = m_manager.getContext();
+ m_composition = new CompositionMetadata(m_manager.getContext(), element, handler, name);
+ }
+
+ /**
+ * Start method.
+ * Build service implementation type, factory and instance.
+ * @throws CompositionException if a consistent mapping cannot be discovered.
+ */
+ public void start() throws CompositionException {
+ m_composition.buildMapping();
+
+ m_instanceName = m_composition.getSpecificationMetadata().getName() + "Provider-Gen";
+ m_clazz = m_composition.buildPOJO();
+ m_metadata = m_composition.buildMetadata(m_instanceName);
+
+ // Create the factory
+ m_factory = new ComponentFactory(m_context, m_clazz, m_metadata);
+ m_factory.start();
+
+ // Create the exports
+ m_exports = new ServiceExporter(m_composition.getSpecificationMetadata().getName(), "(instance.name=" + m_instanceName + ")", false, false,
+ m_scope, m_context, this);
+ m_exports.start();
+ }
+
+ /**
+ * Stop the provided service.
+ * Kill the exporter, the instance and the factory.
+ */
+ public void stop() {
+ if (m_exports != null) {
+ m_exports.stop();
+ m_exports = null;
+ }
+ if (m_instance != null) {
+ m_instance.dispose();
+ m_instance = null;
+ }
+ if (m_factory != null) {
+ m_factory.stop();
+ m_factory = null;
+ }
+ }
+
+ protected CompositeManager getManager() {
+ return m_manager;
+ }
+
+ /**
+ * The exporter becomes valid.
+ * @param exporter : the exporter
+ */
+ public void validating(ServiceExporter exporter) {
+ }
+
+ /**
+ * The exporter becomes invalid.
+ * @param exporter : the exporter
+ */
+ public void invalidating(ServiceExporter exporter) {
+ }
+
+ /**
+ * Unregister published service.
+ */
+ protected void unregister() {
+ if (m_instance != null) {
+ m_instance.dispose();
+ m_instance = null;
+ }
+ }
+
+ /**
+ * Register published service.
+ */
+ protected void register() {
+ if (m_exports != null) {
+ if (m_instance != null) { m_instance.dispose(); }
+ Properties p = new Properties();
+ p.put("name", m_instanceName);
+ List fields = m_composition.getFieldList();
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMetadata fm = (FieldMetadata) fields.get(i);
+ if (fm.isUseful() && !fm.getSpecification().isInterface()) {
+ String type = fm.getSpecification().getComponentType();
+ Object o = getObjectByType(type);
+ p.put(fm.getName(), o);
+ }
+ }
+ try {
+ m_instance = m_factory.createComponentInstance(p, m_manager.getServiceContext());
+ } catch (UnacceptableConfiguration e) {
+ e.printStackTrace();
+ } catch (MissingHandlerException e) {
+ e.printStackTrace();
+ } catch (ConfigurationException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Get an object from the given type.
+ * @param type : type
+ * @return an object from an instance of this type or null
+ */
+ private Object getObjectByType(String type) {
+ InstanceHandler h = (InstanceHandler) m_manager.getCompositeHandler("org.apache.felix.ipojo.composite.instance.InstanceHandler");
+ Object o = h.getObjectFromInstance(type);
+ if (o == null) {
+ m_manager.getFactory().getLogger().log(Logger.ERROR, "An instance object cannot be found for the type : " + type);
+ }
+ return o;
+
+ }
+
+ public String getSpecification() {
+ return m_composition.getSpecificationMetadata().getName();
+ }
+
+ /**
+ * Check the provided service state.
+ * @return true if the exporter is publishing.
+ */
+ public boolean getState() {
+ if (m_exports != null && m_exports.isPublishing()) {
+ return true;
+ }
+ return false;
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,363 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.HandlerManager;
+import org.apache.felix.ipojo.IPojoConfiguration;
+import org.apache.felix.ipojo.PolicyServiceContext;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.composite.CompositeHandler;
+import org.apache.felix.ipojo.composite.instance.InstanceHandler;
+import org.apache.felix.ipojo.composite.service.importer.ImportHandler;
+import org.apache.felix.ipojo.composite.service.importer.ServiceImporter;
+import org.apache.felix.ipojo.composite.service.instantiator.ServiceInstantiatorHandler;
+import org.apache.felix.ipojo.composite.service.instantiator.SvcInstance;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ManifestMetadataParser;
+import org.apache.felix.ipojo.parser.ParseException;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Composite Provided Service Handler.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProvidedServiceHandler extends CompositeHandler {
+
+ /**
+ * External context.
+ */
+ private BundleContext m_context;
+
+ /**
+ * List of "available" services in the internal context.
+ */
+ private List m_services = new ArrayList();
+
+ /**
+ * List of managed services.
+ */
+ private List m_managedServices = new ArrayList();
+
+ /**
+ * List of component type.
+ */
+ private List m_types;
+
+ /**
+ * Initialize the component type.
+ * @param cd : component type description to populate.
+ * @param metadata : component type metadata.
+ * @throws ConfigurationException : metadata are incorrect.
+ * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element)
+ */
+ public void initializeComponentFactory(ComponentTypeDescription cd, Element metadata) throws ConfigurationException {
+ Element[] provides = metadata.getElements("provides", "");
+ for (int i = 0; i < provides.length; i++) {
+ String spec = provides[i].getAttribute("specification");
+ if (spec != null) {
+ cd.addProvidedServiceSpecification(spec);
+ } else {
+ throw new ConfigurationException("Malformed provides : the specification attribute is mandatory");
+ }
+ }
+ }
+
+ /**
+ * Configure the handler.
+ * @param metadata : the metadata of the component
+ * @param configuration : the instance configuration
+ * @see org.apache.felix.ipojo.CompositeHandler#configure(org.apache.felix.ipojo.CompositeManager,
+ * org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+ */
+ public void configure(Element metadata, Dictionary configuration) {
+ m_context = getCompositeManager().getContext();
+
+ // Get composition metadata
+ Element[] provides = metadata.getElements("provides", "");
+ if (provides.length == 0) { return; }
+
+ for (int i = 0; i < provides.length; i++) {
+ ProvidedService ps = new ProvidedService(this, provides[i], "" + i);
+ m_managedServices.add(ps);
+ }
+ }
+
+ /**
+ * Start method.
+ * Start all managed provided service.
+ * @see org.apache.felix.ipojo.CompositeHandler#start()
+ */
+ public void start() {
+ // Compute imports and instances
+ computeAvailableServices();
+ computeAvailableTypes();
+
+ for (int i = 0; i < m_managedServices.size(); i++) {
+ ProvidedService ps = (ProvidedService) m_managedServices.get(i);
+ try {
+ checkServiceSpecification(ps);
+ ps.start();
+ } catch (CompositionException e) {
+ error("Cannot start the provided service handler", e);
+ setValidity(false);
+ return;
+ }
+ }
+ setValidity(true);
+ }
+
+ /**
+ * Stop method.
+ * Stop all managed provided service.
+ * @see org.apache.felix.ipojo.CompositeHandler#stop()
+ */
+ public void stop() {
+ for (int i = 0; i < m_managedServices.size(); i++) {
+ ProvidedService ps = (ProvidedService) m_managedServices.get(i);
+ ps.stop();
+ }
+ }
+
+ /**
+ * Handler state changed.
+ * @param state : the new instance state.
+ * @see org.apache.felix.ipojo.CompositeHandler#stateChanged(int)
+ */
+ public void stateChanged(int state) {
+ if (state == ComponentInstance.INVALID) {
+ for (int i = 0; i < m_managedServices.size(); i++) {
+ ProvidedService ps = (ProvidedService) m_managedServices.get(i);
+ ps.unregister();
+ }
+ return;
+ }
+
+ // If the new state is VALID => register all the services
+ if (state == ComponentInstance.VALID) {
+ for (int i = 0; i < m_managedServices.size(); i++) {
+ ProvidedService ps = (ProvidedService) m_managedServices.get(i);
+ ps.register();
+ }
+ return;
+ }
+ }
+
+ /**
+ * Build the list of available specification.
+ * @return the list of available specification.
+ */
+ protected List getSpecifications() {
+ return m_services;
+ }
+
+ /**
+ * Build the list of available specifications.
+ */
+ private void computeAvailableServices() {
+ // Get instantiated services :
+ ImportHandler ih = (ImportHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":requires");
+ ServiceInstantiatorHandler sh = (ServiceInstantiatorHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":service");
+
+ for (int i = 0; sh != null && i < sh.getInstances().size(); i++) {
+ SvcInstance svc = (SvcInstance) sh.getInstances().get(i);
+ String itf = svc.getSpecification();
+ boolean agg = svc.isAggregate();
+ boolean opt = svc.isOptional();
+
+ SpecificationMetadata sm = new SpecificationMetadata(itf, m_context, agg, opt, this);
+ m_services.add(sm);
+ }
+
+ for (int i = 0; ih != null && i < ih.getRequirements().size(); i++) {
+ ServiceImporter si = (ServiceImporter) ih.getRequirements().get(i);
+ String itf = si.getSpecification();
+ boolean agg = si.isAggregate();
+ boolean opt = si.isOptional();
+
+ SpecificationMetadata sm = new SpecificationMetadata(itf, m_context, agg, opt, this);
+ m_services.add(sm);
+ }
+ }
+
+ /**
+ * Check composite requirement against service specification requirement is available.
+ * @param ps : the provided service to check
+ * @throws CompositionException : occurs if the specification field of the service specification cannot be analyzed correctly.
+ */
+ private void checkServiceSpecification(ProvidedService ps) throws CompositionException {
+ try {
+ Class spec = m_context.getBundle().loadClass(ps.getSpecification());
+ Field specField = spec.getField("specification");
+ Object o = specField.get(null);
+ if (o instanceof String) {
+ Element specification = ManifestMetadataParser.parse((String) o);
+ Element[] reqs = specification.getElements("requires");
+ for (int j = 0; j < reqs.length; j++) {
+ ServiceImporter imp = getAttachedRequirement(reqs[j]);
+ if (imp != null) {
+ // Fix service-level dependency flag
+ imp.setServiceLevelDependency();
+ }
+ checkRequirement(imp, reqs[j]);
+ }
+ } else {
+ error( "[" + getCompositeManager().getInstanceName() + "] The specification field of the service specification " + ps.getSpecification() + " need to be a String");
+ throw new CompositionException("Service Specification checking failed : The specification field of the service specification " + ps.getSpecification() + " need to be a String");
+ }
+ } catch (NoSuchFieldException e) {
+ return; // No specification field
+ } catch (ClassNotFoundException e) {
+ error( "[" + getCompositeManager().getInstanceName() + "] The service specification " + ps.getSpecification() + " cannot be load");
+ throw new CompositionException("The service specification " + ps.getSpecification() + " cannot be load : " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ error( "[" + getCompositeManager().getInstanceName() + "] The field 'specification' of the service specification " + ps.getSpecification() + " is not accessible : " + e.getMessage());
+ throw new CompositionException("The field 'specification' of the service specification " + ps.getSpecification() + " is not accessible : " + e.getMessage());
+ } catch (IllegalAccessException e) {
+ error( "[" + getCompositeManager().getInstanceName() + "] The field 'specification' of the service specification " + ps.getSpecification() + " is not accessible : " + e.getMessage());
+ throw new CompositionException("The field 'specification' of the service specification " + ps.getSpecification() + " is not accessible : " + e.getMessage());
+ } catch (ParseException e) {
+ error( "[" + getCompositeManager().getInstanceName() + "] The field 'specification' of the service specification " + ps.getSpecification() + " does not contain a valid String : " + e.getMessage());
+ throw new CompositionException("The field 'specification' of the service specification " + ps.getSpecification() + " does not contain a valid String : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Look for the implementation (i.e. composite) requirement for the given service-level requirement metadata.
+ * @param element : the service-level requirement metadata
+ * @return the ServiceImporter object, null if not found or if the DependencyHandler is not plugged to the instance
+ */
+ private ServiceImporter getAttachedRequirement(Element element) {
+ ImportHandler ih = (ImportHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":requires");
+ if (ih == null) { return null; }
+
+ String id = element.getAttribute("id");
+ if (id != null) {
+ // Look for dependency Id
+ for (int i = 0; i < ih.getRequirements().size(); i++) {
+ ServiceImporter imp = (ServiceImporter) ih.getRequirements().get(i);
+ if (imp.getId().equals(id)) { return imp; }
+ }
+ }
+
+ // If not found or no id, look for a dependency with the same specification
+ String requirement = element.getAttribute("specification");
+ for (int i = 0; i < ih.getRequirements().size(); i++) {
+ ServiceImporter imp = (ServiceImporter) ih.getRequirements().get(i);
+ if (imp.getSpecification().equals(requirement)) { return imp; }
+ }
+ return null;
+ }
+
+ /**
+ * Check the correctness of the composite requirement against the service level dependency.
+ * @param imp : requirement to check
+ * @param elem : service-level dependency metadata
+ * @throws CompositionException : occurs if the requirement does not match with service-level specification requirement
+ */
+ private void checkRequirement(ServiceImporter imp, Element elem) throws CompositionException {
+ String op = elem.getAttribute("optional");
+ boolean opt = op != null && op.equalsIgnoreCase("true");
+
+ String ag = elem.getAttribute("aggregate");
+ boolean agg = ag != null && ag.equalsIgnoreCase("true");
+
+ if (imp == null) {
+ // Add the missing requirement
+ ImportHandler ih = (ImportHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":requires");
+ if (ih == null) {
+ // Look for the import handler factory
+ HandlerManager ci = null;
+ try {
+ ServiceReference[] refs = m_context.getServiceReferences(Factory.class.getName(), "(&(handler.name=requires)(handler.namespace=" + IPojoConfiguration.IPOJO_NAMESPACE + ")(handler.type=composite))");
+ Factory factory = (Factory) m_context.getService(refs[0]);
+ ci = (HandlerManager) factory.createComponentInstance(null, getCompositeManager().getServiceContext());
+ } catch (Exception e) {
+ e.printStackTrace(); // Should not happen
+ }
+ // Add the required handler
+ try {
+ ci.init(getCompositeManager(), new Element("composite", ""), new Properties());
+ } catch (ConfigurationException e) {
+ error( "Internal error : cannot configure the Import Handler : " + e.getMessage());
+ throw new CompositionException("Internal error : cannot configure the Import Handler : " + e.getMessage());
+ }
+ ih = (ImportHandler) ci.getHandler();
+ getCompositeManager().addCompositeHandler(ci);
+ }
+ String spec = elem.getAttribute("specification");
+ String filter = "(&(objectClass=" + spec + ")(!(instance.name=" + getCompositeManager().getInstanceName() + ")))"; // Cannot import yourself
+ String f = elem.getAttribute("filter");
+ if (f != null) {
+ filter = "(&" + filter + f + ")";
+ }
+
+ ServiceImporter si = new ServiceImporter(spec, filter, agg, opt, getCompositeManager().getContext(), getCompositeManager().getServiceContext(), PolicyServiceContext.LOCAL, null, ih);
+ ih.getRequirements().add(si);
+ SpecificationMetadata sm = new SpecificationMetadata(spec, m_context, agg, opt, this);
+ m_services.add(sm); // Update the available types
+ return;
+ }
+
+ if (imp.isAggregate() && !agg) {
+ error( "[" + getCompositeManager().getInstanceName() + "] The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");
+ throw new CompositionException("The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");
+ }
+
+ String filter = elem.getAttribute("filter");
+ if (filter != null) {
+ String filter2 = imp.getFilter();
+ if (filter2 == null || !filter2.equalsIgnoreCase(filter)) {
+ error( "[" + getCompositeManager().getInstanceName() + "] The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement");
+ throw new CompositionException("The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement");
+ }
+ }
+ }
+
+ public HandlerDescription getDescription() {
+ return new ProvidedServiceHandlerDescription(this, m_managedServices);
+ }
+
+ /**
+ * Build available instance types.
+ */
+ private void computeAvailableTypes() {
+ InstanceHandler ih = (InstanceHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":instance");
+ if (ih == null) {
+ m_types = new ArrayList();
+ } else {
+ m_types = ih.getUsedType();
+ }
+ }
+
+ public List getInstanceType() {
+ return m_types;
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,74 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.composite.CompositeHandler;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Provided Service Handler Description for composite.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProvidedServiceHandlerDescription extends HandlerDescription {
+
+ /**
+ * Provided Service Description list.
+ */
+ private List m_providedServices = new ArrayList();
+
+ /**
+ * Constructor.
+ *
+ * @param h : composite handler.
+ * @param ps : The list of Provided Service.
+ */
+ public ProvidedServiceHandlerDescription(CompositeHandler h, List ps) {
+ super(h);
+ m_providedServices = ps;
+ }
+
+ /**
+ * Get the handler description.
+ * @return the provided service handler description
+ * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
+ */
+ public Element getHandlerInfo() {
+ Element services = super.getHandlerInfo();
+ for (int i = 0; i < m_providedServices.size(); i++) {
+ ProvidedService ps = (ProvidedService) m_providedServices.get(i);
+ Element service = new Element("service", "");
+ String state = "unregistered";
+ if (ps.getState()) {
+ state = "registered";
+ }
+ String spec = "[" + ps.getSpecification() + "]";
+ service.addAttribute(new Attribute("Specification", spec));
+ service.addAttribute(new Attribute("State", state));
+ services.addElement(service);
+ }
+ return services;
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,363 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ServiceContext;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Export an service from the scope to the parent context.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceExporter implements ServiceListener {
+
+ /**
+ * Destination context.
+ */
+ private BundleContext m_destination;
+
+ /**
+ * Origin context.
+ */
+ private ServiceContext m_origin;
+
+ /**
+ * Exported specification.
+ */
+ private String m_specification;
+
+ /**
+ * LDAP filter filtering internal provider.
+ */
+ private Filter m_filter;
+
+ /**
+ * String form of the LDAP filter.
+ */
+ private String m_filterStr;
+
+ /**
+ * Should be exported several providers.
+ */
+ private boolean m_aggregate = false;
+
+ /**
+ * Is this exports optional?
+ */
+ private boolean m_optional = false;
+
+ /**
+ * Reference on the provided service.
+ */
+ private ProvidedService m_ps;
+
+ /**
+ * Is the export valid?
+ */
+ private boolean m_isValid;
+
+ private class Record {
+ /**
+ * Internal Reference.
+ */
+ private ServiceReference m_ref;
+ /**
+ * External Registration.
+ */
+ private ServiceRegistration m_reg;
+ /**
+ * Exposed object.
+ */
+ private Object m_svcObject;
+ }
+
+ /**
+ * List of managed records.
+ */
+ private List/* <Record> */m_records = new ArrayList()/* <Record> */;
+
+ /**
+ * Constructor.
+ *
+ * @param specification : exported service specification.
+ * @param filter : LDAP filter
+ * @param multiple : is the export an aggregate export?
+ * @param optional : is the export optional?
+ * @param from : internal service context
+ * @param to : external bundle context
+ * @param exp : handler
+ */
+ public ServiceExporter(String specification, String filter, boolean multiple, boolean optional, ServiceContext from, BundleContext to, ProvidedService exp) {
+ this.m_destination = to;
+ this.m_origin = from;
+ this.m_ps = exp;
+ try {
+ this.m_filter = to.createFilter(filter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ return;
+ }
+ this.m_aggregate = multiple;
+ this.m_specification = specification;
+ this.m_optional = optional;
+ }
+
+ /**
+ * Start method.
+ * Start the export and the provider tracking.
+ */
+ public synchronized void start() {
+ try {
+ ServiceReference[] refs = m_origin.getServiceReferences(m_specification, null);
+ if (refs != null) {
+ for (int i = 0; i < refs.length; i++) {
+ if (m_filter.match(refs[i])) {
+ Record rec = new Record();
+ rec.m_ref = refs[i];
+ m_records.add(rec);
+ }
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+
+ // Publish available services
+ if (m_records.size() > 0) {
+ if (m_aggregate) {
+ for (int i = 0; i < m_records.size(); i++) {
+ Record rec = (Record) m_records.get(i);
+ rec.m_svcObject = m_origin.getService(rec.m_ref);
+ rec.m_reg = m_destination.registerService(m_specification, rec.m_svcObject, getProps(rec.m_ref));
+ }
+ } else {
+ Record rec = (Record) m_records.get(0);
+ if (rec.m_reg == null) {
+ rec.m_svcObject = m_origin.getService(rec.m_ref);
+ rec.m_reg = m_destination.registerService(m_specification, rec.m_svcObject, getProps(rec.m_ref));
+ }
+ }
+ }
+
+ // Register service listener
+ try {
+ m_origin.addServiceListener(this, "(" + Constants.OBJECTCLASS + "=" + m_specification + ")");
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+
+ m_isValid = isSatisfied();
+ }
+
+ /**
+ * Transform service reference property in a dictionary.
+ * instance.name and factory.name are injected too.
+ * @param ref : the service reference.
+ * @return the dictionary containing all property of the given service reference.
+ */
+ private Dictionary getProps(ServiceReference ref) {
+ Properties prop = new Properties();
+ String[] keys = ref.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ prop.put(keys[i], ref.getProperty(keys[i]));
+ }
+
+ prop.put("instance.name", m_ps.getManager().getInstanceName());
+ prop.put("factory.name", m_ps.getManager().getFactory().getName());
+
+ return prop;
+ }
+
+ /**
+ * Stop method.
+ * Remove the service listener and unregister all exported service.
+ */
+ public synchronized void stop() {
+ m_origin.removeServiceListener(this);
+
+ for (int i = 0; i < m_records.size(); i++) {
+ Record rec = (Record) m_records.get(i);
+ rec.m_svcObject = null;
+ if (rec.m_reg != null) {
+ rec.m_reg.unregister();
+ m_origin.ungetService(rec.m_ref);
+ rec.m_ref = null;
+ }
+ }
+
+ m_records.clear();
+ }
+
+ /**
+ * Check exporter validity.
+ * @return true if the exports is optional, or a service is really exported
+ */
+ public boolean isSatisfied() {
+ return m_optional || m_records.size() > 0;
+ }
+
+ /**
+ * Check if a service is published.
+ * @return true if at least one service is published by this handler
+ */
+ public boolean isPublishing() {
+ return m_records.size() > 0;
+ }
+
+ /**
+ * Get the list of records using the given reference.
+ * @param ref : the service reference
+ * @return the list of records using the given reference, empty if no record used this reference
+ */
+ private List/* <Record> */getRecordsByRef(ServiceReference ref) {
+ List l = new ArrayList();
+ for (int i = 0; i < m_records.size(); i++) {
+ Record rec = (Record) m_records.get(i);
+ if (rec.m_ref == ref) {
+ l.add(rec);
+ }
+ }
+ return l;
+ }
+
+ /**
+ * Service Listener Implementation.
+ * @param ev : the service event
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent ev) {
+ if (ev.getType() == ServiceEvent.REGISTERED) {
+ arrivalManagement(ev.getServiceReference());
+ }
+ if (ev.getType() == ServiceEvent.UNREGISTERING) {
+ departureManagement(ev.getServiceReference());
+ }
+
+ if (ev.getType() == ServiceEvent.MODIFIED) {
+ if (m_filter.match(ev.getServiceReference())) {
+ // Test if the ref is always matching with the filter
+ List l = getRecordsByRef(ev.getServiceReference());
+ if (l.size() > 0) { // The ref is already contained => update
+ // the properties
+ for (int i = 0; i < l.size(); i++) { // Stop the implied
+ // record
+ Record rec = (Record) l.get(i);
+ if (rec.m_reg != null) {
+ rec.m_reg.setProperties(getProps(rec.m_ref));
+ }
+ }
+ } else { // it is a new mathcing service => add it
+ arrivalManagement(ev.getServiceReference());
+ }
+ } else {
+ List l = getRecordsByRef(ev.getServiceReference());
+ if (l.size() > 0) { // The ref is already contained => the
+ // service does no more match
+ departureManagement(ev.getServiceReference());
+ }
+ }
+ }
+ }
+
+ /**
+ * Manage the arrival of a service.
+ * @param ref : the new service reference.
+ */
+ private void arrivalManagement(ServiceReference ref) {
+ // Check if the new service match
+ if (m_filter.match(ref)) {
+ // Add it to the record list
+ Record rec = new Record();
+ rec.m_ref = ref;
+ m_records.add(rec);
+ // Publishing ?
+ if (m_records.size() == 1 || m_aggregate) { // If the service is the
+ // first one, or if it
+ // is a multiple imports
+ rec.m_svcObject = m_origin.getService(rec.m_ref);
+ rec.m_reg = m_destination.registerService(m_specification, rec.m_svcObject, getProps(rec.m_ref));
+ }
+ // Compute the new state
+ if (!m_isValid && isSatisfied()) {
+ m_isValid = true;
+ m_ps.validating(this);
+ }
+ }
+ }
+
+ /**
+ * Manage the departure of a service.
+ * @param ref : the new service reference.
+ */
+ private void departureManagement(ServiceReference ref) {
+ List l = getRecordsByRef(ref);
+ for (int i = 0; i < l.size(); i++) { // Stop the implied record
+ Record rec = (Record) l.get(i);
+ if (rec.m_reg != null) {
+ rec.m_svcObject = null;
+ rec.m_reg.unregister();
+ rec.m_reg = null;
+ m_origin.ungetService(rec.m_ref);
+ }
+ }
+ m_records.removeAll(l);
+
+ // Check the validity & if we need to reimport the service
+ if (m_records.size() > 0) {
+ // There is other available services
+ if (!m_aggregate) { // Import the next one
+ Record rec = (Record) m_records.get(0);
+ if (rec.m_svcObject == null) { // It is the first service who
+ // disappears - create the next
+ // one
+ rec.m_svcObject = m_origin.getService(rec.m_ref);
+ rec.m_reg = m_destination.registerService(m_specification, rec.m_svcObject, getProps(rec.m_ref));
+ }
+ }
+ } else {
+ if (!m_optional) {
+ m_isValid = false;
+ m_ps.invalidating(this);
+ }
+ }
+ }
+
+
+ protected String getSpecification() {
+ return m_specification;
+ }
+
+
+ public String getFilter() {
+ return m_filterStr;
+ }
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,160 @@
+/*
+ * 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.felix.ipojo.composite.service.provides;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * Represent a service specification.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class SpecificationMetadata {
+
+ /**
+ * Name of the specification, i.e. name of the interface.
+ */
+ private String m_name;
+
+ /**
+ * List of the method contained in the specification.
+ */
+ private List/* <MethodMetadata> */m_methods = new ArrayList/* <MethodMetadata> */();
+
+ /**
+ * Is the specification an aggregate?
+ */
+ private boolean m_isAggregate;
+
+ /**
+ * Is the specification optional?
+ */
+ private boolean m_isOptional = false;
+
+ /**
+ * Is the specification an interface?
+ */
+ private boolean m_isInterface = true;
+
+ /**
+ * Component Type.
+ */
+ private String m_componentType = null;
+
+ /**
+ * Reference on the handler.
+ */
+ private ProvidedServiceHandler m_handler;
+
+ /**
+ * Constructor.
+ * @param name : specification name.
+ * @param bc : bundle context.
+ * @param isAggregate : is the specification aggregate.
+ * @param isOptional : is the specification optional.
+ * @param psd : the handler.
+ */
+ public SpecificationMetadata(String name, BundleContext bc, boolean isAggregate, boolean isOptional, ProvidedServiceHandler psd) {
+ m_name = name;
+ m_handler = psd;
+
+ // Populate methods :
+ try {
+ Class clazz = bc.getBundle().loadClass(name);
+ Method[] methods = clazz.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ MethodMetadata method = new MethodMetadata(methods[i]);
+ m_methods.add(method);
+ }
+ } catch (ClassNotFoundException e) {
+ m_handler.error( "Cannot open " + name + " : " + e.getMessage());
+ return;
+ }
+
+ m_isAggregate = isAggregate;
+ m_isOptional = isOptional;
+ }
+
+ /**
+ * Constructor.
+ * @param c : class
+ * @param type : component type
+ * @param psd : the parent handler
+ */
+ public SpecificationMetadata(Class c, String type, ProvidedServiceHandler psd) {
+ m_handler = psd;
+ m_isAggregate = false;
+ m_isOptional = false;
+ m_componentType = type;
+ m_name = c.getName();
+ Method[] methods = c.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ MethodMetadata method = new MethodMetadata(methods[i]);
+ m_methods.add(method);
+ }
+ m_isInterface = false;
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public List/* <MethodMetadata> */getMethods() {
+ return m_methods;
+ }
+
+ /**
+ * Get a method by its name.
+ * @param name : method name
+ * @return the method metadata contained in the current specification with the given name. Null if the method is not found.
+ */
+ public MethodMetadata getMethodByName(String name) {
+ for (int i = 0; i < m_methods.size(); i++) {
+ MethodMetadata met = (MethodMetadata) m_methods.get(i);
+ if (met.getMethod().getName().equals(name)) {
+ return met;
+ }
+ }
+ return null;
+ }
+
+ public boolean isAggregate() {
+ return m_isAggregate;
+ }
+
+ public boolean isOptional() {
+ return m_isOptional;
+ }
+
+ public boolean isInterface() {
+ return m_isInterface;
+ }
+
+ public void setIsOptional(boolean optional) {
+ m_isOptional = optional;
+ }
+
+ public String getComponentType() {
+ return m_componentType;
+ }
+
+}
Added: felix/sandbox/clement/ipojo/composite/src/main/resources/metadata.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/composite/src/main/resources/metadata.xml?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/composite/src/main/resources/metadata.xml (added)
+++ felix/sandbox/clement/ipojo/composite/src/main/resources/metadata.xml Fri Dec 21 11:28:07 2007
@@ -0,0 +1,27 @@
+<ipojo>
+<!-- Composite Handler -->
+<handler classname="org.apache.felix.ipojo.composite.instance.InstanceHandler" name="instance" type="composite" architecture="false">
+ <!-- <controller field="m_isValid"/> -->
+ <requires filter="(factory.state=1)" field="m_factories" optional="true">
+ <callback type="bind" method="bindFactory"/>
+ <callback type="unbind" method="unbindFactory"/>
+ </requires>
+</handler>
+<handler classname="org.apache.felix.ipojo.composite.service.importer.ImportHandler" name="requires" type="composite" architecture="false">
+ <!-- <controller field="m_valid"/> -->
+</handler>
+<handler classname="org.apache.felix.ipojo.composite.service.importer.ExportHandler" name="exports" type="composite" architecture="false">
+ <!-- <controller field="m_valid"/> -->
+</handler>
+<handler classname="org.apache.felix.ipojo.composite.service.instantiator.ServiceInstantiatorHandler" name="service" type="composite" architecture="false">
+ <!-- <controller field="m_isValid"/> -->
+</handler>
+<handler classname="org.apache.felix.ipojo.composite.service.provides.ProvidedServiceHandler" name="provides" type="composite" architecture="false">
+ <!-- <controller field="m_valid"/>-->
+</handler>
+<handler classname="org.apache.felix.ipojo.composite.architecture.ArchitectureHandler" name="architecture" type="composite" architecture="false">
+ <provides>
+ <property field="m_name" name="instance.name" value=""/>
+ </provides>
+</handler>
+</ipojo>
\ No newline at end of file