felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From clem...@apache.org
Subject svn commit: r1453391 [2/4] - in /felix/trunk/ipojo: arch-gogo/ arch-gogo/src/main/java/org/apache/felix/ipojo/arch/gogo/ runtime/composite-it/src/it/ipojo-composite-import-export-test/src/test/java/org/apache/felix/ipojo/runtime/core/ runtime/composite...
Date Wed, 06 Mar 2013 15:44:14 GMT
Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,75 @@
+/*
+ * 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.extender.internal.builder;
+
+import org.apache.felix.ipojo.IPojoFactory;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilder;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilderException;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * An Factory builder using a reflective call to build the factory.
+ * <p/>
+ * This builder is compatible with the original iPOJO method consisting in calling a constructor receiving the bundle
+ * context and the metadata as parameters.
+ * <p/>
+ * This factory builder need the constructor to be called.
+ */
+public class ReflectiveFactoryBuilder implements FactoryBuilder {
+
+    /**
+     * The constructor to call.
+     */
+    private final Constructor<? extends IPojoFactory> m_constructor;
+
+    /**
+     * Creates the factory builder.
+     *
+     * @param constructor the constructor that will be called when a new component factory will be created.
+     */
+    public ReflectiveFactoryBuilder(Constructor<? extends IPojoFactory> constructor) {
+        m_constructor = constructor;
+    }
+
+    /**
+     * Calls the wrapped constructor to create an iPOJO factory.
+     *
+     * @param bundleContext the bundle context of the bundle declaring the component type
+     * @param metadata      the metadata of the component type (<code>component</code> element).
+     * @return the created iPOJO factory
+     * @throws FactoryBuilderException if the constructor cannot be called or throws an error.
+     */
+    public IPojoFactory build(BundleContext bundleContext, Element metadata) throws FactoryBuilderException {
+        try {
+            return m_constructor.newInstance(bundleContext, metadata);
+        } catch (InstantiationException e) {
+            throw new FactoryBuilderException("Cannot create instance of " + m_constructor.getDeclaringClass(), e);
+        } catch (IllegalAccessException e) {
+            throw new FactoryBuilderException(m_constructor.getDeclaringClass() + " constructor is not " +
+                    "accessible (not public)", e);
+        } catch (InvocationTargetException e) {
+            throw new FactoryBuilderException("Cannot create instance of " + m_constructor.getDeclaringClass(), e);
+        }
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,135 @@
+/*
+ * 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.extender.internal.declaration;
+
+import org.apache.felix.ipojo.extender.Declaration;
+import org.apache.felix.ipojo.extender.Status;
+import org.apache.felix.ipojo.extender.internal.AbstractService;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Common code to all Declaration objects.
+ */
+public abstract class AbstractDeclaration extends AbstractService implements Declaration, Status {
+
+    /**
+     * The message used when a declaration is bound.
+     */
+
+    public static final String DECLARATION_BOUND_MESSAGE = "Declaration bound";
+    /**
+     * Is the declaration bound (i.e. successfully fulfilled), or not.
+     */
+    private boolean m_bound = false;
+
+    /**
+     * When not bound, the reason, otherwise {@link #DECLARATION_BOUND_MESSAGE}
+     */
+    private String m_message;
+
+    /**
+     * If an error was thrown during the binding, the error.
+     */
+    private Throwable m_throwable;
+
+    protected AbstractDeclaration(BundleContext bundleContext, Class<?> type) {
+        super(bundleContext, type);
+    }
+
+    /**
+     * @return whether the declaration is bound or not.
+     */
+    public boolean isBound() {
+        return m_bound;
+    }
+
+    /**
+     * @return the message. The message contains the not-bound reason.
+     */
+    public String getMessage() {
+        return m_message;
+    }
+
+    /**
+     * @return the error if something went wrong during the binding process.
+     */
+    public Throwable getThrowable() {
+        return m_throwable;
+    }
+
+    /**
+     * Gets the status of the declaration. This method returns an immutable object.
+     *
+     * @return the declaration status.
+     */
+    public Status getStatus() {
+        // We return an immutable object, created on the fly.
+        return new Status() {
+            final boolean m_bound = AbstractDeclaration.this.m_bound;
+            final String m_message = AbstractDeclaration.this.m_message;
+            final Throwable m_throwable = AbstractDeclaration.this.m_throwable;
+
+            public boolean isBound() {
+                return this.m_bound;
+            }
+
+            public String getMessage() {
+                return this.m_message;
+            }
+
+            public Throwable getThrowable() {
+                return this.m_throwable;
+            }
+        };
+    }
+
+    /**
+     * Binds the declaration.
+     * This method just set the status, message and error.
+     */
+    public void bind() {
+        m_bound = true;
+        m_message = DECLARATION_BOUND_MESSAGE;
+        m_throwable = null;
+    }
+
+    /**
+     * Unbinds the declaration.
+     *
+     * @param message an explanation
+     * @see #unbind(String, Throwable)
+     */
+    public void unbind(String message) {
+        unbind(message, null);
+    }
+
+    /**
+     * Unbinds the declaration.
+     * The flag, message and error are set.
+     *
+     * @param message   an explanation
+     * @param throwable an error
+     */
+    public void unbind(String message, Throwable throwable) {
+        m_bound = false;
+        m_message = message;
+        m_throwable = throwable;
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,64 @@
+/*
+ * 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.extender.internal.declaration;
+
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilder;
+import org.osgi.framework.BundleContext;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+/**
+ * Default implementation of the iPOJO Extension Declaration.
+ */
+public class DefaultExtensionDeclaration extends AbstractDeclaration implements ExtensionDeclaration {
+
+    private final FactoryBuilder m_factoryBuilder;
+    private final String m_type;
+
+    public DefaultExtensionDeclaration(BundleContext bundleContext, FactoryBuilder factoryBuilder, String type) {
+        super(bundleContext, ExtensionDeclaration.class);
+        m_factoryBuilder = factoryBuilder;
+        m_type = type;
+    }
+
+    public FactoryBuilder getFactoryBuilder() {
+        return m_factoryBuilder;
+    }
+
+    public String getExtensionName() {
+        return m_type;
+    }
+
+    @Override
+    public void start() {
+        super.start();
+        bind();
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(ExtensionDeclaration.EXTENSION_NAME_PROPERTY, m_type);
+        return properties;
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,96 @@
+/*
+ * 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.extender.internal.declaration;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.extender.InstanceDeclaration;
+import org.osgi.framework.BundleContext;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+/**
+ * Default implementation of the instance declaration.
+ */
+public class DefaultInstanceDeclaration extends AbstractDeclaration implements InstanceDeclaration {
+
+    private static final Dictionary<String, Object> EMPTY_DICTIONARY = new Hashtable<String, Object>();
+
+    private final String m_componentName;
+    private final Dictionary<String, Object> m_configuration;
+    private final String m_componentVersion;
+    private final String m_instanceName;
+
+    public DefaultInstanceDeclaration(BundleContext bundleContext, String componentName) {
+        this(bundleContext, componentName, EMPTY_DICTIONARY);
+    }
+
+    public DefaultInstanceDeclaration(BundleContext bundleContext, String componentName, Dictionary<String, Object> configuration) {
+        super(bundleContext, InstanceDeclaration.class);
+        m_componentName = componentName;
+        m_configuration = configuration;
+        m_componentVersion = initComponentVersion();
+        m_instanceName = initInstanceName();
+    }
+
+    private String initInstanceName() {
+        String name = (String) m_configuration.get(Factory.INSTANCE_NAME_PROPERTY);
+        if (name == null) {
+            name = UNNAMED_INSTANCE;
+        }
+        return name;
+    }
+
+    private String initComponentVersion() {
+        return (String) m_configuration.get(Factory.FACTORY_VERSION_PROPERTY);
+    }
+
+    public Dictionary<String, Object> getConfiguration() {
+        return m_configuration;
+    }
+
+    public String getComponentName() {
+        return m_componentName;
+    }
+
+    public String getComponentVersion() {
+        return m_componentVersion;
+    }
+
+    public String getInstanceName() {
+        return m_instanceName;
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(InstanceDeclaration.COMPONENT_NAME_PROPERTY, m_componentName);
+
+        String version = getComponentVersion();
+        if (version != null) {
+            properties.put(InstanceDeclaration.COMPONENT_VERSION_PROPERTY, version);
+        }
+
+        properties.put(InstanceDeclaration.INSTANCE_NAME, m_instanceName);
+
+        return properties;
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,96 @@
+/*
+ * 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.extender.internal.declaration;
+
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Default implementation of the component type declaration.
+ */
+public class DefaultTypeDeclaration extends AbstractDeclaration implements TypeDeclaration {
+
+    private final Element m_componentMetadata;
+    private final String m_componentName;
+    private final String m_componentVersion;
+    private final String m_extension;
+    private boolean visible = true;
+
+    public DefaultTypeDeclaration(BundleContext bundleContext, Element componentMetadata) {
+        super(bundleContext, TypeDeclaration.class);
+        m_componentMetadata = componentMetadata;
+        visible = initVisible();
+        m_componentName = initComponentName();
+        m_componentVersion = initComponentVersion(bundleContext);
+        m_extension = initExtension();
+    }
+
+    private String initExtension() {
+        if (m_componentMetadata.getNameSpace() == null) {
+            return m_componentMetadata.getName();
+        }
+        return m_componentMetadata.getNameSpace() + ":" + m_componentMetadata.getName();
+    }
+
+    private String initComponentVersion(BundleContext bundleContext) {
+        String version = m_componentMetadata.getAttribute("version");
+        if (version != null) {
+            if ("bundle".equalsIgnoreCase(version)) {
+                return bundleContext.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);
+            }
+        }
+        return version;
+    }
+
+    private String initComponentName() {
+        String name = m_componentMetadata.getAttribute("name");
+        if (name == null) {
+            name = m_componentMetadata.getAttribute("classname");
+        }
+        return name;
+    }
+
+    private boolean initVisible() {
+        String publicAttribute = m_componentMetadata.getAttribute("public");
+        return (publicAttribute == null) || !publicAttribute.equalsIgnoreCase("false");
+    }
+
+    public String getComponentName() {
+        return m_componentName;
+    }
+
+    public String getComponentVersion() {
+        return m_componentVersion;
+    }
+
+    public String getExtension() {
+        return m_extension;
+    }
+
+    public Element getComponentMetadata() {
+        return m_componentMetadata;
+    }
+
+    public boolean isPublic() {
+        return visible;
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,109 @@
+/*
+ * 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.extender.internal.linker;
+
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.extender.internal.Lifecycle;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * The linker is responsible to bind extension declaration to type declaration.
+ * It tracks TypeDeclaration, and reifies them as factory.
+ */
+public class DeclarationLinker implements ServiceTrackerCustomizer, Lifecycle {
+    /**
+     * The bundle context. It uses the iPOJO bundle context.
+     */
+    private final BundleContext m_bundleContext;
+
+    /**
+     * The queue service on which we delegate the binding process.
+     */
+    private final QueueService m_queueService;
+
+    /**
+     * The service tracker looking for TypeDeclaration.
+     */
+    private final ServiceTracker m_typeTracker;
+
+    /**
+     * Creates the linker.
+     *
+     * @param bundleContext the bundle context
+     * @param queueService  the queue service
+     */
+    public DeclarationLinker(BundleContext bundleContext, QueueService queueService) {
+        m_bundleContext = bundleContext;
+        m_queueService = queueService;
+        m_typeTracker = new ServiceTracker(m_bundleContext, TypeDeclaration.class.getName(), this);
+    }
+
+    /**
+     * When the iPOJO management starts, we look for type declaration.
+     */
+    public void start() {
+        m_typeTracker.open(true);
+    }
+
+    /**
+     * When iPOJO stops, we close the tracker.
+     */
+    public void stop() {
+        m_typeTracker.close();
+    }
+
+    /**
+     * A new type declaration was published.
+     *
+     * @param reference the service reference of the type declaration
+     * @return the managed type object wrapping the service object.
+     */
+    public Object addingService(ServiceReference reference) {
+        TypeDeclaration declaration = (TypeDeclaration) m_bundleContext.getService(reference);
+        ManagedType managedType = new ManagedType(reference.getBundle().getBundleContext(), m_queueService, declaration);
+        managedType.start();
+        return managedType;
+    }
+
+    /**
+     * Type declaration cannot be modified.
+     *
+     * @param reference the reference
+     * @param service   the object returned by {@link #addingService(org.osgi.framework.ServiceReference)}
+     */
+    public void modifiedService(ServiceReference reference, Object service) {
+        // Ignored
+    }
+
+    /**
+     * A type declaration service was withdrawn from the  service registry.
+     *
+     * @param reference the leaving reference
+     * @param service   the object returned by {@link #addingService(org.osgi.framework.ServiceReference)}
+     */
+    public void removedService(ServiceReference reference, Object service) {
+        ManagedType managedType = (ManagedType) service;
+        managedType.stop();
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,340 @@
+/*
+ * 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.extender.internal.linker;
+
+import org.apache.felix.ipojo.*;
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.InstanceDeclaration;
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilderException;
+import org.apache.felix.ipojo.extender.internal.Lifecycle;
+import org.apache.felix.ipojo.extender.internal.ReferenceableCallable;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * This class is responsible to create the factory for a given type declaration. It also instructs the factories to
+ * create
+ * the instance for each instance declaration targeting the managed factory.
+ */
+public class ManagedType implements FactoryStateListener, Lifecycle {
+    /**
+     * The bundle context
+     */
+    private final BundleContext m_bundleContext;
+    /**
+     * The queue service used for the creation.
+     */
+    private final QueueService m_queueService;
+    /**
+     * The type declaration that we have to handle.
+     */
+    private final TypeDeclaration m_declaration;
+    /**
+     * The service tracker tracking {@link ExtensionDeclaration} services.
+     */
+    private ServiceTracker m_extensionTracker;
+
+    /**
+     * The service tracker tracking the {@link InstanceDeclaration} services.
+     */
+    private ServiceTracker m_instanceTracker;
+
+    /**
+     * The job used to instantiate the factory.
+     */
+    private Future<IPojoFactory> m_future;
+
+    /**
+     * If the Managed Type cannot be initializes, sets this flag to true and no links will be created.
+     */
+    private boolean m_frozen;
+
+    /**
+     * Constructs a Managed Type object for the given type declaration.
+     *
+     * @param bundleContext the bundle context
+     * @param queueService  the queue service
+     * @param declaration   the declaration
+     */
+    public ManagedType(BundleContext bundleContext, QueueService queueService, TypeDeclaration declaration) {
+        m_bundleContext = bundleContext;
+        m_queueService = queueService;
+        m_declaration = declaration;
+        try {
+            initExtensionTracker();
+            initInstanceTracker();
+        } catch (InvalidSyntaxException e) {
+            // Error during filter creation, freeze the declaration and add a meaningful message
+            m_frozen = true;
+            m_declaration.unbind("Filter creation error", e);
+        }
+    }
+
+    /**
+     * Initializes the extension declaration tracker.
+     *
+     * @throws InvalidSyntaxException cannot happen
+     */
+    private void initExtensionTracker() throws InvalidSyntaxException {
+        String filter = String.format(
+                "(&(objectclass=%s)(%s=%s))",
+                ExtensionDeclaration.class.getName(),
+                ExtensionDeclaration.EXTENSION_NAME_PROPERTY,
+                m_declaration.getExtension()
+        );
+        m_extensionTracker = new ServiceTracker(m_bundleContext, m_bundleContext.createFilter(filter), new ExtensionSupport());
+    }
+
+    /**
+     * Initializes the instance declaration tracker.
+     *
+     * @throws InvalidSyntaxException cannot happen
+     */
+    private void initInstanceTracker() throws InvalidSyntaxException {
+
+        String filter;
+        String version = m_declaration.getComponentVersion();
+        if (version != null) {
+            // Track instance for:
+            // * this component AND
+            // * this component's version OR no version
+            filter = String.format(
+                    "(&(objectClass=%s)(%s=%s)(|(%s=%s)(!(%s=*))))",
+                    InstanceDeclaration.class.getName(),
+                    InstanceDeclaration.COMPONENT_NAME_PROPERTY,
+                    m_declaration.getComponentName(),
+                    InstanceDeclaration.COMPONENT_VERSION_PROPERTY,
+                    version,
+                    InstanceDeclaration.COMPONENT_VERSION_PROPERTY
+            );
+        } else {
+            // Track instance for:
+            // * this component AND no version
+            filter = String.format(
+                    "(&(objectClass=%s)(%s=%s)(!(%s=*)))",
+                    InstanceDeclaration.class.getName(),
+                    InstanceDeclaration.COMPONENT_NAME_PROPERTY,
+                    m_declaration.getComponentName(),
+                    InstanceDeclaration.COMPONENT_VERSION_PROPERTY
+            );
+        }
+        m_instanceTracker = new ServiceTracker(m_bundleContext, m_bundleContext.createFilter(filter), new InstanceSupport());
+    }
+
+    /**
+     * Starting the management.
+     * We open only the extension tracker.
+     */
+    public void start() {
+        if (!m_frozen) {
+            m_extensionTracker.open(true);
+        }
+    }
+
+    /**
+     * Stopping the management.
+     */
+    public void stop() {
+        m_instanceTracker.close();
+        m_extensionTracker.close();
+    }
+
+    /**
+     * The factory we have built has a state in his change.
+     *
+     * @param factory  the changing factory
+     * @param newState the new factory state
+     */
+    public void stateChanged(Factory factory, int newState) {
+        if (Factory.VALID == newState) {
+            // Start tracking instances
+            m_instanceTracker.open(true);
+        } else {
+            // Un-track all instances
+            m_instanceTracker.close();
+        }
+    }
+
+    /**
+     * The service tracker customizer for extension declaration.
+     * It submits a factory building job when an extension matching our type declaration is found.
+     */
+    private class ExtensionSupport implements ServiceTrackerCustomizer {
+        public Object addingService(ServiceReference reference) {
+            // TODO Check if we can cast the instance
+            final Object service = m_bundleContext.getService(reference);
+            if (service instanceof ExtensionDeclaration) {
+                m_future = m_queueService.submit(new ReferenceableCallable<IPojoFactory>(reference.getBundle()) {
+
+                    /**
+                     * The factory creation job.
+                     * @return the IPojoFactory
+                     * @throws Exception the factory cannot be created
+                     */
+                    public IPojoFactory call() throws Exception {
+                        ExtensionDeclaration declaration = (ExtensionDeclaration) service;
+                        try {
+                            // Build and start the factory instance
+                            IPojoFactory factory = declaration.getFactoryBuilder().build(m_bundleContext, m_declaration.getComponentMetadata());
+                            factory.addFactoryStateListener(ManagedType.this);
+                            factory.start();
+
+                            // Change the status
+                            m_declaration.bind();
+
+                            return factory;
+                        } catch (FactoryBuilderException e) {
+                            m_declaration.unbind(String.format("Cannot build '%s' factory instance", m_declaration.getExtension()), e);
+                        } catch (Throwable t) {
+                            m_declaration.unbind(String.format("Error during '%s' factory instance creation", m_declaration.getExtension()), t);
+                        }
+
+                        return null;
+                    }
+                });
+            }
+
+            return null;
+        }
+
+        public void modifiedService(ServiceReference reference, Object o) {
+        }
+
+        public void removedService(ServiceReference reference, Object o) {
+
+            // Then stop the factory
+            try {
+                IPojoFactory factory = m_future.get();
+                // It is possible that the factory couldn't be created
+                if (factory != null) {
+                    factory.stop();
+                    factory.removeFactoryStateListener(ManagedType.this);
+                    m_declaration.unbind("Extension '%s' is missing");
+                }
+            } catch (InterruptedException e) {
+                m_declaration.unbind("Could not create Factory", e);
+            } catch (ExecutionException e) {
+                m_declaration.unbind("Factory creation throw an Exception", e);
+            }
+            m_future = null;
+        }
+    }
+
+    private class InstanceSupport implements ServiceTrackerCustomizer {
+        public Object addingService(final ServiceReference reference) {
+            // TODO Check if we can cast the instance
+            Object service = m_bundleContext.getService(reference);
+            if (service instanceof InstanceDeclaration) {
+                final InstanceDeclaration instanceDeclaration = (InstanceDeclaration) service;
+
+                // Check that instance is not already bound
+                if (instanceDeclaration.getStatus().isBound()) {
+                    return null;
+                }
+
+                // Handle visibility (private/public factories)
+                if (!m_declaration.isPublic()) {
+                    if (!reference.getBundle().equals(m_bundleContext.getBundle())) {
+                        Bundle origin = m_bundleContext.getBundle();
+                        instanceDeclaration.unbind(
+                                String.format("Component '%s/%s' is private. It only accept instances " +
+                                        "from bundle %s/%s [%d] (instance bundle origin: %d)",
+                                        m_declaration.getComponentName(),
+                                        m_declaration.getComponentVersion(),
+                                        origin.getSymbolicName(),
+                                        origin.getVersion(),
+                                        origin.getBundleId(),
+                                        reference.getBundle().getBundleId())
+                        );
+                        return null;
+                    }
+                }
+
+                return m_queueService.submit(new ReferenceableCallable<ComponentInstance>(reference.getBundle()) {
+                    public ComponentInstance call() throws Exception {
+                        try {
+                            // Create the component's instance
+                            // It is automatically started
+                            // Future.get should never be null since this tracker is started when the factory has been created
+                            ComponentInstance instance = m_future.get().createComponentInstance(instanceDeclaration.getConfiguration());
+
+                            // Notify the declaration that everything is fine
+                            instanceDeclaration.bind();
+
+                            return instance;
+                        } catch (UnacceptableConfiguration c) {
+                            m_declaration.unbind(String.format("Instance configuration is invalid (component:%s/%s, bundle:%d)",
+                                    m_declaration.getComponentName(),
+                                    m_declaration.getComponentVersion(),
+                                    reference.getBundle().getBundleId()),
+                                    c);
+                        } catch (MissingHandlerException e) {
+                            m_declaration.unbind(String.format("Component '%s/%s' is missing some handlers", m_declaration.getComponentName(), m_declaration.getComponentVersion()), e);
+                        } catch (ConfigurationException e) {
+                            m_declaration.unbind(String.format("Component '%s/%s' is incorrect", m_declaration.getComponentName(), m_declaration.getComponentVersion()), e);
+                        }
+
+                        return null;
+                    }
+                });
+            }
+
+            return null;
+        }
+
+        public void modifiedService(ServiceReference reference, Object o) {
+        }
+
+        public void removedService(ServiceReference reference, Object o) {
+            InstanceDeclaration instanceDeclaration = (InstanceDeclaration) m_bundleContext.getService(reference);
+            Future<ComponentInstance> future = (Future<ComponentInstance>) o;
+            ComponentInstance instance = null;
+            try {
+                instance = future.get();
+                // It is possible that the instance couldn't be created
+                if (instance != null) {
+                    String message = String.format("Factory for Component '%s/%s' is missing",
+                            instance.getFactory().getName(),
+                            m_declaration.getComponentVersion());
+                    instanceDeclaration.unbind(message);
+
+                    instance.stop();
+                    instance.dispose();
+                }
+
+            } catch (InterruptedException e) {
+                instanceDeclaration.unbind("Could not create ComponentInstance", e);
+            } catch (ExecutionException e) {
+                instanceDeclaration.unbind("ComponentInstance creation throw an Exception", e);
+            }
+        }
+    }
+
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java Wed Mar  6 15:44:12 2013
@@ -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.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.osgi.framework.Bundle;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A bundle processor chaining others processor.
+ * It composes the <em>extender</em> mechanism.
+ * <p/>
+ * Instance must be created using the {@link #create(org.apache.felix.ipojo.extender.internal.BundleProcessor...)}
+ * method.
+ */
+public class ChainedBundleProcessor implements BundleProcessor {
+
+    /**
+     * The list of processors.
+     * Be aware that the order if important, as processors will be called in the insertion order.
+     * <p/>
+     * Once the chained bundle processor is created, this list cannot be modified.
+     */
+    private final List<BundleProcessor> m_processors = new ArrayList<BundleProcessor>();
+
+    private ChainedBundleProcessor() {
+        // Just here to avoid direct creation.
+    }
+
+    /**
+     * Creates a new chained bundle processor.
+     *
+     * @param processors the set of processor to chain. Cannot be <code>null</code> or empty.
+     * @return the created bundle processor
+     * @throws IllegalArgumentException if the given processor list is <code>null</code> or empty.
+     */
+    public static ChainedBundleProcessor create(BundleProcessor... processors) {
+        if (processors == null || processors.length == 0) {
+            throw new IllegalArgumentException("Chained processor cannot be created without processors");
+        }
+        ChainedBundleProcessor chain = new ChainedBundleProcessor();
+        Collections.addAll(chain.m_processors, processors);
+        return chain;
+    }
+
+    /**
+     * Gets the list of processors.
+     * This method returns a copy of the list of processor.
+     *
+     * @return a copy of the processor list
+     */
+    public List<BundleProcessor> getProcessors() {
+        List<BundleProcessor> list = new ArrayList<BundleProcessor>();
+        list.addAll(m_processors);
+        return list;
+    }
+
+    /**
+     * A bundle is starting.
+     * Call the {@link BundleProcessor#activate(org.osgi.framework.Bundle)} method on all chained processors.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(Bundle bundle) {
+        for (BundleProcessor processor : m_processors) {
+            processor.activate(bundle);
+        }
+    }
+
+    /**
+     * A bundle is stopping.
+     * Call the {@link BundleProcessor#deactivate(org.osgi.framework.Bundle)} method on all chained processors.
+     *
+     * @param bundle the bundle
+     */
+    public void deactivate(Bundle bundle) {
+        List<BundleProcessor> reverse = new ArrayList<BundleProcessor>(m_processors);
+        Collections.reverse(reverse);
+        for (BundleProcessor processor : reverse) {
+            processor.deactivate(bundle);
+        }
+    }
+
+    /**
+     * The iPOJO bundle is starting.
+     * Call the {@link org.apache.felix.ipojo.extender.internal.BundleProcessor#start()}  method on all chained
+     * processors.
+     */
+    public void start() {
+        for (BundleProcessor processor : m_processors) {
+            processor.start();
+        }
+    }
+
+    /**
+     * The iPOJO bundle is stopping.
+     * Call the {@link org.apache.felix.ipojo.extender.internal.BundleProcessor#stop()} method on all chained
+     * processors.
+     */
+    public void stop() {
+        List<BundleProcessor> reverse = new ArrayList<BundleProcessor>(m_processors);
+        Collections.reverse(reverse);
+        for (BundleProcessor processor : reverse) {
+            processor.stop();
+        }
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,231 @@
+/*
+ * 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.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultInstanceDeclaration;
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultTypeDeclaration;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ManifestMetadataParser;
+import org.apache.felix.ipojo.parser.ParseException;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.Bundle;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Processor handling the {@link #IPOJO_HEADER} and {@link #IPOJO_HEADER_ALT}
+ * header from the bundle manifest.
+ */
+public class ComponentsBundleProcessor implements BundleProcessor {
+
+    /**
+     * iPOJO Component Type and Instance declaration header.
+     */
+    public static final String IPOJO_HEADER = "iPOJO-Components";
+
+    /**
+     * iPOJO Component Type and Instance declaration header
+     * (alternative).
+     * This header was introduced because of BND supporting only header
+     * starting with an uppercase.
+     */
+    public static final String IPOJO_HEADER_ALT = "IPOJO-Components";
+
+    /**
+     * The attribute used in instance configuration specifying the targeted component (i.e. factory).
+     */
+    public static final String COMPONENT_INSTANCE_ATTRIBUTE = "component";
+
+    /**
+     * The logger.
+     */
+    private final Log m_logger;
+
+    /**
+     * Registry storing the bundle to components and instances declared within this bundle.
+     */
+    private final Map<Bundle, ComponentsAndInstances> m_registry = new HashMap<Bundle, ComponentsAndInstances>();
+
+    /**
+     * Creates the component bundle processor.
+     *
+     * @param logger the logger.
+     */
+    public ComponentsBundleProcessor(Log logger) {
+        m_logger = logger;
+    }
+
+    /**
+     * A bundle is starting.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(Bundle bundle) {
+        Dictionary dict = bundle.getHeaders();
+        // Check bundle
+        String header = (String) dict.get(IPOJO_HEADER);
+        // Check the alternative header
+        if (header == null) {
+            header = (String) dict.get(IPOJO_HEADER_ALT);
+        }
+
+        if (header != null) {
+            try {
+                parse(bundle, header);
+            } catch (IOException e) {
+                m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+            } catch (ParseException e) {
+                m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+            }
+        }
+
+    }
+
+    /**
+     * A bundle is stopping.
+     *
+     * @param bundle the bundle
+     */
+    public void deactivate(Bundle bundle) {
+        ComponentsAndInstances cai = m_registry.remove(bundle);
+        if (cai != null) {
+            cai.stop();
+        }
+    }
+
+    /**
+     * {@inheritDoc BundleProcessor#start}
+     */
+    public void start() {
+        // Nothing to do
+    }
+
+    /**
+     * {@inheritDoc BundleProcessor#stop}
+     * <p/>
+     * This method cleans up all created factories and instances.
+     */
+    public void stop() {
+        // Ignored, for a simple ordered shutdown, use ReverseBundleProcessor
+    }
+
+    /**
+     * Parses the internal metadata (from the manifest
+     * (in the iPOJO-Components property)). This methods
+     * creates factories and add instances to the instance creator.
+     *
+     * @param bundle     the owner bundle.
+     * @param components The iPOJO Header String.
+     * @throws IOException    if the manifest can not be found
+     * @throws ParseException if the parsing process failed
+     */
+    private void parse(Bundle bundle, String components) throws IOException, ParseException {
+        ManifestMetadataParser parser = new ManifestMetadataParser();
+        parser.parseHeader(components);
+
+        // Get the component type declaration
+        Element[] metadata = parser.getComponentsMetadata();
+        for (int i = 0; i < metadata.length; i++) {
+            handleTypeDeclaration(bundle, metadata[i]);
+        }
+
+        Dictionary[] instances = parser.getInstances();
+        for (int i = 0; instances != null && i < instances.length; i++) {
+            handleInstanceDeclaration(bundle, instances[i]);
+        }
+    }
+
+    /**
+     * Extracts and builds the declaration attached to an instance.
+     *
+     * @param bundle   the bundle declaring the instance
+     * @param instance the instance configuration (parsed from the header)
+     */
+    private void handleInstanceDeclaration(Bundle bundle, Dictionary instance) {
+
+        String component = (String) instance.get(COMPONENT_INSTANCE_ATTRIBUTE);
+        //String v = (String) instance.get(Factory.FACTORY_VERSION_PROPERTY); //TODO CES to GSA, why this is commented ?
+
+        DefaultInstanceDeclaration declaration = new DefaultInstanceDeclaration(bundle.getBundleContext(),
+                component, instance);
+        declaration.start();
+
+        getComponentsAndInstances(bundle).m_instances.add(declaration);
+
+    }
+
+    /**
+     * Adds a component factory to the factory list.
+     *
+     * @param metadata the new component metadata.
+     * @param bundle   the bundle.
+     */
+    private void handleTypeDeclaration(Bundle bundle, Element metadata) {
+
+        DefaultTypeDeclaration declaration = new DefaultTypeDeclaration(bundle.getBundleContext(), metadata);
+        declaration.start();
+
+        getComponentsAndInstances(bundle).m_types.add(declaration);
+
+    }
+
+    /**
+     * Gets the {@link ComponentsAndInstances} declared by the given bundle.
+     *
+     * @param bundle the bundle
+     * @return the set of component and instances declared by the bundle, <code>null</code> otherwise
+     */
+    private ComponentsAndInstances getComponentsAndInstances(Bundle bundle) {
+        ComponentsAndInstances cai = m_registry.get(bundle);
+        if (cai == null) {
+            cai = new ComponentsAndInstances();
+            m_registry.put(bundle, cai);
+        }
+        return cai;
+    }
+
+    /**
+     * Container storing the components and instances declared by a bundle.
+     * This class is not intended to be used outside from the current processor.
+     */
+    private static class ComponentsAndInstances {
+        List<DefaultTypeDeclaration> m_types = new ArrayList<DefaultTypeDeclaration>();
+        List<DefaultInstanceDeclaration> m_instances = new ArrayList<DefaultInstanceDeclaration>();
+
+        /**
+         * Stops all declarations.
+         */
+        void stop() {
+            for (DefaultInstanceDeclaration instance : m_instances) {
+                instance.stop();
+            }
+            for (DefaultTypeDeclaration declaration : m_types) {
+                declaration.stop();
+            }
+            m_instances.clear();
+            m_types.clear();
+        }
+    }
+
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,169 @@
+/*
+ * 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.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.apache.felix.ipojo.extender.internal.builder.ReflectiveFactoryBuilder;
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultExtensionDeclaration;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import java.util.*;
+
+/**
+ * Bundle processor handling the {@link #IPOJO_EXTENSION} header.
+ */
+public class ExtensionBundleProcessor implements BundleProcessor {
+
+    /**
+     * iPOJO Extension declaration header.
+     */
+    public static final String IPOJO_EXTENSION = "IPOJO-Extension";
+
+    /**
+     * Logger.
+     */
+    private final Log m_logger;
+
+    /**
+     * The map storing the association between bundles and the list of extension declaration.
+     */
+    private Map<Bundle, List<DefaultExtensionDeclaration>> m_extensions = new HashMap<Bundle, List<DefaultExtensionDeclaration>>();
+
+    /**
+     * Creates the processor.
+     *
+     * @param logger the logger
+     */
+    public ExtensionBundleProcessor(Log logger) {
+        m_logger = logger;
+    }
+
+    /**
+     * A bundle is starting.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(Bundle bundle) {
+        Dictionary dict = bundle.getHeaders();
+        // Check for abstract factory type
+        String extension = (String) dict.get(IPOJO_EXTENSION);
+        if (extension != null) {
+            activateExtensions(bundle, extension);
+        }
+    }
+
+    /**
+     * A bundle is stopping.
+     *
+     * @param bundle the bundle
+     */
+    public void deactivate(Bundle bundle) {
+        List<DefaultExtensionDeclaration> declarations = m_extensions.get(bundle);
+        if (declarations != null) {
+            for (DefaultExtensionDeclaration declaration : declarations) {
+                declaration.stop();
+            }
+            m_extensions.remove(bundle);
+        }
+    }
+
+    /**
+     * iPOJO is starting.
+     * Nothing to do.
+     */
+    public void start() {
+        // Nothing to do
+    }
+
+    /**
+     * iPOJO is stopping.
+     * We clean up all extension in the reverse order of their installation.
+     */
+    public void stop() {
+        // Construct a new instance to avoid ConcurrentModificationException since deactivate also change the extensions
+        // list
+        // Ignored, for a simple ordered shutdown, use ReverseBundleProcessor
+    }
+
+    /**
+     * Parses an IPOJO-Extension manifest header and then creates
+     * iPOJO extensions (factory types).
+     *
+     * @param bundle the bundle containing the header.
+     * @param header the header to parse.
+     */
+    private void activateExtensions(Bundle bundle, String header) {
+        String[] extensions = ParseUtils.split(header, ",");
+        for (int i = 0; extensions != null && i < extensions.length; i++) {
+            String[] segments = ParseUtils.split(extensions[i], ":");
+
+            /*
+             * Get the fully qualified type name.
+             * type = [namespace] name
+             */
+            String[] nameparts = ParseUtils.split(segments[0].trim(), " \t");
+            String type = nameparts.length == 1 ? nameparts[0] : nameparts[0] + ":" + nameparts[1];
+
+            Class clazz;
+            try {
+                clazz = bundle.loadClass(segments[1]);
+            } catch (ClassNotFoundException e) {
+                m_logger.log(Logger.ERROR, "Cannot load the extension " + type, e);
+                return;
+            }
+
+            try {
+                ReflectiveFactoryBuilder builder = new ReflectiveFactoryBuilder(clazz.getConstructor(BundleContext.class, Element.class));
+                DefaultExtensionDeclaration declaration = new DefaultExtensionDeclaration(bundle.getBundleContext(), builder, type);
+
+                getBundleDeclarations(bundle).add(declaration);
+
+                declaration.start();
+
+                m_logger.log(Logger.DEBUG, "New factory type available: " + type);
+            } catch (NoSuchMethodException e) {
+                m_logger.log(Logger.ERROR,
+                        String.format("Extension '%s' is missing the required (BundleContext, Element) public " +
+                                "constructor", clazz.getName()));
+            }
+        }
+    }
+
+    /**
+     * Gets the list of declaration for the given method.
+     *
+     * @param bundle the bundle
+     * @return the list of extension declaration associated to the given bundle, <code>null</code> otherwise.
+     */
+    private List<DefaultExtensionDeclaration> getBundleDeclarations(Bundle bundle) {
+        List<DefaultExtensionDeclaration> declarations = m_extensions.get(bundle);
+        if (declarations == null) {
+            declarations = new ArrayList<DefaultExtensionDeclaration>();
+            m_extensions.put(bundle, declarations);
+        }
+        return declarations;
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,52 @@
+/*
+ * 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.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.osgi.framework.Bundle;
+
+/**
+ * A bundle processor delegating to a wrapped processor.
+ * Implementation defined how we retrieve the delegate.
+ */
+public abstract class ForwardingBundleProcessor implements BundleProcessor {
+    /**
+     * Implementation must implement this method to retrieve the wrapped bundle processor.
+     *
+     * @return the wrapped bundle processor on which we delegate all calls.
+     */
+    protected abstract BundleProcessor delegate();
+
+    public void activate(Bundle bundle) {
+        delegate().activate(bundle);
+    }
+
+    public void deactivate(Bundle bundle) {
+        delegate().deactivate(bundle);
+    }
+
+    public void start() {
+        delegate().start();
+    }
+
+    public void stop() {
+        delegate().stop();
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,73 @@
+/*
+ * 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.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.apache.felix.ipojo.extender.internal.ReferenceableCallable;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.Bundle;
+
+/**
+ * A bundle processor submitting the activating job to the queue service.
+ * The submitted job relies on a delegated bundle processor.
+ */
+public class QueuingActivationProcessor extends ForwardingBundleProcessor {
+    /**
+     * The wrapped bundle processor used by the job.
+     */
+    private final BundleProcessor m_delegate;
+
+    /**
+     * The queue service.
+     */
+    private final QueueService m_queueService;
+
+    /**
+     * Creates an instance of the queuing bundle processor
+     *
+     * @param delegate     the bundle processor used by the submitted job
+     * @param queueService the used queue service
+     */
+    public QueuingActivationProcessor(BundleProcessor delegate, QueueService queueService) {
+        m_delegate = delegate;
+        m_queueService = queueService;
+    }
+
+    @Override
+    protected BundleProcessor delegate() {
+        return m_delegate;
+    }
+
+    /**
+     * A bundle is starting.
+     * The processing of the bundle is wrapped in a job submitted to the queue service.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(final Bundle bundle) {
+        m_queueService.submit(new ReferenceableCallable<Boolean>(bundle) {
+            public Boolean call() throws Exception {
+                QueuingActivationProcessor.super.activate(bundle);
+                return true;
+            }
+        });
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,96 @@
+/*
+ * 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.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.osgi.framework.Bundle;
+
+import java.util.LinkedList;
+
+/**
+ * A bundle processor delegating a wrapped bundle processor. On stop, the bundles are processed in reverse.
+ */
+public class ReverseBundleProcessor extends ForwardingBundleProcessor {
+
+    /**
+     * The wrapped bundle processor.
+     */
+    private final BundleProcessor m_delegate;
+
+    /**
+     * A list of bundle to process.
+     */
+    private LinkedList<Bundle> m_bundles = new LinkedList<Bundle>();
+
+    /**
+     * Creates the processor.
+     *
+     * @param delegate the processor on which call are delegated
+     */
+    public ReverseBundleProcessor(BundleProcessor delegate) {
+        m_delegate = delegate;
+    }
+
+    /**
+     * @return the wrapped processor.
+     */
+    @Override
+    protected BundleProcessor delegate() {
+        return m_delegate;
+    }
+
+    /**
+     * A bundle is starting.
+     * The bundle is added to the list, and the processing delegated to the wrapped processor.
+     *
+     * @param bundle the bundle
+     */
+    @Override
+    public void activate(Bundle bundle) {
+        m_bundles.addLast(bundle);
+        super.activate(bundle);
+    }
+
+    /**
+     * A bundle is stopping.
+     * The bundle is removed from the list and the processing delegated to the wrapped processor.
+     *
+     * @param bundle the bundle
+     */
+    @Override
+    public void deactivate(Bundle bundle) {
+        m_bundles.remove(bundle);
+        super.deactivate(bundle);
+    }
+
+    /**
+     * iPOJO is stopping.
+     * The bundle that are still in the list are processed in the <strong>reverse</strong> order by the wrapped
+     * processor.
+     */
+    @Override
+    public void stop() {
+        // deactivate in reverse order
+        while (!m_bundles.isEmpty()) {
+            super.deactivate(m_bundles.pollLast());
+        }
+        super.stop();
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,151 @@
+/*
+ * 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.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.internal.AbstractService;
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.BundleContext;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * An asynchronous implementation of the queue service. This implementation relies on an executor service.
+ */
+public class ExecutorQueueService extends AbstractService implements LifecycleQueueService {
+
+    /**
+     * The default thread pool size (3).
+     */
+    private final static int DEFAULT_QUEUE_SIZE = 3;
+
+    /**
+     * The executor service.
+     */
+    private final ExecutorService m_executorService;
+
+    /**
+     * The statistics populated by this queue service.
+     */
+    private final Statistic m_statistic = new Statistic();
+
+    /**
+     * Creates the queue service using the default pool size.
+     *
+     * @param bundleContext the bundle context.
+     */
+    public ExecutorQueueService(BundleContext bundleContext) {
+        this(bundleContext, DEFAULT_QUEUE_SIZE);
+    }
+
+    /**
+     * Creates the queue service.
+     *
+     * @param bundleContext the bundle context.
+     * @param size          the thread pool size.
+     */
+    public ExecutorQueueService(BundleContext bundleContext, int size) {
+        this(bundleContext, Executors.newFixedThreadPool(size));
+    }
+
+    /**
+     * Creates the queue service.
+     *
+     * @param bundleContext the bundle context.
+     * @param size          the thread pool size
+     * @param threadFactory the thread factory
+     */
+    public ExecutorQueueService(BundleContext bundleContext, int size, ThreadFactory threadFactory) {
+        this(bundleContext, Executors.newFixedThreadPool(size, threadFactory));
+    }
+
+
+    /**
+     * Creates the queue service.
+     * All others constructors delegates to this one.
+     *
+     * @param bundleContext   the bundle context
+     * @param executorService the executor service we have to use
+     */
+    private ExecutorQueueService(BundleContext bundleContext, ExecutorService executorService) {
+        super(bundleContext, QueueService.class);
+        m_executorService = executorService;
+    }
+
+    /**
+     * Stops the service.
+     */
+    public void stop() {
+        m_executorService.shutdown();
+        super.stop();
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(QueueService.QUEUE_MODE_PROPERTY, QueueService.ASYNCHRONOUS_QUEUE_MODE);
+        return properties;
+    }
+
+    public int getFinished() {
+        return m_statistic.getFinishedCounter().get();
+    }
+
+    public int getWaiters() {
+        return m_statistic.getWaiters().size();
+    }
+
+    public int getCurrents() {
+        return m_statistic.getCurrentsCounter().get();
+    }
+
+    public List<JobInfo> getWaitersInfo() {
+        List<JobInfo> snapshot;
+        synchronized (m_statistic.getWaiters()) {
+            snapshot = new ArrayList<JobInfo>(m_statistic.getWaiters());
+        }
+        return Collections.unmodifiableList(snapshot);
+    }
+
+    /**
+     * Submits a job to the queue. The submitted job is wrapped into a {@link JobInfoCallable} to collect the
+     * statistics.
+     *
+     * @param callable    the job
+     * @param callback    callback called when the job is processed
+     * @param description a description of the job
+     * @return the reference on the submitted job
+     */
+    public <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description) {
+        return m_executorService.submit(new JobInfoCallable<T>(m_statistic, callable, callback, description));
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, String description) {
+        return submit(callable, null, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable) {
+        return submit(callable, "No description");
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,172 @@
+/*
+ * 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.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A callable computing job statistics. The job is given as another callable.
+ * The statistics are global, so must be used carefully.
+ */
+public class JobInfoCallable<T> implements Callable<T>, JobInfo {
+
+    /**
+     * The statistic object.
+     */
+    private final Statistic m_statistic;
+
+    /**
+     * The genuine job.
+     */
+    private final Callable<T> m_delegate;
+
+    /**
+     * A callback notified when the job is processed.
+     */
+    private final Callback<T> m_callback;
+
+    /**
+     * The job description.
+     */
+    private final String m_description;
+
+    /**
+     * The date (in milli) when this object is created.
+     */
+    private long enlistmentTime = System.currentTimeMillis();
+
+    /**
+     * The date when the job processing started.
+     */
+    private long startTime = -1;
+
+    /**
+     * The date when the job processing is completed.
+     */
+    private long endTime = -1;
+
+    /**
+     * Creates the job info callable.
+     *
+     * @param statistic   the statistics that will be populated
+     * @param delegate    the real job
+     * @param callback    the callback notified when the job is completed
+     * @param description the job description
+     */
+    public JobInfoCallable(Statistic statistic,
+                           Callable<T> delegate,
+                           Callback<T> callback,
+                           String description) {
+        m_statistic = statistic;
+        m_delegate = delegate;
+        m_callback = callback;
+        m_description = description;
+        m_statistic.getWaiters().add(this);
+    }
+
+    /**
+     * Executes the job.
+     * This method updates the statistics.
+     *
+     * @return the job result
+     * @throws Exception the job execution failed
+     */
+    public T call() throws Exception {
+        m_statistic.getWaiters().remove(this);
+        startTime = System.currentTimeMillis();
+        m_statistic.getCurrentsCounter().incrementAndGet();
+        T result = null;
+        try {
+            result = m_delegate.call();
+            return result;
+        } catch (Exception e) {
+            if (m_callback != null) {
+                m_callback.error(this, e);
+            }
+            throw e;
+        } finally {
+            m_statistic.getCurrentsCounter().decrementAndGet();
+            m_statistic.getFinishedCounter().incrementAndGet();
+            endTime = System.currentTimeMillis();
+            if (m_callback != null) {
+                m_callback.success(this, result);
+            }
+        }
+    }
+
+    /**
+     * @return the enlistment date.
+     */
+    public long getEnlistmentTime() {
+        return enlistmentTime;
+    }
+
+    /**
+     * @return the job start date.
+     */
+    public long getStartTime() {
+        return startTime;
+    }
+
+    /**
+     * @return the job completion date.
+     */
+    public long getEndTime() {
+        return endTime;
+    }
+
+    /**
+     * Computes the time spent in the waiting queue
+     *
+     * @return the waited time, if the job is still waiting, gets the current waited time
+     */
+    public long getWaitDuration() {
+        long end = startTime;
+        if (end == -1) {
+            // Not yet started
+            // Still waiting
+            end = System.currentTimeMillis();
+        }
+        return end - enlistmentTime;
+    }
+
+    /**
+     * Computes the time spent to execute the job (this does not include the waiting).
+     * If the job is not executed yet, or is still executing, {@literal -1} is returned
+     *
+     * @return the execution duration, or {@literal -1}.
+     */
+    public long getExecutionDuration() {
+        if ((startTime == -1) || (endTime == -1)) {
+            return -1;
+        }
+        return endTime - startTime;
+    }
+
+    /**
+     * @return the job description
+     */
+    public String getDescription() {
+        return m_description;
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java Wed Mar  6 15:44:12 2013
@@ -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.extender.internal.queue;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * A thread factory setting the name of the created thread.
+ * This thread factory delegates the thread creation on another factory, it just set the thread name (actually just
+ * set a prefix).
+ */
+public class PrefixedThreadFactory implements ThreadFactory {
+
+    /**
+     * The wrapped thread factory on which creation is delegated.
+     */
+    private final ThreadFactory m_threadFactory;
+
+    /**
+     * The prefix.
+     */
+    private final String m_prefix;
+
+    /**
+     * Creates the object using the default thread factory.
+     *
+     * @param prefix the prefix
+     */
+    public PrefixedThreadFactory(String prefix) {
+        this(Executors.defaultThreadFactory(), prefix);
+    }
+
+    /**
+     * Creates the object delegating to the given thread factory.
+     *
+     * @param threadFactory the thread factory
+     * @param prefix        the prefix
+     */
+    public PrefixedThreadFactory(ThreadFactory threadFactory, String prefix) {
+        m_threadFactory = threadFactory;
+        m_prefix = prefix;
+    }
+
+    /**
+     * Creates a new thread.
+     * Prepend the prefix to the thread name
+     *
+     * @param r the runnable
+     * @return the thread object
+     */
+    public Thread newThread(Runnable r) {
+        Thread thread = m_threadFactory.newThread(r);
+        thread.setName(m_prefix + thread.getName());
+        return thread;
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java?rev=1453391&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java Wed Mar  6 15:44:12 2013
@@ -0,0 +1,70 @@
+/*
+ * 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.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Objects wrapping the {@link org.apache.felix.ipojo.extender.queue.QueueService} statistics.
+ */
+public class Statistic {
+    /**
+     * The synchronized list of waiting jobs.
+     */
+    private final List<JobInfo> m_waiters = Collections.synchronizedList(new ArrayList<JobInfo>());
+
+    /**
+     * The number of completed jobs.
+     */
+    private final AtomicInteger m_finished = new AtomicInteger(0);
+
+    /**
+     * The number of job being processed.
+     */
+    private final AtomicInteger m_currents = new AtomicInteger(0);
+
+    /**
+     * @return the number of completed jobs.
+     */
+    public AtomicInteger getFinishedCounter() {
+        return m_finished;
+    }
+
+    /**
+     * @return the list of waiting jobs.
+     */
+    public List<JobInfo> getWaiters() {
+        return m_waiters;
+    }
+
+    /**
+     * @return the number of jobs under processing.
+     */
+    public AtomicInteger getCurrentsCounter() {
+        return m_currents;
+    }
+
+
+}



Mime
View raw message