felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From clem...@apache.org
Subject 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...
Date Fri, 21 Dec 2007 19:28:13 GMT
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



Mime
View raw message