Commit the new iPOJO version (0.7.6).
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@642265 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/pom.xml b/ipojo/core/pom.xml
index 813548b..c7ef593 100644
--- a/ipojo/core/pom.xml
+++ b/ipojo/core/pom.xml
@@ -1,118 +1,125 @@
<!--
- 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.
+ 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.
-->
<project>
- <parent>
- <groupId>org.apache.felix</groupId>
- <artifactId>felix</artifactId>
- <version>1.0.2</version>
- <relativePath>../../pom/pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <packaging>bundle</packaging>
- <name>Apache Felix iPOJO</name>
- <artifactId>org.apache.felix.ipojo</artifactId>
- <version>0.7.5-SNAPSHOT</version>
- <dependencies>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>org.osgi.core</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- <version>1.0.0</version>
- </dependency>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>org.apache.felix.ipojo.metadata</artifactId>
- <version>0.7.5-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>org.apache.felix.ipojo.manipulator</artifactId>
- <version>0.7.5-SNAPSHOT</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <version>1.4.0</version>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Bundle-Name>iPOJO</Bundle-Name>
- <Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
- <Bundle-Description> iPOJO </Bundle-Description>
- <Bundle-Activator>org.apache.felix.ipojo.Extender</Bundle-Activator>
- <Import-Package>
- org.osgi.framework,
- org.osgi.service.cm,
- org.osgi.service.log,
- !org.objectweb.asm*
- </Import-Package>
- <Private-Package>
- org.apache.felix.ipojo.manipulation,
- org.apache.felix.ipojo.composite.architecture,
- org.apache.felix.ipojo.composite.service*,
- org.apache.felix.ipojo.composite.instance,
- org.apache.felix.ipojo.handlers.architecture,
- org.apache.felix.ipojo.handlers.configuration,
- org.apache.felix.ipojo.handlers.dependency.nullable,
- org.apache.felix.ipojo.handlers.lifecycle.callback,
- org.apache.felix.ipojo.handlers.lifecycle.controller,
- org.objectweb.asm*;-split-package:=merge-first
- </Private-Package>
- <Export-Package>
- org.apache.felix.ipojo; version="0.7.5",
- org.apache.felix.ipojo.metadata; version="0.7.5",
- org.apache.felix.ipojo.architecture; version="0.7.5",
- org.apache.felix.ipojo.parser; version="0.7.5",
- org.apache.felix.ipojo.util; version="0.7.5",
- org.apache.felix.ipojo.handlers.dependency; version="0.7.5",
- org.apache.felix.ipojo.handlers.providedservice; version="0.7.5",
- org.apache.felix.ipojo.composite; version="0.7.5",
- org.osgi.service.cm,
- org.osgi.service.log
- </Export-Package>
- <_donotcopy>(CVS|.svn|.+.bak|~.+|metadata.xml)</_donotcopy>
- </instructions>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-ipojo-plugin</artifactId>
- <version>${pom.version}</version>
- <executions>
- <execution>
- <goals>
- <goal>ipojo-bundle</goal>
- </goals>
- <configuration>
- <metadata>metadata.xml</metadata>
- <ignoreAnnotations>true</ignoreAnnotations>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <parent>
+ <artifactId>iPOJO</artifactId>
+ <groupId>org.apache.felix</groupId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Apache Felix iPOJO</name>
+ <artifactId>org.apache.felix.ipojo</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.ipojo.metadata</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.ipojo.manipulator</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>iPOJO</Bundle-Name>
+ <Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
+ <Bundle-Description>
+ iPOJO Core Framework
+ </Bundle-Description>
+ <Bundle-Activator>
+ org.apache.felix.ipojo.Extender
+ </Bundle-Activator>
+ <IPOJO-Extension>
+ component:org.apache.felix.ipojo.ComponentFactory,
+ handler:org.apache.felix.ipojo.HandlerFactory
+ </IPOJO-Extension>
+ <Import-Package>
+ org.osgi.framework, org.osgi.service.cm,
+ org.osgi.service.log
+ </Import-Package>
+ <Private-Package>
+ org.apache.felix.ipojo.handlers.architecture,
+ org.apache.felix.ipojo.handlers.configuration,
+ org.apache.felix.ipojo.handlers.lifecycle.callback,
+ org.apache.felix.ipojo.handlers.lifecycle.controller
+ </Private-Package>
+ <Export-Package>
+ org.apache.felix.ipojo; version="0.7.6",
+ org.apache.felix.ipojo.metadata;
+ version="0.7.6",
+ org.apache.felix.ipojo.architecture;
+ version="0.7.6",
+ org.apache.felix.ipojo.parser;
+ version="0.7.6",
+ org.apache.felix.ipojo.util;
+ version="0.7.6",
+ org.apache.felix.ipojo.handlers.dependency;
+ version="0.7.6",
+ org.apache.felix.ipojo.handlers.providedservice;
+ version="0.7.6",
+ org.apache.felix.ipojo.context;
+ version="0.7.6", org.osgi.service.cm,
+ org.osgi.service.log
+ </Export-Package>
+ <_donotcopy>
+ (CVS|.svn|.+.bak|~.+|metadata.xml)
+ </_donotcopy>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <metadata>metadata.xml</metadata>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
index d5ff230..1c62ecf 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
@@ -21,27 +21,22 @@
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.PojoMetadata;
import org.apache.felix.ipojo.util.Logger;
import org.apache.felix.ipojo.util.Tracker;
import org.apache.felix.ipojo.util.TrackerCustomizer;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
/**
* The component factory manages component instance objects. This management
@@ -50,379 +45,114 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ComponentFactory implements Factory, ManagedServiceFactory, TrackerCustomizer {
-
- /**
- * List of the managed instance name. This list is shared by all factories.
- */
- protected static List m_instancesName = new ArrayList();
-
- /**
- * Component-Type description exposed by the factory service.
- */
- protected ComponentDescription m_componentDesc;
-
- /**
- * List of the managed instance managers. The key of this map is the
- * name (i.e. instance names) of the created instance
- */
- protected Map m_componentInstances = new HashMap();
-
- /**
- * Component Type provided by this factory.
- */
- protected Element m_componentMetadata;
-
- /**
- * The bundle context reference.
- */
- protected BundleContext m_context = null;
-
- /**
- * Factory Name. Could be the component class name if the
- * factory name is not set.
- */
- protected String m_factoryName;
-
- /**
- * List of required handler.
- */
- protected List m_handlerIdentifiers = new ArrayList();
-
- /**
- * List of listeners.
- */
- protected List m_listeners = new ArrayList(5);
-
- /**
- * Logger for the factory (and all component instance).
- */
- protected Logger m_logger;
-
- /**
- * Factory state.
- */
- protected int m_state = Factory.INVALID;
+public class ComponentFactory extends IPojoFactory implements TrackerCustomizer {
/**
* Tracker used to track required handler factories.
*/
protected Tracker m_tracker;
-
- /**
- * Is the factory public (expose as a service).
- */
- protected boolean m_isPublic;
/**
* Class loader to delegate loading.
*/
private FactoryClassloader m_classLoader = null;
-
+
/**
* Component Implementation class.
*/
private byte[] m_clazz = null;
-
+
/**
* Component Implementation Class Name.
*/
- private String m_componentClassName = null;
-
+ private String m_classname = null;
+
/**
- * Index used to generate instance name if not set.
+ * Manipulation Metadata of the internal POJO.
*/
- private long m_index = 0;
-
- /**
- * Service Registration of this factory (Factory & ManagedServiceFactory).
- */
- private ServiceRegistration m_sr;
-
+ private PojoMetadata m_manipulation = null;
+
/**
* Create a instance manager factory. The class is given in parameter. The
* component type is not a composite.
- * @param bc : bundle context
+ * @param context : bundle context
* @param clazz : the component class
- * @param cm : metadata of the component
+ * @param element : metadata of the component
+ * @throws ConfigurationException occurs when the element describing the factory is malformed.
*/
- public ComponentFactory(BundleContext bc, byte[] clazz, Element cm) {
- this(bc, cm);
+ public ComponentFactory(BundleContext context, byte[] clazz, Element element) throws ConfigurationException {
+ this(context, element);
m_clazz = clazz;
}
-
- /**
- * Create a instance manager factory.
- * @param bc : bundle context
- * @param cm : metadata of the component to create
- */
- public ComponentFactory(BundleContext bc, Element cm) {
- m_context = bc;
- m_componentMetadata = cm;
-
- if (! check(cm)) {
- return;
- }
-
- computeFactoryName();
- m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
-
- String fac = cm.getAttribute("factory");
- m_isPublic = fac == null || ! fac.equalsIgnoreCase("false");
-
- computeRequiredHandlers();
-
- }
-
- /**
- * Add a factory listener.
- * @param l : the factory listener to add
- * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
- */
- public void addFactoryStateListener(FactoryStateListener l) {
- synchronized (m_listeners) {
- m_listeners.add(l);
- }
- // TODO do we need to notify the actual state of the factory to the new listener ?
- }
/**
- * A new handler factory is detected.
- * Test if the factory can be used or not.
- * @param reference : the new service reference.
- * @return true if the given factory reference match with a required handler.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
+ * Create a instance manager factory.
+ * @param context : bundle context
+ * @param element : metadata of the component to create
+ * @throws ConfigurationException occurs when the element describing the factory is malformed.
*/
- public boolean addingService(ServiceReference reference) {
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (hi.m_reference == null && match(hi, reference)) {
- int oldP = hi.m_level;
- hi.setReference(reference);
- // If the priority has changed, sort the list.
- if (oldP != hi.m_level) {
- Collections.sort(m_handlerIdentifiers);
- }
- return true;
- }
- }
- return false;
+ public ComponentFactory(BundleContext context, Element element) throws ConfigurationException {
+ super(context, element);
+ check(element); // NOPMD. This invocation is normal.
}
-
- /**
- * A matching service has been added to the tracker, we can no compute the factory state.
- * @param reference : added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference reference) {
- if (m_state == INVALID) {
- try {
- computeFactoryState();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- }
- }
+
+ public ComponentTypeDescription getComponentTypeDescription() {
+ return new PrimitiveTypeDescription(this);
}
/**
* Check method : allow a factory to check if given element are correct.
* A component factory metadata are correct if they contain the 'classname' attribute.
- * @param cm : the metadata
- * @return true if the metadata are correct
+ * @param element : the metadata
+ * @throws ConfigurationException occurs when the element describing the factory is malformed.
*/
- public boolean check(Element cm) {
- m_componentClassName = cm.getAttribute("className");
- if (m_componentClassName == null) {
- System.err.println("A component needs a class name : " + cm);
- return false;
- } else {
- return true;
- }
+ public void check(Element element) throws ConfigurationException {
+ m_classname = element.getAttribute("className");
+ if (m_classname == null) { throw new ConfigurationException("A component needs a class name : " + element); }
+ }
+
+ public String getClassName() {
+ return m_classname;
}
/**
- * Create an instance. The given configuration needs to contain the 'name'
- * property.
- * @param configuration : configuration of the created instance.
- * @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
- * not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs if an handler is unavailable when the instance is created.
- * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+ * Create a primitive instance.
+ * @param config : instance configuration
+ * @param context : service context.
+ * @param handlers : handler to use
+ * @return the created instance
+ * @throws org.apache.felix.ipojo.ConfigurationException : if the configuration process failed.
+ * @see org.apache.felix.ipojo.IPojoFactory#createInstance(java.util.Dictionary, org.apache.felix.ipojo.IPojoContext, org.apache.felix.ipojo.HandlerManager[])
*/
- public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
- return createComponentInstance(configuration, null);
- }
-
- /**
- * Create an instance. The given configuration needs to contain the 'name'
- * property.
- * @param configuration : configuration of the created instance.
- * @param serviceContext : the service context to push for this instance.
- * @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
- * not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
- * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
- */
- public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
- if (configuration == null) {
- configuration = new Properties();
- }
-
+ public ComponentInstance createInstance(Dictionary config, IPojoContext context, HandlerManager[] handlers) throws org.apache.felix.ipojo.ConfigurationException {
+ InstanceManager instance = new InstanceManager(this, context, handlers);
+ instance.configure(m_componentMetadata, config);
try {
- checkAcceptability(configuration);
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new UnacceptableConfiguration("The configuration " + configuration + " is not acceptable for " + m_factoryName + ": " + e.getMessage());
+ instance.start();
+ return instance;
+ } catch (IllegalStateException e) {
+ // An exception occurs during the start method.
+ m_logger.log(Logger.ERROR, e.getMessage(), e);
+ throw new ConfigurationException(e.getMessage());
}
-
- String n = null;
- if (configuration.get("name") != null) {
- n = (String) configuration.get("name");
- if (m_instancesName.contains(n)) {
- throw new UnacceptableConfiguration("Name already used : " + n);
- }
- } else {
- n = generateName();
- configuration.put("name", n);
- }
- m_instancesName.add(n);
-
- BundleContext context = null;
- if (serviceContext == null) {
- context = new IPojoContext(m_context);
- } else {
- context = new IPojoContext(m_context, serviceContext);
- }
-
- List handlers = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- handlers.add(getHandlerInstance(hi, serviceContext));
- }
-
- InstanceManager instance = new InstanceManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[m_handlerIdentifiers.size()]));
- try {
- instance.configure(m_componentMetadata, configuration);
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
- }
-
- m_componentInstances.put(n, instance);
- instance.start();
-
- return instance;
}
/**
* Define a class.
* @param name : qualified name of the class
- * @param b : byte array of the class
+ * @param clazz : byte array of the class
* @param domain : protection domain of the class
* @return the defined class object
*/
- public Class defineClass(String name, byte[] b, ProtectionDomain domain) {
+ public Class defineClass(String name, byte[] clazz, ProtectionDomain domain) {
if (m_classLoader == null) {
m_classLoader = new FactoryClassloader();
}
- return m_classLoader.defineClass(name, b, domain);
- }
-
- /**
- * Delete an instance.
- * @param in : name of the instance to delete
- * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
- */
- public synchronized void deleted(String in) {
- m_instancesName.remove(in);
- final ComponentInstance cm = (ComponentInstance) m_componentInstances.remove(in);
- if (cm == null) {
- return; // do nothing, the component does not exist !
- } else {
- cm.dispose();
- }
+ return m_classLoader.defineClass(name, clazz, domain);
}
/**
- * Get the component type description.
- * @return the component type description object. Null if not already computed.
- */
- public ComponentDescription getComponentDescription() {
- return m_componentDesc;
- }
-
- /**
- * Get the component type description attached to this factory.
- * @return : the component type description
- * @see org.apache.felix.ipojo.Factory#getDescription()
- */
- public Element getDescription() {
- if (m_componentDesc == null) { return new Element("No description available for " + m_factoryName, ""); }
- return m_componentDesc.getDescription();
- }
-
- /**
- * Get the logger used by instances of he current factory.
- * @return the factory logger.
- */
- public Logger getLogger() {
- return m_logger;
- }
-
- /**
- * Get the list of missing handlers.
- * @return the list of missing handlers (namespace:name)
- * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
- */
- public List getMissingHandlers() {
- List l = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (hi.m_reference == null) {
- l.add(hi.getFullName());
- }
- }
- return l;
- }
-
- /**
- * Get the name of this factory.
- *
- * @return the name of this factory
- * @see org.apache.felix.ipojo.Factory#getName()
- */
- public String getName() {
- return m_factoryName;
- }
-
- /**
- * Get the list of required handlers.
- * @return the list of required handlers (namespace:name)
- * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
- */
- public List getRequiredHandlers() {
- List l = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- l.add(hi.getFullName());
- }
- return l;
- }
-
- public String getClassName() {
- return m_componentClassName;
- }
-
- public int getState() {
- return m_state;
- }
-
- /**
* Return the URL of a resource.
* @param resName : resource name
* @return the URL of the resource
@@ -432,24 +162,6 @@
}
/**
- * Check if the given configuration is acceptable as a component instance
- * configuration. This method checks that if all the configurable properties
- * have a value.
- * @param conf : the configuration to check
- * @return true when the configuration seems to be acceptable
- */
- public boolean isAcceptable(Dictionary conf) {
- try {
- checkAcceptability(conf);
- } catch (UnacceptableConfiguration e) {
- return false;
- } catch (MissingHandlerException e) {
- return false;
- }
- return true;
- }
-
- /**
* Load a class.
* @param className : name of the class to load
* @return the resulting Class object
@@ -457,22 +169,144 @@
* @throws ClassNotFoundException : happen when the class is not found
*/
public Class loadClass(String className) throws ClassNotFoundException {
- if (m_clazz != null && className.equals(m_componentClassName)) {
+ if (m_clazz != null && className.equals(m_classname)) {
// Used the factory classloader to load the component implementation
// class
if (m_classLoader == null) {
m_classLoader = new FactoryClassloader();
}
- try {
- return m_classLoader.defineClass(m_componentClassName, m_clazz, null);
- } catch (Exception e) {
- throw new ClassNotFoundException("[Bundle " + m_context.getBundle().getBundleId() + "] Cannot define the class : " + className, e);
- }
+ return m_classLoader.defineClass(m_classname, m_clazz, null);
}
return m_context.getBundle().loadClass(className);
}
/**
+ * Start the factory.
+ */
+ public synchronized void starting() {
+ if (m_requiredHandlers.size() != 0) {
+ try {
+ String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")" + "(factory.state=1)" + ")";
+ m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
+ m_tracker.open();
+ } catch (InvalidSyntaxException e) {
+ m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
+ stop();
+ }
+ }
+ }
+
+ /**
+ * Stop all the instance managers.
+ */
+ public synchronized void stopping() {
+ m_tracker.close();
+ m_tracker = null;
+ m_classLoader = null;
+ m_clazz = null;
+ }
+
+ /**
+ * Compute the factory name.
+ * @return the factory name.
+ */
+ public String getFactoryName() {
+ String name = m_componentMetadata.getAttribute("name");
+ if (name == null) { // No factory name, try with factory attribute
+ name = m_componentMetadata.getAttribute("factory");
+ if (name == null || name.equalsIgnoreCase("true") || name.equalsIgnoreCase("false")) { // Avoid boolean case
+ name = m_componentMetadata.getAttribute("className");
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Compute required handlers.
+ * @return the required handler list.
+ */
+ public List getRequiredHandlerList() {
+ List list = new ArrayList();
+ Element[] elems = m_componentMetadata.getElements();
+ for (int i = 0; i < elems.length; i++) {
+ Element current = elems[i];
+ if (!"manipulation".equals(current.getName())) {
+ RequiredHandler req = new RequiredHandler(current.getName(), current.getNameSpace());
+ if (!list.contains(req)) {
+ list.add(req);
+ }
+ }
+ }
+
+ // Add architecture if architecture != 'false'
+ String arch = m_componentMetadata.getAttribute("architecture");
+ if (arch == null || arch.equalsIgnoreCase("true")) {
+ list.add(new RequiredHandler("architecture", null));
+ }
+
+ // Add lifecycle callback if immediate = true
+ RequiredHandler reqCallback = new RequiredHandler("callback", null);
+ String imm = m_componentMetadata.getAttribute("immediate");
+ if (!list.contains(reqCallback) && imm != null && imm.equalsIgnoreCase("true")) {
+ list.add(reqCallback);
+ }
+
+ return list;
+ }
+
+ /**
+ * A new handler factory is detected.
+ * Test if the factory can be used or not.
+ * @param reference : the new service reference.
+ * @return true if the given factory reference match with a required handler.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
+ */
+ public boolean addingService(ServiceReference reference) {
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ if (req.getReference() == null && match(req, reference)) {
+ int oldP = req.getLevel();
+ req.setReference(reference);
+ // If the priority has changed, sort the list.
+ if (oldP != req.getLevel()) {
+ Collections.sort(m_requiredHandlers);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A matching service has been added to the tracker, we can no compute the factory state.
+ * @param reference : added reference.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+ */
+ public void addedService(ServiceReference reference) {
+ if (m_state == INVALID) {
+ computeFactoryState();
+ }
+ }
+
+ /**
+ * A used factory disappears.
+ * @param reference : service reference.
+ * @param service : factory object.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+ */
+ public void removedService(ServiceReference reference, Object service) {
+ // Look for the implied reference and invalid the handler identifier
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ if (reference.equals(req.getReference())) {
+ req.unRef(); // This method will unget the service.
+ computeFactoryState();
+ return; // The factory can be used only once.
+ }
+ }
+ }
+
+ /**
* A used handler factory is modified.
* @param reference : the service reference
* @param service : the Factory object (if already get)
@@ -483,561 +317,15 @@
}
/**
- * Reconfigure an existing instance.
- * @param properties : the new configuration to push.
- * @throws UnacceptableConfiguration : occurs if the new configuration is
- * not consistent with the component type.
- * @throws MissingHandlerException : occurs if the current factory is not valid.
- * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
+ * Returns manipulation metadata of this component type.
+ * The returned object is computed at the first call and then is cached.
+ * @return manipulation metadata of this component type.
*/
- public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
- if (properties == null || properties.get("name") == null) {
- throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
+ public PojoMetadata getPojoMetadata() {
+ if (m_manipulation == null) {
+ m_manipulation = new PojoMetadata(m_componentMetadata);
}
- final String name = (String) properties.get("name");
- InstanceManager cm = (InstanceManager) m_componentInstances.get(name);
-
- if (cm == null) {
- return; // The instance does not exist.
- } else {
- checkAcceptability(properties); // Test if the configuration is acceptable
- cm.reconfigure(properties); // re-configure the component
- }
- }
-
- /**
- * A used factory disappears.
- * @param reference : service reference.
- * @param service : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference reference, Object service) {
- // Look for the implied reference and invalid the handler identifier
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (reference.equals(hi.getReference())) {
- hi.unRef(); // This method will unget the service.
- try {
- computeFactoryState();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- }
- return; // The factory can be used only once.
- }
- }
- }
-
- /**
- * Remove a factory listener.
- * @param l : the factory listener to remove
- * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
- */
- public void removeFactoryStateListener(FactoryStateListener l) {
- synchronized (m_listeners) {
- m_listeners.remove(l);
- }
- }
-
- /**
- * Start the factory.
- */
- public synchronized void start() {
- if (m_componentDesc != null) { // Already started.
- return;
- }
-
- if (m_handlerIdentifiers.size() != 0) {
- try {
- String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
- + "(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")"
- + "(factory.state=1)"
- + ")";
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
- } catch (InvalidSyntaxException e) {
- m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
- stop();
- return;
- }
- }
-
- try {
- computeFactoryState();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- return;
- }
-
- if (m_isPublic) {
- // Exposition of the factory service
- m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, getProperties());
- }
- }
-
- /**
- * Stop all the instance managers.
- */
- public synchronized void stop() {
- if (m_sr != null) {
- m_sr.unregister();
- m_sr = null;
- }
-
- if (m_tracker != null) {
- m_tracker.close();
- }
-
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- InstanceManager ci = (InstanceManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
- }
- m_instancesName.remove(ci.getInstanceName());
- }
-
- m_componentInstances.clear();
-
- // Release each handler
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
- }
-
- m_tracker = null;
- m_componentDesc = null;
- m_classLoader = null;
- m_clazz = null;
- m_state = INVALID;
- }
-
- /**
- * Create of update an instance.
- * @param in : name of the instance
- * @param properties : configuration of the instance
- * @throws ConfigurationException : if the configuration is not consistent
- * for this component type
- * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String,
- * java.util.Dictionary)
- */
- public synchronized void updated(String in, Dictionary properties) throws ConfigurationException {
- final InstanceManager cm = (InstanceManager) m_componentInstances.get(in);
- if (cm == null) {
- try {
- properties.put("name", in); // Add the name in the configuration
- createComponentInstance(properties);
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- }
- } else {
- try {
- properties.put("name", in); // Add the name in the configuration
- reconfigure(properties); // re-configure the component
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The facotry is not valid, at least one handler is missing : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- }
- }
- }
-
- /**
- * Test is a configuration is acceptable for the factory.
- * @param conf : the configuration to test.
- * @throws UnacceptableConfiguration : the configuration is not acceptable.
- * @throws MissingHandlerException : the factory is not valid.
- */
- protected void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
- if (m_state == Factory.INVALID) {
- throw new MissingHandlerException(getMissingHandlers());
- }
-
- List props = m_componentDesc.getRequiredProperties();
- for (int i = 0; i < props.size(); i++) {
- // Failed if the props has no default value and the configuration does not push a value
- if (conf.get(props.get(i)) == null) {
- throw new UnacceptableConfiguration("The configuration does not contains the \"" + props.get(i) + "\" property");
- }
- }
- }
-
- /**
- * Compute the component type description.
- * The factory must be valid when calling this method.
- * @throws org.apache.felix.ipojo.ConfigurationException if one handler has rejected the configuration.
- */
- protected void computeDescription() throws org.apache.felix.ipojo.ConfigurationException {
- m_componentDesc = new ComponentDescription(this);
-
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- HandlerManager hm = getHandlerInstance(hi, null);
- Handler ch = hm.getHandler();
- try {
- ch.setLogger(getLogger());
- ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
- ((Pojo) ch).getComponentInstance().dispose();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- ((Pojo) ch).getComponentInstance().dispose();
- throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
- }
- }
- }
-
- /**
- * Compute the factory name.
- */
- protected void computeFactoryName() {
- m_factoryName = m_componentMetadata.getAttribute("name");
- if (m_factoryName == null) { // No factory name, try with factory attribute
- m_factoryName = m_componentMetadata.getAttribute("factory");
- if (m_factoryName == null || m_factoryName.equalsIgnoreCase("true") || m_factoryName.equalsIgnoreCase("false")) { // Avoid boolean case
- m_factoryName = m_componentMetadata.getAttribute("className");
- }
- }
- }
-
- /**
- * Compute factory state.
- * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the component type cannot be initialize.
- */
- protected void computeFactoryState() throws org.apache.felix.ipojo.ConfigurationException {
- boolean isValid = true;
- for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- isValid = hi.m_reference != null;
- }
-
- if (isValid) {
- if (m_state == INVALID) {
-
- if (m_componentDesc == null) {
- computeDescription();
- }
-
- m_state = VALID;
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
- }
- return;
- }
- } else {
- if (m_state == VALID) {
- m_state = INVALID;
-
- // Notify listeners.
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
- }
-
- // Dispose created instances.
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- InstanceManager ci = (InstanceManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
- }
- m_instancesName.remove(ci.m_name);
- }
-
- m_componentInstances.clear();
-
- // Update service properties TODO : really useful ?
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
-
- return;
- }
- }
- }
-
- /**
- * Compute required handlers.
- */
- protected void computeRequiredHandlers() {
- Element[] elems = m_componentMetadata.getElements();
- for (int i = 0; i < elems.length; i++) {
- Element current = elems[i];
- if (current.getName().equals("manipulation")) { continue; }
- HandlerIdentifier hi = new HandlerIdentifier(current.getName(), current.getNameSpace());
- if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
- }
-
- // Add architecture if architecture != 'false'
- HandlerIdentifier hi = new HandlerIdentifier("architecture", null);
- String arch = m_componentMetadata.getAttribute("architecture");
- if (arch == null || arch.equalsIgnoreCase("true")) {
- m_handlerIdentifiers.add(hi);
- }
-
- // Add lifecycle callback if immediate = true
- HandlerIdentifier hi2 = new HandlerIdentifier("callback", null);
- String imm = m_componentMetadata.getAttribute("immediate");
- if (! m_handlerIdentifiers.contains(hi2) && imm != null && imm.equalsIgnoreCase("true")) {
- m_handlerIdentifiers.add(hi2);
- }
- }
-
- /**
- * Callback called by instance when disposed.
- * @param ci : the destroyed instance
- */
- protected void disposed(ComponentInstance ci) {
- String name = ci.getInstanceName();
- m_instancesName.remove(name);
- m_componentInstances.remove(name);
- }
-
- /**
- * Generate an instance name.
- * @return an non already used name
- */
- protected synchronized String generateName() {
- String name = m_factoryName + "-" + m_index;
- while (m_instancesName.contains(name)) {
- m_index = m_index + 1;
- name = m_factoryName + "-" + m_index;
- }
- return name;
- }
-
- /**
- * Return the bundle context.
- * @return the Bundle Context.
- */
- public BundleContext getBundleContext() {
- return m_context;
- }
-
- /**
- * Get the implementation class of the component type.
- *
- * @return the name of the component-type implementation class.
- */
- protected String getComponentClassName() {
- return m_componentClassName;
- }
-
- /**
- * Compute factory properties.
- * @return the properties.
- */
- protected Properties getProperties() {
- final Properties props = new Properties();
-
- props.put("component.class", m_componentClassName);
-
- props.put("factory.name", m_factoryName);
- props.put(Constants.SERVICE_PID, m_factoryName); // Service PID is required for the integration in the configuration admin.
-
- if (m_componentDesc != null) {
- props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
- props.put("component.properties", m_componentDesc.getProperties());
- props.put("component.description", m_componentDesc);
- }
-
- // Add factory state
- props.put("factory.state", "" + m_state);
-
- return props;
- }
-
- /**
- * Check if the given handler identifier and the service reference can match.
- * @param hi : the handler identifier.
- * @param ref : the service reference.
- * @return true if the service reference can fulfill the handler requirement
- */
- protected boolean match(HandlerIdentifier hi, ServiceReference ref) {
- String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
- String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
- if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
- return name.equals(hi.m_name) && hi.m_namespace == null;
- }
- return name.equals(hi.m_name) && ns.equals(hi.m_namespace);
- }
-
- /**
- * Return an handler object.
- * @param hi : handler to create.
- * @param sc : service context in which create the handler (instance context).
- * @return the Handler object.
- */
- private HandlerManager getHandlerInstance(HandlerIdentifier hi, ServiceContext sc) {
- try {
- return (HandlerManager) hi.getFactory().createComponentInstance(null, sc);
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed: " + e.getMessage());
- stop();
- return null;
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
- stop();
- return null;
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The configuration of the handler " + hi.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
- stop();
- return null;
- }
- }
-
- /**
- * Structure storing required handlers.
- */
- class HandlerIdentifier implements Comparable {
- /**
- * Factory to create this handler.
- */
- private HandlerFactory m_factory;
-
- /**
- * Handler name.
- */
- private String m_name;
-
- /**
- * Handler start level.
- */
- private int m_level = Integer.MAX_VALUE;
-
- /**
- * Handler namespace.
- */
- private String m_namespace;
-
- /**
- * Service Reference of the handler factory.
- */
- private ServiceReference m_reference;
-
- /**
- * Constructor.
- * @param n : handler name.
- * @param ns : handler namespace.
- */
- public HandlerIdentifier(String n, String ns) {
- m_name = n;
- m_namespace = ns;
- }
-
- /**
- * Equals method.
- * Two handlers are equals if they have same name and namespace or they share the same service reference.
- * @param o : object to compare to the current object.
- * @return : true if the two compared object are equals
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object o) {
- if (m_namespace == null) {
- return ((HandlerIdentifier) o).m_name.equalsIgnoreCase(m_name) && ((HandlerIdentifier) o).m_namespace == null;
- } else {
- return ((HandlerIdentifier) o).m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(((HandlerIdentifier) o).m_namespace);
- }
- }
-
- /**
- * Get the factory object used for this handler.
- * The object is get when used for the first time.
- * @return the factory object.
- */
- public HandlerFactory getFactory() {
- if (m_reference == null) {
- return null;
- }
- if (m_factory == null) {
- m_factory = (HandlerFactory) m_tracker.getService(getReference());
- }
- return m_factory;
- }
-
- /**
- * Get the handler full name (namespace:name).
- * @return the handler full name
- */
- public String getFullName() {
- if (m_namespace == null) {
- return IPojoConfiguration.IPOJO_NAMESPACE + ":" + m_name;
- } else {
- return m_namespace + ":" + m_name;
- }
- }
-
- public String getName() {
- return m_name;
- }
-
- public String getNamespace() {
- return m_namespace;
- }
-
- public ServiceReference getReference() {
- return m_reference;
- }
-
- public int getLevel() {
- return m_level;
- }
-
- /**
- * Release the reference of the used factory.
- */
- public void unRef() {
- if (m_reference != null) {
- m_tracker.ungetService(m_reference);
- m_factory = null;
- m_reference = null;
- }
- }
-
- /**
- * Set the service reference.
- * If the new service reference is null, it unget the used factory (if already get).
- * @param ref : new service reference.
- */
- public void setReference(ServiceReference ref) {
- m_reference = ref;
- Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
- if (p != null) {
- m_level = p.intValue();
- }
- }
-
- /**
- * Start level Comparison.
- * This method is used to sort the handler array.
- * @param o : object on which compare.
- * @return -1, 0, +1 according to the comparison of their start level.
- * @see java.lang.Comparable#compareTo(java.lang.Object)
- */
- public int compareTo(Object o) {
- if (o instanceof HandlerIdentifier) {
- HandlerIdentifier hi = (HandlerIdentifier) o;
- if (this.m_level == hi.m_level) {
- return 0;
- } else if (this.m_level < hi.m_level) {
- return -1;
- } else {
- return +1;
- }
- }
- return 0;
- }
+ return m_manipulation;
}
/**
@@ -1048,22 +336,20 @@
/**
* Map of defined classes [Name, Class Object].
*/
- private Map m_definedClasses = new HashMap();
+ private final Map m_definedClasses = new HashMap();
/**
* The defineClass method.
* @param name : name of the class
- * @param b : the byte array of the class
+ * @param clazz : the byte array of the class
* @param domain : the protection domain
* @return : the defined class.
*/
- public Class defineClass(String name, byte[] b, ProtectionDomain domain) {
- if (m_definedClasses.containsKey(name)) {
- return (Class) m_definedClasses.get(name);
- }
- final Class c = super.defineClass(name, b, 0, b.length, domain);
- m_definedClasses.put(name, c);
- return c;
+ public Class defineClass(String name, byte[] clazz, ProtectionDomain domain) {
+ if (m_definedClasses.containsKey(name)) { return (Class) m_definedClasses.get(name); }
+ Class clas = super.defineClass(name, clazz, 0, clazz.length, domain);
+ m_definedClasses.put(name, clas);
+ return clas;
}
/**
@@ -1084,8 +370,44 @@
* @return : the loaded class
* @throws ClassNotFoundException : the class to load is not found
*/
- protected Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
+ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
return m_context.getBundle().loadClass(name);
}
}
+
+ private final class PrimitiveTypeDescription extends ComponentTypeDescription {
+
+ /**
+ * Constructor.
+ * @param factory : the represented factory.
+ */
+ public PrimitiveTypeDescription(Factory factory) {
+ super(factory);
+ }
+
+ /**
+ * Compute the properties to publish :
+ * component.class contains the pojo class name.
+ * @return the dictionary of properties to publish
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+ */
+ public Dictionary getPropertiesToPublish() {
+ Dictionary dict = super.getPropertiesToPublish();
+ if (m_classname != null) {
+ dict.put("component.class", m_classname);
+ }
+ return dict;
+ }
+
+ /**
+ * Add the "implementation-class" attribute to the type description.
+ * @return the component type description.
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getDescription()
+ */
+ public Element getDescription() {
+ Element elem = super.getDescription();
+ elem.addAttribute(new Attribute("Implementation-Class", m_classname));
+ return elem;
+ }
+ }
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
deleted file mode 100644
index a87015e..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * 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;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.felix.ipojo.architecture.ComponentDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.Tracker;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * The component factory manages component instance objects. This management
- * consist in creating and managing component instance build with the component
- * factory. This class could export Factory and ManagedServiceFactory services.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class CompositeFactory extends ComponentFactory implements Factory {
-
- /**
- * Service Registration of this factory (Factory & ManagedServiceFactory).
- */
- private ServiceRegistration m_sr;
-
- /**
- * Create a composite factory.
- * @param bc : bundle context
- * @param cm : metadata of the component to create
- */
- public CompositeFactory(BundleContext bc, Element cm) {
- super(bc, cm);
- }
-
- /**
- * Check if the metadata are well formed.
- * @param cm : metadata
- * @return true if the metadata are correct.
- * @see org.apache.felix.ipojo.ComponentFactory#check(org.apache.felix.ipojo.metadata.Element)
- */
- public boolean check(Element cm) {
- m_factoryName = cm.getAttribute("name");
- if (m_factoryName == null) {
- System.err.println("A composite needs a name");
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Check if the given handler identifier can be fulfilled by the given service reference.
- * @param hi : handler identifier.
- * @param ref : service reference.
- * @return true if the service reference can fulfill the given handler identifier
- * @see org.apache.felix.ipojo.ComponentFactory#match(org.apache.felix.ipojo.ComponentFactory.HandlerIdentifier, org.osgi.framework.ServiceReference)
- */
- public boolean match(HandlerIdentifier hi, ServiceReference ref) {
- String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
- String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
- String type = (String) ref.getProperty(Handler.HANDLER_TYPE_PROPERTY);
-
- if ("composite".equals(type)) {
- if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
- return name.equals(hi.getName()) && hi.getNamespace() == null;
- }
- return name.equals(hi.getName()) && ns.equals(hi.getNamespace());
- } else {
- return false;
- }
- }
-
-
- /**
- * Compute required handlers.
- */
- protected void computeRequiredHandlers() {
- Element[] elems = m_componentMetadata.getElements();
- for (int i = 0; i < elems.length; i++) {
- Element current = elems[i];
- HandlerIdentifier hi = new HandlerIdentifier(current.getName(), current.getNameSpace());
- if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
- }
-
- // Add architecture if architecture != 'false'
- String arch = m_componentMetadata.getAttribute("architecture");
- if (arch == null || arch.equalsIgnoreCase("true")) {
- HandlerIdentifier hi = new HandlerIdentifier("architecture", null);
- if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
- }
- }
-
- /**
- * Stop all the instance managers.
- */
- public synchronized void stop() {
- if (m_tracker != null) {
- m_tracker.close();
- }
-
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- CompositeManager ci = (CompositeManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
- }
- m_instancesName.remove(ci.getInstanceName());
- }
-
- m_componentInstances.clear();
- if (m_sr != null) {
- m_sr.unregister();
- m_sr = null;
- }
- m_tracker = null;
- m_componentDesc = null;
- m_state = INVALID;
- }
-
- /**
- * Start all the instance managers.
- */
- public synchronized void start() {
- if (m_componentDesc != null) { // Already started.
- return;
- }
- if (m_handlerIdentifiers.size() != 0) {
- try {
- String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
- + "(" + Handler.HANDLER_TYPE_PROPERTY + "=" + CompositeHandler.HANDLER_TYPE + ")"
- + "(factory.state=1)"
- + ")";
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
- } catch (InvalidSyntaxException e) {
- m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
- stop();
- return;
- }
- }
-
- try {
- computeFactoryState();
- } catch (ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- return;
- }
-
- // Check if the factory should be exposed
- if (m_isPublic) {
- // Exposition of the factory service
- m_sr = m_context.registerService(new String[] { Factory.class.getName() }, this, getProperties());
- }
- }
-
-
- /**
- * Compute factory service properties.
- * @return the factory service properties
- * @see org.apache.felix.ipojo.ComponentFactory#getProperties()
- */
- protected Properties getProperties() {
- final Properties props = new Properties();
-
- if (m_componentDesc != null) {
- props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
- props.put("component.properties", m_componentDesc.getProperties());
- props.put("component.description", m_componentDesc);
- }
-
- // Add factory state
- props.put("factory.state", "" + m_state);
-
- props.put("factory.name", m_factoryName);
-
- return props;
- }
-
- public String getClassName() {
- return "composite";
- }
-
-
- /**
- * Create an instance. The given configuration needs to contain the 'name'
- * property.
- * @param configuration : configuration of the created instance.
- * @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
- * not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs if an handler is unavailable when the instance is created.
- * @throws ConfigurationException : occurs if an error occurs during the instance configuration.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
- */
- public synchronized ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
- return createComponentInstance(configuration, null);
- }
-
- /**
- * Create an instance. The given configuration needs to contain the 'name'
- * property.
- * @param configuration : configuration of the created instance.
- * @param serviceContext : the service context to push for this instance.
- * @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
- * not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
- * @throws ConfigurationException : occurs when the instance configuration failed.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
- */
- public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
- if (configuration == null) {
- configuration = new Properties();
- }
-
- try {
- checkAcceptability(configuration);
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new UnacceptableConfiguration("The configuration " + configuration + " is not acceptable for " + m_factoryName + ": " + e.getMessage());
- }
-
-
- String in = null;
- if (configuration.get("name") != null) {
- in = (String) configuration.get("name");
- } else {
- in = generateName();
- configuration.put("name", in);
- }
-
- if (m_instancesName.contains(in)) {
- throw new UnacceptableConfiguration("Name already used : " + in + "(" + m_instancesName + ")");
- } else {
- m_instancesName.add(in);
- }
-
- BundleContext context = null;
- if (serviceContext == null) {
- context = new IPojoContext(m_context);
- } else {
- context = new IPojoContext(m_context, serviceContext);
- }
- ComponentInstance instance = null;
- List handlers = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- handlers.add(getHandlerInstance(hi, serviceContext));
- }
-
- final CompositeManager inst = new CompositeManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[0]));
- inst.configure(m_componentMetadata, configuration);
- instance = inst;
-
- m_componentInstances.put(in, instance);
- instance.start();
- return instance;
- }
-
- /**
- * Reconfigure an existing instance.
- * @param properties : the new configuration to push.
- * @throws UnacceptableConfiguration : occurs if the new configuration is
- * not consistent with the component type.
- * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
- * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
- */
- public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
- if (properties == null || properties.get("name") == null) {
- throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
- }
- final String name = (String) properties.get("name");
-
- ComponentInstance cm = (CompositeManager) m_componentInstances.get(name);
-
- if (cm == null) {
- return; // The instance does not exist.
- }
-
- cm.reconfigure(properties); // re-configure the component
- }
-
- /**
- * Compute factory state.
- * @throws ConfigurationException : occurs if the component type cannot be initialized correctly.
- */
- protected void computeFactoryState() throws ConfigurationException {
- boolean isValid = true;
- for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- isValid = hi.getReference() != null;
- }
-
- if (isValid && m_componentDesc == null) {
- computeDescription();
- }
-
- if (isValid && m_state == INVALID) {
- m_state = VALID;
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
- }
- return;
- }
-
- if (!isValid && m_state == VALID) {
- m_state = INVALID;
-
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- CompositeManager ci = (CompositeManager) it.next();
- ci.kill();
- m_instancesName.remove(ci.getInstanceName());
- }
-
- m_componentInstances.clear();
-
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
-
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
- }
- return;
- }
-
- }
-
- /**
- * Compute component type description.
- * @throws ConfigurationException : if one handler has rejected the configuration.
- * @see org.apache.felix.ipojo.ComponentFactory#computeDescription()
- */
- public void computeDescription() throws ConfigurationException {
- List l = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- l.add(hi.getFullName());
- }
-
- m_componentDesc = new ComponentDescription(this);
-
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- HandlerManager hm = getHandlerInstance(hi, null);
- hm.getHandler();
- Handler ch = hm.getHandler();
- ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
- ((Pojo) ch).getComponentInstance().dispose();
- }
- }
-
- /**
- * Get a composite handler object for the given handler identifier.
- * @param handler : the handler identifier.
- * @param sc : the service context in which creating the handler.
- * @return the composite handler object or null if not found.
- */
- private HandlerManager getHandlerInstance(HandlerIdentifier handler, ServiceContext sc) {
- Factory factory = (Factory) m_context.getService(handler.getReference());
- try {
- return (HandlerManager) factory.createComponentInstance(null, sc);
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The creation of the composite handler " + handler.getFullName() + " has failed: " + e.getMessage());
- stop();
- return null;
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The creation of the composite handler " + handler.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
- stop();
- return null;
- } catch (ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The creation of the composite handler " + handler.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
- stop();
- return null;
- }
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeHandler.java
deleted file mode 100644
index bf243e9..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeHandler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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 Handler Abstract Class. An composite handler need implements these
- * method to be notified of lifecycle change...
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public abstract class CompositeHandler extends Handler {
-
- /**
- * Composite Handler type.
- */
- public static final String HANDLER_TYPE = "composite";
-
- /**
- * Reference on the composite manager.
- */
- private CompositeManager m_manager;
-
- /**
- * Set the manager.
- * This method me be called only once time.
- * @param cm : the composite manager.
- */
- protected final void attach(ComponentInstance cm) {
- m_manager = (CompositeManager) cm;
- setLogger(m_manager.getFactory().getLogger());
- }
-
- public final CompositeManager getCompositeManager() {
- return m_manager;
- }
-
- /**
- * Get a plugged handler of the same container.
- * This method must be call only in the start method (or after).
- * In the configure method, this method can not return a consistent
- * result as all handlers are not plugged.
- * @param name : name of the handler to find (class name).
- * @return the composite handler object or null if the handler is not found.
- */
- public final Handler getHandler(String name) {
- return m_manager.getCompositeHandler(name);
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java
deleted file mode 100644
index 69eb78f..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * 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;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-
-import org.apache.felix.ipojo.architecture.Architecture;
-import org.apache.felix.ipojo.architecture.InstanceDescription;
-import org.apache.felix.ipojo.composite.CompositeServiceContext;
-import org.apache.felix.ipojo.metadata.Element;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-/**
- * iPOJO Composite manager. The composite manager class manages one instance of
- * a component type which is a composition. It manages component lifecycle, and
- * handlers...
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class CompositeManager implements ComponentInstance, InstanceStateListener {
-
- /**
- * The context of the component.
- */
- private BundleContext m_context;
-
- /**
- * Parent factory (ComponentFactory).
- */
- private ComponentFactory m_factory;
-
- /**
- * Composite Handler list.
- */
- private HandlerManager[] m_handlers = new HandlerManager[0];
-
- /**
- * Instance State Listener List.
- */
- private List m_instanceListeners = new ArrayList();
-
- /**
- * Internal service context of the composition.
- */
- private CompositeServiceContext m_internalContext;
-
- /**
- * Name of the component instance.
- */
- private String m_name;
-
- /**
- * Component state (STOPPED at the beginning).
- */
- private int m_state = STOPPED;
-
- /**
- * Construct a new Component Manager.
- * @param factory : the factory managing the instance manager
- * @param bc : the bundle context to give to the instance
- * @param handlers : the handlers to plug
- */
- public CompositeManager(ComponentFactory factory, BundleContext bc, HandlerManager[] handlers) {
- m_factory = factory;
- m_context = bc;
- // Initialize the service context.
- m_internalContext = new CompositeServiceContext(m_context, this);
- m_handlers = handlers;
- }
-
- /**
- * Plug the given handler to the current container.
- * @param h : the handler to plug.
- */
- public synchronized void addCompositeHandler(HandlerManager h) {
- if (m_handlers.length > 0) {
- HandlerManager[] newInstances = new HandlerManager[m_handlers.length + 1];
- System.arraycopy(m_handlers, 0, newInstances, 0, m_handlers.length);
- newInstances[m_handlers.length] = h;
- m_handlers = newInstances;
- } else {
- m_handlers = new HandlerManager[] { h };
- }
- }
-
- /**
- * Add an instance to the created instance list.
- * @param listener : the instance state listener to add.
- * @see org.apache.felix.ipojo.ComponentInstance#addInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
- */
- public void addInstanceStateListener(InstanceStateListener listener) {
- synchronized (m_instanceListeners) {
- m_instanceListeners.add(listener);
- }
- }
-
- /**
- * Configure the instance manager. Stop the existing handler, clear the
- * handler list, change the metadata, recreate the handler
- *
- * @param cm : the component type metadata
- * @param configuration : the configuration of the instance
- * @throws ConfigurationException : occurs when the component type are incorrect.
- */
- public void configure(Element cm, Dictionary configuration) throws ConfigurationException {
- // Add the name
- m_name = (String) configuration.get("name");
-
- // Create the standard handlers and add these handlers to the list
- for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].init(this, cm, configuration);
- }
- }
-
- /**
- * Dispose the instance.
- * @see org.apache.felix.ipojo.ComponentInstance#dispose()
- */
- public void dispose() {
- if (m_state > STOPPED) { stop(); }
-
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
- }
-
- m_factory.disposed(this);
-
- // Cleaning
- m_state = DISPOSED;
- for (int i = m_handlers.length - 1; i > -1; i--) {
- m_handlers[i].dispose();
- }
- m_handlers = new HandlerManager[0];
- m_instanceListeners.clear();
- }
-
- /**
- * Return a specified handler.
- * @param name : class name of the handler to find
- * @return : the handler, or null if not found
- */
- public CompositeHandler getCompositeHandler(String name) {
- for (int i = 0; i < m_handlers.length; i++) {
- HandlerFactory fact = (HandlerFactory) m_handlers[i].getFactory();
- if (fact.getHandlerName().equals(name) || fact.getComponentClassName().equals(name)) {
- return (CompositeHandler) m_handlers[i].getHandler();
- }
- }
- return null;
- }
-
- /**
- * Get the bundle context used by this instance.
- * @return the parent context of the instance.
- * @see org.apache.felix.ipojo.ComponentInstance#getContext()
- */
- public BundleContext getContext() {
- return m_context;
- }
-
- /**
- * Get the factory which create this instance.
- * @return the factory of the component
- * @see org.apache.felix.ipojo.ComponentInstance#getFactory()
- */
- public ComponentFactory getFactory() {
- return m_factory;
- }
-
- /**
- * Get the global bundle context.
- * @return the global bundle context.
- */
- public BundleContext getGlobalContext() {
- IPojoContext c = (IPojoContext) m_context;
- return c.getGlobalContext();
- }
-
- /**
- * Return the instance description of this instance.
- * @return the instance description.
- * @see org.apache.felix.ipojo.ComponentInstance#getInstanceDescription()
- */
- public InstanceDescription getInstanceDescription() {
- InstanceDescription instanceDescription = new InstanceDescription(m_name, m_state, getContext().getBundle().getBundleId(), m_factory.getComponentDescription());
- CompositeHandler[] handlers = getRegistredCompositeHandlers();
- for (int i = 0; i < handlers.length; i++) {
- instanceDescription.addHandler(handlers[i].getDescription());
- }
-
- // Get instances description of internal instance
- ServiceReference[] refs;
- try {
- refs = m_internalContext.getServiceReferences(Architecture.class.getName(), null);
- if (refs != null) {
- for (int i = 0; i < refs.length; i++) {
- Architecture arch = (Architecture) m_internalContext.getService(refs[i]);
- instanceDescription.addInstance(arch.getInstanceDescription());
- m_internalContext.ungetService(refs[i]);
- }
- }
- } catch (InvalidSyntaxException e) {
- e.printStackTrace(); // Should not happen
- }
- return instanceDescription;
- }
-
- /**
- * Get the instance name.
- * @return the instance name
- * @see org.apache.felix.ipojo.ComponentInstance#getInstanceName()
- */
- public String getInstanceName() {
- return m_name;
- }
-
- /**
- * Get the parent service context.
- * @return the parent service context.
- */
- public ServiceContext getParentServiceContext() {
- IPojoContext c = (IPojoContext) m_context;
- return c.getServiceContext();
- }
-
- /**
- * REturn the list of handlers plugged on this instance.
- * @return the list of the registered handlers.
- */
- public CompositeHandler[] getRegistredCompositeHandlers() {
- CompositeHandler[] h = new CompositeHandler[m_handlers.length];
- for (int i = 0; i < m_handlers.length; i++) {
- h[i] = (CompositeHandler) m_handlers[i].getHandler();
- }
- return h;
- }
-
- /**
- * Get the internal service context of this instance.
- * @return the internal service context.
- */
- public ServiceContext getServiceContext() {
- return m_internalContext;
- }
-
- /**
- * Get the actual state of the instance.
- * @return the actual state of the instance
- * @see org.apache.felix.ipojo.ComponentInstance#getState()
- */
- public int getState() {
- return m_state;
- }
-
- /**
- * Check if the instance is started.
- * @return true if the instance is started.
- * @see org.apache.felix.ipojo.ComponentInstance#isStarted()
- */
- public boolean isStarted() {
- return m_state > STOPPED;
- }
-
- /**
- * Reconfigure the current instance.
- * @param configuration : the new instance configuration.
- * @see org.apache.felix.ipojo.ComponentInstance#reconfigure(java.util.Dictionary)
- */
- public void reconfigure(Dictionary configuration) {
- for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].reconfigure(configuration);
- }
- }
-
- /**
- * Remove an instance state listener.
- * @param listener : the listener to remove
- * @see org.apache.felix.ipojo.ComponentInstance#removeInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
- */
- public void removeInstanceStateListener(InstanceStateListener listener) {
- synchronized (m_instanceListeners) {
- m_instanceListeners.remove(listener);
- }
- }
-
- /**
- * Set the state of the component.
- * if the state changed call the stateChanged(int) method on the handlers.
- * @param state : new state
- */
- public void setState(int state) {
- if (m_state != state) {
- if (state > m_state) {
- // The state increases (Stopped = > IV, IV => V) => invoke handlers from the higher priority to the lower
- m_state = state;
- for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].getHandler().stateChanged(state);
- }
- } else {
- // The state decreases (V => IV, IV = > Stopped, Stopped => Disposed)
- m_state = state;
- for (int i = m_handlers.length - 1; i > -1; i--) {
- m_handlers[i].getHandler().stateChanged(state);
- }
- }
-
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, state);
- }
- }
- }
-
- /**
- * Start the instance manager.
- */
- public synchronized void start() {
- if (m_state > STOPPED) {
- return;
- } // Instance already started
-
-
- // The new state of the component is UNRESOLVED
- m_state = INVALID;
-
- m_internalContext.start(); // Turn on the factory tracking
-
- for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].start();
- m_handlers[i].addInstanceStateListener(this);
- }
-
- for (int i = 0; i < m_handlers.length; i++) {
- if (m_handlers[i].getState() != VALID) {
- setState(INVALID);
- return;
- }
- }
- setState(VALID);
-
- }
-
- /**
- * State Change listener callback.
- * This method is notified at each time a plugged handler becomes invalid.
- * @param instance : changing instance
- * @param newState : new state
- * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
- */
- public synchronized void stateChanged(ComponentInstance instance, int newState) {
- if (m_state <= STOPPED) { return; }
-
- // Update the component state if necessary
- if (newState == INVALID && m_state == VALID) {
- // Need to update the state to UNRESOLVED
- setState(INVALID);
- return;
- }
- if (newState == VALID && m_state == INVALID) {
- // An handler becomes valid => check if all handlers are valid
- boolean isValid = true;
- for (int i = 0; i < m_handlers.length; i++) {
- isValid = isValid && m_handlers[i].getState() == VALID;
- }
-
- if (isValid) { setState(VALID); }
- }
- if (newState == DISPOSED) {
- kill();
- }
- }
-
- /**
- * Stop the instance manager.
- */
- public synchronized void stop() {
- if (m_state <= STOPPED) {
- return;
- } // Instance already stopped
-
- setState(INVALID);
- // Stop all the handlers
- for (int i = m_handlers.length - 1; i > -1; i--) {
- m_handlers[i].removeInstanceStateListener(this);
- m_handlers[i].stop();
- }
-
- m_internalContext.stop(); // Turn off the factory tracking
- m_state = STOPPED;
-
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
- }
- }
-
- /**
- * Kill the current instance.
- * Only the factory of this instance can call this method.
- */
- protected synchronized void kill() {
- if (m_state > STOPPED) { stop(); }
-
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
- }
-
- // Cleaning
- m_state = DISPOSED;
-
- for (int i = m_handlers.length - 1; i > -1; i--) {
- m_handlers[i].dispose();
- }
- m_handlers = new HandlerManager[0];
- m_instanceListeners.clear();
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java
index 90c9ba4..cde3140 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java
@@ -29,11 +29,6 @@
* Serialization Id.
*/
private static final long serialVersionUID = 1L;
-
- /**
- * Message.
- */
- private String m_message;
/**
* Component Type on which the error occurs.
@@ -46,8 +41,8 @@
* @param typ : component type
*/
ConfigurationException(String mes, String typ) {
+ super(mes);
m_type = typ;
- m_message = mes;
}
/**
@@ -55,7 +50,7 @@
* @param mes : message
*/
public ConfigurationException(String mes) {
- m_message = mes;
+ super(mes);
}
/**
@@ -64,10 +59,10 @@
* @see java.lang.Throwable#getMessage()
*/
public String getMessage() {
- if (m_type != null) {
- return "The configuration is not correct for the type " + m_type + " : " + m_message;
+ if (m_type == null) {
+ return super.getMessage();
} else {
- return m_message;
+ return "The configuration is not correct for the type " + m_type + " : " + super.getMessage();
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ContextListener.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ContextListener.java
new file mode 100644
index 0000000..d592c5c
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ContextListener.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+
+/**
+ * Context Source Listener.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ContextListener {
+
+ /**
+ * A monitored value has been modified.
+ * @param source : context source containing the property
+ * @param property : modified property name
+ * @param value : new value of the property
+ */
+ void update(ContextSource source, String property, Object value);
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ContextSource.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ContextSource.java
new file mode 100644
index 0000000..e55f163
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ContextSource.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+import java.util.Dictionary;
+
+
+/**
+ * Context Source service interface.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ContextSource {
+
+ /**
+ * Get the current value of the given property.
+ * @param property : property name
+ * @return the property value, null if unknown
+ */
+ Object getProperty(String property);
+
+ /**
+ * Get the whole context.
+ * @return the dictionary [Property, Value]
+ */
+ Dictionary getContext();
+
+ /**
+ * Register a context listener on the given set of properties.
+ * The listener will be notified of every change made on these properties.
+ * @param listener : the context listener to register.
+ * @param properties : property set monitored by the listener.
+ */
+ void registerContextListener(ContextListener listener, String[] properties);
+
+ /**
+ * Unregister the given context listener.
+ * @param listener : the listener to unregister.
+ */
+ void unregisterContextListener(ContextListener listener);
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
index aeb4c0f..fd9ab38 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
@@ -19,20 +19,27 @@
package org.apache.felix.ipojo;
import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
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.parser.ParseUtils;
+import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
-import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
-import org.osgi.service.log.LogService;
/**
* iPOJO Extender.
@@ -42,39 +49,52 @@
public class Extender implements SynchronousBundleListener, BundleActivator {
/**
- * iPOJO Manifest header.
+ * iPOJO Component Type and Instance declaration header.
*/
private static final String IPOJO_HEADER = "iPOJO-Components";
-
+
+ /**
+ * iPOJO Extension declaration header.
+ */
+ private static final String IPOJO_EXTENSION = "IPOJO-Extension";
+
+ /**
+ * iPOJO Extender logger.
+ */
+ private Logger m_logger;
+
/**
* iPOJO Bundle Context.
*/
private BundleContext m_context;
-
+
/**
- * Dictionary of [BundleId, Factory List].
+ * Declared instance manager.
*/
- private Dictionary m_components;
-
+ private InstanceCreator m_creator;
+
/**
- * Dictionary of [BundleId, Instance Creator].
+ * iPOJO Bundle.
*/
- private Dictionary m_creators;
-
+ private Bundle m_bundle;
+
/**
- * iPOJO Bundle Id.
+ * List of factory types.
*/
- private long m_bundleId;
-
+ private List m_factoryTypes = new ArrayList();
+
+ /**
+ * List of unbound types.
+ */
+ private final List m_unboundTypes = new ArrayList();
+
/**
* Bundle Listener Notification.
* @param event : the bundle event.
* @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
*/
public synchronized void bundleChanged(BundleEvent event) {
- if (event.getBundle().getBundleId() == m_bundleId) {
- return;
- }
+ if (event.getBundle() == m_bundle) { return; }
switch (event.getType()) {
case BundleEvent.STARTED:
@@ -83,7 +103,7 @@
case BundleEvent.STOPPING:
closeManagementFor(event.getBundle());
break;
- default:
+ default:
break;
}
@@ -94,42 +114,109 @@
* @param bundle : the bundle.
*/
private void closeManagementFor(Bundle bundle) {
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
- InstanceCreator creator = (InstanceCreator) m_creators.get(bundle);
- if (cfs == null && creator == null) { return; }
- for (int i = 0; cfs != null && i < cfs.length; i++) {
- ComponentFactory factory = cfs[i];
- factory.stop();
+ List toRemove = new ArrayList();
+ for (int k = 0; k < m_factoryTypes.size(); k++) {
+ ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);
+
+ // Delete instances declared in the leaving bundle.
+ m_creator.removeInstancesFromBundle(bundle.getBundleId());
+
+ // Look for component type created from this bundle.
+ if (mft.m_created != null) {
+ List cfs = (List) mft.m_created.remove(bundle);
+ for (int i = 0; cfs != null && i < cfs.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) cfs.get(i);
+ m_creator.removeFactory(factory);
+ factory.stop();
+ }
+ }
+
+ // If the leaving bundle has declared mft : destroy all created factories.
+ if (mft.m_bundle == bundle) {
+ if (mft.m_created != null) {
+ Iterator iterator = mft.m_created.keySet().iterator();
+ while (iterator.hasNext()) {
+ Bundle key = (Bundle) iterator.next();
+ List list = (List) mft.m_created.get(key);
+ for (int i = 0; i < list.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) list.get(i);
+ factory.stop();
+ m_unboundTypes.add(new UnboundComponentType(mft.m_type, factory.m_componentMetadata, factory.getBundleContext()
+ .getBundle()));
+ }
+ }
+ }
+ toRemove.add(mft);
+ }
}
- if (creator != null) { creator.stop(); }
-
- m_components.remove(bundle);
- m_creators.remove(bundle);
-
+
+ for (int i = 0; i < toRemove.size(); i++) {
+ ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) toRemove.get(i);
+ m_logger.log(Logger.WARNING, "The factory type available: " + mft.m_type + " is no more available");
+ mft.m_bundle = null;
+ mft.m_clazz = null;
+ mft.m_created = null;
+ mft.m_type = null;
+ m_factoryTypes.remove(mft);
+ }
}
/**
- * Check if the given bundle is an iPOJO bundle, and begin the iPOJO management is true.
+ * Check if the given bundle is an iPOJO bundle, and begin the iPOJO management is true.
* @param bundle : the bundle to check.
*/
private void startManagementFor(Bundle bundle) {
- // Check bundle
Dictionary dict = bundle.getHeaders();
+ // Check for abstract factory type
+ String typeHeader = (String) dict.get(IPOJO_EXTENSION);
+ if (typeHeader != null) {
+ parseAbstractFactoryType(bundle, typeHeader);
+ }
+
+ // Check bundle
String header = (String) dict.get(IPOJO_HEADER);
- if (header == null) {
- return;
- } else {
+ if (header != null) {
try {
parse(bundle, header);
} catch (IOException e) {
- err("An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+ m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
} catch (ParseException e) {
- err("A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+ m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
}
}
-
}
-
+
+ /**
+ * Parse an IPOJO-Extension manifest header.
+ * @param bundle : bundle containing the header.
+ * @param header : header to parse.
+ */
+ private void parseAbstractFactoryType(Bundle bundle, String header) {
+ String[] arr = ParseUtils.split(header, ",");
+ for (int i = 0; arr != null && i < arr.length; i++) {
+ String[] arr2 = ParseUtils.split(arr[i], ":");
+ String type = arr2[0];
+ Class clazz;
+ try {
+ clazz = bundle.loadClass(arr2[1]);
+ } catch (ClassNotFoundException e) {
+ m_logger.log(Logger.ERROR, "Cannot load the extension " + type, e);
+ return;
+ }
+ ManagedAbstractFactoryType mft = new ManagedAbstractFactoryType(clazz, type, bundle);
+ m_factoryTypes.add(mft);
+ m_logger.log(Logger.WARNING, "New factory type available: " + type);
+
+ for (int j = m_unboundTypes.size() - 1; j >= 0; j--) {
+ UnboundComponentType unbound = (UnboundComponentType) m_unboundTypes.get(j);
+ if (unbound.m_type.equals(type)) {
+ createAbstractFactory(unbound.m_bundle, unbound.m_description);
+ m_unboundTypes.remove(unbound);
+ }
+ }
+ }
+ }
+
/**
* Parse the internal metadata (from the manifest (in the iPOJO-Components property)).
* @param bundle : the owner bundle.
@@ -140,35 +227,40 @@
private void parse(Bundle bundle, String components) throws IOException, ParseException {
ManifestMetadataParser parser = new ManifestMetadataParser();
parser.parseHeader(components);
-
- Element[] componentsMetadata = parser.getComponentsMetadata(); // Get the component type declaration
- for (int i = 0; i < componentsMetadata.length; i++) { addComponentFactory(bundle, componentsMetadata[i]); }
-
- start(bundle, parser.getInstances());
+
+ Element[] metadata = parser.getComponentsMetadata(); // Get the component type declaration
+ for (int i = 0; i < metadata.length; i++) {
+ createAbstractFactory(bundle, metadata[i]);
+ }
+
+ Dictionary[] instances = parser.getInstances();
+ for (int i = 0; instances != null && i < instances.length; i++) {
+ m_creator.addInstance(instances[i], bundle.getBundleId());
+ }
}
/**
* iPOJO Starting method.
- * @param bc : iPOJO bundle context.
- * @throws Exception : the start method failed.
+ * @param context : iPOJO bundle context.
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
- public void start(BundleContext bc) throws Exception {
- m_context = bc;
- m_bundleId = bc.getBundle().getBundleId();
- m_components = new Hashtable();
- m_creators = new Hashtable();
+ public void start(BundleContext context) {
+ m_context = context;
+ m_bundle = context.getBundle();
+ m_creator = new InstanceCreator(context);
+
+ m_logger = new Logger(m_context, "IPOJO Extender");
// Begin by initializing core handlers
- startManagementFor(bc.getBundle());
+ startManagementFor(m_bundle);
synchronized (this) {
// listen to any changes in bundles.
m_context.addBundleListener(this);
// compute already started bundles.
- for (int i = 0; i < bc.getBundles().length; i++) {
- if (bc.getBundles()[i].getState() == Bundle.ACTIVE) {
- startManagementFor(bc.getBundles()[i]);
+ for (int i = 0; i < context.getBundles().length; i++) {
+ if (context.getBundles()[i].getState() == Bundle.ACTIVE) {
+ startManagementFor(context.getBundles()[i]);
}
}
}
@@ -176,96 +268,238 @@
/**
* Stop the iPOJO Management.
- * @param bc : bundle context.
- * @throws Exception : the stop method failed.
+ * @param context : bundle context.
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
- public void stop(BundleContext bc) throws Exception {
+ public void stop(BundleContext context) {
m_context.removeBundleListener(this);
- Enumeration e = m_components.keys();
- while (e.hasMoreElements()) {
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(e.nextElement());
- for (int i = 0; i < cfs.length; i++) {
- cfs[i].stop();
+
+ for (int k = 0; k < m_factoryTypes.size(); k++) {
+ ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);
+
+ if (mft.m_created != null) {
+ Iterator iterator = mft.m_created.keySet().iterator();
+ while (iterator.hasNext()) {
+ Bundle key = (Bundle) iterator.next();
+ List list = (List) mft.m_created.get(key);
+ for (int i = 0; i < list.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) list.get(i);
+ m_creator.removeFactory(factory);
+ factory.dispose();
+ }
+ }
}
}
- m_components = null;
- Enumeration e2 = m_creators.keys();
- while (e2.hasMoreElements()) {
- InstanceCreator creator = (InstanceCreator) m_creators.remove(e2.nextElement());
- creator.stop();
- }
- m_creators = null;
+
+ m_factoryTypes = null;
+ m_creator = null;
}
-
+
/**
* Add a component factory to the factory list.
- * @param cm : the new component metadata.
+ * @param metadata : the new component metadata.
* @param bundle : the bundle.
*/
- private void addComponentFactory(Bundle bundle, Element cm) {
- ComponentFactory factory = null;
- if (cm.getName().equalsIgnoreCase("component")) {
- factory = new ComponentFactory(bundle.getBundleContext(), cm);
- } else if (cm.getName().equalsIgnoreCase("composite")) {
- factory = new CompositeFactory(bundle.getBundleContext(), cm);
- } else if (cm.getName().equalsIgnoreCase("handler")) {
- factory = new HandlerFactory(bundle.getBundleContext(), cm);
- } else {
- err("Not recognized element type : " + cm.getName(), null);
- }
-
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-
- // If the factory array is not empty add the new factory at the end
- if (cfs != null && cfs.length != 0) {
- ComponentFactory[] newFactory = new ComponentFactory[cfs.length + 1];
- System.arraycopy(cfs, 0, newFactory, 0, cfs.length);
- newFactory[cfs.length] = factory;
- cfs = newFactory;
- m_components.put(bundle, cfs);
- } else {
- m_components.put(bundle, new ComponentFactory[] {factory}); // Else create an array of size one with the new Factory
- }
- }
-
- /**
- * Start the management of factories and create instances.
- * @param bundle : the bundle.
- * @param confs : the instances to create.
- */
- private void start(Bundle bundle, Dictionary[] confs) {
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-
- // Start the factories
- if (cfs != null) {
- for (int j = 0; j < cfs.length; j++) {
- cfs[j].start();
+ private void createAbstractFactory(Bundle bundle, Element metadata) {
+ ManagedAbstractFactoryType factoryType = null;
+ // First, look for factory-type (component, handler, composite ...)
+ for (int i = 0; i < m_factoryTypes.size(); i++) {
+ ManagedAbstractFactoryType type = (ManagedAbstractFactoryType) m_factoryTypes.get(i);
+ if (type.m_type.equals(metadata.getName())) {
+ factoryType = type;
+ break;
}
}
- // Create the instance creator if needed.
- if (confs.length > 0) {
- m_creators.put(bundle, new InstanceCreator(bundle.getBundleContext(), confs, cfs));
+ // If not found, return. It will wait for a new component type factory.
+ if (factoryType == null) {
+ m_logger.log(Logger.WARNING, "Type of component not yet recognized : " + metadata.getName());
+ m_unboundTypes.add(new UnboundComponentType(metadata.getName(), metadata, bundle));
+ return;
+ }
+
+ // Once found, we invoke the AbstractFactory constructor to create the component factory.
+ Class clazz = factoryType.m_clazz;
+ try {
+ // Look for the constructor, and invoke it.
+ Constructor cst = clazz.getConstructor(new Class[] { BundleContext.class, Element.class });
+ IPojoFactory factory = (IPojoFactory) cst.newInstance(new Object[] { getBundleContext(bundle), metadata });
+
+ // Add the created factory in the m_createdFactories map.
+ if (factoryType.m_created == null) {
+ factoryType.m_created = new HashMap();
+ List list = new ArrayList();
+ list.add(factory);
+ factoryType.m_created.put(bundle, list);
+ } else {
+ List list = (List) factoryType.m_created.get(bundle);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(factory);
+ factoryType.m_created.put(bundle, list);
+ } else {
+ list.add(factory);
+ }
+ }
+
+ // Start the created factory.
+ factory.start();
+ // Then add the factory to the instance creator.
+ m_creator.addFactory(factory);
+
+ } catch (SecurityException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (NoSuchMethodException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName() + ": the given class constructor cannot be found");
+ } catch (IllegalArgumentException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (InstantiationException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (IllegalAccessException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (InvocationTargetException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e.getTargetException());
}
}
-
+
/**
- * Log an error message in a log service (if available) and display the message in the console.
- * @param message : the message to log
- * @param t : an attached error (can be null)
+ * Structure storing an iPOJO extension.
*/
- private void err(String message, Throwable t) {
- ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
- if (ref != null) {
- LogService log = (LogService) m_context.getService(ref);
- log.log(LogService.LOG_ERROR, message, t);
- m_context.ungetService(ref);
- }
- if (t != null) {
- System.err.println("[iPOJO-Core] " + message + " : " + t.getMessage());
- } else {
- System.err.println("[iPOJO-Core] " + message);
+ private final class ManagedAbstractFactoryType {
+ /**
+ * TYpe (i.e.) name of the extension.
+ */
+ String m_type;
+
+ /**
+ * Abstract Factory class.
+ */
+ Class m_clazz;
+
+ /**
+ * Bundle object containing the declaration of the extension.
+ */
+ Bundle m_bundle;
+
+ /**
+ * Factories created by this extension.
+ */
+ private Map m_created;
+
+ /**
+ * Constructor.
+ * @param factory : abstract factory class.
+ * @param type : name of the extension.
+ * @param bundle : bundle declaring the extension.
+ */
+ protected ManagedAbstractFactoryType(Class factory, String type, Bundle bundle) {
+ m_bundle = bundle;
+ m_clazz = factory;
+ m_type = type;
}
}
+
+ /**
+ * Structure storing unbound component type declaration.
+ * Unbound means that there is no extension able to manage it.
+ */
+ private final class UnboundComponentType {
+ /**
+ * Component type description.
+ */
+ private final Element m_description;
+
+ /**
+ * Bundle declaring this type.
+ */
+ private final Bundle m_bundle;
+
+ /**
+ * Required extension name.
+ */
+ private final String m_type;
+
+ /**
+ * Constructor.
+ * @param description : description of the component type.
+ * @param bundle : bundle declaring this type.
+ * @param type : required extension name.
+ */
+ protected UnboundComponentType(String type, Element description, Bundle bundle) {
+ m_type = type;
+ m_description = description;
+ m_bundle = bundle;
+ }
+ }
+
+ /**
+ * Compute the bundle context from the bundle class by introspection.
+ * @param bundle : bundle.
+ * @return the bundle context object or null if not found.
+ */
+ public BundleContext getBundleContext(Bundle bundle) {
+ if (bundle == null) { return null; }
+
+ // getBundleContext (OSGi 4.1)
+ Method meth = null;
+ try {
+ meth = bundle.getClass().getMethod("getBundleContext", new Class[0]);
+ } catch (SecurityException e) {
+ // Nothing do to, will try the Equinox method
+ } catch (NoSuchMethodException e) {
+ // Nothing do to, will try the Equinox method
+ }
+
+ // try Equinox getContext if not found.
+ if (meth == null) {
+ try {
+ meth = bundle.getClass().getMethod("getContext", new Class[0]);
+ } catch (SecurityException e) {
+ // Nothing do to, will try field inspection
+ } catch (NoSuchMethodException e) {
+ // Nothing do to, will try field inspection
+ }
+ }
+
+ if (meth != null) {
+ if (! meth.isAccessible()) {
+ // If not accessible, try to set the accessibility.
+ meth.setAccessible(true);
+ }
+ try {
+ return (BundleContext) meth.invoke(bundle, new Object[0]);
+ } catch (IllegalArgumentException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (IllegalAccessException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (InvocationTargetException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e.getTargetException());
+ return null;
+ }
+ }
+
+ // Else : Field inspection (KF and Prosyst)
+ Field[] fields = bundle.getClass().getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (BundleContext.class.isAssignableFrom(fields[i].getType())) {
+ if (!fields[i].isAccessible()) {
+ fields[i].setAccessible(true);
+ }
+ try {
+ return (BundleContext) fields[i].get(bundle);
+ } catch (IllegalArgumentException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (IllegalAccessException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ }
+ }
+ }
+ m_logger.log(Logger.ERROR, "Cannot find the BundleContext for " + bundle.getSymbolicName(), null);
+ return null;
+ }
+
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
index bcc2d55..a8bff35 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
@@ -21,7 +21,7 @@
import java.util.Dictionary;
import java.util.List;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.osgi.framework.BundleContext;
@@ -72,7 +72,7 @@
* Get the component type description.
* @return the component type description object
*/
- ComponentDescription getComponentDescription();
+ ComponentTypeDescription getComponentDescription();
/**
* Check if the given configuration is acceptable as a configuration of a component instance.
@@ -97,15 +97,15 @@
/**
* Add a factory state listener on the current factory.
- * @param l : the listener to add
+ * @param listener : the listener to add
*/
- void addFactoryStateListener(FactoryStateListener l);
+ void addFactoryStateListener(FactoryStateListener listener);
/**
* Remove the given factory state listener from the listener list.
- * @param l : the listener to remove
+ * @param listener : the listener to remove
*/
- void removeFactoryStateListener(FactoryStateListener l);
+ void removeFactoryStateListener(FactoryStateListener listener);
/**
* Get the list of missing handlers.
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/FieldInterceptor.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/FieldInterceptor.java
new file mode 100644
index 0000000..d8d4823
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/FieldInterceptor.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+* Field interceptor.
+* A class implementing this interface is able to be notified of field accesses.
+* The listener need to be register on the instance manager.
+*
+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+*/
+public interface FieldInterceptor {
+
+ /**
+ * This method is called when a PUTFIELD operation is detected.
+ * @param pojo : the pojo object setting the value
+ * @param fieldName : the field name
+ * @param value : the value passed to the field
+ */
+ void onSet(Object pojo, String fieldName, Object value);
+
+ /**
+ * This method is called when a GETFIELD operation is detected.
+ * @param pojo : the pojo object getting the value
+ * @param fieldName : the field name
+ * @param value : the value passed to the field (by the previous call)
+ * @return : the managed value of the field
+ */
+ Object onGet(Object pojo, String fieldName, Object value);
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
index 48cb786..42107af 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
@@ -20,7 +20,7 @@
import java.util.Dictionary;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.Logger;
@@ -31,17 +31,17 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public abstract class Handler {
-
+
/**
* Handler namespace property.
*/
public static final String HANDLER_NAMESPACE_PROPERTY = "handler.namespace";
-
+
/**
* Handler name property.
*/
public static final String HANDLER_NAME_PROPERTY = "handler.name";
-
+
/**
* Handler type property.
*/
@@ -51,39 +51,73 @@
* Handler priority.
*/
public static final String HANDLER_LEVEL_PROPERTY = "handler.level";
-
+
/**
- * Handler logger.
+ * Handler validity.
*/
- private Logger m_logger;
-
+ protected boolean m_isValid = true;
+
/**
- * Set the logger use by this handler.
- * @param logger : the logger object to use.
+ * HandlerManager managing the current handler.
*/
- final void setLogger(Logger logger) {
- m_logger = logger;
- }
-
+ protected HandlerManager m_instance;
+
/**
- * Log method.
- * @param level : message level (Logger class constant)
+ * Set the factory attached to this handler object.
+ * This method must be override to depend on each component factory type.
+ * @param factory : the factory.
+ */
+ public abstract void setFactory(Factory factory);
+
+ /**
+ * Get the logger to use in the handler.
+ * This method must be override to depend on each component factory type logging policy.
+ * @return the logger.
+ */
+ public abstract Logger getLogger();
+
+ /**
+ * Log method (warning).
* @param message : message to log
*/
- public final void log(int level, String message) {
- m_logger.log(level, message);
+ public final void warn(String message) {
+ getLogger().log(Logger.WARNING, message);
}
-
+
/**
- * Log method.
- * @param level : message level (Logger class constant)
+ * Log method (error).
* @param message : message to log
- * @param ex : exception to attach to the message
*/
- public final void log(int level, String message, Throwable ex) {
- m_logger.log(level, message, ex);
+ public final void error(String message) {
+ getLogger().log(Logger.ERROR, message);
}
-
+
+ /**
+ * Log method (info).
+ * @param message : message to log
+ */
+ public final void info(String message) {
+ getLogger().log(Logger.INFO, message);
+ }
+
+ /**
+ * Log method (warning).
+ * @param message : message to log
+ * @param exception : exception to attach to the message
+ */
+ public final void warn(String message, Throwable exception) {
+ getLogger().log(Logger.WARNING, message, exception);
+ }
+
+ /**
+ * Log method (error).
+ * @param message : message to log
+ * @param exception : exception to attach to the message
+ */
+ public final void error(String message, Throwable exception) {
+ getLogger().log(Logger.ERROR, message, exception);
+ }
+
/**
* Get a plugged handler of the same container.
* This method must be call only in the start method (or after).
@@ -93,41 +127,65 @@
* @return the handler object or null if the handler is not found.
*/
public abstract Handler getHandler(String name);
-
+
/**
* Attach the current handler object to the given component instance.
* An attached handler becomes a part of the instance container.
- * @param ci : the component instance on which the current handler will be attached.
+ * @param instance : the component instance on which the current handler will be attached.
*/
- protected abstract void attach(ComponentInstance ci);
-
+ protected abstract void attach(ComponentInstance instance);
+
/**
* Check if the current handler is valid.
+ * This check test the handlers validity.
* This method must not be override.
* @return true if the handler is valid.
*/
public final boolean isValid() {
return ((Pojo) this).getComponentInstance().getState() == ComponentInstance.VALID;
}
-
-
+
+ /**
+ * Set the validity of the current handler.
+ * @param isValid : if true the handler becomes valid, else it becomes invalid.
+ */
+ public final void setValidity(boolean isValid) {
+ if (m_isValid != isValid) {
+ m_isValid = isValid;
+ HandlerManager instance = getHandlerManager();
+ if (isValid) {
+ instance.stateChanged(instance, ComponentInstance.VALID);
+ } else {
+ instance.stateChanged(instance, ComponentInstance.INVALID);
+ }
+ }
+ }
+
+ public final boolean getValidity() {
+ return m_isValid;
+ }
+
/**
* Get the component instance of the current handler.
* @return : the component instance.
*/
- public final ComponentInstance getInstance() {
- return ((Pojo) this).getComponentInstance();
+ public final HandlerManager getHandlerManager() {
+ if (m_instance != null) { return m_instance; }
+ m_instance = (HandlerManager) ((Pojo) this).getComponentInstance();
+ return m_instance;
}
-
+
/**
* Initialize component factory.
* This method aims to gather component factory properties. Each handler wanting to contribute need to override this
* method and add properties to the given component description.
- * @param cd : component description.
+ * @param typeDesc : component description.
* @param metadata : component type metadata.
* @throws ConfigurationException : if the metadata are not correct (early detection).
*/
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException { }
+ public void initializeComponentFactory(ComponentTypeDescription typeDesc, Element metadata) throws ConfigurationException {
+ // The default implementation does nothing.
+ }
/**
* Configure the handler.
@@ -151,7 +209,9 @@
* This method is called when the component state changed.
* @param state : the new state
*/
- public void stateChanged(int state) { }
+ public void stateChanged(int state) {
+ // The default implementation does nothing.
+ }
/**
* Return the current handler description.
@@ -166,5 +226,7 @@
* The instance is reconfiguring.
* @param configuration : New instance configuration.
*/
- public void reconfigure(Dictionary configuration) { }
+ public void reconfigure(Dictionary configuration) {
+ // The default implementation does nothing.
+ }
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
index 04bc706..08bff14 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
@@ -18,20 +18,12 @@
*/
package org.apache.felix.ipojo;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Dictionary;
-import java.util.Iterator;
-import java.util.List;
import java.util.Properties;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.Tracker;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceRegistration;
/**
* The component factory manages component instance objects. This management
@@ -43,20 +35,20 @@
public class HandlerFactory extends ComponentFactory implements Factory {
/**
- * Service Registration of this factory (Factory & ManagedServiceFactory).
+ * iPOJO Default Namespace.
*/
- private ServiceRegistration m_sr;
-
+ public static final String IPOJO_NAMESPACE = "org.apache.felix.ipojo";
+
/**
* Handler type (composite|primitive).
* Default: handler.
*/
private String m_type = "primitive";
-
+
/**
* Default iPOJO Namespace.
*/
- private String m_namespace = IPojoConfiguration.IPOJO_NAMESPACE;
+ private String m_namespace = IPOJO_NAMESPACE;
/**
* Get the handler start level.
@@ -67,114 +59,67 @@
/**
* Create a composite factory.
- * @param bc : bundle context
- * @param cm : metadata of the component to create
+ * @param context : bundle context
+ * @param metadata : metadata of the component to create
+ * @throws ConfigurationException occurs when the element describing the factory is malformed.
*/
- public HandlerFactory(BundleContext bc, Element cm) {
- super(bc, cm);
-
+ public HandlerFactory(BundleContext context, Element metadata) throws ConfigurationException {
+ super(context, metadata);
+
// Get the name
- m_factoryName = cm.getAttribute("name").toLowerCase();
- if (m_factoryName == null) {
- System.err.println("An Handler needs a name");
- return;
- }
-
+ m_factoryName = metadata.getAttribute("name");
+ if (m_factoryName == null) { throw new ConfigurationException("An Handler needs a name"); }
+
// Get the type
- String t = cm.getAttribute("type");
- if (t != null) {
- m_type = t;
+ String type = metadata.getAttribute("type");
+ if (type != null) {
+ m_type = type;
}
-
- String l = cm.getAttribute("level");
- if (l != null) {
- m_level = new Integer(l).intValue();
+
+ String level = metadata.getAttribute("level");
+ if (level != null) {
+ m_level = new Integer(level).intValue();
}
-
+
// Get the namespace
- String ns = cm.getAttribute("namespace");
- if (ns != null) {
- m_namespace = ns.toLowerCase();
- }
+ String namespace = metadata.getAttribute("namespace");
+ if (namespace != null) {
+ m_namespace = namespace.toLowerCase();
+ }
}
-
+
public String getNamespace() {
return m_namespace;
}
-
+
public String getHandlerName() {
return m_namespace + ":" + getName();
}
-
+
public String getType() {
return m_type;
}
-
+
public int getStartLevel() {
return m_level;
}
- /**
- * Start all the instance managers.
- */
- public synchronized void start() {
- if (m_sr != null) { // Already started.
- return;
- }
-
- if (m_handlerIdentifiers.size() != 0) {
- try {
- String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")"
- + "(factory.state=1)"
- + ")";
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
- } catch (InvalidSyntaxException e) {
- m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
- stop();
- return;
- }
- }
-
- try {
- computeFactoryState();
- } catch (ConfigurationException e) {
- m_logger.log(Logger.ERROR, "Cannot initilize the factory " + e.getMessage());
- stop();
- return;
- }
-
- // Exposition of the factory service (always public for handlers)
- m_sr = m_context.registerService(new String[] { Factory.class.getName()}, this, getProperties());
+ public ComponentTypeDescription getComponentTypeDescription() {
+ return new HandlerTypeDescription(this);
}
-
+
/**
* Stop the factory.
* This method does not disposed created instances.
* These instances will be disposed by the instance managers.
*/
- public synchronized void stop() {
- if (m_sr != null) {
- m_sr.unregister();
- m_sr = null;
- }
-
+ public synchronized void stopping() {
if (m_tracker != null) {
m_tracker.close();
m_tracker = null;
}
-
- // Release each handler
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
- }
-
- m_handlerIdentifiers.clear();
- m_listeners.clear();
- m_state = INVALID;
}
-
-
+
/**
* Compute factory service properties.
* This method add three mandatory handler factory properties (name, namespace and type)
@@ -183,164 +128,53 @@
*/
protected Properties getProperties() {
Properties props = new Properties();
-
- // Add factory state
- props.put("factory.state", "" + m_state);
- props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);
- props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);
- props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);
- if (m_level != Integer.MAX_VALUE) {
- props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));
- }
-
return props;
}
-
- /**
- * Compute handler factory state.
- * @throws ConfigurationException : occurs when an handler cannot be initialized.
- */
- protected void computeFactoryState() throws ConfigurationException {
- boolean isValid = true;
- for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- isValid = hi.getReference() != null;
- }
-
- if (isValid) {
- if (m_state == INVALID) {
- m_state = VALID;
-
- if (m_sr == null) {
- m_componentDesc = new ComponentDescription(this);
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- HandlerManager hm = getHandlerInstance(hi, null);
- hm.getHandler();
- Handler ch = hm.getHandler();
- ch.setLogger(getLogger());
- ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
- ((Pojo) ch).getComponentInstance().dispose();
- }
- }
-
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
- }
- return;
- }
- } else {
- if (m_state == VALID) {
- m_state = INVALID;
-
- // Notify listeners.
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
- }
- // Dispose created instances.
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- InstanceManager ci = (InstanceManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
- }
- m_instancesName.remove(ci.m_name);
- }
-
- m_componentInstances.clear();
-
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
-
- return;
- }
- }
- }
-
/**
* Create an instance. The given configuration needs to contain the 'name'
* property.
* @param configuration : configuration of the created instance.
- * @param serviceContext : the service context to push for this instance.
+ * @param context : the service context to push for this instance.
+ * @param handlers : handler array to used.
* @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
* not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
* @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
* @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
*/
- public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
- if (m_state == Factory.INVALID) {
- throw new MissingHandlerException(getMissingHandlers());
- }
-
- if (configuration == null) {
- configuration = new Properties();
- }
-
- String in = null;
- if (configuration.get("name") != null) {
- in = (String) configuration.get("name");
- } else {
- in = generateName();
- configuration.put("name", in);
- }
-
- if (m_instancesName.contains(in)) {
- throw new UnacceptableConfiguration("Name already used : " + in);
- } else {
- m_instancesName.add(in);
- }
-
- BundleContext context = null;
- if (serviceContext == null) {
- context = new IPojoContext(m_context);
- } else {
- context = new IPojoContext(m_context, serviceContext);
- }
- List handlers = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- handlers.add(getHandlerInstance(hi, serviceContext));
- }
-
- HandlerManager instance = new HandlerManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[handlers.size()]));
+ public ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws ConfigurationException {
+ HandlerManager instance = new HandlerManager(this, context, handlers);
instance.configure(m_componentMetadata, configuration);
-
- m_componentInstances.put(in, instance);
-
-
return instance;
}
-
- /**
- * Return an handler object.
- * @param hi : handler to create.
- * @param sc : service context in which create the handler (instance context).
- * @return the Handler object.
- */
- private HandlerManager getHandlerInstance(HandlerIdentifier hi, ServiceContext sc) {
- try {
- return (HandlerManager) hi.getFactory().createComponentInstance(null, sc);
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed: " + e.getMessage());
- stop();
- return null;
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
- stop();
- return null;
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The configuration of the handler " + hi.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
- stop();
- return null;
+
+ private class HandlerTypeDescription extends ComponentTypeDescription {
+
+ /**
+ * Constructor.
+ * @param factory : factory.
+ */
+ public HandlerTypeDescription(Factory factory) {
+ super(factory);
+ }
+
+ /**
+ * Add properties to publish :
+ * handler.name, handler.namespace, handler.type and handler.level if the level is not Integer.MAX.
+ * @return return the dictionary to publish.
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+ */
+ public Dictionary getPropertiesToPublish() {
+ Dictionary props = super.getPropertiesToPublish();
+
+ props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);
+ props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);
+ props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);
+ if (m_level != Integer.MAX_VALUE) {
+ props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));
+ }
+ return props;
}
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
index 7754ef5..e2f4003 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
@@ -24,12 +24,12 @@
import org.osgi.framework.BundleContext;
/**
-* The handler manager manages an handler instance.
-*
-* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
-*/
+ * The handler manager manages an handler instance.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
public class HandlerManager extends InstanceManager {
-
+
/**
* Handler object (contained).
*/
@@ -38,13 +38,13 @@
/**
* Constructor.
* @param factory : handler factory
- * @param bc : bundle context
+ * @param context : bundle context
* @param handlers : handler array
*/
- public HandlerManager(ComponentFactory factory, BundleContext bc, HandlerManager[] handlers) {
- super(factory, bc, handlers);
+ public HandlerManager(ComponentFactory factory, BundleContext context, HandlerManager[] handlers) {
+ super(factory, context, handlers);
}
-
+
/**
* Get the contained handler object.
* If not already created it creates the object.
@@ -56,73 +56,68 @@
}
return m_handler;
}
-
+
/**
* Create and initialize the handler object.
- * @param ci : component instance on which the handler will be attached.
- * @param cm : component metadata.
+ * @param instance : component instance on which the handler will be attached.
+ * @param metadata : component metadata.
* @param configuration : instance configuration.
* @throws ConfigurationException if the handler configuration failed.
*/
- public void init(ComponentInstance ci, Element cm, Dictionary configuration) throws ConfigurationException {
+ public void init(ComponentInstance instance, Element metadata, Dictionary configuration) throws ConfigurationException {
createHandlerObject();
- m_handler.attach(ci);
- m_handler.configure(cm, configuration);
+ m_handler.setFactory(instance.getFactory());
+ m_handler.attach(instance);
+ m_handler.configure(metadata, configuration);
}
-
+
/**
* Create the handler object.
* This method does nothing if the object is already created.
*/
private void createHandlerObject() {
if (m_handler != null) { return; }
- Handler h = (Handler) createPojoObject();
- if (h instanceof PrimitiveHandler) {
- m_handler = (PrimitiveHandler) h;
- } else {
- m_handler = (CompositeHandler) h;
- }
+ m_handler = (Handler) createPojoObject();
}
-
+
/**
* Start the instance manager.
*/
public synchronized void start() {
- if (m_state != STOPPED) {
- return;
- } // Instance already started
+ if (m_state != STOPPED) { return; } // Instance already started
for (int i = 0; i < m_handlers.length; i++) {
m_handlers[i].addInstanceStateListener(this);
m_handlers[i].start();
}
-
+
m_handler.start(); // Call the handler start method.
-
+
for (int i = 0; i < m_handlers.length; i++) {
- if (! m_handlers[i].getHandler().isValid()) {
+ if (!m_handlers[i].getHandler().isValid()) {
setState(INVALID);
return;
}
}
- setState(VALID);
+ if (m_handler.getValidity()) {
+ setState(VALID);
+ } else {
+ setState(INVALID);
+ }
}
-
+
/**
* Stop the instance manager.
*/
public synchronized void stop() {
- if (m_state == STOPPED) {
- return;
- } // Instance already stopped
-
+ if (m_state == STOPPED) { return; } // Instance already stopped
setState(INVALID);
-
+
if (m_handler != null) {
m_handler.stop();
}
-
+
// Stop all the handlers
for (int i = m_handlers.length - 1; i > -1; i--) {
m_handlers[i].removeInstanceStateListener(this);
@@ -130,13 +125,13 @@
}
m_state = STOPPED;
- if (m_instanceListeners != null) {
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
+ if (m_listeners != null) {
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, STOPPED);
}
}
}
-
+
/**
* Dispose the instance.
* @see org.apache.felix.ipojo.ComponentInstance#dispose()
@@ -145,7 +140,7 @@
super.dispose();
m_handler = null;
}
-
+
/**
* Kill the current instance.
* Only the factory of this instance can call this method.
@@ -155,4 +150,31 @@
m_handler = null;
}
+ /**
+ * State Change listener callback.
+ * This method is notified at each time a plugged handler becomes invalid.
+ * @param instance : changing instance
+ * @param newState : new state
+ * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
+ */
+ public synchronized void stateChanged(ComponentInstance instance, int newState) {
+ if (m_state <= STOPPED) { return; }
+
+ // Update the component state if necessary
+ if (newState == INVALID && m_state == VALID) {
+ // Need to update the state to UNRESOLVED
+ setState(INVALID);
+ return;
+ }
+ if (newState == VALID && m_state == INVALID) {
+ // An handler becomes valid => check if all handlers are valid
+ if (!m_handler.getValidity()) { return; }
+ for (int i = 0; i < m_handlers.length; i++) {
+ if (m_handlers[i].getState() != VALID) { return; }
+ }
+ setState(VALID);
+ return;
+ }
+ }
+
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
deleted file mode 100644
index 78d3434..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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;
-
-import org.apache.felix.ipojo.composite.instance.InstanceHandler;
-import org.apache.felix.ipojo.composite.service.importer.ImportHandler;
-import org.apache.felix.ipojo.composite.service.instantiator.ServiceInstantiatorHandler;
-import org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler;
-import org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler;
-import org.apache.felix.ipojo.handlers.dependency.DependencyHandler;
-import org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler;
-import org.apache.felix.ipojo.handlers.lifecycle.controller.ControllerHandler;
-import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler;
-import org.apache.felix.ipojo.util.Logger;
-
-/**
- * iPOJO Configuration : Default Log Level - Available (core) handlers.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class IPojoConfiguration {
-
- /**
- * iPOJO logger log level.
- */
- public static final int LOG_LEVEL = Logger.WARNING;
-
-
- /**
- * iPOJO Default Namespace.
- */
- public static final String IPOJO_NAMESPACE = "org.apache.felix.ipojo";
-
- /**
- * Available handlers in the iPOJO bundle.
- */
- public static final Class[] INTERNAL_HANDLERS = new Class[] {
- DependencyHandler.class,
- ProvidedServiceHandler.class,
- ConfigurationHandler.class,
- LifecycleCallbackHandler.class,
- ControllerHandler.class,
- ArchitectureHandler.class
- };
-
- /**
- * Available composite handlers in the iPOJO bundle.
- */
- public static final Class[] INTERNAL_COMPOSITE_HANDLERS = new Class[] {
- ServiceInstantiatorHandler.class,
- ImportHandler.class,
- InstanceHandler.class,
- org.apache.felix.ipojo.composite.service.provides.ProvidedServiceHandler.class,
- org.apache.felix.ipojo.composite.architecture.ArchitectureHandler.class
- };
-
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java
index a1e2e53..09bfcdf 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java
@@ -54,25 +54,24 @@
/**
* Constructor. Used when the service context = the bundle context
*
- * @param bc : bundle context
+ * @param context : bundle context
*/
- public IPojoContext(BundleContext bc) {
- m_bundleContext = bc;
+ public IPojoContext(BundleContext context) {
+ m_bundleContext = context;
}
/**
* Constructor. Used when the service context and the bundle context are
* different
*
- * @param bc : bundle context
- * @param sc : service context
+ * @param bundleContext : bundle context
+ * @param serviceContext : service context
*/
- public IPojoContext(BundleContext bc, ServiceContext sc) {
- m_bundleContext = bc;
- m_serviceContext = sc;
+ public IPojoContext(BundleContext bundleContext, ServiceContext serviceContext) {
+ m_bundleContext = bundleContext;
+ m_serviceContext = serviceContext;
}
-
/**
* Add a bundle listener.
* @param listener : the listener to add
@@ -119,7 +118,6 @@
}
}
-
/**
* Create a Filter object.
* @param filter : the string form of the LDAP filter to create
@@ -158,12 +156,12 @@
/**
* Get the bundle object with the given id.
- * @param id : bundle id
+ * @param bundleId : bundle id
* @return the bundle object
* @see org.osgi.framework.BundleContext#getBundle(long)
*/
- public Bundle getBundle(long id) {
- return m_bundleContext.getBundle(id);
+ public Bundle getBundle(long bundleId) {
+ return m_bundleContext.getBundle(bundleId);
}
/**
@@ -175,7 +173,6 @@
return m_bundleContext.getBundles();
}
-
/**
* Get a data file.
* @param filename : File name.
@@ -340,7 +337,7 @@
return m_serviceContext.ungetService(reference);
}
}
-
+
/**
* Get the global context, i.e. the bundle context of the factory.
* @return the global bundle context.
@@ -348,15 +345,12 @@
public BundleContext getGlobalContext() {
return m_bundleContext;
}
-
+
/**
* Get the service context, i.e. the composite context.
* @return the service context.
*/
public ServiceContext getServiceContext() {
- if (m_serviceContext == null) {
- return this;
- }
return m_serviceContext;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
new file mode 100644
index 0000000..44ae438
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
@@ -0,0 +1,829 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * This class abstracts iPOJO factories.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class IPojoFactory implements Factory, ManagedServiceFactory {
+
+ /**
+ * List of the managed instance name. This list is shared by all factories.
+ */
+ protected static List m_instancesName = new ArrayList();
+
+ /**
+ * Component-Type description exposed by the factory service.
+ */
+ protected ComponentTypeDescription m_componentDesc;
+
+ /**
+ * List of the managed instance managers. The key of this map is the name (i.e. instance names) of the created instance
+ */
+ protected Map m_componentInstances = new HashMap();
+
+ /**
+ * Component Type provided by this factory.
+ */
+ protected Element m_componentMetadata;
+
+ /**
+ * The bundle context reference.
+ */
+ protected BundleContext m_context = null;
+
+ /**
+ * Factory Name. Could be the component class name if the factory name is not set.
+ */
+ protected String m_factoryName;
+
+ /**
+ * List of required handler.
+ */
+ protected List m_requiredHandlers = new ArrayList();
+
+ /**
+ * List of listeners.
+ */
+ protected List m_listeners = new ArrayList(2);
+
+ /**
+ * Logger for the factory (and all component instance).
+ */
+ protected Logger m_logger;
+
+ /**
+ * Is the factory public (expose as a service).
+ */
+ protected boolean m_isPublic;
+
+ /**
+ * Service Registration of this factory (Factory & ManagedServiceFactory).
+ */
+ protected ServiceRegistration m_sr;
+
+ /**
+ * Factory state.
+ */
+ protected int m_state = Factory.INVALID;
+
+ /**
+ * Index used to generate instance name if not set.
+ */
+ private long m_index = 0;
+
+ /**
+ * Flag indicating if this factory has already a computed description or not.
+ */
+ private boolean m_described;
+
+ /**
+ * Constructor.
+ * @param context : bundle context of the bundle containing the factory.
+ * @param metadata : description of the component type.
+ * @throws ConfigurationException occurs when the element describing the factory is malformed.
+ */
+ public IPojoFactory(BundleContext context, Element metadata) throws ConfigurationException {
+ m_context = context;
+ m_componentMetadata = metadata;
+ m_factoryName = getFactoryName();
+ String fac = metadata.getAttribute("factory");
+ m_isPublic = fac == null || !fac.equalsIgnoreCase("false");
+ m_logger = new Logger(m_context, m_factoryName);
+ m_requiredHandlers = getRequiredHandlerList();
+ }
+
+ public ComponentTypeDescription getComponentTypeDescription() {
+ return new ComponentTypeDescription(this);
+ }
+
+ /**
+ * Add a factory listener.
+ * @param listener : the factory listener to add.
+ * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
+ */
+ public void addFactoryStateListener(FactoryStateListener listener) {
+ synchronized (m_listeners) {
+ m_listeners.add(listener);
+ }
+ }
+
+ /**
+ * Get the logger used by instances of he current factory.
+ * @return the factory logger.
+ */
+ public Logger getLogger() {
+ return m_logger;
+ }
+
+ /**
+ * Compute the factory name.
+ * @return the factory name.
+ */
+ public abstract String getFactoryName();
+
+ /**
+ * Compute the required handler list.
+ * @return the required handler list
+ */
+ public abstract List getRequiredHandlerList();
+
+ /**
+ * Create an instance.
+ * @param config : instance configuration
+ * @param context : ipojo context to use
+ * @param handlers : handler array to use
+ * @return the new component instance.
+ * @throws ConfigurationException : occurs when the instance creation failed during the configuration process.
+ */
+ public abstract ComponentInstance createInstance(Dictionary config, IPojoContext context, HandlerManager[] handlers)
+ throws ConfigurationException;
+
+ /**
+ * Create an instance. The given configuration needs to contain the 'name' property.
+ * @param configuration : configuration of the created instance.
+ * @return the created component instance.
+ * @throws UnacceptableConfiguration : occurs if the given configuration is not consistent with the component type of this factory.
+ * @throws MissingHandlerException : occurs if an handler is unavailable when the instance is created.
+ * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
+ * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+ */
+ public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException,
+ ConfigurationException {
+ return createComponentInstance(configuration, null);
+ }
+
+ /**
+ * Create an instance. The given configuration needs to contain the 'name' property.
+ * @param configuration : configuration of the created instance.
+ * @param serviceContext : the service context to push for this instance.
+ * @return the created component instance.
+ * @throws UnacceptableConfiguration : occurs if the given configuration is not consistent with the component type of this factory.
+ * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
+ * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
+ * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+ */
+ public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, // NOPMD
+ MissingHandlerException, ConfigurationException {
+ if (configuration == null) {
+ configuration = new Properties();
+ }
+
+ try {
+ checkAcceptability(configuration);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+ throw new UnacceptableConfiguration("The configuration "
+ + configuration
+ + " is not acceptable for "
+ + m_factoryName
+ + ": "
+ + e.getMessage());
+ }
+
+ String name = null;
+ if (configuration.get("name") == null) {
+ name = generateName();
+ configuration.put("name", name);
+ } else {
+ name = (String) configuration.get("name");
+ if (m_instancesName.contains(name)) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : Name already used");
+ throw new UnacceptableConfiguration("Name already used : " + name);
+ }
+ }
+
+ IPojoContext context = null;
+ if (serviceContext == null) {
+ context = new IPojoContext(m_context);
+ } else {
+ context = new IPojoContext(m_context, serviceContext);
+ }
+
+ HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];
+ for (int i = 0; i < handlers.length; i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ handlers[i] = getHandler(req, serviceContext);
+ }
+ try {
+ ComponentInstance instance = createInstance(configuration, context, handlers);
+ m_instancesName.add(name);
+ m_componentInstances.put(name, instance);
+ return instance;
+ } catch (ConfigurationException e) {
+ m_logger.log(Logger.ERROR, e.getMessage());
+ throw new ConfigurationException(e.getMessage(), m_factoryName);
+ }
+ }
+
+ public BundleContext getBundleContext() {
+ return m_context;
+ }
+
+ /**
+ * Get the factory class name.
+ * @return the factory classname.
+ * @see org.apache.felix.ipojo.Factory#getClassName()
+ */
+ public abstract String getClassName();
+
+ /**
+ * Get the component type description.
+ * @return the component type description object. Null if not already computed.
+ */
+ public ComponentTypeDescription getComponentDescription() {
+ return m_componentDesc;
+ }
+
+ /**
+ * Get the component type description (Element-Attribute form).
+ * @return the component type description.
+ * @see org.apache.felix.ipojo.Factory#getDescription()
+ */
+ public Element getDescription() {
+ if (m_componentDesc == null) {
+ return new Element("No description available for " + m_factoryName, "");
+ }
+ return m_componentDesc.getDescription();
+ }
+
+ /**
+ * Compute the list of missing handlers.
+ * @return list of missing handlers.
+ * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
+ */
+ public List getMissingHandlers() {
+ List list = new ArrayList();
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ if (req.getReference() == null) {
+ list.add(req.getFullName());
+ }
+ }
+ return list;
+ }
+
+ public String getName() {
+ return m_factoryName;
+ }
+
+ /**
+ * Get the list of required handlers.
+ * @return list of required handlers.
+ * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
+ */
+ public List getRequiredHandlers() {
+ List list = new ArrayList();
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ list.add(req.getFullName());
+ }
+ return list;
+ }
+
+ public int getState() {
+ return m_state;
+ }
+
+ /**
+ * Check if the configuration is acceptable.
+ * @param conf : the configuration to test.
+ * @return true if the configuration is acceptable.
+ * @see org.apache.felix.ipojo.Factory#isAcceptable(java.util.Dictionary)
+ */
+ public boolean isAcceptable(Dictionary conf) {
+ try {
+ checkAcceptability(conf);
+ } catch (MissingHandlerException e) {
+ return false;
+ } catch (UnacceptableConfiguration e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if the configuration is acceptable.
+ * @param conf : the configuration to test.
+ * @throws UnacceptableConfiguration occurs if the configuration is unacceptable.
+ * @throws MissingHandlerException occurs if an handler is missing.
+ */
+ public void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
+ if (m_state == Factory.INVALID) {
+ throw new MissingHandlerException(getMissingHandlers());
+ }
+
+ // Check that the configuration does not override immutable properties.
+ PropertyDescription[] props = m_componentDesc.getProperties();
+ for (int i = 0; i < props.length; i++) {
+ // Is the property immutable
+ if (props[i].isImmutable() && conf.get(props[i].getName()) != null) {
+ throw new UnacceptableConfiguration("The property " + props[i] + " cannot be overide : immutable property"); // The instance
+ // configuration try
+ // to override an
+ // immutable property.
+ }
+ // Is the property required.
+ if (props[i].getValue() == null && conf.get(props[i].getName()) == null) {
+ throw new UnacceptableConfiguration("The property " + props[i].getName() + " is missing"); // The property must be set.
+ }
+ }
+ }
+
+ /**
+ * Reconfigure an existing instance.
+ * @param properties : the new configuration to push.
+ * @throws UnacceptableConfiguration : occurs if the new configuration is not consistent with the component type.
+ * @throws MissingHandlerException : occurs if the current factory is not valid.
+ * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
+ */
+ public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
+ if (properties == null || properties.get("name") == null) {
+ throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
+ }
+ String name = (String) properties.get("name");
+ ComponentInstance instance = (ComponentInstance) m_componentInstances.get(name);
+
+ if (instance == null) {
+ return; // The instance does not exist.
+ } else {
+ checkAcceptability(properties); // Test if the configuration is acceptable
+ instance.reconfigure(properties); // re-configure the component
+ }
+ }
+
+ /**
+ * Remove a factory listener.
+ * @param listener : the factory listener to remove.
+ * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
+ */
+ public void removeFactoryStateListener(FactoryStateListener listener) {
+ synchronized (m_listeners) {
+ m_listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Stopping method. This method is call when the factory is stopping.
+ */
+ public abstract void stopping();
+
+ /**
+ * Stop all the instance managers.
+ */
+ public synchronized void stop() {
+ if (m_sr != null) {
+ m_sr.unregister();
+ m_sr = null;
+ }
+
+ stopping();
+
+ if (m_state == VALID) {
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ }
+ }
+ m_state = INVALID;
+
+ // Dispose created instances.
+ Set col = m_componentInstances.keySet();
+ String[] keys = (String[]) col.toArray(new String[col.size()]);
+ for (int i = 0; i < keys.length; i++) {
+ ComponentInstance instance = (ComponentInstance) m_componentInstances.get(keys[i]);
+ if (instance.getState() != ComponentInstance.DISPOSED) {
+ instance.dispose();
+ }
+ }
+
+ // Release each handler
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ ((RequiredHandler) m_requiredHandlers.get(i)).unRef();
+ }
+
+ m_described = false;
+ m_componentDesc = null;
+ m_componentInstances.clear();
+ }
+
+ /**
+ * Destroy the factory. The factory cannot be restarted.
+ * Only the extender can call this method.
+ */
+ void dispose() {
+ stop();
+ m_componentMetadata = null;
+ m_componentInstances = null;
+ m_context = null;
+ m_requiredHandlers = null;
+ m_listeners = null;
+ m_logger = null;
+ }
+
+ /**
+ * Starting method. This method is called when the factory is starting.
+ */
+ public abstract void starting();
+
+ /**
+ * Start the factory.
+ */
+ public synchronized void start() {
+ if (m_described) { // Already started.
+ return;
+ }
+
+ m_componentDesc = getComponentTypeDescription();
+
+ starting();
+
+ computeFactoryState();
+
+ if (m_isPublic) {
+ // Exposition of the factory service
+ m_sr =
+ m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, m_componentDesc
+ .getPropertiesToPublish());
+ }
+ }
+
+ /**
+ * Create of update an instance.
+ * @param name : name of the instance
+ * @param properties : configuration of the instance
+ * @throws org.osgi.service.cm.ConfigurationException : if the configuration is not consistent for this component type
+ * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary)
+ */
+ public synchronized void updated(String name, Dictionary properties) throws org.osgi.service.cm.ConfigurationException {
+ InstanceManager instance = (InstanceManager) m_componentInstances.get(name);
+ if (instance == null) {
+ try {
+ properties.put("name", name); // Add the name in the configuration
+ createComponentInstance(properties);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ } catch (ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ }
+ } else {
+ try {
+ properties.put("name", name); // Add the name in the configuration
+ reconfigure(properties); // re-configure the component
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "The facotry is not valid, at least one handler is missing : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Delete an instance.
+ * @param name : name of the instance to delete
+ * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
+ */
+ public synchronized void deleted(String name) {
+ m_instancesName.remove(name);
+ ComponentInstance instance = (ComponentInstance) m_componentInstances.remove(name);
+ if (instance != null) {
+ instance.dispose();
+ }
+ }
+
+ /**
+ * Callback called by instance when disposed.
+ * @param instance : the destroyed instance
+ */
+ public void disposed(ComponentInstance instance) {
+ String name = instance.getInstanceName();
+ m_instancesName.remove(name);
+ m_componentInstances.remove(name);
+ }
+
+ /**
+ * Compute the component type description. The factory must be valid when calling this method.
+ */
+ protected void computeDescription() {
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ Handler handler = getHandler(req, null).getHandler();
+ try {
+ handler.setFactory(this);
+ handler.initializeComponentFactory(m_componentDesc, m_componentMetadata);
+ ((Pojo) handler).getComponentInstance().dispose();
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ ((Pojo) handler).getComponentInstance().dispose();
+ m_logger.log(Logger.ERROR, e.getMessage());
+ stop();
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Compute factory state.
+ */
+ protected void computeFactoryState() {
+ boolean isValid = true;
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ if (req.getReference() == null) {
+ isValid = false;
+ break;
+ }
+
+ }
+
+ if (isValid) {
+ if (m_state == INVALID) {
+
+ if (!m_described) {
+ computeDescription();
+ m_described = true;
+ }
+
+ m_state = VALID;
+ if (m_sr != null) {
+ m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
+ }
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
+ }
+ return;
+ }
+ } else {
+ if (m_state == VALID) {
+ m_state = INVALID;
+
+ // Notify listeners.
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ }
+
+ // Dispose created instances.
+ Set col = m_componentInstances.keySet();
+ String[] keys = (String[]) col.toArray(new String[col.size()]);
+ for (int i = 0; i < keys.length; i++) {
+ ComponentInstance instance = (ComponentInstance) m_componentInstances.get(keys[i]);
+ if (instance.getState() != ComponentInstance.DISPOSED) {
+ instance.dispose();
+ }
+ m_instancesName.remove(instance.getInstanceName());
+ }
+
+ m_componentInstances.clear();
+
+ if (m_sr != null) {
+ m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
+ }
+
+ return;
+ }
+ }
+ }
+
+ /**
+ * Check if the given handler identifier and the service reference can match.
+ * @param req : the handler identifier.
+ * @param ref : the service reference.
+ * @return true if the service reference can fulfill the handler requirement
+ */
+ protected boolean match(RequiredHandler req, ServiceReference ref) {
+ String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
+ String namespace = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
+ if (HandlerFactory.IPOJO_NAMESPACE.equals(namespace)) {
+ return name.equals(req.getName()) && req.getNamespace() == null;
+ }
+ return name.equals(req.getName()) && namespace.equals(req.getNamespace());
+ }
+
+ /**
+ * Return the handler object for the given required handler. The handler is instantiated in the given service context.
+ * @param req : handler to create.
+ * @param context : service context in which create the handler (instance context).
+ * @return the Handler object.
+ */
+ protected HandlerManager getHandler(RequiredHandler req, ServiceContext context) {
+ try {
+ return (HandlerManager) req.getFactory().createComponentInstance(null, context);
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "The creation of the handler " + req.getFullName() + " has failed: " + e.getMessage());
+ stop();
+ return null;
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The creation of the handler "
+ + req.getFullName()
+ + " has failed (UnacceptableConfiguration): "
+ + e.getMessage());
+ stop();
+ return null;
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The configuration of the handler "
+ + req.getFullName()
+ + " has failed (ConfigurationException): "
+ + e.getMessage());
+ stop();
+ return null;
+ }
+ }
+
+ /**
+ * Helping method generating a new unique name.
+ * @return an non already used name
+ */
+ protected synchronized String generateName() {
+ String name = m_factoryName + "-" + m_index;
+ while (m_instancesName.contains(name)) {
+ m_index = m_index + 1;
+ name = m_factoryName + "-" + m_index;
+ }
+ return name;
+ }
+
+ /**
+ * Structure storing required handlers.
+ */
+ protected class RequiredHandler implements Comparable {
+ /**
+ * Factory to create this handler.
+ */
+ private HandlerFactory m_factory;
+
+ /**
+ * Handler name.
+ */
+ private String m_name;
+
+ /**
+ * Handler start level.
+ */
+ private int m_level = Integer.MAX_VALUE;
+
+ /**
+ * Handler namespace.
+ */
+ private String m_namespace;
+
+ /**
+ * Service Reference of the handler factory.
+ */
+ private ServiceReference m_reference;
+
+ /**
+ * Constructor.
+ * @param name : handler name.
+ * @param namespace : handler namespace.
+ */
+ public RequiredHandler(String name, String namespace) {
+ m_name = name;
+ m_namespace = namespace;
+ }
+
+ /**
+ * Equals method. Two handlers are equals if they have same name and namespace or they share the same service reference.
+ * @param object : object to compare to the current object.
+ * @return : true if the two compared object are equals
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object object) {
+ if (object instanceof RequiredHandler) {
+ RequiredHandler req = (RequiredHandler) object;
+ if (m_namespace == null) {
+ return req.m_name.equalsIgnoreCase(m_name) && req.m_namespace == null;
+ } else {
+ return req.m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(req.m_namespace);
+ }
+ } else {
+ return false;
+ }
+
+ }
+
+ /**
+ * Get the factory object used for this handler. The object is get when used for the first time.
+ * @return the factory object.
+ */
+ public HandlerFactory getFactory() {
+ if (m_reference == null) {
+ return null;
+ }
+ if (m_factory == null) {
+ m_factory = (HandlerFactory) m_context.getService(getReference());
+ }
+ return m_factory;
+ }
+
+ /**
+ * Get the handler full name (namespace:name).
+ * @return the handler full name
+ */
+ public String getFullName() {
+ if (m_namespace == null) {
+ return HandlerFactory.IPOJO_NAMESPACE + ":" + m_name;
+ } else {
+ return m_namespace + ":" + m_name;
+ }
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public String getNamespace() {
+ return m_namespace;
+ }
+
+ public ServiceReference getReference() {
+ return m_reference;
+ }
+
+ public int getLevel() {
+ return m_level;
+ }
+
+ /**
+ * Release the reference of the used factory.
+ */
+ public void unRef() {
+ if (m_reference != null) {
+ // m_context.ungetService(m_reference); // Will be unget automatically
+ m_factory = null;
+ m_reference = null;
+ }
+ }
+
+ /**
+ * Set the service reference. If the new service reference is null, it unget the used factory (if already get).
+ * @param ref : new service reference.
+ */
+ public void setReference(ServiceReference ref) {
+ m_reference = ref;
+ Integer level = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
+ if (level != null) {
+ m_level = level.intValue();
+ }
+ }
+
+ /**
+ * Start level Comparison. This method is used to sort the handler array.
+ * @param object : object on which compare.
+ * @return -1, 0, +1 according to the comparison of their start level.
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object object) {
+ if (object instanceof RequiredHandler) {
+ RequiredHandler req = (RequiredHandler) object;
+ if (this.m_level == req.m_level) {
+ return 0;
+ } else if (this.m_level < req.m_level) {
+ return -1;
+ } else {
+ return +1;
+ }
+ }
+ return 0;
+ }
+ }
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
index c356b2a..7333161 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
@@ -18,51 +18,238 @@
*/
package org.apache.felix.ipojo;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.Tracker;
-import org.apache.felix.ipojo.util.TrackerCustomizer;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
/**
- * An instance creator aims to create instances and to track their factories.
- * It's allow to create instance from outside factories.
- *
+ * An instance creator aims to create instances and to track their factories. It's allow to create instance from outside factories.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class InstanceCreator implements TrackerCustomizer, FactoryStateListener {
- /**
- * Bundle Context.
- */
- private BundleContext m_context;
+public class InstanceCreator implements FactoryStateListener {
/**
* Logger to log messages if error occurs.
*/
private Logger m_logger;
-
- /**
- * Private factories.
- */
- private ComponentFactory[] m_factories;
/**
- * This structure aims to manage a configuration. It stores all necessary
- * information to create an instance and to track the factory.
+ * Configurations to create and maintains.
*/
- private class ManagedConfiguration {
+ private List m_idle = new ArrayList();
+
+ /**
+ * Map storing created instance. [AbstractFactory, List [ManagedInstance]]
+ */
+ private Map m_attached = new HashMap();
+
+ /**
+ * Abstract Factory list.
+ */
+ private List m_factories = new ArrayList();
+
+ /**
+ * Constructor.
+ * @param context : iPOJO bundle context.
+ */
+ public InstanceCreator(BundleContext context) {
+ m_logger = new Logger(context, "iPOJO Instance Creator");
+ }
+
+ /**
+ * Add an instance to manage.
+ * @param instance : instance configuration
+ * @param bundle : bundle id declaring the instance
+ */
+ synchronized void addInstance(Dictionary instance, long bundle) {
+ ManagedInstance managed = new ManagedInstance(instance, bundle);
+ for (int i = 0; i < m_factories.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) m_factories.get(i);
+ if (factory.getState() == Factory.VALID && managed.match(factory)) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ // Subscribe to the factory state change
+ factory.addFactoryStateListener(this);
+ } else {
+ list.add(managed);
+ }
+ return;
+ }
+ }
+ // If there is no matching factory, add the instance to the idle list
+ m_idle.add(managed);
+ }
+
+ /**
+ * Dispose and stop to manage all instances declared by the given bundle.
+ * @param bundle : bundle.
+ */
+ void removeInstancesFromBundle(long bundle) {
+ // Disposes instance from attached instances
+ Collection col = m_attached.keySet();
+ Iterator iterator = col.iterator();
+ List instanceToRemove = new ArrayList();
+ List factoryToRemove = new ArrayList();
+ while (iterator.hasNext()) {
+ IPojoFactory factory = (IPojoFactory) iterator.next();
+ List list = (List) m_attached.get(factory);
+ for (int i = 0; i < list.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) list.get(i);
+ if (managed.m_bundleId == bundle) {
+ managed.dispose();
+ instanceToRemove.add(managed);
+ }
+ }
+ if (!instanceToRemove.isEmpty()) {
+ list.removeAll(instanceToRemove);
+ if (list.isEmpty()) {
+ factory.removeFactoryStateListener(this);
+ factoryToRemove.add(factory);
+ }
+ }
+ }
+
+ for (int i = 0; i < factoryToRemove.size(); i++) {
+ m_attached.remove(factoryToRemove.get(i));
+ }
+
+ // Delete idle instances
+ instanceToRemove.clear();
+ for (int i = 0; i < m_idle.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+ if (managed.m_bundleId == bundle) {
+ instanceToRemove.add(managed);
+ }
+ }
+ m_idle.removeAll(instanceToRemove);
+ }
+
+ /**
+ * A new factory appears.
+ * @param factory : the new factory.
+ */
+ public synchronized void addFactory(IPojoFactory factory) {
+ List createdInstances = new ArrayList(1);
+ m_factories.add(factory);
+ for (int i = 0; i < m_idle.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+ if (managed.match(factory)) {
+ // We have to subscribe to the factory.
+ factory.addFactoryStateListener(this);
+ if (factory.getState() == Factory.VALID) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ } else {
+ list.add(managed);
+ }
+ createdInstances.add(managed);
+ }
+ }
+ }
+ if (!createdInstances.isEmpty()) {
+ m_idle.removeAll(createdInstances);
+ }
+ }
+
+ /**
+ * A factory is leaving.
+ * @param factory : the leaving factory
+ */
+ void removeFactory(IPojoFactory factory) {
+ factory.removeFactoryStateListener(this);
+ m_factories.remove(factory);
+ onInvalidation(factory);
+ m_attached.remove(factory);
+ }
+
+ /**
+ * The given factory becomes valid.
+ * @param factory : the factory becoming valid.
+ */
+ private void onValidation(IPojoFactory factory) {
+ List toRemove = new ArrayList();
+ for (int i = 0; i < m_idle.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+ if (managed.match(factory)) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ } else {
+ list.add(managed);
+ }
+ toRemove.add(managed);
+ }
+ }
+ if (!toRemove.isEmpty()) {
+ m_idle.removeAll(toRemove);
+ }
+ }
+
+ /**
+ * The given factory becomes invalid.
+ * @param factory : factory which becomes invalid.
+ */
+ private void onInvalidation(IPojoFactory factory) {
+ List instances = (List) m_attached.remove(factory);
+ if (instances != null) {
+ for (int i = 0; i < instances.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) instances.get(i);
+ managed.dispose();
+ m_idle.add(managed);
+ }
+ }
+ }
+
+ /**
+ * Factory state changed method.
+ * @param factory : factory.
+ * @param newState : new state.
+ * @see org.apache.felix.ipojo.FactoryStateListener#stateChanged(org.apache.felix.ipojo.Factory, int)
+ */
+ public void stateChanged(Factory factory, int newState) {
+ if (newState == Factory.VALID) {
+ onValidation((IPojoFactory) factory);
+ } else {
+ onInvalidation((IPojoFactory) factory);
+ }
+ }
+
+ /**
+ * This structure aims to manage a configuration. It stores all necessary information to create an instance and to track the factory.
+ */
+ private class ManagedInstance {
/**
* Configuration of the instance to create.
*/
private Dictionary m_configuration;
/**
- * Factory name.
+ * Bundle which create the instance.
*/
- private String m_factoryName;
+ private long m_bundleId;
+
+ /**
+ * Factory used to create the instance.
+ */
+ private IPojoFactory m_factory;
/**
* Created instance.
@@ -71,27 +258,20 @@
/**
* Constructor.
- *
* @param conf : the configuration to create.
+ * @param bundle : the bundle in which the instance is declared.
*/
- ManagedConfiguration(Dictionary conf) {
+ ManagedInstance(Dictionary conf, long bundle) {
m_configuration = conf;
- }
-
- /**
- * Return the managed configuration.
- * @return the configuration.
- */
- Dictionary getConfiguration() {
- return m_configuration;
+ m_bundleId = bundle;
}
/**
* Return the used factory name.
* @return the factory
*/
- String getFactory() {
- return m_factoryName;
+ IPojoFactory getFactory() {
+ return m_factory;
}
/**
@@ -103,215 +283,59 @@
}
/**
- * Set the factory name.
- *
- * @param name : the factory name.
+ * Test if the given factory match with the factory required by this instance. A factory matches if its name or its class name is equals to
+ * the 'component' property of the instance. Then the acceptability of the configuration is checked.
+ * @param factory : the factory to confront against the current instance.
+ * @return true if the factory match.
*/
- void setFactory(String name) {
- m_factoryName = name;
+ public boolean match(IPojoFactory factory) {
+ // Test factory name (and classname)
+ String component = (String) m_configuration.get("component");
+ if (factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component)) {
+ // Test factory accessibility
+ if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
+ // Test the configuration validity.
+ if (factory.isAcceptable(m_configuration)) {
+ return true;
+ } else {
+ m_logger.log(Logger.ERROR, "An instance can be bound to a matching factory, however the configuration seems unacceptable : "
+ + m_configuration);
+ }
+ }
+ }
+ return false;
}
/**
- * Set the instance object.
- *
- * @param instance : the instance
+ * Create the instance by using the given factory.
+ * @param factory : the factory to use to create the instance. The factory must match.
*/
- void setInstance(ComponentInstance instance) {
- m_instance = instance;
- }
- }
-
- /**
- * Configurations to create and maintains.
- */
- private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];
-
- /**
- * Service Tracker tracking factories.
- */
- private Tracker m_tracker;
-
- /**
- * Constructor.
- *
- * @param context : the bundle context.
- * @param configurations : configuration set to create and maintain.
- * @param factories : private factories.
- */
- public InstanceCreator(BundleContext context, Dictionary[] configurations, ComponentFactory[] factories) {
- m_context = context;
- m_logger = new Logger(context, "InstanceCreator" + context.getBundle().getBundleId(), Logger.WARNING);
-
- m_configurations = new ManagedConfiguration[configurations.length];
- m_factories = factories;
-
- for (int i = 0; i < configurations.length; i++) {
- ManagedConfiguration conf = new ManagedConfiguration(configurations[i]);
- m_configurations[i] = conf;
- // Get the component type name :
- String componentType = (String) conf.getConfiguration().get("component");
-
- boolean found = false;
- for (int j = 0; m_factories != null && !found && j < m_factories.length; j++) {
- if (m_factories[j].m_state == Factory.VALID && (m_factories[j].getName().equals(componentType) || (m_factories[j].getComponentClassName() != null && m_factories[j].getComponentClassName().equals(componentType)))) {
- createInstance(m_factories[j], conf);
- found = true;
- }
+ public void create(IPojoFactory factory) {
+ try {
+ m_factory = factory;
+ m_instance = m_factory.createComponentInstance(m_configuration);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+ + e.getMessage());
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+ + e.getMessage());
+ } catch (ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+ + e.getMessage());
}
}
-
- for (int i = 0; m_factories != null && i < m_factories.length; i++) {
- m_factories[i].addFactoryStateListener(this);
- }
-
-
- String filter = "(&(objectclass=" + Factory.class.getName() + ")(factory.state=1))";
- try {
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
- } catch (InvalidSyntaxException e) {
- e.printStackTrace();
- return;
- }
- }
- /**
- * Create an instance using the given factory and the given configuration.
- *
- * @param fact : the factory name to used.
- * @param config : the configuration.
- */
- private void createInstance(Factory fact, ManagedConfiguration config) {
- Dictionary conf = config.getConfiguration();
- try {
- config.setInstance(fact.createComponentInstance(conf));
- config.setFactory(fact.getName());
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "A factory is available for the configuration but the configuration is not acceptable", e);
- stop();
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The instance creation has failed, at least one handler is missing", e);
- stop();
- } catch (ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The instance creation has failed, an error during the configuration has occured", e);
- stop();
- }
- }
-
- /**
- * Stop all created instances.
- */
- public synchronized void stop() {
- m_tracker.close();
-
- for (int i = 0; m_factories != null && i < m_factories.length; i++) {
- m_factories[i].removeFactoryStateListener(this);
- }
-
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null) {
- m_configurations[i].getInstance().dispose();
+ /**
+ * Dispose the current instance.
+ */
+ public void dispose() {
+ if (m_instance != null) {
+ m_instance.dispose();
}
- m_configurations[i].setInstance(null);
- m_configurations[i].setFactory(null);
+ m_instance = null;
+ m_factory = null;
}
-
- m_factories = null;
- m_tracker = null;
- m_logger = null;
- m_configurations = null;
- }
-
- /**
- * Factory state changed method.
- * @param factory : factory.
- * @param newState : new state.
- * @see org.apache.felix.ipojo.FactoryStateListener#stateChanged(org.apache.felix.ipojo.Factory, int)
- */
- public void stateChanged(Factory factory, int newState) {
- if (newState == Factory.VALID) {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null
- && (m_configurations[i].getConfiguration().get("component").equals(factory.getName()) || m_configurations[i].getConfiguration().get(
- "component").equals(((ComponentFactory) factory).getComponentClassName()))) {
- Factory fact = factory;
- createInstance(fact, m_configurations[i]);
- }
- }
- return;
- } else {
- // newState == INVALID
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(factory.getName())) {
- m_configurations[i].setInstance(null);
- m_configurations[i].setFactory(null);
- }
- }
- return;
- }
- }
-
- /**
- * A new factory has been detected.
- * @param ref : the factory service reference.
- * @return true if the factory can be used to create a managed instance.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference ref) {
- String factoryName = (String) ref.getProperty("factory.name");
- String componentClass = (String) ref.getProperty("component.class");
- boolean isValid = ((String) ref.getProperty("factory.state")).equals("" + Factory.VALID);
- Factory fact = (Factory) m_tracker.getService(ref);
-
- boolean used = false;
- if (isValid) {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null
- && (m_configurations[i].getConfiguration().get("component").equals(factoryName) || m_configurations[i].getConfiguration().get("component").equals(componentClass))) {
- createInstance(fact, m_configurations[i]);
- used = true;
- }
- }
- }
- return used;
- }
-
- /**
- * A matching service has been added to the tracker.
- * Nothing to do, as all action are computed in the adding method.
- * @param ref : added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference ref) { }
-
- /**
- * A used factory is modified.
- * @param ref : modified reference.
- * @param obj : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference ref, Object obj) { }
-
- /**
- * A used factory disappears.
- * All created instance are disposed.
- * @param ref : service reference.
- * @param obj : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference ref, Object obj) {
- String name = (String) ref.getProperty("factory.name");
- if (name == null) { return; }
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getFactory() != null && m_configurations[i].getFactory().equals(name)) {
- if (m_configurations[i].getInstance() != null) {
- m_configurations[i].getInstance().dispose();
- m_configurations[i].setInstance(null);
- }
- m_configurations[i].setFactory(null);
- }
- }
- m_tracker.ungetService(ref);
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index b310ece..01172df 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -19,7 +19,9 @@
package org.apache.felix.ipojo;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
@@ -35,13 +37,10 @@
import org.osgi.framework.BundleContext;
/**
- * The instance manager class manages one instance of a component type. It
- * manages component lifecycle, component instance creation and handlers.
- *
+ * The instance manager class manages one instance of a component type. It manages component lifecycle, component instance creation and handlers.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class InstanceManager implements ComponentInstance, InstanceStateListener {
-
/**
* Name of the component instance.
*/
@@ -51,7 +50,7 @@
* Name of the component type implementation class.
*/
protected String m_className;
-
+
/**
* Handler list.
*/
@@ -61,12 +60,12 @@
* Component state (STOPPED at the beginning).
*/
protected int m_state = STOPPED;
-
+
/**
* Instance State Listener List.
*/
- protected List m_instanceListeners = null;
-
+ protected List m_listeners = null;
+
/**
* Parent factory (ComponentFactory).
*/
@@ -78,12 +77,12 @@
private BundleContext m_context;
/**
- * Map [field, handler list] storing handlers interested by the field.
+ * Map [field, field interceptor list] storing handlers interested by the field.
*/
- private Map m_fieldRegistration = new HashMap();
-
+ private Map m_fieldRegistration;
+
/**
- * Map [method identifier, handler list] storing handlers interested by the method.
+ * Map [method identifier, method interceptor list] storing handlers interested by the method.
*/
private Map m_methodRegistration;
@@ -95,78 +94,89 @@
/**
* Instances of the components.
*/
- private Object[] m_pojoObjects = null;
+ private List m_pojoObjects;
- /**
- * Is the component instance state changing?
- */
- private boolean m_inTransition = false;
-
/**
- * Queue of stored state changed.
+ * Factory method. Contains the name of the static method used to create POJO objects.
+ */
+ private String m_factoryMethod = null;
+
+ /**
+ * Is the component instance state changing?
+ */
+ private boolean m_inTransition = false;
+
+ /**
+ * Queue of stored state changed.
*/
private List m_stateQueue = new ArrayList();
-
+
/**
* Map of [field, value], storing POJO field value.
*/
- private Map m_map = new HashMap();
+ private Map m_fields = new HashMap();
+
+ /**
+ * Map method [id=>method].
+ */
+ private Map m_methods = new HashMap();
/**
* Construct a new Component Manager.
- *
* @param factory : the factory managing the instance manager
- * @param bc : the bundle context to give to the instance
+ * @param context : the bundle context to give to the instance
* @param handlers : handlers array
*/
- public InstanceManager(ComponentFactory factory, BundleContext bc, HandlerManager[] handlers) {
+ public InstanceManager(ComponentFactory factory, BundleContext context, HandlerManager[] handlers) {
m_factory = factory;
- m_context = bc;
+ m_context = context;
m_handlers = handlers;
}
/**
- * Configure the instance manager. Stop the existing handler, clear the
- * handler list, change the metadata, recreate the handlers
- *
- * @param cm : the component type metadata
+ * Configure the instance manager. Stop the existing handler, clear the handler list, change the metadata, recreate the handlers
+ * @param metadata : the component type metadata
* @param configuration : the configuration of the instance
* @throws ConfigurationException : occurs if the metadata are not correct
*/
- public void configure(Element cm, Dictionary configuration) throws ConfigurationException {
- m_className = cm.getAttribute("className");
-
+ public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
+ m_className = metadata.getAttribute("className");
+
// Add the name
m_name = (String) configuration.get("name");
-
+
+ // Get the factory method if presents.
+ m_factoryMethod = (String) metadata.getAttribute("factory-method");
+
// Create the standard handlers and add these handlers to the list
for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].init(this, cm, configuration);
+ m_handlers[i].init(this, metadata, configuration);
}
}
/**
- * Get the description of the current instance.
+ * Get the description of the current instance.
* @return the instance description.
* @see org.apache.felix.ipojo.ComponentInstance#getInstanceDescription()
*/
public InstanceDescription getInstanceDescription() {
int componentState = getState();
- InstanceDescription instanceDescription = new InstanceDescription(m_name, componentState, getContext().getBundle().getBundleId(), m_factory.getComponentDescription());
+ InstanceDescription desc =
+ new InstanceDescription(m_name, componentState, getContext().getBundle().getBundleId(), m_factory.getComponentDescription());
if (m_pojoObjects != null) {
- String[] objects = new String[m_pojoObjects.length];
- for (int i = 0; i < m_pojoObjects.length; i++) {
- objects[i] = m_pojoObjects[i].toString();
+ String[] objects = new String[m_pojoObjects.size()];
+ for (int i = 0; i < m_pojoObjects.size(); i++) {
+ objects[i] = m_pojoObjects.get(i).toString();
}
- instanceDescription.setCreatedObjects(objects);
+ desc.setCreatedObjects(objects);
}
Handler[] handlers = getRegistredHandlers();
for (int i = 0; i < handlers.length; i++) {
- instanceDescription.addHandler(handlers[i].getDescription());
+ desc.addHandler(handlers[i].getDescription());
}
- return instanceDescription;
+ return desc;
}
/**
@@ -174,22 +184,21 @@
* @return the handler array of plugged handlers.
*/
public Handler[] getRegistredHandlers() {
- Handler[] h = new Handler[m_handlers.length];
+ Handler[] handler = new Handler[m_handlers.length];
for (int i = 0; i < m_handlers.length; i++) {
- h[i] = m_handlers[i].getHandler();
+ handler[i] = m_handlers[i].getHandler();
}
- return h;
+ return handler;
}
/**
* Return a specified handler.
- *
* @param name : class name of the handler to find or its qualified name (namespace:name)
* @return : the handler, or null if not found
*/
public Handler getHandler(String name) {
for (int i = 0; i < m_handlers.length; i++) {
- HandlerFactory fact = (HandlerFactory) m_handlers[i].getHandler().getInstance().getFactory();
+ HandlerFactory fact = (HandlerFactory) m_handlers[i].getHandler().getHandlerManager().getFactory();
if (fact.getHandlerName().equals(name)) {
return m_handlers[i].getHandler();
}
@@ -198,24 +207,83 @@
}
/**
+ * Give access to a field value to the first created pojo.
+ * This method process by analyzing both managed fields and pojo fields (by reflection).
+ * If no pojo were already created try only on managed fields.
+ * @param fieldName : field name.
+ * @return the field value, null is returned if the value is managed and not already set.
+ */
+ public synchronized Object getFieldValue(String fieldName) {
+ if (m_pojoObjects == null) {
+ return getFieldValue(fieldName, null);
+ } else {
+ return getFieldValue(fieldName, m_pojoObjects.get(0)); // Use the first pojo.
+ }
+ }
+
+ /**
+ * Give access to a field value to the given created pojo.
+ * This method process by analyzing both managed fields and pojo fields (by reflection).
+ * If the given pojo is null, try only on managed fields.
+ * @param fieldName : field name.
+ * @param pojo : the pojo on which computing field value.
+ * @return the field value, null is returned if the value is managed and not already set.
+ */
+ public synchronized Object getFieldValue(String fieldName, Object pojo) {
+ Object setByContainer = null;
+
+ if (m_fields != null) {
+ setByContainer = m_fields.get(fieldName);
+ }
+
+ if (setByContainer == null && pojo != null) { // In the case of no given pojo, return null.
+ // If null either the value was not already set or has the null value.
+ try {
+ Field field = pojo.getClass().getDeclaredField(fieldName);
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ return field.get(pojo);
+ } catch (SecurityException e) {
+ m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on field " + fieldName + " to obtain the value : " + e.getMessage());
+ } catch (NoSuchFieldException e) {
+ m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on field " + fieldName + " to obtain the value : " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on field " + fieldName + " to obtain the value : " + e.getMessage());
+ } catch (IllegalAccessException e) {
+ m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on field " + fieldName + " to obtain the value : " + e.getMessage());
+ }
+ return null;
+ } else {
+ return setByContainer;
+ }
+ }
+
+ /**
* Start the instance manager.
*/
public synchronized void start() {
if (m_state != STOPPED) { // Instance already started
return;
- }
-
+ }
+
for (int i = 0; i < m_handlers.length; i++) {
m_handlers[i].addInstanceStateListener(this);
- m_handlers[i].start();
+ try {
+ m_handlers[i].start();
+ } catch (IllegalStateException e) {
+ m_factory.getLogger().log(Logger.ERROR, e.getMessage());
+ stop();
+ throw e;
+ }
}
-
+
for (int i = 0; i < m_handlers.length; i++) {
-
if (m_handlers[i].getState() != VALID) {
setState(INVALID);
return;
}
+
}
setState(VALID);
}
@@ -227,26 +295,27 @@
if (m_state == STOPPED) {
return;
} // Instance already stopped
-
+
setState(INVALID);
-
+
+ m_state = STOPPED;
+
// Stop all the handlers
for (int i = m_handlers.length - 1; i > -1; i--) {
m_handlers[i].removeInstanceStateListener(this);
m_handlers[i].stop();
}
-
+
m_pojoObjects = null;
- m_state = STOPPED;
- if (m_instanceListeners != null) {
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
+ if (m_listeners != null) {
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, STOPPED);
}
}
}
-
- /**
+
+ /**
* Dispose the instance.
* @see org.apache.felix.ipojo.ComponentInstance#dispose()
*/
@@ -254,100 +323,79 @@
if (m_state > STOPPED) { // Valid or invalid
stop();
}
-
+
m_state = DISPOSED;
-
- if (m_instanceListeners != null) {
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
- }
- m_instanceListeners = null;
+
+ for (int i = 0; m_listeners != null && i < m_listeners.size(); i++) {
+ ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, DISPOSED);
}
-
- m_factory.disposed(this);
-
+ m_listeners = null;
+
for (int i = m_handlers.length - 1; i > -1; i--) {
m_handlers[i].dispose();
}
-
- m_map.clear();
- m_handlers = new HandlerManager[0];
- m_fieldRegistration = new HashMap();
- m_methodRegistration = new HashMap();
- m_clazz = null;
- m_inTransition = false;
- }
-
- /**
- * Kill the current instance.
- * Only the factory of this instance can call this method.
- */
- protected void kill() {
- if (m_state > STOPPED) {
- stop();
- }
- if (m_instanceListeners != null) {
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
- }
- m_instanceListeners = null;
- }
- // Cleaning
- m_state = DISPOSED;
-
- for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].dispose();
- }
-
- m_map.clear();
m_handlers = new HandlerManager[0];
+ m_factory.disposed(this);
+ m_fields.clear();
m_fieldRegistration = new HashMap();
m_methodRegistration = new HashMap();
m_clazz = null;
m_inTransition = false;
-
}
-
+
/**
- * Set the state of the component instance.
- * if the state changed call the stateChanged(int) method on the handlers.
- * This method has a reentrant mechanism. If in the flow of the first call the method is called another times,
- * the second call is stored and executed after the first one is finished.
+ * Set the state of the component instance. if the state changed call the stateChanged(int) method on the handlers. This method has a reentrant
+ * mechanism. If in the flow of the first call the method is called another times, the second call is stored and executed after the first one is
+ * finished.
* @param state : the new state
*/
public synchronized void setState(int state) {
if (m_inTransition) {
- m_stateQueue.add(new Integer(state));
+ m_stateQueue.add(new Integer(state));
return;
}
-
+
if (m_state != state) {
m_inTransition = true;
if (state > m_state) {
// The state increases (Stopped = > IV, IV => V) => invoke handlers from the higher priority to the lower
m_state = state;
- for (int i = 0; i < m_handlers.length; i++) {
- m_handlers[i].getHandler().stateChanged(state);
+ try {
+ for (int i = 0; i < m_handlers.length; i++) {
+ m_handlers[i].getHandler().stateChanged(state);
+ }
+ } catch (IllegalStateException e) {
+ // When an illegal state exception happens, the instance manager must be stopped immediately.
+ m_stateQueue.clear();
+ stop();
+ return;
}
} else {
// The state decreases (V => IV, IV = > Stopped, Stopped => Disposed)
m_state = state;
- for (int i = m_handlers.length - 1; i > -1; i--) {
- m_handlers[i].getHandler().stateChanged(state);
+ try {
+ for (int i = m_handlers.length - 1; i > -1; i--) {
+ m_handlers[i].getHandler().stateChanged(state);
+ }
+ } catch (IllegalStateException e) {
+ // When an illegal state exception happens, the instance manager must be stopped immediately.
+ m_stateQueue.clear();
+ stop();
+ return;
}
}
-
- if (m_instanceListeners != null) {
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, state);
+
+ if (m_listeners != null) {
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, state);
}
}
}
-
+
m_inTransition = false;
- if (! m_stateQueue.isEmpty()) {
+ if (!m_stateQueue.isEmpty()) {
int newState = ((Integer) (m_stateQueue.remove(0))).intValue();
setState(newState);
}
@@ -370,18 +418,18 @@
public boolean isStarted() {
return m_state > STOPPED;
}
-
+
/**
* Register an instance state listener.
* @param listener : listener to register.
* @see org.apache.felix.ipojo.ComponentInstance#addInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
*/
- public void addInstanceStateListener(InstanceStateListener listener) {
- if (m_instanceListeners == null) {
- m_instanceListeners = new ArrayList();
+ public synchronized void addInstanceStateListener(InstanceStateListener listener) {
+ if (m_listeners == null) {
+ m_listeners = new ArrayList();
}
- synchronized (m_instanceListeners) {
- m_instanceListeners.add(listener);
+ synchronized (m_listeners) {
+ m_listeners.add(listener);
}
}
@@ -390,12 +438,12 @@
* @param listener : listener to unregister.
* @see org.apache.felix.ipojo.ComponentInstance#removeInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
*/
- public void removeInstanceStateListener(InstanceStateListener listener) {
- if (m_instanceListeners != null) {
- synchronized (m_instanceListeners) {
- m_instanceListeners.remove(listener);
- if (m_instanceListeners.size() == 0) {
- m_instanceListeners = null;
+ public synchronized void removeInstanceStateListener(InstanceStateListener listener) {
+ if (m_listeners != null) {
+ synchronized (m_listeners) {
+ m_listeners.remove(listener);
+ if (m_listeners.isEmpty()) {
+ m_listeners = null;
}
}
}
@@ -424,129 +472,186 @@
}
/**
- * Add an instance to the created instance list.
- * @param o : the instance to add
- */
- private synchronized void addInstance(Object o) {
- if (m_pojoObjects != null) {
- Object[] newInstances = new Object[m_pojoObjects.length + 1];
- System.arraycopy(m_pojoObjects, 0, newInstances, 0, m_pojoObjects.length);
- newInstances[m_pojoObjects.length] = o;
- m_pojoObjects = newInstances;
- } else {
- m_pojoObjects = new Object[] { o };
- }
- }
-
- /**
* Get the array of object created by the instance.
* @return the created instance of the component instance.
*/
public Object[] getPojoObjects() {
- return m_pojoObjects;
+ if (m_pojoObjects == null) {
+ return null;
+ }
+ return m_pojoObjects.toArray(new Object[m_pojoObjects.size()]);
}
/**
- * Delete the created instance (remove it from the list, to allow the
- * garbage collector to eat the instance).
- *
- * @param o : the instance to delete
- */
- public synchronized void deletePojoObject(Object o) {
- int idx = -1;
- for (int i = 0; i < m_pojoObjects.length; i++) {
- if (m_pojoObjects[i] == o) {
- idx = i;
- break;
- }
- }
-
- if (idx >= 0) {
- if ((m_pojoObjects.length - 1) == 0) {
- m_pojoObjects = null;
- } else {
- Object[] newInstances = new Object[m_pojoObjects.length - 1];
- System.arraycopy(m_pojoObjects, 0, newInstances, 0, idx);
- if (idx < newInstances.length) {
- System.arraycopy(m_pojoObjects, idx + 1, newInstances, idx, newInstances.length - idx);
- }
- m_pojoObjects = newInstances;
- }
- }
- }
-
- /**
- * Create an instance of the component. This method need to be called one
- * time only for singleton provided service
- *
+ * Create an instance of the component. This method need to be called one time only for singleton provided service
* @return a new instance
*/
public Object createPojoObject() {
-
if (m_clazz == null) {
load();
}
+
Object instance = null;
- try {
- // Try to find if there is a constructor with a bundle context as
- // parameter :
+
+ if (m_factoryMethod == null) {
+ // No factory-method, we use the constructor.
try {
- Constructor constructor = m_clazz.getConstructor(new Class[] { InstanceManager.class, BundleContext.class });
- constructor.setAccessible(true);
- instance = constructor.newInstance(new Object[] { this, m_context });
+ // Try to find if there is a constructor with a bundle context as parameter :
+ try {
+ Constructor cst = m_clazz.getDeclaredConstructor(new Class[] { InstanceManager.class, BundleContext.class });
+ if (! cst.isAccessible()) {
+ cst.setAccessible(true);
+ }
+ Object[] args = new Object[] { this, m_context };
+ onEntry(null, m_className, new Object[] {m_context});
+ instance = cst.newInstance(args);
+ onExit(null, m_className, instance);
+ } catch (NoSuchMethodException e) {
+ // Create an instance if no instance are already created with <init>()BundleContext
+ if (instance == null) {
+ Constructor cst = m_clazz.getDeclaredConstructor(new Class[] { InstanceManager.class });
+ if (! cst.isAccessible()) {
+ cst.setAccessible(true);
+ }
+ Object[] args = new Object[] {this};
+ onEntry(null, m_className, new Object[0]);
+ instance = cst.newInstance(args);
+ onExit(null, m_className, instance);
+ }
+ }
+ } catch (IllegalAccessException e) {
+ m_factory.getLogger().log(Logger.ERROR,
+ "[" + m_name + "] createInstance -> The POJO constructor is not accessible : " + e.getMessage());
+ stop();
+ } catch (SecurityException e) {
+ m_factory.getLogger().log(
+ Logger.ERROR,
+ "["
+ + m_name
+ + "] createInstance -> The Component Instance is not accessible (security reason) : "
+ + e.getMessage());
+ stop();
+ } catch (InvocationTargetException e) {
+ m_factory.getLogger().log(
+ Logger.ERROR,
+ "["
+ + m_name
+ + "] createInstance -> Cannot invoke the constructor method (illegal target) : "
+ + e.getTargetException().getMessage());
+ onError(null, m_className, e.getTargetException());
+ stop();
} catch (NoSuchMethodException e) {
- instance = null;
+ m_factory.getLogger().log(Logger.ERROR,
+ "[" + m_name + "] createInstance -> Cannot invoke the constructor (method not found) : " + e.getMessage());
+ stop();
+ } catch (IllegalArgumentException e) {
+ m_factory.getLogger().log(Logger.ERROR,
+ "[" + m_name + "] createInstance -> The POJO constructor invocation failed : " + e.getMessage());
+ stop();
+ } catch (InstantiationException e) {
+ m_factory.getLogger().log(Logger.ERROR,
+ "[" + m_name + "] createInstance -> The POJO constructor invocation failed : " + e.getMessage());
+ stop();
+ }
+ } else {
+ try {
+ // Build the pojo object with the factory-method.
+ Method factory = null;
+ // Try with the bundle context
+ try {
+ factory = m_clazz.getDeclaredMethod(m_factoryMethod, new Class[] { BundleContext.class });
+ if (! factory.isAccessible()) {
+ factory.setAccessible(true);
+ }
+ Object[] args = new Object[] { m_context };
+ onEntry(null, m_className, args);
+ instance = factory.invoke(null, new Object[] { m_context });
+ } catch (NoSuchMethodException e1) {
+ // Try without the bundle context
+ try {
+ factory = m_clazz.getDeclaredMethod(m_factoryMethod, new Class[0]);
+ if (! factory.isAccessible()) {
+ factory.setAccessible(true);
+ }
+ Object[] args = new Object[0];
+ onEntry(null, m_className, args);
+ instance = factory.invoke(null, args);
+ } catch (NoSuchMethodException e2) {
+ // Error : factory-method not found
+ m_factory.getLogger().log(
+ Logger.ERROR,
+ "["
+ + m_name
+ + "] createInstance -> Cannot invoke the factory-method (method not found) : "
+ + e2.getMessage());
+ stop();
+ }
+ }
+
+ // Now call the setInstanceManager method.
+ Method method = instance.getClass().getDeclaredMethod("_setInstanceManager", new Class[] { InstanceManager.class });
+ if (!method.isAccessible()) {
+ method.setAccessible(true);
+ }
+ method.invoke(instance, new Object[] { this });
+ onExit(null, m_className, instance);
+
+ } catch (SecurityException e) {
+ // Error : invocation failed
+ m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> Cannot invoke the factory-method : " + e.getMessage());
+ stop();
+ } catch (IllegalArgumentException e) {
+ // Error : arguments mismatch
+ m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> Cannot invoke the factory-method : " + e.getMessage());
+ stop();
+ } catch (IllegalAccessException e) {
+ // Error : illegal access
+ m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> Cannot invoke the factory-method : " + e.getMessage());
+ stop();
+ } catch (InvocationTargetException e) {
+ // Error : invocation failed
+ m_factory.getLogger().log(Logger.ERROR,
+ "[" + m_name + "] createInstance -> The factory-method returns an exception : " + e.getTargetException());
+ onError(null, m_className, e.getTargetException());
+ stop();
+ } catch (NoSuchMethodException e) {
+ // Error : _setInstanceManager method is missing
+ m_factory.getLogger()
+ .log(
+ Logger.ERROR,
+ "["
+ + m_name
+ + "] createInstance -> Cannot invoke the factory-method (the _setInstanceManager method does not exist) : "
+ + e.getMessage());
+ stop();
}
- // Create an instance if no instance are already created with
- // <init>()BundleContext
- if (instance == null) {
- Constructor constructor = m_clazz.getConstructor(new Class[] { InstanceManager.class });
- constructor.setAccessible(true);
- instance = constructor.newInstance(new Object[] { this });
+ }
+
+ // Register the new instance in not already present.
+ if (m_pojoObjects == null) {
+ m_pojoObjects = new ArrayList(1);
+ }
+ if (!m_pojoObjects.contains(instance)) {
+ m_pojoObjects.add(instance);
+ // Call createInstance on Handlers :
+ for (int i = 0; i < m_handlers.length; i++) {
+ ((PrimitiveHandler) m_handlers[i].getHandler()).onCreation(instance);
}
-
- } catch (InstantiationException e) {
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> The Component Instance cannot be instancied : " + e.getMessage());
- stop();
- } catch (IllegalAccessException e) {
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> The Component Instance is not accessible : " + e.getMessage());
- stop();
- } catch (SecurityException e) {
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> The Component Instance is not accessible (security reason) : " + e.getMessage());
- stop();
- } catch (InvocationTargetException e) {
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> Cannot invoke the constructor method (illegal target) : " + e.getTargetException().getMessage());
- e.printStackTrace();
- stop();
- } catch (NoSuchMethodException e) {
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> Cannot invoke the constructor (method not found) : " + e.getMessage());
- stop();
- }
- if (instance == null) {
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] createInstance -> Cannot create the instance");
- stop();
}
- // Register the new instance
- addInstance(instance);
- // Call createInstance on Handlers :
- for (int i = 0; i < m_handlers.length; i++) {
- ((PrimitiveHandler) m_handlers[i].getHandler()).objectCreated(instance);
- }
return instance;
}
/**
- * Get the first object created by the instance.
- * If no object created, create and return one object.
+ * Get the first object created by the instance. If no object created, create and return one object.
* @return the instance of the component instance to use for singleton component
*/
public synchronized Object getPojoObject() {
if (m_pojoObjects == null) {
- createPojoObject();
+ return createPojoObject();
}
- return m_pojoObjects[0];
+ return m_pojoObjects.get(0);
}
/**
@@ -561,134 +666,219 @@
}
/**
- * Register an handler. The handler will be notified of event on each field
- * given in the list.
- *
- * @param h : the handler to register
+ * Register an handler. The handler will be notified of event on each field given in the list.
+ * @param handler : the handler to register
* @param fields : the field metadata list
* @param methods : the method metadata list
+ * @deprecated use register(FieldMetadata fm, FieldInterceptor fi) and register(MethodMetadata mm, MethodInterceptor mi) instead.
*/
- public void register(PrimitiveHandler h, FieldMetadata[] fields, MethodMetadata[] methods) {
+ public void register(PrimitiveHandler handler, FieldMetadata[] fields, MethodMetadata[] methods) {
for (int i = 0; fields != null && i < fields.length; i++) {
- if (m_fieldRegistration.get(fields[i].getFieldName()) == null) {
- m_fieldRegistration.put(fields[i].getFieldName(), new PrimitiveHandler[] { h });
+ register(fields[i], handler);
+ }
+ for (int i = 0; methods != null && i < methods.length; i++) {
+ register(methods[i], handler);
+ }
+
+ }
+
+ /**
+ * Register a field interceptor.
+ * @param field : intercepted field
+ * @param interceptor : interceptor
+ */
+ public void register(FieldMetadata field, FieldInterceptor interceptor) {
+ if (m_fieldRegistration == null) {
+ m_fieldRegistration = new HashMap();
+ m_fieldRegistration.put(field.getFieldName(), new FieldInterceptor[] { interceptor });
+ } else {
+ FieldInterceptor[] list = (FieldInterceptor[]) m_fieldRegistration.get(field.getFieldName());
+ if (list == null) {
+ m_fieldRegistration.put(field.getFieldName(), new FieldInterceptor[] { interceptor });
} else {
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_fieldRegistration.get(fields[i].getFieldName());
for (int j = 0; j < list.length; j++) {
- if (list[j] == h) {
+ if (list[j] == interceptor) {
return;
}
}
- PrimitiveHandler[] newList = new PrimitiveHandler[list.length + 1];
+ FieldInterceptor[] newList = new FieldInterceptor[list.length + 1];
System.arraycopy(list, 0, newList, 0, list.length);
- newList[list.length] = h;
- m_fieldRegistration.put(fields[i].getFieldName(), newList);
+ newList[list.length] = interceptor;
+ m_fieldRegistration.put(field.getFieldName(), newList);
}
}
- for (int i = 0; methods != null && i < methods.length; i++) {
- if (m_methodRegistration == null) {
- m_methodRegistration = new HashMap();
- m_methodRegistration.put(methods[i].getMethodIdentifier(), new PrimitiveHandler[] { h });
- } else {
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_methodRegistration.get(methods[i].getMethodIdentifier());
- if (list == null) {
- m_methodRegistration.put(methods[i].getMethodIdentifier(), new PrimitiveHandler[] { h });
- } else {
- for (int j = 0; j < list.length; j++) {
- if (list[j] == h) {
- return;
- }
+ }
+
+ /**
+ * Register a method interceptor.
+ * @param method : intercepted method
+ * @param interceptor : interceptor
+ */
+ public void register(MethodMetadata method, MethodInterceptor interceptor) {
+ if (m_methodRegistration == null) {
+ m_methodRegistration = new HashMap();
+ m_methodRegistration.put(method.getMethodIdentifier(), new MethodInterceptor[] { interceptor });
+ } else {
+ MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(method.getMethodIdentifier());
+ if (list == null) {
+ m_methodRegistration.put(method.getMethodIdentifier(), new MethodInterceptor[] { interceptor });
+ } else {
+ for (int j = 0; j < list.length; j++) {
+ if (list[j] == interceptor) {
+ return;
}
- PrimitiveHandler[] newList = new PrimitiveHandler[list.length + 1];
- System.arraycopy(list, 0, newList, 0, list.length);
- newList[list.length] = h;
- m_methodRegistration.put(methods[i].getMethodIdentifier(), newList);
}
+ MethodInterceptor[] newList = new MethodInterceptor[list.length + 1];
+ System.arraycopy(list, 0, newList, 0, list.length);
+ newList[list.length] = interceptor;
+ m_methodRegistration.put(method.getMethodIdentifier(), newList);
}
}
-
}
/**
- * This method is called by the manipulated class each time that a GETFIELD
- * instruction is found. The method ask to each handler which value need to
- * be returned.
- *
- * @param fieldName : the field name on which the GETFIELD instruction is
- * called
- * @return the value decided by the last asked handler (throw a warning if
- * two fields decide two different values)
+ * This method is called by the manipulated class each time that a GETFIELD instruction is found. The method ask to each handler which value need
+ * to be returned.
+ * @param pojo : the pojo object on which the field was get
+ * @param fieldName : the field name on which the GETFIELD instruction is called
+ * @return the value decided by the last asked handler (throw a warning if two fields decide two different values)
*/
- public Object getterCallback(String fieldName) {
- Object initialValue = m_map.get(fieldName);
+ public Object onGet(Object pojo, String fieldName) {
+ Object initialValue = m_fields.get(fieldName);
Object result = initialValue;
// Get the list of registered handlers
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_fieldRegistration.get(fieldName);
+
+ FieldInterceptor[] list = (FieldInterceptor[]) m_fieldRegistration.get(fieldName);
for (int i = 0; list != null && i < list.length; i++) {
- Object handlerResult = list[i].getterCallback(fieldName, initialValue);
+ Object handlerResult = list[i].onGet(null, fieldName, initialValue);
if (handlerResult == initialValue) {
continue; // Non-binding case (default implementation).
} else {
if (result != initialValue) {
- if ((handlerResult != null && ! handlerResult.equals(result)) || (result != null && handlerResult == null)) {
- m_factory.getLogger().log(Logger.WARNING, "A conflict was detected on the injection of " + fieldName + " - return the last value from " + list[i].getInstance().getInstanceName());
+ if ((handlerResult != null && !handlerResult.equals(result)) || (result != null && handlerResult == null)) {
+ m_factory.getLogger().log(
+ Logger.WARNING,
+ "A conflict was detected on the injection of "
+ + fieldName);
}
}
result = handlerResult;
}
}
-
- if ((result != null && ! result.equals(initialValue)) || (result == null && initialValue != null)) {
+
+ if ((result != null && !result.equals(initialValue)) || (result == null && initialValue != null)) {
// A change occurs => notify the change
- m_map.put(fieldName, result);
+ m_fields.put(fieldName, result);
for (int i = 0; list != null && i < list.length; i++) {
- list[i].setterCallback(fieldName, result);
+ list[i].onSet(null, fieldName, result);
}
}
-
- return result;
+
+ return result;
}
-
+
/**
* Dispatch entry method event on registered handler.
+ * @param pojo : the pojo object on which method is invoked.
* @param methodId : method id
+ * @param args : argument array
*/
- public void entryCallback(String methodId) {
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_methodRegistration.get(methodId);
+ public void onEntry(Object pojo, String methodId, Object[] args) {
+ if (m_methodRegistration == null) {
+ return;
+ }
+ MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
+ Method method = getMethodById(methodId);
for (int i = 0; list != null && i < list.length; i++) {
- list[i].entryCallback(methodId);
+ list[i].onEntry(pojo, method, args);
}
}
/**
- * Dispatch exit method event on registered handler.
- * The given returned object is an instance of Exception if the method has launched an exception.
+ * Dispatch exit method event on registered handler. The given returned object is an instance of Exception if the method has launched an
+ * exception. If the given object is null, either the method returns void, either the method has returned null.
+ * @param pojo : the pojo object on which the method was invoked
+ * @param methodId : method id
+ * @param result : returned object.
+ */
+ public void onExit(Object pojo, String methodId, Object result) {
+ if (m_methodRegistration == null) {
+ return;
+ }
+ MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
+ Method method = getMethodById(methodId);
+ for (int i = 0; list != null && i < list.length; i++) {
+ list[i].onExit(pojo, method, result);
+ }
+ for (int i = 0; list != null && i < list.length; i++) {
+ list[i].onFinally(pojo, method);
+ }
+ }
+
+ /**
+ * Dispatch error method event on registered handler. The given returned object is an instance of Exception if the method has thrown an exception.
* If the given object is null, either the method returns void, either the method has returned null.
+ * @param pojo : the pojo object on which the method was invoked
* @param methodId : method id
- * @param e : returned object.
+ * @param error : throwable object.
*/
- public void exitCallback(String methodId, Object e) {
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_methodRegistration.get(methodId);
+ public void onError(Object pojo, String methodId, Throwable error) {
+ if (m_methodRegistration == null) {
+ return;
+ }
+ MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
+ Method method = getMethodById(methodId);
for (int i = 0; list != null && i < list.length; i++) {
- list[i].exitCallback(methodId, e);
+ list[i].onError(pojo, method, error);
+ }
+ for (int i = 0; list != null && i < list.length; i++) {
+ list[i].onFinally(pojo, method);
}
}
/**
- * This method is called by the manipulated class each time that a PUTFILED
- * instruction is found. the method send to each handler the new value.
- *
- * @param fieldName : the field name on which the PUTFIELD instruction is
- * called
+ * Get method object by id.
+ * @param methodId : method id
+ * @return : the method object or null if the method cannot be found.
+ */
+ private Method getMethodById(String methodId) {
+ Method method = (Method) m_methods.get(methodId);
+ if (method == null) {
+ Method[] mets = m_clazz.getDeclaredMethods();
+ for (int i = 0; i < mets.length; i++) {
+ // Check if the method was not already computed. If not, compute the Id and check.
+ if (!m_methods.containsValue(mets[i]) && (MethodMetadata.computeMethodId(mets[i]).equals(methodId))) {
+ // Store the new methodId
+ m_methods.put(methodId, mets[i]);
+ return mets[i];
+ }
+ }
+ // If not found, it is a constructor, return null in this case.
+ if (methodId.equals(m_clazz.getName())) {
+ // Constructor.
+ return null;
+ }
+ // Cannot happen
+ m_factory.getLogger().log(Logger.ERROR, "A methodID cannot be associate with a POJO method : " + methodId);
+ return null;
+ } else {
+ return method;
+ }
+ }
+
+ /**
+ * This method is called by the manipulated class each time that a PUTFILED instruction is found. the method send to each handler the new value.
+ * @param pojo : the pojo object on which the field was set
+ * @param fieldName : the field name on which the PUTFIELD instruction is called
* @param objectValue : the value of the field
*/
- public void setterCallback(String fieldName, Object objectValue) {
- Object o = m_map.get(fieldName);
- if ((o != null && ! o.equals(objectValue)) || (o == null && objectValue != null)) {
- m_map.put(fieldName, objectValue);
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_fieldRegistration.get(fieldName);
+ public void onSet(Object pojo, String fieldName, Object objectValue) {
+ Object value = m_fields.get(fieldName);
+ if ((value != null && !value.equals(objectValue)) || (value == null && objectValue != null)) {
+ m_fields.put(fieldName, objectValue);
+ FieldInterceptor[] list = (FieldInterceptor[]) m_fieldRegistration.get(fieldName);
for (int i = 0; list != null && i < list.length; i++) {
- list[i].setterCallback(fieldName, objectValue);
+ list[i].onSet(null, fieldName, objectValue);
}
}
}
@@ -701,11 +891,11 @@
public BundleContext getContext() {
return m_context;
}
-
+
public BundleContext getGlobalContext() {
return ((IPojoContext) m_context).getGlobalContext();
}
-
+
public ServiceContext getLocalServiceContext() {
return ((IPojoContext) m_context).getServiceContext();
}
@@ -748,15 +938,16 @@
}
/**
- * State Change listener callback.
- * This method is notified at each time a plugged handler becomes invalid.
- * @param instance : changing instance
+ * State Change listener callback. This method is notified at each time a plugged handler becomes invalid.
+ * @param instance : changing instance
* @param newState : new state
* @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
*/
public synchronized void stateChanged(ComponentInstance instance, int newState) {
- if (m_state <= STOPPED) { return; }
-
+ if (m_state <= STOPPED) {
+ return;
+ }
+
// Update the component state if necessary
if (newState == INVALID && m_state == VALID) {
// Need to update the state to UNRESOLVED
@@ -766,36 +957,35 @@
if (newState == VALID && m_state == INVALID) {
// An handler becomes valid => check if all handlers are valid
for (int i = 0; i < m_handlers.length; i++) {
- if (m_handlers[i].getState() != VALID) { return; }
+ if (m_handlers[i].getState() != VALID) {
+ return;
+ }
}
setState(VALID);
return;
- }
+ }
}
-
+
/**
- * Get the list of registered fields.
- * This method is invoked by the POJO itself.
+ * Get the list of registered fields. This method is invoked by the POJO itself.
* @return the set of registered fields.
*/
public Set getRegistredFields() {
- if (m_fieldRegistration != null) {
- return m_fieldRegistration.keySet();
- } else {
+ if (m_fieldRegistration == null) {
return null;
}
+ return m_fieldRegistration.keySet();
}
-
+
/**
- * Get the list of registered methods.
- * This method is invoked by the POJO itself.
+ * Get the list of registered methods. This method is invoked by the POJO itself.
* @return the set of registered methods.
*/
public Set getRegistredMethods() {
- if (m_methodRegistration != null) {
- return m_methodRegistration.keySet();
- } else {
+ if (m_methodRegistration == null) {
return null;
+ } else {
+ return m_methodRegistration.keySet();
}
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java
new file mode 100644
index 0000000..951452f
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo;
+
+import java.lang.reflect.Method;
+
+/**
+* Method interceptor.
+* A class implementing this interface is able to be notified of method invocation.
+* The listener need to be register on the instance manager.
+* For event are send to the listener : before the method entry, after the method returns,
+* when an error is thrown by the method, and before the after either a returns or an error (finally)
+*
+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+*/
+public interface MethodInterceptor {
+
+ /**
+ * This method is called when the execution enter in a method.
+ * @param pojo : pojo on which the method is called.
+ * @param method : method invoked.
+ * @param args arguments array.
+ */
+ void onEntry(Object pojo, Method method, Object[] args);
+
+ /**
+ * This method is called when the execution exit a method (before a return or a throw).
+ * If the given returned object is null, either the method is void, either it returns null.
+ * You must not modified the returned object.
+ * @param pojo : the pojo on which the method exits.
+ * @param method : exiting method.
+ * @param returnedObj : the returned object (boxed for primitive type)
+ */
+ void onExit(Object pojo, Method method, Object returnedObj);
+
+ /**
+ * This method is called when the execution throw an exception in the given method.
+ * @param pojo : the pojo on which the method was accessed.
+ * @param method : invoked method.
+ * @param throwable : the thrown exception
+ */
+ void onError(Object pojo, Method method, Throwable throwable);
+
+ /**
+ * This method is called when the execution of a method will terminate :
+ * just before to throw an exception or before to return.
+ * OnError or OnExit was already called.
+ * @param pojo : the pojo on which the method was accessed.
+ * @param method : invoked method.
+ */
+ void onFinally(Object pojo, Method method);
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/MissingHandlerException.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/MissingHandlerException.java
index 7e90e43..3ba91b4 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/MissingHandlerException.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/MissingHandlerException.java
@@ -42,6 +42,7 @@
* @param missing : list of missing handlers.
*/
public MissingHandlerException(List missing) {
+ super();
m_message = "Missing handlers : ";
for (int i = 0; i < missing.size(); i++) {
m_message += (String) missing.get(i) + " ";
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Nullable.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Nullable.java
index 22ce37c..797d02e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Nullable.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Nullable.java
@@ -1,28 +1,28 @@
-/*
- * 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;
-
-/**
- * A Nullable object must implement this interface.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public interface Nullable {
- // Nothing
-}
+/*
+ * 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;
+
+/**
+ * A Nullable object must implement this interface.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Nullable {
+ // Nothing
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java
index 45034a2..501050c 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java
@@ -22,7 +22,6 @@
import java.io.InputStream;
import java.util.Dictionary;
-import org.apache.felix.ipojo.composite.ServiceReferenceImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
@@ -85,7 +84,11 @@
public PolicyServiceContext(BundleContext global, ServiceContext local, int policy) {
m_global = global;
m_local = local;
- m_policy = policy;
+ if (m_local == null) {
+ m_policy = GLOBAL;
+ } else {
+ m_policy = policy;
+ }
}
/**
@@ -137,23 +140,7 @@
case LOCAL_AND_GLOBAL:
ServiceReference[] refLocal = m_local.getAllServiceReferences(clazz, filter);
ServiceReference[] refGlobal = m_global.getAllServiceReferences(clazz, filter);
- if (refLocal != null && refGlobal != null) {
- ServiceReference[] refs = new ServiceReference[refLocal.length + refGlobal.length];
- int j = 0;
- for (int i = 0; i < refLocal.length; i++) {
- refs[j] = refLocal[i];
- j++;
- }
- for (int i = 0; i < refGlobal.length; i++) {
- refs[j] = refGlobal[i];
- j++;
- }
- return refs;
- } else if (refLocal != null && refGlobal == null) {
- return refLocal;
- } else {
- return refGlobal;
- }
+ return computeServiceReferencesFromBoth(refLocal, refGlobal);
default:
return null;
}
@@ -166,7 +153,7 @@
* @see org.apache.felix.ipojo.ServiceContext#getService(org.osgi.framework.ServiceReference)
*/
public Object getService(ServiceReference ref) {
- switch(m_policy) {
+ switch(m_policy) { // NOPMD No break needed as we return in each branch.
case LOCAL:
// The reference comes from the local scope
return m_local.getService(ref);
@@ -174,8 +161,7 @@
// The reference comes from the global registry
return m_global.getService(ref);
case LOCAL_AND_GLOBAL:
- if (ref instanceof org.apache.felix.ipojo.composite.ServiceReferenceImpl) {
- // The reference comes from a composite, i.e. necessary the local composite
+ if (ref instanceof org.apache.felix.ipojo.context.ServiceReferenceImpl) {
return m_local.getService(ref);
} else {
return m_global.getService(ref);
@@ -192,17 +178,17 @@
* @see org.apache.felix.ipojo.ServiceContext#getServiceReference(java.lang.String)
*/
public ServiceReference getServiceReference(String clazz) {
- switch (m_policy) {
+ switch (m_policy) { // NOPMD No break needed as we return in each branch.
case LOCAL:
return m_local.getServiceReference(clazz);
case GLOBAL:
return m_global.getServiceReference(clazz);
case LOCAL_AND_GLOBAL:
ServiceReference refLocal = m_local.getServiceReference(clazz);
- if (refLocal != null) {
- return refLocal;
+ if (refLocal == null) {
+ return m_global.getServiceReference(clazz);
} else {
- return m_global.getServiceReference(clazz);
+ return refLocal;
}
default:
return null;
@@ -226,28 +212,31 @@
case LOCAL_AND_GLOBAL:
ServiceReference[] refLocal = m_local.getServiceReferences(clazz, filter);
ServiceReference[] refGlobal = m_global.getServiceReferences(clazz, filter);
- if (refLocal != null && refGlobal != null) {
- ServiceReference[] refs = new ServiceReference[refLocal.length + refGlobal.length];
- int j = 0;
- for (int i = 0; i < refLocal.length; i++) {
- refs[j] = refLocal[i];
- j++;
- }
- for (int i = 0; i < refGlobal.length; i++) {
- refs[j] = refGlobal[i];
- j++;
- }
- return refs;
- } else if (refLocal != null && refGlobal == null) {
- return refLocal;
- } else {
- return refGlobal;
- }
+ return computeServiceReferencesFromBoth(refLocal, refGlobal);
default:
return null;
}
}
+
+ /**
+ * Compute the service reference array from the two given set of service references.
+ * @param refLocal : local references
+ * @param refGlobal : global references
+ * @return the set of service reference
+ */
+ private ServiceReference[] computeServiceReferencesFromBoth(ServiceReference[] refLocal, ServiceReference[] refGlobal) {
+ if (refLocal == null) {
+ return refGlobal; // If refGlobal is null, return null, else return refGlobal
+ } else if (refGlobal == null) { // refLocal != null && refGlobal == null
+ return refLocal;
+ } else { // Both refGlobal and refLocal are not null
+ ServiceReference[] refs = new ServiceReference[refLocal.length + refGlobal.length];
+ System.arraycopy(refLocal, 0, refs, 0, refLocal.length);
+ System.arraycopy(refGlobal, 0, refs, refLocal.length, refGlobal.length);
+ return refs;
+ }
+ }
/**
* This method is not supported.
@@ -294,7 +283,7 @@
* @see org.apache.felix.ipojo.ServiceContext#ungetService(org.osgi.framework.ServiceReference)
*/
public boolean ungetService(ServiceReference reference) {
- if (reference instanceof ServiceReferenceImpl) {
+ if (reference instanceof org.apache.felix.ipojo.context.ServiceReferenceImpl) {
return m_local.ungetService(reference);
} else {
return m_global.ungetService(reference);
@@ -343,12 +332,12 @@
/**
* Get the bundle object with the given id.
- * @param id : bundle id
+ * @param bundleId : bundle id
* @return the bundle object
* @see org.osgi.framework.BundleContext#getBundle(long)
*/
- public Bundle getBundle(long id) {
- return m_global.getBundle(id);
+ public Bundle getBundle(long bundleId) {
+ return m_global.getBundle(bundleId);
}
/**
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
index 25a9eda..8add263 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
@@ -18,6 +18,12 @@
*/
package org.apache.felix.ipojo;
+import java.lang.reflect.Method;
+
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.apache.felix.ipojo.util.Logger;
+
/**
@@ -25,7 +31,7 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public abstract class PrimitiveHandler extends Handler {
+public abstract class PrimitiveHandler extends Handler implements FieldInterceptor, MethodInterceptor {
/**
* "Primitive" Handler type (value).
@@ -37,20 +43,45 @@
*/
private InstanceManager m_manager;
+
+ /**
+ * Factory of the instance manager.
+ */
+ private ComponentFactory m_factory;
+
/**
* Attach the current handler to the given instance.
- * @param im ! the instance on which the current handler will be attached.
+ * @param manager ! the instance on which the current handler will be attached.
* @see org.apache.felix.ipojo.Handler#attach(org.apache.felix.ipojo.ComponentInstance)
*/
- protected final void attach(ComponentInstance im) {
- m_manager = (InstanceManager) im;
- setLogger(m_manager.getFactory().getLogger());
+ protected final void attach(ComponentInstance manager) {
+ m_manager = (InstanceManager) manager;
+ }
+
+ public final void setFactory(Factory factory) {
+ m_factory = (ComponentFactory) factory;
+ }
+
+ public Logger getLogger() {
+ return m_factory.getLogger();
}
public InstanceManager getInstanceManager() {
return m_manager;
}
+ public ComponentFactory getFactory() {
+ return m_factory;
+ }
+
+ public Element[] getMetadata() {
+ return null;
+ }
+
+ public PojoMetadata getPojoMetadata() {
+ return m_factory.getPojoMetadata();
+ }
+
/**
* Get a plugged handler of the same container.
* This method must be call only in the start method (or after).
@@ -65,45 +96,76 @@
/**
* This method is called when a PUTFIELD operation is detected.
+ * @param pojo : the pojo object setting the value
* @param fieldName : the field name
* @param value : the value passed to the field
*/
- public void setterCallback(String fieldName, Object value) {
- return;
+ public void onSet(Object pojo, String fieldName, Object value) {
+ // Nothing do do in the default implementation
}
/**
* This method is called when a GETFIELD operation is detected.
+ * @param pojo : the pojo object getting the value
* @param fieldName : the field name
* @param value : the value passed to the field (by the previous call)
* @return : the managed value of the field
*/
- public Object getterCallback(String fieldName, Object value) {
+ public Object onGet(Object pojo, String fieldName, Object value) {
return value;
}
/**
* This method is called when the execution enter in a method.
- * @param methodId : the method identifier
+ * @param pojo : pojo on which the method is called.
+ * @param method : method invoked.
+ * @param args arguments array.
*/
- public void entryCallback(String methodId) { }
+ public void onEntry(Object pojo, Method method, Object[] args) {
+ // Nothing do do in the default implementation
+ }
/**
* This method is called when the execution exit a method (before a return or a throw).
- * If the given returned object is an instance of Exception, this means that the method throwed this exception.
* If the given returned object is null, either the method is void, either it returns null.
* You must not modified the returned object.
- * @param methodId : the method identifier
+ * @param pojo : the pojo on which the method exits.
+ * @param method : exiting method.
* @param returnedObj : the returned object (boxed for primitive type)
*/
- public void exitCallback(String methodId, Object returnedObj) { }
+ public void onExit(Object pojo, Method method, Object returnedObj) {
+ // Nothing do do in the default implementation
+ }
+
+ /**
+ * This method is called when the execution throw an exception in the given method.
+ * @param pojo : the pojo on which the method was accessed.
+ * @param method : invoked method.
+ * @param throwable : the thrown exception
+ */
+ public void onError(Object pojo, Method method, Throwable throwable) {
+ // Nothing do do in the default implementation
+ }
+
+ /**
+ * This method is called when the execution of a method will terminate :
+ * just before to throw an exception or before to return.
+ * OnError or OnExit was already called.
+ * @param pojo : the pojo on which the method was accessed.
+ * @param method : invoked method.
+ */
+ public void onFinally(Object pojo, Method method) {
+ // Nothing do do in the default implementation
+ }
/**
* This method is called when an instance of the component is created, but
* before someone can use it.
* @param instance : the created instance
*/
- public void objectCreated(Object instance) { }
+ public void onCreation(Object instance) {
+ // Nothing do do in the default implementation
+ }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
similarity index 66%
rename from ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
rename to ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
index 1e6c94f..feb86ba 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
@@ -18,20 +18,21 @@
*/
package org.apache.felix.ipojo.architecture;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Dictionary;
+import java.util.Properties;
import org.apache.felix.ipojo.ComponentFactory;
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
/**
* Component Type description.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ComponentDescription {
+public class ComponentTypeDescription {
/**
* Provided service by the component type.
@@ -42,13 +43,6 @@
* Configuration Properties accepted by the component type.
*/
private PropertyDescription[] m_properties = new PropertyDescription[0];
-
- /**
- * List of required properties.
- * This list contains only property which does not have a default value.
- */
- private List m_requiredProperties = new ArrayList();
-
/**
* Represented factory.
@@ -59,13 +53,9 @@
* Constructor.
* @param factory : represented factory.
*/
- public ComponentDescription(Factory factory) {
+ public ComponentTypeDescription(Factory factory) {
m_factory = factory;
}
-
- public List getRequiredProperties() {
- return m_requiredProperties;
- }
/**
* Get a printable form of the current component type description.
@@ -98,36 +88,40 @@
* @param value : property value.
*/
public void addProperty(String name, String value) {
- PropertyDescription pd = new PropertyDescription(name, String.class.getName(), value);
- addProperty(pd);
+ addProperty(name, value, false);
+ }
+
+ /**
+ * Add a String property in the component type.
+ * @param name : property name.
+ * @param value : property value.
+ * @param immutable : the property is immutable.
+ */
+ public void addProperty(String name, String value, boolean immutable) {
+ PropertyDescription prop = new PropertyDescription(name, String.class.getName(), value);
+ addProperty(prop);
}
/**
* Add a configuration properties to the component type.
* @param pd : the property to add
*/
- public void addProperty(PropertyDescription pd) {
- String n = pd.getName();
- if ("name".equals(n)) {
- pd = new PropertyDescription(n, pd.getType(), null); // Instance name case.
- }
+ public void addProperty(PropertyDescription pd) { //NOPMD remove the instance name of the 'name' property.
+ String name = pd.getName();
+ if ("name".equals(name)) {
+ pd = new PropertyDescription(name, pd.getType(), null); //NOPMD Instance name case.
+ }
// Check if the property is not already in the array
for (int i = 0; i < m_properties.length; i++) {
PropertyDescription desc = m_properties[i];
- if (desc.getName().equals(n)) {
- return;
- }
+ if (desc.getName().equals(name)) { return; }
}
PropertyDescription[] newProps = new PropertyDescription[m_properties.length + 1];
System.arraycopy(m_properties, 0, newProps, 0, m_properties.length);
newProps[m_properties.length] = pd;
m_properties = newProps;
-
- if (pd.getValue() == null) {
- m_requiredProperties.add(n);
- }
}
/**
@@ -156,6 +150,37 @@
public String getName() {
return m_factory.getName();
}
+
+ /**
+ * Compute the default service properties to publish :
+ * factory.name, service.pid, component.providedServiceSpecification, component.properties, component.description, factory.State.
+ * @return : the dictionary of properties to publish.
+ */
+ public Dictionary getPropertiesToPublish() {
+ Properties props = new Properties();
+
+ props.put("factory.name", m_factory.getName());
+ props.put(Constants.SERVICE_PID, m_factory.getName()); // Service PID is required for the integration in the configuration admin.
+
+ props.put("component.providedServiceSpecifications", m_providedServiceSpecification);
+ props.put("component.properties", m_properties);
+ props.put("component.description", this);
+
+ // add every immutable property
+ for (int i = 0; i < m_properties.length; i++) {
+ if (m_properties[i].isImmutable() && m_properties[i].getValue() != null) {
+ props.put(m_properties[i].getName(), m_properties[i].getObjectValue(m_factory.getBundleContext()));
+ }
+ }
+
+ // Add factory state
+ props.put("factory.state", new Integer(m_factory.getState()));
+
+ return props;
+
+ }
+
+
/**
* Get the component type description.
@@ -165,14 +190,9 @@
Element desc = new Element("Factory", "");
desc.addAttribute(new Attribute("name", m_factory.getName()));
- desc.addAttribute(new Attribute("bundle", "" + ((ComponentFactory) m_factory).getBundleContext().getBundle().getBundleId()));
-
- String cn = getClassName();
- if (cn == null) {
- desc.addAttribute(new Attribute("Composite", "true"));
- } else {
- desc.addAttribute(new Attribute("Implementation-Class", getClassName()));
- }
+ desc.addAttribute(
+ new Attribute("bundle",
+ Long.toString(((ComponentFactory) m_factory).getBundleContext().getBundle().getBundleId())));
String state = "valid";
if (m_factory.getState() == Factory.INVALID) {
@@ -181,12 +201,12 @@
desc.addAttribute(new Attribute("state", state));
// Display required & missing handlers
- Element rh = new Element("RequiredHandlers", "");
- rh.addAttribute(new Attribute("list", m_factory.getRequiredHandlers().toString()));
- Element mh = new Element("MissingHandlers", "");
- mh.addAttribute(new Attribute("list", m_factory.getMissingHandlers().toString()));
- desc.addElement(rh);
- desc.addElement(mh);
+ Element req = new Element("RequiredHandlers", "");
+ req.addAttribute(new Attribute("list", m_factory.getRequiredHandlers().toString()));
+ Element missing = new Element("MissingHandlers", "");
+ missing.addAttribute(new Attribute("list", m_factory.getMissingHandlers().toString()));
+ desc.addElement(req);
+ desc.addElement(missing);
for (int i = 0; i < m_providedServiceSpecification.length; i++) {
Element prov = new Element("provides", "");
@@ -198,10 +218,10 @@
Element prop = new Element("property", "");
prop.addAttribute(new Attribute("name", m_properties[i].getName()));
prop.addAttribute(new Attribute("type", m_properties[i].getType()));
- if (m_properties[i].getValue() != null) {
- prop.addAttribute(new Attribute("value", m_properties[i].getValue()));
- } else {
+ if (m_properties[i].getValue() == null) {
prop.addAttribute(new Attribute("value", "REQUIRED"));
+ } else {
+ prop.addAttribute(new Attribute("value", m_properties[i].getValue()));
}
desc.addElement(prop);
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/HandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/HandlerDescription.java
index 8847575..2cd3a5a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/HandlerDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/HandlerDescription.java
@@ -18,7 +18,6 @@
*/
package org.apache.felix.ipojo.architecture;
-import org.apache.felix.ipojo.CompositeHandler;
import org.apache.felix.ipojo.Handler;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
@@ -43,21 +42,11 @@
/**
* Constructor.
*
- * @param h : handler.
+ * @param handler : handler.
*/
- public HandlerDescription(Handler h) {
- m_handlerName = h.getClass().getName();
- m_isValid = h.isValid();
- }
-
- /**
- * Constructor.
- *
- * @param h : composite handler.
- */
- public HandlerDescription(CompositeHandler h) {
- m_handlerName = h.getClass().getName();
- m_isValid = h.isValid();
+ public HandlerDescription(Handler handler) {
+ m_handlerName = handler.getClass().getName();
+ m_isValid = handler.isValid();
}
/**
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
index 14bb1e8..3ebb43a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
@@ -57,7 +57,7 @@
/**
* Component Type of the instance.
*/
- private ComponentDescription m_type;
+ private ComponentTypeDescription m_type;
/**
* COntained instance list.
@@ -70,16 +70,16 @@
* @param name : the name of the component instance.
* @param state : the state of the instance.
* @param bundleId : bundle id owning this instance.
- * @param cd : the component type description of this instance.
+ * @param desc : the component type description of this instance.
*/
- public InstanceDescription(String name, int state, long bundleId, ComponentDescription cd) {
+ public InstanceDescription(String name, int state, long bundleId, ComponentTypeDescription desc) {
m_name = name;
m_state = state;
m_createdObjects = new String[0];
m_handlers = new HandlerDescription[0];
m_containedInstances = new InstanceDescription[0];
m_bundleId = bundleId;
- m_type = cd;
+ m_type = desc;
}
/**
@@ -110,7 +110,7 @@
* Get the component type description of the described instance.
* @return : the component type description of this instance.
*/
- public ComponentDescription getComponentDescription() {
+ public ComponentTypeDescription getComponentDescription() {
return m_type;
}
@@ -124,12 +124,12 @@
/**
* Add an handler description to the list.
- * @param hd : the handler description to add
+ * @param desc : the handler description to add
*/
- public void addHandler(HandlerDescription hd) {
+ public void addHandler(HandlerDescription desc) {
// Verify that the dependency description is not already in the array.
for (int i = 0; i < m_handlers.length; i++) {
- if (m_handlers[i] == hd) {
+ if (m_handlers[i] == desc) {
return; // NOTHING TO DO, the description is already in the
// array
}
@@ -137,7 +137,7 @@
// The component Description is not in the array, add it
HandlerDescription[] newHd = new HandlerDescription[m_handlers.length + 1];
System.arraycopy(m_handlers, 0, newHd, 0, m_handlers.length);
- newHd[m_handlers.length] = hd;
+ newHd[m_handlers.length] = desc;
m_handlers = newHd;
}
@@ -163,10 +163,10 @@
/**
* Set the state of the component.
*
- * @param i : the state
+ * @param state : the state
*/
- public void setState(int i) {
- m_state = i;
+ public void setState(int state) {
+ m_state = state;
}
/**
@@ -215,7 +215,7 @@
instance.addAttribute(new Attribute("state", "disposed"));
}
// Bundle
- instance.addAttribute(new Attribute("bundle", "" + m_bundleId));
+ instance.addAttribute(new Attribute("bundle", Long.toString(m_bundleId)));
// Component Type
instance.addAttribute(new Attribute("component.type", m_type.getName()));
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/PropertyDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/PropertyDescription.java
index f3f63f4..222be42 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/PropertyDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/PropertyDescription.java
@@ -18,6 +18,10 @@
*/
package org.apache.felix.ipojo.architecture;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.util.Property;
+import org.osgi.framework.BundleContext;
+
/**
* Property Information.
*
@@ -39,6 +43,14 @@
* Default value of the property.
*/
private String m_value = null;
+
+
+ /**
+ * Immutable property flag
+ * IF true, the property cannot be override by the instance configuration.
+ * Moreover, immutable properties are exposed on the factory service too.
+ */
+ private boolean m_immutable = false;
/**
* Constructor.
@@ -52,6 +64,21 @@
m_type = type;
m_value = value;
}
+
+ /**
+ * Constructor.
+ *
+ * @param name : name of the property
+ * @param type : type of the property
+ * @param value : default value of the property
+ * @param immutable : the property is immutable.
+ */
+ public PropertyDescription(String name, String type, String value, boolean immutable) {
+ m_name = name;
+ m_type = type;
+ m_value = value;
+ m_immutable = immutable;
+ }
/**
* Get the current property name.
@@ -76,5 +103,27 @@
public String getValue() {
return m_value;
}
+
+ /**
+ * Is the property immutable.
+ * @return true if the property is immutable.
+ */
+ public boolean isImmutable() {
+ return m_immutable;
+ }
+ /**
+ * Get the object value of the current immutable property.
+ * @param context : bundle context to use to load classes.
+ * @return the object value of the current property.
+ */
+ public Object getObjectValue(BundleContext context) {
+ Class type = null;
+ try {
+ type = Property.computeType(m_type, context);
+ return Property.create(type, m_value);
+ } catch (ConfigurationException e) {
+ return m_value; // Cannot create the object.
+ }
+ }
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
deleted file mode 100644
index d3449d6..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * 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;
-
-import java.io.File;
-import java.io.InputStream;
-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.Factory;
-import org.apache.felix.ipojo.IPojoContext;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.util.Tracker;
-import org.apache.felix.ipojo.util.TrackerCustomizer;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * CompositeServiceContext Class. This class provides an implementation of the
- * service context for composite.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class CompositeServiceContext implements ServiceContext, TrackerCustomizer {
-
- /**
- * Structure storing the reference, the factory and the registration.
- */
- private class Record {
- /**
- * Reference of the represented factory from the external context.
- */
- private ServiceReference m_ref;
- /**
- * Registration of the factory in the internal context.
- */
- private ServiceRegistration m_reg;
- /**
- * Represented Factory.
- */
- private FactoryProxy m_fact;
- }
-
- /**
- * List of imported factories.
- */
- private List m_factories = new ArrayList();
-
- /**
- * External context.
- */
- private BundleContext m_parent;
-
- /**
- * Internal service registry.
- */
- private ServiceRegistry m_registry;
-
- /**
- * Component Instance who creates this registry.
- */
- private ComponentInstance m_instance;
-
- /**
- * Global service context.
- */
- private BundleContext m_global;
-
- /**
- * Tracker tracking Factories to import.
- */
- private Tracker m_tracker;
-
- /**
- * Constructor. This constructor instantiate a service registry with the
- * given bundle context.
- *
- * @param bc : the bundle context
- */
- public CompositeServiceContext(BundleContext bc) {
- m_registry = new ServiceRegistry(bc);
- m_parent = bc;
- if (m_parent instanceof IPojoContext) {
- m_global = ((IPojoContext) m_parent).getGlobalContext();
- } else {
- m_global = m_parent; // the parent context is the global context
- }
- }
-
- /**
- * Constructor.
- *
- * @param bc : the bundle context
- * @param ci : the component instance owning this context
- */
- public CompositeServiceContext(BundleContext bc, ComponentInstance ci) {
- this(bc);
- m_instance = ci;
- }
-
- /**
- * Add a service listener.
- * @param arg0 : The service listener to add
- * @see org.apache.felix.ipojo.ServiceContext#addServiceListener(org.osgi.framework.ServiceListener)
- */
- public void addServiceListener(ServiceListener arg0) {
- m_registry.addServiceListener(arg0);
- }
-
- /**
- * Add a filtered service listener.
- * @param arg0 : the service listener object to add
- * @param arg1 : the LDAP filter for this listener
- * @throws InvalidSyntaxException : occurs if the LDAP filter is malformed
- * @see org.apache.felix.ipojo.ServiceContext#addServiceListener(org.osgi.framework.ServiceListener,
- * java.lang.String)
- */
- public void addServiceListener(ServiceListener arg0, String arg1) throws InvalidSyntaxException {
- m_registry.addServiceListener(arg0, arg1);
- }
-
- /**
- * Get all service references.
- * @param arg0 : The required service interface.
- * @param arg1 : LDAP filter
- * @return the list of all service reference matching with the query
- * @throws InvalidSyntaxException : occurs when the given filter is malformed
- * @see org.apache.felix.ipojo.ServiceContext#getAllServiceReferences(java.lang.String,
- * java.lang.String)
- */
- public ServiceReference[] getAllServiceReferences(String arg0, String arg1) throws InvalidSyntaxException {
- return m_registry.getAllServiceReferences(arg0, arg1);
- }
-
- /**
- * Get a service object for the given service reference.
- * @param arg0 : the service reference
- * @return the service object or null if the reference is no more valid or if the object is not accessible
- * @see org.apache.felix.ipojo.ServiceContext#getService(org.osgi.framework.ServiceReference)
- */
- public Object getService(ServiceReference arg0) {
- return m_registry.getService(m_instance, arg0);
- }
-
-
- /**
- * Get a service reference for the required interface.
- * @param arg0 : the required interface name
- * @return the service reference or null if no available provider
- * @see org.apache.felix.ipojo.ServiceContext#getServiceReference(java.lang.String)
- */
- public ServiceReference getServiceReference(String arg0) {
- return m_registry.getServiceReference(arg0);
- }
-
- /**
- * Get all accessible service reference for the given query.
- * @param clazz : required interface
- * @param filter : LDAP filter
- * @return the list (array) of service reference matching with the query.
- * @throws InvalidSyntaxException : occurs when the LDAP filter is malformed
- * @see org.apache.felix.ipojo.ServiceContext#getServiceReferences(java.lang.String, java.lang.String)
- */
- public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
- return m_registry.getServiceReferences(clazz, filter);
- }
-
-
- /**
- * Register a service inside the composite context.
- * @param arg0 : list of interfaces to register.
- * @param arg1 : service object
- * @param arg2 : properties list
- * @return the service registration
- * @see org.apache.felix.ipojo.ServiceContext#registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)
- */
- public ServiceRegistration registerService(String[] arg0, Object arg1, Dictionary arg2) {
- return m_registry.registerService(m_instance, arg0, arg1, arg2);
- }
-
- /**
- * Register a service inside the composite context.
- * @param arg0 : interface to register.
- * @param arg1 : service object
- * @param arg2 : properties list
- * @return the service registration
- * @see org.apache.felix.ipojo.ServiceContext#registerService(java.lang.String, java.lang.Object, java.util.Dictionary)
- */
- public ServiceRegistration registerService(String arg0, Object arg1, Dictionary arg2) {
- return m_registry.registerService(m_instance, arg0, arg1, arg2);
- }
-
- /**
- * Remove a service listener.
- * @param arg0 : the service listener to remove
- * @see org.apache.felix.ipojo.ServiceContext#removeServiceListener(org.osgi.framework.ServiceListener)
- */
- public void removeServiceListener(ServiceListener arg0) {
- m_registry.removeServiceListener(arg0);
- }
-
- /**
- * Unget a service.
- * @param arg0 the service reference to unget
- * @return true
- * @see org.apache.felix.ipojo.ServiceContext#ungetService(org.osgi.framework.ServiceReference)
- */
- public boolean ungetService(ServiceReference arg0) {
- return m_registry.ungetService(m_instance, arg0);
- }
-
- /**
- * Import a factory form the parent to the internal registry.
- *
- * @param ref : the reference of the factory to import.
- */
- private void importFactory(ServiceReference ref) {
- Record rec = new Record();
- m_factories.add(rec);
- Dictionary dict = new Properties();
- for (int j = 0; j < ref.getPropertyKeys().length; j++) {
- dict.put(ref.getPropertyKeys()[j], ref.getProperty(ref.getPropertyKeys()[j]));
- }
- rec.m_fact = new FactoryProxy((Factory) m_tracker.getService(ref), this);
- rec.m_reg = registerService(Factory.class.getName(), rec.m_fact, dict);
- rec.m_ref = ref;
- }
-
- /**
- * Remove a factory of the available factory list.
- *
- * @param ref : the reference on the factory to remove.
- */
- private void removeFactory(ServiceReference ref) {
- for (int i = 0; i < m_factories.size(); i++) {
- Record rec = (Record) m_factories.get(i);
- if (rec.m_ref == ref) {
- if (rec.m_reg != null) {
- rec.m_reg.unregister();
- rec.m_fact = null;
- }
- m_tracker.ungetService(rec.m_ref);
- m_factories.remove(rec);
- return;
- }
- }
- }
-
- /**
- * Start the registry management.
- */
- public void start() {
- m_tracker = new Tracker(m_global, Factory.class.getName(), this);
- m_tracker.open();
- }
-
- /**
- * Stop the registry management.
- */
- public synchronized void stop() {
- m_tracker.close();
- m_registry.reset();
- for (int i = 0; i < m_factories.size(); i++) {
- Record rec = (Record) m_factories.get(i);
- removeFactory(rec.m_ref);
- }
- m_tracker = null;
- }
-
- /**
- * Check if the factory list contain the given reference.
- *
- * @param ref : the reference to find.
- * @return true if the list contains the given reference.
- */
- private boolean containsRef(ServiceReference ref) {
- for (int i = 0; i < m_factories.size(); i++) {
- Record rec = (Record) m_factories.get(i);
- if (rec.m_ref == ref) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Add a bundle listener.
- * Delegate on the global bundle context.
- * @param arg0 : bundle listener to add
- * @see org.osgi.framework.BundleContext#addBundleListener(org.osgi.framework.BundleListener)
- */
- public void addBundleListener(BundleListener arg0) {
- m_global.addBundleListener(arg0);
- }
-
- /**
- * Add a framework listener.
- * Delegate on the global bundle context.
- * @param arg0 : framework listener to add.
- * @see org.osgi.framework.BundleContext#addFrameworkListener(org.osgi.framework.FrameworkListener)
- */
- public void addFrameworkListener(FrameworkListener arg0) {
- m_global.addFrameworkListener(arg0);
- }
-
- /**
- * Create a LDAP filter.
- * @param arg0 : String-form of the filter
- * @return the created filter object
- * @throws InvalidSyntaxException : if the given argument is not a valid against the LDAP grammar.
- * @see org.osgi.framework.BundleContext#createFilter(java.lang.String)
- */
- public Filter createFilter(String arg0) throws InvalidSyntaxException {
- return m_global.createFilter(arg0);
- }
-
- /**
- * Get the current bundle.
- * @return the current bundle
- * @see org.osgi.framework.BundleContext#getBundle()
- */
- public Bundle getBundle() {
- return m_global.getBundle();
- }
-
- /**
- * Get the bundle object with the given id.
- * @param id : bundle id
- * @return the bundle object
- * @see org.osgi.framework.BundleContext#getBundle(long)
- */
- public Bundle getBundle(long id) {
- return m_global.getBundle(id);
- }
-
- /**
- * Get installed bundles.
- * @return the list of installed bundles
- * @see org.osgi.framework.BundleContext#getBundles()
- */
- public Bundle[] getBundles() {
- return m_global.getBundles();
- }
-
-
- /**
- * Get a data file.
- * @param filename : File name.
- * @return the File object
- * @see org.osgi.framework.BundleContext#getDataFile(java.lang.String)
- */
- public File getDataFile(String filename) {
- return m_global.getDataFile(filename);
- }
-
- /**
- * Get a property value.
- * @param key : key of the asked property
- * @return the property value (object) or null if no property are associated with the given key
- * @see org.osgi.framework.BundleContext#getProperty(java.lang.String)
- */
- public String getProperty(String key) {
- return m_global.getProperty(key);
- }
-
- /**
- * Install a bundle.
- * @param location : URL of the bundle to install
- * @return the installed bundle
- * @throws BundleException : if the bundle cannot be installed correctly
- * @see org.osgi.framework.BundleContext#installBundle(java.lang.String)
- */
- public Bundle installBundle(String location) throws BundleException {
- return m_global.installBundle(location);
- }
-
- /**
- * Install a bundle.
- * @param location : URL of the bundle to install
- * @param input :
- * @return the installed bundle
- * @throws BundleException : if the bundle cannot be installed correctly
- * @see org.osgi.framework.BundleContext#installBundle(java.lang.String, java.io.InputStream)
- */
- public Bundle installBundle(String location, InputStream input) throws BundleException {
- return m_global.installBundle(location, input);
- }
-
- /**
- * Remove a bundle listener.
- * @param listener : the listener to remove
- * @see org.osgi.framework.BundleContext#removeBundleListener(org.osgi.framework.BundleListener)
- */
- public void removeBundleListener(BundleListener listener) {
- m_global.removeBundleListener(listener);
- }
-
- /**
- * Remove a framework listener.
- * @param listener : the listener to remove
- * @see org.osgi.framework.BundleContext#removeFrameworkListener(org.osgi.framework.FrameworkListener)
- */
- public void removeFrameworkListener(FrameworkListener listener) {
- m_global.removeFrameworkListener(listener);
- }
-
- /**
- * A new factory is detected.
- * @param reference : service reference
- * @return true if not already imported.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference reference) {
- if (!containsRef(reference)) {
- return true;
- }
- return false;
- }
-
- /**
- * A matching reference has been added. The import factory can now be imported.
- * @param reference : the added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference reference) {
- importFactory(reference);
- }
-
- /**
- * An imported factory is modified.
- * @param reference : modified reference
- * @param service : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference reference, Object service) {
- for (int i = 0; i < m_factories.size(); i++) {
- Record rec = (Record) m_factories.get(i);
- if (rec.m_ref == reference) {
- Dictionary dict = new Properties();
- for (int j = 0; j < reference.getPropertyKeys().length; j++) {
- dict.put(reference.getPropertyKeys()[j], reference.getProperty(reference.getPropertyKeys()[j]));
- }
- rec.m_reg.setProperties(dict);
- return;
- }
- }
- }
-
- /**
- * An imported factory disappears.
- * @param reference : reference
- * @param service : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference reference, Object service) {
- if (containsRef(reference)) {
- removeFactory(reference);
- }
-
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
deleted file mode 100644
index 73a61e7..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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;
-
-import java.util.Dictionary;
-import java.util.List;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.Factory;
-import org.apache.felix.ipojo.FactoryStateListener;
-import org.apache.felix.ipojo.MissingHandlerException;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.UnacceptableConfiguration;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.osgi.framework.BundleContext;
-
-/**
- * Bridge representing a Factory inside a composition.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class FactoryProxy implements Factory {
-
- /**
- * Delegated factory.
- */
- private Factory m_delegate;
-
- /**
- * Destination context.
- */
- private ServiceContext m_context;
-
- /**
- * Constructor.
- * @param fact : the targeted factory.
- * @param s : the service context to target.
- */
- public FactoryProxy(Factory fact, ServiceContext s) {
- m_delegate = fact;
- m_context = s;
- }
-
- /**
- * Create an instance manager (i.e. component type instance).
- * @param configuration : the configuration properties for this component.
- * @return the created instance manager.
- * @throws UnacceptableConfiguration : when a given configuration is not valid.
- * @throws MissingHandlerException : occurs when the creation failed due to a missing handler (the factory should be invalid)
- * @throws ConfigurationException : occurs when the creation failed due to a configuration issue
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
- */
- public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
- return m_delegate.createComponentInstance(configuration, m_context);
- }
-
- /**
- * Create an instance manager (i.e. component type instance). This has these
- * service interaction in the scope given in argument.
- * @param configuration : the configuration properties for this component.
- * @param serviceContext : the service context of the component.
- * @return the created instance manager.
- * @throws UnacceptableConfiguration : when the given configuration is not valid.
- * @throws MissingHandlerException : when at least one handler is missing.
- * @throws ConfigurationException : when an issue occurs during the oconfiguration of the instance.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary,
- * org.apache.felix.ipojo.ServiceContext)
- */
- public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
- return m_delegate.createComponentInstance(configuration, serviceContext);
- }
-
- /**
- * Get the component type information containing provided service,
- * configuration properties ...
- * @return the component type information.
- * @see org.apache.felix.ipojo.Factory#getDescription()
- */
- public Element getDescription() {
- return m_delegate.getDescription();
- }
-
- /**
- * Return the factory name.
- * @return the name of the factory.
- * @see org.apache.felix.ipojo.Factory#getName()
- */
- public String getName() {
- return m_delegate.getName();
- }
-
- /**
- * Check if the given configuration is acceptable as a configuration of a
- * component instance.
- * @param conf : the configuration to test
- * @return true if the configuration is acceptable
- * @see org.apache.felix.ipojo.Factory#isAcceptable(java.util.Dictionary)
- */
- public boolean isAcceptable(Dictionary conf) {
- return m_delegate.isAcceptable(conf);
- }
-
- /**
- * Reconfigure an instance already created. This configuration need to have
- * the name property to identify the instance.
- * @param conf : the configuration to reconfigure the instance.
- * @throws UnacceptableConfiguration : if the given configuration is not
- * consistent for the targeted instance.
- * @throws MissingHandlerException : when at least one handler is missing
- * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
- */
- public void reconfigure(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
- m_delegate.reconfigure(conf);
- }
-
- /**
- * Add a factory listener.
- * @param l : the listener to add.
- * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
- */
- public void addFactoryStateListener(FactoryStateListener l) {
- m_delegate.addFactoryStateListener(l);
-
- }
-
- public List getMissingHandlers() {
- return m_delegate.getMissingHandlers();
- }
-
- public List getRequiredHandlers() {
- return m_delegate.getRequiredHandlers();
- }
-
- /**
- * Remove a service listener.
- * @param l : the listener to remove
- * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
- */
- public void removeFactoryStateListener(FactoryStateListener l) {
- m_delegate.removeFactoryStateListener(l);
-
- }
-
- public ComponentDescription getComponentDescription() {
- return m_delegate.getComponentDescription();
- }
-
- public String getClassName() {
- return m_delegate.getClassName();
- }
-
- public int getState() {
- return m_delegate.getState();
- }
-
- public BundleContext getBundleContext() {
- return m_delegate.getBundleContext();
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/architecture/ArchitectureHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/architecture/ArchitectureHandler.java
deleted file mode 100644
index ff9ab36..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/architecture/ArchitectureHandler.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.architecture;
-
-import java.util.Dictionary;
-
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.architecture.Architecture;
-import org.apache.felix.ipojo.architecture.InstanceDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-
-/**
- * Composite Architecture Handler.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ArchitectureHandler extends CompositeHandler implements Architecture {
-
- /**
- * Name of the component.
- */
- private String m_name;
-
- /**
- * 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_name = (String) configuration.get("name");
- }
-
- /**
- * Stop the handler.
- * @see org.apache.felix.ipojo.Handler#stop()
- */
- public void stop() { }
-
- /**
- * Start the handler.
- * @see org.apache.felix.ipojo.Handler#start()
- */
- public void start() {
- log(Logger.INFO, "Start composite architecture handler with " + m_name + " name");
- }
-
- /**
- * Get the instance description.
- * @return the instance description
- * @see org.apache.felix.ipojo.architecture.Architecture#getDescription()
- */
- public InstanceDescription getInstanceDescription() {
- return getCompositeManager().getInstanceDescription();
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
deleted file mode 100644
index b4f82b9..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * 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.instance;
-
-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.CompositeHandler;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.Factory;
-import org.apache.felix.ipojo.InstanceManager;
-import org.apache.felix.ipojo.InstanceStateListener;
-import org.apache.felix.ipojo.MissingHandlerException;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.UnacceptableConfiguration;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.ParseException;
-import org.apache.felix.ipojo.util.Logger;
-
-/**
- * Composite Instance Handler.
- * This handler allows creating an instance inside a composite.
- * This instance is determine by its type and a configuration.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class InstanceHandler extends CompositeHandler implements InstanceStateListener {
-
- /**
- * Internal context.
- */
- private ServiceContext m_scope;
-
- /**
- * Is the handler valid ?
- * (Lifecycle controller)
- */
- private boolean m_isValid = false;
-
- /**
- * Available factories.
- */
- private Factory[] m_factories;
-
-
- /**
- * This structure aims to manage a configuration. It stores all necessary
- * information to create an instance and to track the factory.
- */
- class ManagedConfiguration {
- /**
- * Configuration of the instance to create.
- */
- private Dictionary m_configuration;
-
- /**
- * Factory name.
- */
- private String m_factoryName;
-
- /**
- * Created instance.
- */
- private ComponentInstance m_instance;
-
- /**
- * Desired Factory (can be the classname).
- */
- private String m_desiredFactory;
-
- /**
- * Constructor.
- *
- * @param conf : the configuration to create.
- */
- ManagedConfiguration(Dictionary conf) {
- m_configuration = conf;
- m_desiredFactory = (String) conf.get("component");
- }
-
- /**
- * Return the managed configuration.
- * @return the configuration.
- */
- Dictionary getConfiguration() {
- return m_configuration;
- }
-
- /**
- * Return the used factory name.
- * @return the factory name
- */
- String getFactory() {
- return m_factoryName;
- }
-
- String getNeededFactoryName() {
- return m_desiredFactory;
- }
-
- /**
- * Return the created instance.
- * @return the instance (or null if no instance are created).
- */
- ComponentInstance getInstance() {
- return m_instance;
- }
-
- /**
- * Set the factory name.
- *
- * @param name : the factory name.
- */
- void setFactory(String name) {
- m_factoryName = name;
- }
-
- /**
- * Set the instance object.
- *
- * @param instance : the instance
- */
- void setInstance(ComponentInstance instance) {
- m_instance = instance;
- }
- }
-
- /**
- * Configurations to create and maintains.
- */
- private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];
-
- /**
- * Create an instance using the given factory and the given configuration.
- *
- * @param fact : the factory name to used.
- * @param config : the configuration.
- */
- private void createInstance(Factory fact, ManagedConfiguration config) {
- Dictionary conf = config.getConfiguration();
- try {
- config.setInstance(fact.createComponentInstance(conf, m_scope));
- config.setFactory(fact.getName());
- config.getInstance().addInstanceStateListener(this);
- } catch (UnacceptableConfiguration e) {
- log(Logger.ERROR, "A factory is available for the configuration but the configuration is not acceptable", e);
- } catch (MissingHandlerException e) {
- log(Logger.ERROR, "The instance creation has failed, at least one handler is missing", e);
- } catch (ConfigurationException e) {
- log(Logger.ERROR, "The instance creation has failed, an error during the configuration has occured", e);
- }
- }
-
- /**
- * A new valid factory appears.
- * @param f : factory.
- */
- public void bindFactory(Factory f) {
- boolean implicated = false;
- String factName = f.getName();
- String className = f.getComponentDescription().getClassName();
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null && (m_configurations[i].getNeededFactoryName().equals(factName) || m_configurations[i].getNeededFactoryName().equals(className))) {
- createInstance(f, m_configurations[i]);
- implicated = true;
- }
- }
- if (implicated && ! m_isValid) {
- checkValidity();
- }
- }
-
- /**
- * An existing factory disappears or becomes invalid.
- * @param f : factory
- */
- public void unbindFactory(Factory f) {
- boolean implicated = false;
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(f.getName())) {
- m_configurations[i].setInstance(null);
- m_configurations[i].setFactory(null);
- implicated = true;
- }
- }
- if (implicated && m_isValid) {
- checkValidity();
- }
- }
-
- /**
- * Stop all created instances.
- */
- public synchronized void stop() {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null) {
- m_configurations[i].getInstance().removeInstanceStateListener(this);
- if (m_configurations[i].getInstance().getState() != ComponentInstance.DISPOSED) {
- m_configurations[i].getInstance().dispose();
- }
- }
- m_configurations[i].setInstance(null);
- m_configurations[i].setFactory(null);
- }
- m_configurations = new ManagedConfiguration[0];
- }
-
- /**
- * Configure method.
- * @param metadata : component type metadata.
- * @param configuration : instance configuration.
- * @throws ConfigurationException : occurs an instance cannot be parsed correctly.
- * @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) throws ConfigurationException {
- m_scope = getCompositeManager().getServiceContext();
- Element[] instances = metadata.getElements("instance");
- m_configurations = new ManagedConfiguration[instances.length];
- for (int i = 0; i < instances.length; i++) {
- Dictionary conf = null;
- try {
- conf = parseInstance(instances[i]);
- } catch (ParseException e) {
- log(Logger.ERROR, "An instance cannot be parsed correctly", e);
- throw new ConfigurationException("An instance cannot be parsed correctly : " + e.getMessage());
- }
- m_configurations[i] = new ManagedConfiguration(conf);
- }
- }
-
- /**
- * Parse an Element to get a dictionary.
- * @param instance : the Element describing an instance.
- * @return : the resulting dictionary
- * @throws ParseException : occurs when a configuration cannot be parse correctly.
- */
- private Dictionary parseInstance(Element instance) throws ParseException {
- Dictionary dict = new Properties();
- String name = instance.getAttribute("name");
- if (name != null) {
- dict.put("name", name);
- }
-
- String comp = instance.getAttribute("component");
- if (comp == null) {
- throw new ParseException("An instance does not have the 'component' attribute");
- } else {
- dict.put("component", comp);
- }
-
- for (int i = 0; i < instance.getElements("property").length; i++) {
- parseProperty(instance.getElements("property")[i], dict);
- }
-
- return dict;
- }
-
- /**
- * Parse a property.
- * @param prop : the current element to parse
- * @param dict : the dictionary to populate
- * @throws ParseException : occurs if the property cannot be parsed correctly
- */
- private void parseProperty(Element prop, Dictionary dict) throws ParseException {
- // Check that the property has a name
- String name = prop.getAttribute("name");
- String value = prop.getAttribute("value");
- if (name == null) { throw new ParseException("A property does not have the 'name' attribute"); }
- // Final case : the property element has a 'value' attribute
- if (value != null) {
- dict.put(name, value);
- } else {
- // Recursive case
- // Check if there is 'property' element
- Element[] subProps = prop.getElements("property");
- if (subProps.length == 0) { throw new ParseException("A complex property must have at least one 'property' sub-element"); }
- Dictionary dict2 = new Properties();
- for (int i = 0; i < subProps.length; i++) {
- parseProperty(subProps[i], dict2);
- dict.put(prop.getAttribute("name"), dict2);
- }
- }
- }
-
- /**
- * Start method.
- * @see org.apache.felix.ipojo.CompositeHandler#start()
- */
- public void start() {
- for (int j = 0; j < m_factories.length; j++) {
- String factName = m_factories[j].getName();
- String className = m_factories[j].getClassName();
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null && (m_configurations[i].getNeededFactoryName().equals(factName) || m_configurations[i].getNeededFactoryName().equals(className))) {
- createInstance(m_factories[j], m_configurations[i]);
- }
- }
- }
-
- checkValidity();
- }
-
- /**
- * Check handler validity.
- * The method update the m_validity field.
- * @return the new validity.
- */
- private boolean checkValidity() {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null || m_configurations[i].getInstance().getState() != ComponentInstance.VALID) {
- m_isValid = false;
- return false;
- }
- }
- m_isValid = true;
- return true;
- }
-
- /**
- * Instance state listener.
- * This method listens when managed instance states change.
- * @param instance : instance
- * @param newState : the now state of the given instance
- * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
- */
- public void stateChanged(ComponentInstance instance, int newState) {
- switch (newState) {
- case ComponentInstance.DISPOSED:
- case ComponentInstance.STOPPED:
- break; // Should not happen
- case ComponentInstance.VALID:
- if (!m_isValid) {
- checkValidity();
- }
- break;
- case ComponentInstance.INVALID:
- if (m_isValid) {
- checkValidity();
- }
- break;
- default:
- break;
-
- }
- }
-
- /**
- * Method returning an instance object of the given component type.
- * This method must be called only on 'primitive' type.
- * @param type : type.
- * @return an instance object or null if not found.
- */
- public Object getObjectFromInstance(String type) {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null && type.equals(m_configurations[i].getFactory()) && m_configurations[i].getInstance().getState() == ComponentInstance.VALID) {
- return ((InstanceManager) m_configurations[i].getInstance()).getPojoObject();
- }
- }
- return null;
- }
-
- /**
- * Return the handler description, i.e. the state of created instances.
- * @return the handler description.
- * @see org.apache.felix.ipojo.CompositeHandler#getDescription()
- */
- public HandlerDescription getDescription() {
- List l = new ArrayList();
- for (int i = 0; i < m_configurations.length; i++) {
- l.add(m_configurations[i]);
- }
- return new InstanceHandlerDescription(this, l);
- }
-
- /**
- * Get the list of used component type.
- * @return the list containing the used component type
- */
- public List getUsedType() {
- List result = new ArrayList();
- for (int i = 0; i < m_configurations.length; i++) {
- result.add(m_configurations[i].getConfiguration().get("component"));
- }
- return result;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java
deleted file mode 100644
index 844e3e6..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.instance;
-
-import java.util.List;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.composite.instance.InstanceHandler.ManagedConfiguration;
-import org.apache.felix.ipojo.metadata.Attribute;
-import org.apache.felix.ipojo.metadata.Element;
-
-/**
- * Description of the Instance Handler.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class InstanceHandlerDescription extends HandlerDescription {
-
- /**
- * List of managed instances.
- */
- private List m_instances;
-
- /**
- * Constructor.
- *
- * @param h : handler
- * @param insts : list of component instances
- */
- public InstanceHandlerDescription(CompositeHandler h, List insts) {
- super(h);
- m_instances = insts;
- }
-
- /**
- * Build handler description.
- * @return the handler description
- * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
- */
- public Element getHandlerInfo() {
- Element instances = super.getHandlerInfo();
- for (int i = 0; i < m_instances.size(); i++) {
- ManagedConfiguration inst = (ManagedConfiguration) m_instances.get(i);
- Element instance = new Element("Instance", "");
- if (inst.getInstance() != null) {
- instance.addAttribute(new Attribute("Factory", inst.getFactory()));
- instance.addAttribute(new Attribute("Name", inst.getInstance().getInstanceName()));
- String state = null;
- switch(inst.getInstance().getState()) {
- case ComponentInstance.DISPOSED :
- state = "disposed"; break;
- case ComponentInstance.STOPPED :
- state = "stopped"; break;
- case ComponentInstance.VALID :
- state = "valid"; break;
- case ComponentInstance.INVALID :
- state = "invalid"; break;
- default :
- break;
- }
- instance.addAttribute(new Attribute("State", state));
- instance.addElement(inst.getInstance().getInstanceDescription().getDescription());
- } else {
- instance.addAttribute(new Attribute("Factory", inst.getConfiguration().get("component").toString()));
- instance.addAttribute(new Attribute("State", "Not Available"));
- }
- instances.addElement(instance);
- }
- return instances;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ExportDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ExportDescription.java
deleted file mode 100644
index 9994698..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ExportDescription.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.importer;
-
-import java.util.List;
-
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Attribute;
-import org.apache.felix.ipojo.metadata.Element;
-
-/**
- * Description of the Import Export Handler.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ExportDescription extends HandlerDescription {
-
- /**
- * List of exports.
- */
- private List m_exports;
-
- /**
- * Constructor.
- *
- * @param h : composite handler
- * @param exporters : list of managed exports
- */
- public ExportDescription(CompositeHandler h, List exporters) {
- super(h);
- m_exports = exporters;
- }
-
- /**
- * Build the ImportExport handler description.
- * @return the handler description
- * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
- */
- public Element getHandlerInfo() {
- Element handler = super.getHandlerInfo();
- for (int i = 0; i < m_exports.size(); i++) {
- ServiceExporter exp = (ServiceExporter) m_exports.get(i);
- Element expo = new Element("Exports", "");
- expo.addAttribute(new Attribute("Specification", exp.getSpecification()));
- expo.addAttribute(new Attribute("Filter", exp.getFilter()));
- if (exp.isSatisfied()) {
- expo.addAttribute(new Attribute("State", "resolved"));
- } else {
- expo.addAttribute(new Attribute("State", "unresolved"));
- }
- handler.addElement(expo);
- }
- return handler;
-
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ExportHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ExportHandler.java
deleted file mode 100644
index 707dac8..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ExportHandler.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.importer;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.osgi.framework.BundleContext;
-
-/**
- * This handler manages the import and the export of services from /
- * to the parent context.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ExportHandler extends CompositeHandler {
-
- /**
- * Service Scope.
- */
- private ServiceContext m_scope;
-
- /**
- * Parent context.
- */
- private BundleContext m_context;
-
- /**
- * List of exporters.
- */
- private List m_exporters = new ArrayList();
-
- /**
- * Is the handler valid ?
- * (Lifecycle controller)
- */
- private boolean m_valid;
-
- /**
- * Initialize the component type.
- * @param cd : component type description to populate.
- * @param metadata : component type metadata.
- * @throws ConfigurationException : occurs when the 'specification' attribute is missing
- * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription, org.apache.felix.ipojo.metadata.Element)
- */
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
- // Update the component type description
- Element[] exp = metadata.getElements("exports");
- for (int i = 0; i < exp.length; i++) {
- String spec = exp[i].getAttribute("specification");
- if (spec != null) {
- cd.addProvidedServiceSpecification(spec);
- } else {
- // Malformed exports
- throw new ConfigurationException("Malformed exports - Missing the specification attribute");
- }
- }
- }
-
- /**
- * Configure the handler.
- * @param metadata : the metadata of the component
- * @param conf : the instance configuration
- * @throws ConfigurationException : if the specification attribute is missing in the metadata.
- * @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 conf) throws ConfigurationException {
- m_context = getCompositeManager().getContext();
- m_scope = getCompositeManager().getServiceContext();
-
- Element[] exp = metadata.getElements("exports");
-
- for (int i = 0; i < exp.length; i++) {
- boolean optional = false;
- boolean aggregate = false;
- String specification = exp[i].getAttribute("specification");
- String filter = "(objectClass=" + specification + ")";
-
- String opt = exp[i].getAttribute("optional");
- optional = opt != null && opt.equalsIgnoreCase("true");
-
- String agg = exp[i].getAttribute("aggregate");
- aggregate = agg != null && agg.equalsIgnoreCase("true");
-
- String f = exp[i].getAttribute("filter");
- if (f != null) {
- filter = "(&" + filter + f + ")";
- }
- ServiceExporter si = new ServiceExporter(specification, filter, aggregate, optional, m_scope, m_context, this);
- m_exporters.add(si);
- }
- }
-
- /**
- * Start the handler.
- * Start importers and exporters.
- * @see org.apache.felix.ipojo.CompositeHandler#start()
- */
- public void start() {
- for (int i = 0; i < m_exporters.size(); i++) {
- ServiceExporter se = (ServiceExporter) m_exporters.get(i);
- se.start();
- }
-
- isHandlerValid();
-
- }
-
- /**
- * Stop the handler.
- * Stop all importers and exporters.
- * @see org.apache.felix.ipojo.CompositeHandler#stop()
- */
- public void stop() {
- for (int i = 0; i < m_exporters.size(); i++) {
- ServiceExporter se = (ServiceExporter) m_exporters.get(i);
- se.stop();
- }
- }
-
- /**
- * Check the handler validity.
- * @return true if all importers and exporters are valid
- * @see org.apache.felix.ipojo.CompositeHandler#isValid()
- */
- private boolean isHandlerValid() {
- for (int i = 0; i < m_exporters.size(); i++) {
- ServiceExporter se = (ServiceExporter) m_exporters.get(i);
- if (!se.isSatisfied()) {
- m_valid = false;
- return false;
- }
- }
-
- m_valid = true;
- return true;
- }
-
- /**
- * Notify the handler that an exporter becomes invalid.
- *
- * @param exporter : the implicated exporter.
- */
- protected void invalidating(ServiceExporter exporter) {
- // An export is no more valid
- if (m_valid) {
- m_valid = false;
- }
-
- }
-
- /**
- * Notify the handler that an exporter becomes valid.
- *
- * @param exporter : the implicated exporter.
- */
- protected void validating(ServiceExporter exporter) {
- // An import becomes valid
- if (!m_valid) {
- isHandlerValid();
- }
- }
-
- /**
- * Get the import / export handler description.
- * @return the handler description
- * @see org.apache.felix.ipojo.CompositeHandler#getDescription()
- */
- public HandlerDescription getDescription() {
- return new ExportDescription(this, m_exporters);
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportDescription.java
deleted file mode 100644
index 0a56014..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportDescription.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.importer;
-
-import java.util.List;
-
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Attribute;
-import org.apache.felix.ipojo.metadata.Element;
-
-/**
- * Description of the Import Export Handler.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ImportDescription extends HandlerDescription {
-
- /**
- * List of exports.
- */
- private List m_imports;
-
- /**
- * Constructor.
- *
- * @param h : composite handler
- * @param importers : list of managed imports
- */
- public ImportDescription(CompositeHandler h, List importers) {
- super(h);
- m_imports = importers;
- }
-
- /**
- * Build the ImportExport handler description.
- * @return the handler description
- * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
- */
- public Element getHandlerInfo() {
- Element handler = super.getHandlerInfo();
- for (int i = 0; i < m_imports.size(); i++) {
- ServiceImporter imp = (ServiceImporter) m_imports.get(i);
- Element impo = new Element("Requires", "");
- impo.addAttribute(new Attribute("Specification", imp.getSpecification()));
- if (imp.getFilter() != null) {
- impo.addAttribute(new Attribute("Filter", imp.getFilter()));
- }
- if (imp.isSatisfied()) {
- impo.addAttribute(new Attribute("State", "resolved"));
- for (int j = 0; j < imp.getProviders().size(); j++) {
- Element pr = new Element("Provider", "");
- pr.addAttribute(new Attribute("name", (String) imp.getProviders().get(j)));
- impo.addElement(pr);
- }
- } else {
- impo.addAttribute(new Attribute("State", "unresolved"));
- }
- handler.addElement(impo);
- }
- return handler;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java
deleted file mode 100644
index b54397f..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.importer;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.PolicyServiceContext;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-import org.osgi.framework.BundleContext;
-
-/**
- * This handler manages the import and the export of services from /
- * to the parent context.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ImportHandler extends CompositeHandler {
-
- /**
- * Service Scope.
- */
- private ServiceContext m_scope;
-
- /**
- * Parent context.
- */
- private BundleContext m_context;
-
- /**
- * List of importers.
- */
- private List m_importers = new ArrayList();
-
- /**
- * Is the handler valid ?
- * (Lifecycle controller)
- */
- private boolean m_valid;
-
-
- /**
- * Configure the handler.
- *
- * @param metadata : the metadata of the component
- * @param conf : the instance configuration
- * @throws ConfigurationException : the specification attribute is missing.
- * @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 conf) throws ConfigurationException {
- m_context = getCompositeManager().getContext();
- m_scope = getCompositeManager().getServiceContext();
- Element[] imp = metadata.getElements("requires");
-
- // Get instance filters
- Dictionary filtersConfiguration = null;
- if (conf.get("requires.filters") != null) {
- filtersConfiguration = (Dictionary) conf.get("requires.filters");
- }
-
- for (int i = 0; i < imp.length; i++) {
- boolean optional = false;
- boolean aggregate = false;
- String specification = imp[i].getAttribute("specification");
-
- if (specification != null) {
- String opt = imp[i].getAttribute("optional");
- optional = opt != null && opt.equalsIgnoreCase("true");
-
- String agg = imp[i].getAttribute("aggregate");
- aggregate = agg != null && agg.equalsIgnoreCase("true");
-
- String filter = "(&(objectClass=" + specification + ")(!(instance.name=" + getCompositeManager().getInstanceName() + ")))"; // Cannot import yourself
- String f = imp[i].getAttribute("filter");
- if (f != null) {
- filter = "(&" + filter + f + ")";
- }
-
- String id = imp[i].getAttribute("id");
-
- int scopePolicy = -1;
- String scope = imp[i].getAttribute("scope");
- if (scope != null) {
- if (scope.equalsIgnoreCase("global")) {
- scopePolicy = PolicyServiceContext.GLOBAL;
- } else if (scope.equalsIgnoreCase("composite")) {
- scopePolicy = PolicyServiceContext.LOCAL;
- } else if (scope.equalsIgnoreCase("composite+global")) {
- scopePolicy = PolicyServiceContext.LOCAL_AND_GLOBAL;
- }
- }
-
- // Configure instance filter if available
- if (filtersConfiguration != null && id != null && filtersConfiguration.get(id) != null) {
- filter = (String) filtersConfiguration.get(id);
- }
-
- ServiceImporter si = new ServiceImporter(specification, filter, aggregate, optional, m_context, m_scope, scopePolicy, id, this);
- m_importers.add(si);
- } else { // Malformed import
- log(Logger.ERROR, "Malformed imports : the specification attribute is mandatory");
- throw new ConfigurationException("Malformed imports : the specification attribute is mandatory");
- }
- }
- }
-
- /**
- * Start the handler.
- * Start importers and exporters.
- * @see org.apache.felix.ipojo.CompositeHandler#start()
- */
- public void start() {
- for (int i = 0; i < m_importers.size(); i++) {
- ServiceImporter si = (ServiceImporter) m_importers.get(i);
- si.start();
- }
- isHandlerValid();
- }
-
- /**
- * Stop the handler.
- * Stop all importers and exporters.
- * @see org.apache.felix.ipojo.CompositeHandler#stop()
- */
- public void stop() {
- for (int i = 0; i < m_importers.size(); i++) {
- ServiceImporter si = (ServiceImporter) m_importers.get(i);
- si.stop();
- }
- }
-
- /**
- * Check the handler validity.
- * @return true if all importers and exporters are valid
- * @see org.apache.felix.ipojo.CompositeHandler#isValid()
- */
- public boolean isHandlerValid() {
- for (int i = 0; i < m_importers.size(); i++) {
- ServiceImporter si = (ServiceImporter) m_importers.get(i);
- if (!si.isSatisfied()) {
- m_valid = false;
- return false;
- }
- }
- m_valid = true;
- return true;
- }
-
- /**
- * Notify the handler that an importer is no more valid.
- *
- * @param importer : the implicated importer.
- */
- protected void invalidating(ServiceImporter importer) {
- // An import is no more valid
- if (m_valid) {
- m_valid = false;
- }
- }
-
- /**
- * Notify the handler that an importer becomes valid.
- *
- * @param importer : the implicated importer.
- */
- protected void validating(ServiceImporter importer) {
- // An import becomes valid
- if (!m_valid) {
- isHandlerValid();
- }
- }
-
- /**
- * Get the import / export handler description.
- * @return the handler description
- * @see org.apache.felix.ipojo.CompositeHandler#getDescription()
- */
- public HandlerDescription getDescription() {
- return new ImportDescription(this, m_importers);
- }
-
- public List getRequirements() {
- return m_importers;
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java
deleted file mode 100644
index 52347c5..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * 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.importer;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.util.Tracker;
-import org.apache.felix.ipojo.util.TrackerCustomizer;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-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 TrackerCustomizer {
-
- /**
- * 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 of the handler.
- */
- private ExportHandler m_handler;
-
- /**
- * Is the exporter valid?
- */
- private boolean m_isValid;
-
- /**
- * Tracker tracking internal service (to export).
- */
- private Tracker m_tracker;
-
- /**
- * Structure Reference, Registration, Service Object.
- */
- 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,
- ExportHandler exp) {
- this.m_destination = to;
- this.m_origin = from;
- this.m_handler = 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 provider tracking and the publication.
- */
- public void start() {
- m_tracker = new Tracker(m_origin, m_filter, this);
- m_tracker.open();
-
- 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_handler.getCompositeManager().getInstanceName());
- prop.put("factory.name", m_handler.getCompositeManager().getFactory().getName());
-
- return prop;
- }
-
- /**
- * Stop an exporter.
- * Remove the service listener
- * Unregister all exported services.
- */
- public void stop() {
- m_tracker.close();
-
- 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();
- rec.m_reg = null;
- m_tracker.ungetService(rec.m_ref);
- rec.m_ref = null;
- }
- }
-
- m_tracker = null;
- m_records.clear();
-
- }
-
- /**
- * Check the exporter validity.
- * @return true if optional or 'valid'
- */
- public boolean isSatisfied() {
- return m_optional || 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;
- }
-
- protected String getSpecification() {
- return m_specification;
- }
-
- public String getFilter() {
- return m_filterStr;
- }
-
- /**
- * An exported service appears.
- * @param reference : service reference
- * @return true as the filter guaranty the export.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference reference) {
- return true;
- }
-
- /**
- * A service has been added in the tracker. Can now thest the validity of the exporter.
- * @param reference : the new reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference reference) {
- Record rec = new Record();
- rec.m_ref = reference;
- 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_tracker.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_handler.validating(this);
- }
- }
-
- /**
- * An exported service was modified.
- * @param reference : modified reference
- * @param service : service object
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference reference, Object service) {
- // A published service has been modified
- List l = getRecordsByRef(reference);
- for (int i = 0; i < l.size(); i++) { // Update the implied record
- Record rec = (Record) l.get(i);
- if (rec.m_reg != null) {
- rec.m_reg.setProperties(getProps(reference));
- }
- }
- }
-
- /**
- * An exported service disappears.
- * @param reference : service reference
- * @param service : service object
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference reference, Object service) {
- List l = getRecordsByRef(reference);
- 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_tracker.ungetService(rec.m_ref);
- }
- }
- m_records.removeAll(l);
-
- // Check the validity & if we need to re-import 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 which disappears - create the next one
- rec.m_svcObject = m_tracker.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_handler.invalidating(this);
- }
- }
-
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java
deleted file mode 100644
index 9118fd2..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * 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.importer;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.felix.ipojo.PolicyServiceContext;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.util.Tracker;
-import org.apache.felix.ipojo.util.TrackerCustomizer;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * Import a service form the parent to the internal service registry.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ServiceImporter implements TrackerCustomizer {
-
- /**
- * Destination context.
- */
- private ServiceContext m_destination;
-
- /**
- * Context where service need to be found.
- */
- private ServiceContext m_origin;
-
- /**
- * Imported Specification.
- */
- private String m_specification;
-
- /**
- * LDAP filter filtering external providers.
- */
- private Filter m_filter;
-
- /**
- * String form of the LDAP filter.
- */
- private String m_filterStr;
-
- /**
- * Should we importer several providers?
- */
- private boolean m_aggregate = false;
-
- /**
- * Is the import optional?
- */
- private boolean m_optional = false;
-
- /**
- * Is the importer valid?
- */
- private boolean m_isValid;
-
- /**
- * Resolving policy.
- */
- private int m_policy;
-
- /**
- * TRacker tracking imported service.
- */
- private Tracker m_tracker;
-
- /**
- * Reference on the handler.
- */
- private ImportHandler m_handler;
-
- private class Record {
- /**
- * External Reference.
- */
- private ServiceReference m_ref;
- /**
- * Internal Registration.
- */
- private ServiceRegistration m_reg;
- /**
- * Exposed Object.
- */
- private Object m_svcObject;
-
- /**
- * Test object equality.
- * @param o : object to confront against the current object.
- * @return true if the two objects are equals (same service reference).
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object o) {
- if (o instanceof Record) {
- Record rec = (Record) o;
- return rec.m_ref == m_ref;
- }
- return false;
- }
- }
-
- /**
- * List of managed records.
- */
- private List/*<Record>*/m_records = new ArrayList()/* <Record> */;
-
- /**
- * Requirement Id.
- */
- private String m_id;
-
- /**
- * Is this requirement attached to a service-level requirement.
- */
- private boolean m_isServiceLevelRequirement;
-
- /**
- * Constructor.
- *
- * @param specification : targeted specification
- * @param filter : LDAP filter
- * @param multiple : should the importer imports several services ?
- * @param optional : is the import optional ?
- * @param from : parent context
- * @param to : internal context
- * @param policy : resolving policy
- * @param id : requirement id (may be null)
- * @param in : handler
- */
- public ServiceImporter(String specification, String filter, boolean multiple, boolean optional, BundleContext from, ServiceContext to, int policy, String id,
- ImportHandler in) {
- this.m_destination = to;
- try {
- this.m_filter = from.createFilter(filter);
- } catch (InvalidSyntaxException e) {
- e.printStackTrace();
- return;
- }
- this.m_aggregate = multiple;
- this.m_specification = specification;
- this.m_optional = optional;
- this.m_handler = in;
-
- if (m_id == null) {
- m_id = m_specification;
- } else {
- m_id = id;
- }
-
- if (policy == -1) {
- m_policy = PolicyServiceContext.LOCAL_AND_GLOBAL;
- } else {
- m_policy = policy;
- }
- }
-
- /**
- * Start method to begin the import.
- */
- public void start() {
- m_origin = new PolicyServiceContext(m_handler.getCompositeManager().getGlobalContext(), m_handler.getCompositeManager().getParentServiceContext(), m_policy);
- m_tracker = new Tracker(m_origin, m_filter, this);
- m_tracker.open();
- m_isValid = isSatisfied();
- }
-
- /**
- * Get the properties for the exposed service from the given reference.
- *
- * @param ref : the reference.
- * @return the property dictionary
- */
- 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]));
- }
- return prop;
- }
-
- /**
- * Stop the management of the import.
- */
- public void stop() {
-
- m_tracker.close();
-
- 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_tracker.ungetService(rec.m_ref);
- rec.m_ref = null;
- }
- }
-
- m_tracker = null;
- m_records.clear();
-
- }
-
- /**
- * Check if the import is satisfied.
- * @return true if the import is optional or at least one provider is imported
- */
- public boolean isSatisfied() {
- return m_optional || m_records.size() > 0;
- }
-
- /**
- * Get the record list using the given reference.
- *
- * @param ref : the reference
- * @return the list containing all record using the given 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;
- }
-
- public String getSpecification() {
- return m_specification;
- }
-
- /**
- * Build the list of imported service provider.
- * @return the list of all imported services.
- */
- protected List getProviders() {
- List l = new ArrayList();
- for (int i = 0; i < m_records.size(); i++) {
- l.add((((Record) m_records.get(i)).m_ref).getProperty("instance.name"));
- }
- return l;
-
- }
-
- public String getFilter() {
- return m_filterStr;
- }
-
- /**
- * Set that this dependency is a service level dependency.
- * This forces the scoping policy to be STRICT.
- * @param b
- */
- public void setServiceLevelDependency() {
- m_isServiceLevelRequirement = true;
- m_policy = PolicyServiceContext.LOCAL;
- }
-
- public String getId() {
- return m_id;
- }
-
- public boolean isServiceLevelRequirement() {
- return m_isServiceLevelRequirement;
- }
-
- public boolean isAggregate() {
- return m_aggregate;
- }
-
- public boolean isOptional() {
- return m_optional;
- }
-
- /**
- * A new service is detected.
- * @param reference : service reference
- * @return true if not already imported.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference reference) {
- for (int i = 0; i < m_records.size(); i++) {
- Record rec = (Record) m_records.get(i);
- if (rec.m_ref == reference) {
- return false; // Already contained
- }
- }
- return true;
- }
-
- /**
- * The given service reference was added inside the tracker list.
- * Register the internal service.
- * @param reference : added reference
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference reference) {
- Record rec = new Record();
- rec.m_ref = reference;
- 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_tracker.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_handler.validating(this);
- }
- }
-
- /**
- * An imported service was modified.
- * @param reference : service reference
- * @param service : service object (if already get)
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference reference, Object service) {
- List l = getRecordsByRef(reference);
- 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));
- }
- }
- }
-
- /**
- * An imported service disappears.
- *@param reference : service reference
- * @param service : service object (if already get)
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference reference, Object service) {
- List l = getRecordsByRef(reference);
- 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_tracker.ungetService(rec.m_ref);
- }
- }
- m_records.removeAll(l);
-
- // Check the validity & if we need to re-import 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 which disappears - create the next one
- rec.m_svcObject = m_tracker.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_handler.invalidating(this);
- }
- }
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorDescription.java
deleted file mode 100644
index c3275b9..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorDescription.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.instantiator;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Attribute;
-import org.apache.felix.ipojo.metadata.Element;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Description of the Service Creator Handler.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ServiceInstantiatorDescription extends HandlerDescription {
-
- /**
- * List of managed service instances.
- */
- private List m_instances;
-
- /**
- * Constructor.
- *
- * @param h : composite handler
- * @param insts : list of service instance
- */
- public ServiceInstantiatorDescription(CompositeHandler h, List insts) {
- super(h);
- m_instances = insts;
- }
-
- /**
- * Build service instantiator handler description.
- * @return the handler description
- * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
- */
- public Element getHandlerInfo() {
- Element services = super.getHandlerInfo();
- for (int i = 0; i < m_instances.size(); i++) {
- SvcInstance inst = (SvcInstance) m_instances.get(i);
- Element service = new Element("Service", "");
- service.addAttribute(new Attribute("Specification", inst.getSpecification()));
- String state = "unresolved";
- if (inst.isSatisfied()) {
- state = "resolved";
- }
- service.addAttribute(new Attribute("State", state));
- Map map = inst.getUsedReferences();
- Set keys = map.keySet();
- Iterator it = keys.iterator();
- while (it.hasNext()) {
- ServiceReference ref = (ServiceReference) it.next();
- Object o = map.get(ref);
- if (o != null) {
- Element fact = new Element("Factory", "");
- fact.addAttribute(new Attribute("Name", ((ComponentInstance) o).getFactory().getName()));
- service.addElement(fact);
- }
- }
- services.addElement(service);
- }
- return services;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java
deleted file mode 100644
index b0f1bac..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.instantiator;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.felix.ipojo.CompositeHandler;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.metadata.Element;
-
-/**
- * Service Instantiator Class. This handler allows to instantiate service
- * instance inside the composition.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ServiceInstantiatorHandler extends CompositeHandler {
-
- /**
- * Is the handler valid ?
- * (Lifecycle controller)
- */
- private boolean m_isValid;
-
- /**
- * List of instances to manage.
- */
- private List/* <SvcInstance> */m_instances = new ArrayList();
-
- /**
- * Configure the handler.
- *
- * @param metadata : the metadata of the component
- * @param conf : the instance configuration
- * @throws ConfigurationException : the specification attribute is missing
- * @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 conf) throws ConfigurationException {
- Element[] services = metadata.getElements("service");
- for (int i = 0; i < services.length; i++) {
- String spec = services[i].getAttribute("specification");
- if (spec == null) {
- throw new ConfigurationException("Malformed service : the specification attribute is mandatory");
- }
- String filter = "(&(!(factory.name=" + getCompositeManager().getFactory().getComponentDescription().getName() + "))(factory.state=1))"; // Cannot reinstantiate yourself
- String f = services[i].getAttribute("filter");
- if (f != null) {
- filter = "(&" + filter + f + ")";
- }
- Properties prop = new Properties();
- for (int k = 0; k < services[i].getElements("property").length; k++) {
- String key = services[i].getElements("property")[k].getAttribute("name");
- String value = services[i].getElements("property")[k].getAttribute("value");
- prop.put(key, value);
- }
- String ag = services[i].getAttribute("aggregate");
- boolean agg = ag != null && ag.equalsIgnoreCase("true");
-
- String op = services[i].getAttribute("optional");
- boolean opt = op != null && op.equalsIgnoreCase("true");
-
- SvcInstance inst = new SvcInstance(this, spec, prop, agg, opt, filter);
- m_instances.add(inst);
- }
- }
-
- /**
- * Start the service instantiator handler.
- * Start all created service instance.
- * @see org.apache.felix.ipojo.CompositeHandler#start()
- */
- public void start() {
- // Init
- for (int i = 0; i < m_instances.size(); i++) {
- SvcInstance inst = (SvcInstance) m_instances.get(i);
- inst.start();
- }
-
- m_isValid = isHandlerValid();
- }
-
- /**
- * Check the handler validity.
- * @return true if all created service instances are valid
- * @see org.apache.felix.ipojo.CompositeHandler#isValid()
- */
- private boolean isHandlerValid() {
- for (int i = 0; i < m_instances.size(); i++) {
- SvcInstance inst = (SvcInstance) m_instances.get(i);
- if (!inst.isSatisfied()) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Handler stop method.
- * Stop all created service instance.
- * @see org.apache.felix.ipojo.CompositeHandler#stop()
- */
- public void stop() {
- for (int i = 0; i < m_instances.size(); i++) {
- SvcInstance inst = (SvcInstance) m_instances.get(i);
- inst.stop();
- }
- m_instances.clear();
- }
-
- /**
- * An service instance becomes valid.
- */
- public void validate() {
- if (!m_isValid) {
- if (isHandlerValid()) {
- m_isValid = true;
- }
- }
- }
-
- /**
- * A service instance becomes invalid.
- */
- public void invalidate() {
- if (m_isValid) {
- if (!isHandlerValid()) {
- m_isValid = false;
- }
- }
- }
-
- /**
- * Get the service instantiator handler description.
- * @return the description
- * @see org.apache.felix.ipojo.CompositeHandler#getDescription()
- */
- public HandlerDescription getDescription() {
- return new ServiceInstantiatorDescription(this, m_instances);
- }
-
- public List getInstances() {
- return m_instances;
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
deleted file mode 100644
index a738675..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * 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.instantiator;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.Factory;
-import org.apache.felix.ipojo.MissingHandlerException;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.UnacceptableConfiguration;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.Tracker;
-import org.apache.felix.ipojo.util.TrackerCustomizer;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Manage a service instantiation. This service create component instance
- * providing the required service specification.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class SvcInstance implements TrackerCustomizer {
-
- /**
- * Required specification.
- */
- private String m_specification;
-
- /**
- * Configuration to push to the instance.
- */
- private Dictionary m_configuration;
-
- /**
- * Map of factory references => instance or NO_INSTANCE.
- */
- private Map /* ServiceReference */m_usedRef = new HashMap();
-
- /**
- * Does we instantiate several provider ?
- */
- private boolean m_isAggregate = false;
-
- /**
- * Is the service optional ?
- */
- private boolean m_isOptional = false;
-
- /**
- * Handler creating the service instance.
- */
- private ServiceInstantiatorHandler m_handler;
-
- /**
- * Service Context (internal scope).
- */
- private ServiceContext m_context;
-
- /**
- * True if the service instantiation is valid.
- */
- private boolean m_isValid = false;
-
- /**
- * Tracker used to track required factory.
- */
- private Tracker m_tracker;
-
- /**
- * Constructor.
- * @param h : the handler.
- * @param spec : required specification.
- * @param conf : instance configuration.
- * @param isAgg : is the service instance an aggregate service ?
- * @param isOpt : is the service instance optional ?
- * @param filt : LDAP filter
- */
- public SvcInstance(ServiceInstantiatorHandler h, String spec, Dictionary conf, boolean isAgg, boolean isOpt, String filt) {
- m_handler = h;
- m_context = h.getCompositeManager().getServiceContext();
- m_specification = spec;
- m_configuration = conf;
- m_isAggregate = isAgg;
- m_isOptional = isOpt;
- try {
- m_tracker = new Tracker(m_context, h.getCompositeManager().getContext().createFilter(filt), this);
- } catch (InvalidSyntaxException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Start the service instance.
- * @param sc
- */
- public void start() {
- m_tracker.open();
- m_isValid = isSatisfied();
- }
-
- /**
- * Stop the service instance.
- */
- public void stop() {
- m_tracker.close();
-
- Set keys = m_usedRef.keySet();
- Iterator it = keys.iterator();
- while (it.hasNext()) {
- ServiceReference ref = (ServiceReference) it.next();
- Object o = m_usedRef.get(ref);
- if (o != null) {
- ((ComponentInstance) o).dispose();
- }
- }
- m_usedRef.clear();
- m_tracker = null;
- m_isValid = false;
- }
-
- /**
- * Check if an instance is already created.
- * @return true if at least one instance is created.
- */
- private boolean isAnInstanceCreated() {
- Set keys = m_usedRef.keySet();
- Iterator it = keys.iterator();
- while (it.hasNext()) {
- if (m_usedRef.get(it.next()) != null) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Create an instance for the given reference.
- * The instance is not added inside the map.
- * @param factory : the factory from which we need to create the instance.
- * @return the created component instance.
- */
- private ComponentInstance createInstance(Factory factory) {
- // Add an unique name if not specified.
- Properties p = new Properties();
- Enumeration kk = m_configuration.keys();
- while (kk.hasMoreElements()) {
- String k = (String) kk.nextElement();
- p.put(k, m_configuration.get(k));
- }
- ComponentInstance instance = null;
- try {
- instance = factory.createComponentInstance(p);
- } catch (UnacceptableConfiguration e) {
- e.printStackTrace();
- } catch (MissingHandlerException e) {
- e.printStackTrace();
- } catch (ConfigurationException e) {
- e.printStackTrace();
- }
- return instance;
- }
-
- /**
- * Create an instance for the next available factory.
- */
- private void createNextInstance() {
- Set keys = m_usedRef.keySet();
- Iterator it = keys.iterator();
- ServiceReference ref = (ServiceReference) it.next();
- try {
- Factory factory = (Factory) m_context.getService(ref);
-
- // Add an unique name if not specified.
- Properties p = new Properties();
- Enumeration kk = m_configuration.keys();
- while (kk.hasMoreElements()) {
- String k = (String) kk.nextElement();
- p.put(k, m_configuration.get(k));
- }
-
- ComponentInstance instance = factory.createComponentInstance(p);
- m_usedRef.put(ref, instance);
- m_context.ungetService(ref);
- } catch (UnacceptableConfiguration e) {
- m_handler.log(Logger.ERROR, "A matching factory (" + ref.getProperty("instance.name") + ") seems to refuse the given configuration : " + e.getMessage());
- } catch (MissingHandlerException e) {
- m_handler.log(Logger.ERROR, "A matching factory (" + ref.getProperty("instance.name") + ") seems to refuse the given configuration : " + e.getMessage());
- } catch (ConfigurationException e) {
- m_handler.log(Logger.ERROR, "A matching factory (" + ref.getProperty("instance.name") + ") seems to refuse the given configuration : " + e.getMessage());
- }
- }
-
-
-
- /**
- * Check if the service instance is satisfied.
- * @return true if the service instance if satisfied.
- */
- public boolean isSatisfied() {
- return m_isOptional || m_usedRef.size() > 0;
- }
-
- /**
- * Does the service instance match with the given factory ?
- * @param fact : the factory to test.
- * @return true if the factory match, false otherwise.
- */
- private boolean match(Factory fact) {
- //TODO : use the service reference instead of the factory object to avoid to get the factory.
- // Check if the factory can provide the specification
- Element[] provides = fact.getDescription().getElements("provides");
- for (int i = 0; i < provides.length; i++) {
- if (provides[i].getAttribute("specification").equals(m_specification)) {
-
- // Check that the factory needs every properties contained in
- // the configuration
- Enumeration e = m_configuration.keys();
- while (e.hasMoreElements()) {
- String k = (String) e.nextElement();
- if (!containsProperty(k, fact)) {
- return false;
- }
- }
-
- // Add an unique name if not specified.
- Properties p = new Properties();
- Enumeration keys = m_configuration.keys();
- while (keys.hasMoreElements()) {
- String k = (String) keys.nextElement();
- p.put(k, m_configuration.get(k));
- }
-
- // Check the acceptability.
- return fact.isAcceptable(p);
- }
- }
- return false;
- }
-
- /**
- * Does the factory support the given property ?
- *
- * @param name : name of the property
- * @param factory : factory to test
- * @return true if the factory support this property
- */
- private boolean containsProperty(String name, Factory factory) {
- Element[] props = factory.getDescription().getElements("property");
- for (int i = 0; i < props.length; i++) {
- if (props[i].getAttribute("name").equalsIgnoreCase(name)) {
- return true;
- }
- }
- if (name.equalsIgnoreCase("name")) {
- return true;
- } // Skip the name property
- return false;
- }
-
- /**
- * Get the required specification.
- * @return the required specification.
- */
- public String getSpecification() {
- return m_specification;
- }
-
- public boolean isAggregate() {
- return m_isAggregate;
- }
-
- public boolean isOptional() {
- return m_isOptional;
- }
-
- /**
- * Get the map of used references [reference, component instance].
- * @return the map of used references.
- */
- protected Map getUsedReferences() {
- return m_usedRef;
- }
-
- /**
- * A factory potentially matching with the managed instance appears.
- * @param reference : service reference
- * @return : true if the factory match
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference reference) {
- Factory fact = (Factory) m_tracker.getService(reference);
- if (match(fact)) {
- m_tracker.ungetService(reference);
- return true;
- } else {
- m_tracker.ungetService(reference);
- return false;
- }
-
- }
-
- /**
- * A matching service reference has been added in the tracker.
- * @param reference : added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference reference) {
- Factory fact = (Factory) m_tracker.getService(reference);
- if (m_isAggregate) { // Create an instance for the new factory
- m_usedRef.put(reference, createInstance(fact));
- if (!m_isValid) {
- m_isValid = true;
- m_handler.validate();
- }
- } else {
- if (!isAnInstanceCreated()) {
- m_usedRef.put(reference, createInstance(fact));
- } else {
- m_usedRef.put(reference, null); // Store the reference
- }
- if (!m_isValid) {
- m_isValid = true;
- m_handler.validate();
- }
- }
- m_tracker.ungetService(reference);
- }
-
- /**
- * A used factory was modified.
- * @param reference : service reference
- * @param service : object if already get
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference reference, Object service) { }
-
- /**
- * A used factory disappears.
- * @param reference : service reference
- * @param service : object if already get
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference reference, Object service) {
- // Remove the reference is contained
- Object o = m_usedRef.remove(reference);
- if (o != null) {
- ((ComponentInstance) o).dispose();
- if (m_usedRef.size() > 0) {
- if (!m_isAggregate) {
- createNextInstance(); // Create an instance with another factory
- }
- } else { // No more candidate
- if (!m_isOptional) {
- m_isValid = false;
- m_handler.invalidate();
- }
- }
- }
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionException.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionException.java
deleted file mode 100644
index 4202643..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionException.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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;
-
-/**
- * Exception occurs when a composition error occurs.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class CompositionException extends Exception {
-
- /**
- * serialVersionUID.
- */
- private static final long serialVersionUID = -3063353267573738105L;
-
- /**
- * Message.
- */
- private String m_message;
-
- /**
- * Constructor.
- * @param message : a message.
- */
- public CompositionException(String message) {
- m_message = message;
- }
-
- /**
- * Get the exception message.
- * @return the message.
- * @see java.lang.Throwable#getMessage()
- */
- public String getMessage() {
- return m_message;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
deleted file mode 100644
index da54207..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * 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.apache.felix.ipojo.util.Logger;
-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.log(Logger.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.log(Logger.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");
- 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.log(Logger.ERROR, "A LDAP filter is not valid : " + e.getMessage());
- } catch (ClassNotFoundException e) {
- m_handler.log(Logger.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.log(Logger.WARNING, "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;
- }
-
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java
deleted file mode 100644
index 2839858..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
deleted file mode 100644
index 5e209ae..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
deleted file mode 100644
index b8fcab7..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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;
- }
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
deleted file mode 100644
index 994f01e..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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.CompositeManager;
-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.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;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
deleted file mode 100644
index ef86839..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * 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.CompositeHandler;
-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.ComponentDescription;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-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.apache.felix.ipojo.util.Logger;
-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();
-
- /**
- * Handler validity.
- * (Lifecycle controller)
- */
- private boolean m_valid = false;
-
- /**
- * 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.ComponentDescription, org.apache.felix.ipojo.metadata.Element)
- */
- public void initializeComponentFactory(ComponentDescription 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) {
- log(Logger.ERROR, "Cannot start the provided service handler", e);
- if (m_valid) { m_valid = false; }
- return;
- }
- }
- m_valid = 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 {
- log(Logger.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) {
- log(Logger.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) {
- log(Logger.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) {
- log(Logger.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) {
- log(Logger.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) {
- log(Logger.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) {
- log(Logger.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)) {
- log(Logger.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;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java
deleted file mode 100644
index 19256d6..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.CompositeHandler;
-import org.apache.felix.ipojo.architecture.HandlerDescription;
-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;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java
deleted file mode 100644
index 080c98d..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * 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;
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
deleted file mode 100644
index 6ccf87b..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.apache.felix.ipojo.util.Logger;
-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.log(Logger.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;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceReferenceImpl.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceReferenceImpl.java
similarity index 86%
rename from ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceReferenceImpl.java
rename to ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceReferenceImpl.java
index 1ebbcf3..7bdb382 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceReferenceImpl.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceReferenceImpl.java
@@ -1,112 +1,112 @@
-/*
- * 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;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Internal service reference implementation. This class is used for in the
- * composition.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ServiceReferenceImpl implements ServiceReference {
-
- /**
- * Service Registration attached to the service reference.
- */
- private ServiceRegistrationImpl m_registration = null;
-
- /**
- * Component Instance.
- */
- private ComponentInstance m_cm;
-
- /**
- * Constructor.
- *
- * @param cm : component instance publishing the service.
- * @param sr : registration attached to this service reference.
- */
- public ServiceReferenceImpl(ComponentInstance cm, ServiceRegistrationImpl sr) {
- m_registration = sr;
- m_cm = cm;
- }
-
- /**
- * Not supported in composite.
- * @return null
- * @see org.osgi.framework.ServiceReference#getBundle()
- */
- public Bundle getBundle() {
- return m_cm.getContext().getBundle();
- }
-
- /**
- * Get the service registration for this reference.
- * @return the service registration for this service reference.
- */
- public ServiceRegistrationImpl getServiceRegistration() {
- return m_registration;
- }
-
-
- /**
- * Get a property value.
- * @param s : the key of the required property.
- * @return the property value or null if no property for the given key.
- * @see org.osgi.framework.ServiceReference#getProperty(java.lang.String)
- */
- public Object getProperty(String s) {
- return m_registration.getProperty(s);
- }
-
- /**
- * Get the String arrays of service property keys.
- * @return : the list of property keys.
- * @see org.osgi.framework.ServiceReference#getPropertyKeys()
- */
- public String[] getPropertyKeys() {
- return m_registration.getPropertyKeys();
- }
-
-
- /**
- * Unsupported Operation inside composite.
- * @return bundles using this reference.
- * @see org.osgi.framework.ServiceReference#getUsingBundles()
- */
- public Bundle[] getUsingBundles() {
- throw new UnsupportedOperationException("getUsingBundles is not supported in scope");
- }
-
- /**
- * Check if the current service reference is assignable to the given bundle.
- * @param arg0 : the bundle to check
- * @param arg1 : the class name to check.
- * @return true in the case of composite
- * @see org.osgi.framework.ServiceReference#isAssignableTo(org.osgi.framework.Bundle, java.lang.String)
- */
- public boolean isAssignableTo(Bundle arg0, String arg1) {
- return true;
- }
-
-}
+/*
+ * 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.context;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Internal service reference implementation. This class is used for in the
+ * composition.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceReferenceImpl implements ServiceReference {
+
+ /**
+ * Service Registration attached to the service reference.
+ */
+ private ServiceRegistrationImpl m_registration = null;
+
+ /**
+ * Component Instance.
+ */
+ private ComponentInstance m_cm;
+
+ /**
+ * Constructor.
+ *
+ * @param instance : component instance publishing the service.
+ * @param ref : registration attached to this service reference.
+ */
+ public ServiceReferenceImpl(ComponentInstance instance, ServiceRegistrationImpl ref) {
+ m_registration = ref;
+ m_cm = instance;
+ }
+
+ /**
+ * Not supported in composite.
+ * @return null
+ * @see org.osgi.framework.ServiceReference#getBundle()
+ */
+ public Bundle getBundle() {
+ return m_cm.getContext().getBundle();
+ }
+
+ /**
+ * Get the service registration for this reference.
+ * @return the service registration for this service reference.
+ */
+ public ServiceRegistrationImpl getServiceRegistration() {
+ return m_registration;
+ }
+
+
+ /**
+ * Get a property value.
+ * @param name : the key of the required property.
+ * @return the property value or null if no property for the given key.
+ * @see org.osgi.framework.ServiceReference#getProperty(java.lang.String)
+ */
+ public Object getProperty(String name) {
+ return m_registration.getProperty(name);
+ }
+
+ /**
+ * Get the String arrays of service property keys.
+ * @return : the list of property keys.
+ * @see org.osgi.framework.ServiceReference#getPropertyKeys()
+ */
+ public String[] getPropertyKeys() {
+ return m_registration.getPropertyKeys();
+ }
+
+
+ /**
+ * Unsupported Operation inside composite.
+ * @return bundles using this reference.
+ * @see org.osgi.framework.ServiceReference#getUsingBundles()
+ */
+ public Bundle[] getUsingBundles() {
+ throw new UnsupportedOperationException("getUsingBundles is not supported in scope");
+ }
+
+ /**
+ * Check if the current service reference is assignable to the given bundle.
+ * @param arg0 : the bundle to check
+ * @param arg1 : the class name to check.
+ * @return true in the case of composite
+ * @see org.osgi.framework.ServiceReference#isAssignableTo(org.osgi.framework.Bundle, java.lang.String)
+ */
+ public boolean isAssignableTo(Bundle arg0, String arg1) {
+ return true;
+ }
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistrationImpl.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceRegistrationImpl.java
similarity index 87%
rename from ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistrationImpl.java
rename to ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceRegistrationImpl.java
index 6818899..9cd8edf 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistrationImpl.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceRegistrationImpl.java
@@ -1,257 +1,257 @@
-/*
- * 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;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.InstanceManager;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * Internal service registration implementation. This class is used for in the
- * composition.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ServiceRegistrationImpl implements ServiceRegistration {
-
- /**
- * Service Registry.
- */
- private ServiceRegistry m_registry = null;
-
- /**
- * Interfaces associated with the service object.
- */
- private String[] m_classes = null;
-
- /**
- * Service Id associated with the service object.
- */
- private Long m_serviceId = null;
-
- /**
- * Service object.
- */
- private Object m_svcObj = null;
-
- /**
- * Service factory interface.
- */
- private ServiceFactory m_factory = null;
-
- /**
- * Associated property dictionary.
- */
- private Map m_propMap = null;
-
- /**
- * Re-usable service reference.
- */
- private ServiceReferenceImpl m_ref = null;
-
- /**
- * Property Keys List.
- */
- private List m_list = new ArrayList();
-
- /**
- * Constructor.
- *
- * @param registry : the service registry
- * @param cm : component instance
- * @param classes : published interfaces array
- * @param serviceId : the unique service id
- * @param svcObj : the service object or the service factory object
- * @param dict : service properties
- */
- public ServiceRegistrationImpl(ServiceRegistry registry, ComponentInstance cm, String[] classes, Long serviceId, Object svcObj, Dictionary dict) {
- m_registry = registry;
- m_classes = classes;
- m_serviceId = serviceId;
- m_svcObj = svcObj;
- if (m_svcObj instanceof ServiceFactory) { m_factory = (ServiceFactory) m_svcObj; }
- initializeProperties(dict);
-
- // This reference is the "standard" reference for this service and will
- // always be returned by getReference().
- // Since all reference to this service are supposed to be equal, we use
- // the hash code of this reference for
- // a references to this service in ServiceReference.
- m_ref = new ServiceReferenceImpl(cm, this);
- }
-
- /**
- * Check if the service registration still valid.
- * @return true if the service registration is valid.
- */
- protected boolean isValid() {
- return m_svcObj != null;
- }
-
- /**
- * Get the service reference attached with this service registration.
- * @return the service reference
- * @see org.osgi.framework.ServiceRegistration#getReference()
- */
- public ServiceReference getReference() {
- return m_ref;
- }
-
- /**
- * Add properties to a service registration.
- * @param dict : the properties to add
- * @see org.osgi.framework.ServiceRegistration#setProperties(java.util.Dictionary)
- */
- public void setProperties(Dictionary dict) {
- // Make sure registration is valid.
- if (!isValid()) {
- throw new IllegalStateException("The service registration is no longer valid.");
- }
- // Set the properties.
- initializeProperties(dict);
- // Tell registry about it.
- m_registry.servicePropertiesModified(this);
- }
-
- /**
- * Unregister the service.
- * @see org.osgi.framework.ServiceRegistration#unregister()
- */
- public void unregister() {
- if (m_svcObj != null) {
- m_registry.unregisterService(this);
- m_svcObj = null;
- m_factory = null;
- } else {
- throw new IllegalStateException("Service already unregistered.");
- }
- }
-
- /**
- * Look for a property in the service properties.
- *
- * @param key : property key
- * @return the object associated with the key or null if the key is not
- * present.
- */
- protected Object getProperty(String key) {
- return m_propMap.get(key);
- }
-
- /**
- * Get the property keys.
- * @return the property keys list.
- */
- protected String[] getPropertyKeys() {
- synchronized (m_propMap) {
- m_list.clear();
- Iterator i = m_propMap.entrySet().iterator();
- while (i.hasNext()) {
- Map.Entry entry = (Map.Entry) i.next();
- m_list.add(entry.getKey());
- }
- return (String[]) m_list.toArray(new String[m_list.size()]);
- }
- }
-
- /**
- * Get the service object.
- * @return the service object. Call the service factory if needed.
- */
- protected Object getService() {
- // If the service object is a service factory, then
- // let it create the service object.
- if (m_factory != null) {
- return getFactoryUnchecked();
- } else {
- return m_svcObj;
- }
- }
-
- /**
- * Initialize properties.
- *
- * @param dict : service properties to publish.
- */
- private void initializeProperties(Dictionary dict) {
- // Create a case insensitive map.
- if (m_propMap == null) {
- m_propMap = new StringMap(false);
- } else {
- m_propMap.clear();
- }
-
- if (dict != null) {
- Enumeration keys = dict.keys();
- while (keys.hasMoreElements()) {
- Object key = keys.nextElement();
- m_propMap.put(key, dict.get(key));
- }
- }
- // Add the framework assigned properties.
- m_propMap.put(Constants.OBJECTCLASS, m_classes);
- m_propMap.put(Constants.SERVICE_ID, m_serviceId);
- }
-
- /**
- * Get a service object via a service factory.
- * @return the service object via the service factory invocation.
- */
- private Object getFactoryUnchecked() {
- return m_factory.getService(null, this);
- }
-
- /**
- * Unget a service. (Internal Method)
- *
- * @param cm : component instance using the service.
- * @param svcObj : the unget service object.
- */
- private void ungetFactoryUnchecked(ComponentInstance cm, Object svcObj) {
- if (cm instanceof InstanceManager) {
- m_factory.ungetService(((InstanceManager) cm).getContext().getBundle(), this, svcObj);
- }
-
- }
-
- /**
- * Unget a service.
- *
- * @param cm : component instance using the service.
- * @param srvObj : the unget service object.
- */
- public void ungetService(ComponentInstance cm, Object srvObj) {
- // If the service object is a service factory, then let is release the
- // service object.
- if (m_factory != null) {
- ungetFactoryUnchecked(cm, srvObj);
- }
- }
-
-}
+/*
+ * 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.context;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.InstanceManager;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Internal service registration implementation. This class is used for in the
+ * composition.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceRegistrationImpl implements ServiceRegistration {
+
+ /**
+ * Service Registry.
+ */
+ private ServiceRegistry m_registry = null;
+
+ /**
+ * Interfaces associated with the service object.
+ */
+ private String[] m_classes = null;
+
+ /**
+ * Service Id associated with the service object.
+ */
+ private Long m_serviceId = null;
+
+ /**
+ * Service object.
+ */
+ private Object m_svcObj = null;
+
+ /**
+ * Service factory interface.
+ */
+ private ServiceFactory m_factory = null;
+
+ /**
+ * Associated property dictionary.
+ */
+ private Map m_propMap = null;
+
+ /**
+ * Re-usable service reference.
+ */
+ private ServiceReferenceImpl m_ref = null;
+
+ /**
+ * Property Keys List.
+ */
+ private List m_list = new ArrayList();
+
+ /**
+ * Constructor.
+ *
+ * @param registry : the service registry
+ * @param instance : component instance
+ * @param classes : published interfaces array
+ * @param serviceId : the unique service id
+ * @param svcObj : the service object or the service factory object
+ * @param dict : service properties
+ */
+ public ServiceRegistrationImpl(ServiceRegistry registry, ComponentInstance instance, String[] classes, Long serviceId, Object svcObj, Dictionary dict) {
+ m_registry = registry;
+ m_classes = classes;
+ m_serviceId = serviceId;
+ m_svcObj = svcObj;
+ if (m_svcObj instanceof ServiceFactory) { m_factory = (ServiceFactory) m_svcObj; }
+ initializeProperties(dict);
+
+ // This reference is the "standard" reference for this service and will
+ // always be returned by getReference().
+ // Since all reference to this service are supposed to be equal, we use
+ // the hash code of this reference for
+ // a references to this service in ServiceReference.
+ m_ref = new ServiceReferenceImpl(instance, this);
+ }
+
+ /**
+ * Check if the service registration still valid.
+ * @return true if the service registration is valid.
+ */
+ protected boolean isValid() {
+ return m_svcObj != null;
+ }
+
+ /**
+ * Get the service reference attached with this service registration.
+ * @return the service reference
+ * @see org.osgi.framework.ServiceRegistration#getReference()
+ */
+ public ServiceReference getReference() {
+ return m_ref;
+ }
+
+ /**
+ * Add properties to a service registration.
+ * @param dict : the properties to add
+ * @see org.osgi.framework.ServiceRegistration#setProperties(java.util.Dictionary)
+ */
+ public void setProperties(Dictionary dict) {
+ // Make sure registration is valid.
+ if (!isValid()) {
+ throw new IllegalStateException("The service registration is no longer valid.");
+ }
+ // Set the properties.
+ initializeProperties(dict);
+ // Tell registry about it.
+ m_registry.servicePropertiesModified(this);
+ }
+
+ /**
+ * Unregister the service.
+ * @see org.osgi.framework.ServiceRegistration#unregister()
+ */
+ public void unregister() {
+ if (m_svcObj == null) {
+ throw new IllegalStateException("Service already unregistered.");
+ } else {
+ m_registry.unregisterService(this);
+ m_svcObj = null;
+ m_factory = null;
+ }
+ }
+
+ /**
+ * Look for a property in the service properties.
+ *
+ * @param key : property key
+ * @return the object associated with the key or null if the key is not
+ * present.
+ */
+ protected Object getProperty(String key) {
+ return m_propMap.get(key);
+ }
+
+ /**
+ * Get the property keys.
+ * @return the property keys list.
+ */
+ protected String[] getPropertyKeys() {
+ synchronized (m_propMap) {
+ m_list.clear();
+ Iterator iterator = m_propMap.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ m_list.add(entry.getKey());
+ }
+ return (String[]) m_list.toArray(new String[m_list.size()]);
+ }
+ }
+
+ /**
+ * Get the service object.
+ * @return the service object. Call the service factory if needed.
+ */
+ protected Object getService() {
+ // If the service object is a service factory, then
+ // let it create the service object.
+ if (m_factory == null) {
+ return m_svcObj;
+ } else {
+ return getFactoryUnchecked();
+ }
+ }
+
+ /**
+ * Initialize properties.
+ *
+ * @param dict : service properties to publish.
+ */
+ private void initializeProperties(Dictionary dict) {
+ // Create a case insensitive map.
+ if (m_propMap == null) {
+ m_propMap = new StringMap(false);
+ } else {
+ m_propMap.clear();
+ }
+
+ if (dict != null) {
+ Enumeration keys = dict.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ m_propMap.put(key, dict.get(key));
+ }
+ }
+ // Add the framework assigned properties.
+ m_propMap.put(Constants.OBJECTCLASS, m_classes);
+ m_propMap.put(Constants.SERVICE_ID, m_serviceId);
+ }
+
+ /**
+ * Get a service object via a service factory.
+ * @return the service object via the service factory invocation.
+ */
+ private Object getFactoryUnchecked() {
+ return m_factory.getService(null, this);
+ }
+
+ /**
+ * Unget a service. (Internal Method)
+ *
+ * @param instance : component instance using the service.
+ * @param svcObj : the unget service object.
+ */
+ private void ungetFactoryUnchecked(ComponentInstance instance, Object svcObj) {
+ if (instance instanceof InstanceManager) {
+ m_factory.ungetService(((InstanceManager) instance).getContext().getBundle(), this, svcObj);
+ }
+
+ }
+
+ /**
+ * Unget a service.
+ *
+ * @param instance : component instance using the service.
+ * @param srvObj : the unget service object.
+ */
+ public void ungetService(ComponentInstance instance, Object srvObj) {
+ // If the service object is a service factory, then let is release the
+ // service object.
+ if (m_factory != null) {
+ ungetFactoryUnchecked(instance, srvObj);
+ }
+ }
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceRegistry.java
similarity index 82%
rename from ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java
rename to ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceRegistry.java
index c14c5e4..6eb3d7e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/ServiceRegistry.java
@@ -1,336 +1,344 @@
-/*
- * 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;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-
-import org.apache.felix.ipojo.ComponentInstance;
-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;
-
-/**
- * Internal Service Registry. This class is used for in the composition.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ServiceRegistry {
-
- /**
- * Service Id index.
- */
- private long m_serviceId = 1L;
-
- /**
- * List of service listeners.
- */
- private List m_listeners = new ArrayList(); // ListenerInfo List
-
- /**
- * List of service registration.
- */
- private List m_regs = new ArrayList();
-
- /**
- * A "real" bundle context to create LDAP filter.
- */
- private BundleContext m_bc; // BundleContext to create Filter
-
- /**
- * Listener info structure.
- */
- private class ListenerInfo {
- /**
- * Listener object.
- */
- private ServiceListener m_listener;
- /**
- * Filter associated with the filter.
- */
- private Filter m_filter;
- }
-
- /**
- * Constructor.
- *
- * @param bc : bundle context.
- */
- public ServiceRegistry(BundleContext bc) {
- m_bc = bc;
- }
-
- /**
- * Add a given service listener with no filter.
- *
- * @param arg0 : the service listener to add
- */
- public void addServiceListener(ServiceListener arg0) {
- ListenerInfo li = new ListenerInfo();
- li.m_listener = arg0;
- li.m_filter = null;
- m_listeners.add(li);
- }
-
- /**
- * Unget a service.
- *
- * @param cm : instance releasing the service.
- * @param ref : released reference.
- * @return true if the unget success
- */
- public boolean ungetService(ComponentInstance cm, ServiceReference ref) {
-
- ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
- if (reg.isValid()) {
- reg.ungetService(cm, reg.getService());
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Unregister a service listener.
- *
- * @param arg0 : the service listener to remove
- */
- public void removeServiceListener(ServiceListener arg0) {
- m_listeners.remove(arg0);
- }
-
- /**
- * Register a service.
- *
- * @param cm : provider instance.
- * @param clazz : provided interface.
- * @param svcObj : service object of service factory object.
- * @param dict : service properties.
- * @return the created service registration.
- */
- public ServiceRegistration registerService(ComponentInstance cm, String clazz, Object svcObj, Dictionary dict) {
- synchronized (m_regs) {
- ServiceRegistrationImpl reg = new ServiceRegistrationImpl(this, cm, new String[] { clazz }, new Long(m_serviceId++), svcObj, dict);
- m_regs.add(reg);
- fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
- return reg;
- }
- }
-
- /**
- * Register a service.
- *
- * @param cm : provider instance.
- * @param clazzes : provided interfaces.
- * @param svcObj : service object of service factory object.
- * @param dict : service properties.
- * @return the created service registration.
- */
- public ServiceRegistration registerService(ComponentInstance cm, String[] clazzes, Object svcObj, Dictionary dict) {
- synchronized (m_regs) {
- ServiceRegistrationImpl reg = new ServiceRegistrationImpl(this, cm, clazzes, new Long(m_serviceId++), svcObj, dict);
- m_regs.add(reg);
- fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
- return reg;
- }
- }
-
- /**
- * Dispatch a service event.
- * @param event : the service to dispatch
- */
- private void fireServiceChanged(ServiceEvent event) {
- synchronized (m_listeners) {
- // Iterate on the service listener list to notify service listener
- for (int i = 0; i < m_listeners.size(); i++) {
- ListenerInfo li = (ListenerInfo) m_listeners.get(i);
- ServiceReference sr = event.getServiceReference();
- if (li.m_filter == null) {
- li.m_listener.serviceChanged(event);
- }
- if (li.m_filter != null && li.m_filter.match(sr)) {
- li.m_listener.serviceChanged(event);
- }
- }
- }
- }
-
- /**
- * Get available (and accessible) service references.
- *
- * @param className : required interface
- * @param expr : LDAP filter
- * @return : the list of available service references.
- * @throws InvalidSyntaxException
- * occurs when the LDAP filter is malformed.
- */
- public ServiceReference[] getServiceReferences(String className, String expr) throws InvalidSyntaxException {
- synchronized (m_regs) {
- // Define filter if expression is not null.
- Filter filter = null;
- if (expr != null) {
- filter = m_bc.createFilter(expr);
- }
-
- List refs = new ArrayList();
-
- for (int i = 0; i < m_regs.size(); i++) {
- ServiceRegistrationImpl reg = (ServiceRegistrationImpl) m_regs.get(i);
- // Determine if the registered services matches the search
- // criteria.
- boolean matched = false;
-
- // If className is null, then look at filter only.
- if ((className == null) && ((filter == null) || filter.match(reg.getReference()))) {
- matched = true;
- } else if (className != null) {
- // If className is not null, then first match the
- // objectClass property before looking at the
- // filter.
- String[] objectClass = (String[]) ((ServiceRegistrationImpl) reg).getProperty(Constants.OBJECTCLASS);
- for (int classIdx = 0; classIdx < objectClass.length; classIdx++) {
- if (objectClass[classIdx].equals(className) && ((filter == null) || filter.match(reg.getReference()))) {
- matched = true;
- break;
- }
- }
- }
-
- // Add reference if it was a match.
- if (matched) {
- refs.add(reg.getReference());
- }
- }
-
- if (refs.size() > 0) {
- return (ServiceReference[]) refs.toArray(new ServiceReference[refs.size()]);
- }
- return null;
- }
- }
-
- /**
- * Look for a service reference.
- *
- * @param clazz : required interface.
- * @return the first available provider or null if none available.
- */
- public ServiceReference getServiceReference(String clazz) {
- synchronized (m_regs) {
- try {
- ServiceReference[] refs = getServiceReferences(clazz, null);
- if (refs != null) {
- return refs[0];
- } // If the refs != null we are sure that it exists one reference or more.
- } catch (InvalidSyntaxException ex) {
- System.err.println("Scope Service Registry : Problem when looking for service reference" + ex.getMessage());
- }
- return null;
- }
- }
-
- /**
- * Get a service object.
- * @param cm : component instance requiring the service.
- * @param ref : the required reference.
- * @return the service object.
- */
- public Object getService(ComponentInstance cm, ServiceReference ref) {
- synchronized (m_regs) {
- // Look for the service registration for this ref
- ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
- if (reg.isValid()) {
- // Delegate the service providing to the service registration
- return reg.getService();
- } else {
- return null;
- }
- }
- }
-
- /**
- * Get all service references consistent with the given interface and
- * filter.
- * @param clazz : the required interface.
- * @param filter : the LDAP filter.
- * @return the list of all service reference or null if none available.
- * @throws InvalidSyntaxException occurs when the LDAP filter is malformed.
- */
- public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
- synchronized (m_regs) {
- // Can delegate on getServiceReference, indeed their is no test on
- // the "modularity" conflict.
- return getServiceReferences(clazz, filter);
- }
- }
-
- /**
- * Add a service listener with a filter.
- * @param listener : the service listener to add
- * @param filter : LDAP filter
- */
- public void addServiceListener(ServiceListener listener, String filter) {
- // If the filter is null, subscribe with no filter.
- if (filter == null) {
- addServiceListener(listener);
- return;
- }
-
- ListenerInfo li = new ListenerInfo();
- li.m_listener = listener;
- try {
- li.m_filter = m_bc.createFilter(filter);
- } catch (InvalidSyntaxException ex) {
- System.err.println("Scope Service Registry : Problem when creating a service listener " + ex.getMessage());
- }
- m_listeners.add(li);
- }
-
- /**
- * Dispatch a service properties modified event.
- * @param reg : the implicated service registration.
- */
- public void servicePropertiesModified(ServiceRegistrationImpl reg) {
- fireServiceChanged(new ServiceEvent(ServiceEvent.MODIFIED, reg.getReference()));
- }
-
- /**
- * Unregister a service.
- * @param reg : the service registration to unregister
- */
- public void unregisterService(ServiceRegistrationImpl reg) {
- m_regs.remove(reg);
- fireServiceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()));
- }
-
- /**
- * Reset the service registry.
- */
- protected void reset() {
- m_serviceId = 1L;
- m_listeners = new ArrayList();
- m_regs = new ArrayList();
- }
-}
+/*
+ * 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.context;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.util.Logger;
+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;
+
+/**
+ * Internal Service Registry. This class is used for in the composition.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceRegistry {
+
+ /**
+ * Service Id index.
+ */
+ private long m_serviceId = 1L;
+
+ /**
+ * List of service listeners.
+ */
+ private List m_listeners = new ArrayList(); // ListenerInfo List
+
+ /**
+ * List of service registration.
+ */
+ private List m_regs = new ArrayList();
+
+ /**
+ * A "real" bundle context to create LDAP filter.
+ */
+ private BundleContext m_context; // BundleContext to create Filter
+
+ /**
+ * Registry logger.
+ */
+ private Logger m_logger;
+
+ /**
+ * Listener info structure.
+ */
+ private class ListenerInfo {
+ /**
+ * Listener object.
+ */
+ private ServiceListener m_listener;
+ /**
+ * Filter associated with the filter.
+ */
+ private Filter m_filter;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param context : bundle context.
+ */
+ public ServiceRegistry(BundleContext context) {
+ m_context = context;
+ m_logger = new Logger(m_context, "Registry logger " + m_context.getBundle().getBundleId());
+ }
+
+ /**
+ * Add a given service listener with no filter.
+ *
+ * @param arg0 : the service listener to add
+ */
+ public void addServiceListener(ServiceListener arg0) {
+ ListenerInfo info = new ListenerInfo();
+ info.m_listener = arg0;
+ info.m_filter = null;
+ m_listeners.add(info);
+ }
+
+ /**
+ * Unget a service.
+ *
+ * @param instance : instance releasing the service.
+ * @param ref : released reference.
+ * @return true if the unget success
+ */
+ public boolean ungetService(ComponentInstance instance, ServiceReference ref) {
+
+ ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
+ if (reg.isValid()) {
+ reg.ungetService(instance, reg.getService());
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Unregister a service listener.
+ *
+ * @param arg0 : the service listener to remove
+ */
+ public void removeServiceListener(ServiceListener arg0) {
+ m_listeners.remove(arg0);
+ }
+
+ /**
+ * Register a service.
+ *
+ * @param instance : provider instance.
+ * @param clazz : provided interface.
+ * @param svcObj : service object of service factory object.
+ * @param dict : service properties.
+ * @return the created service registration.
+ */
+ public ServiceRegistration registerService(ComponentInstance instance, String clazz, Object svcObj, Dictionary dict) {
+ synchronized (m_regs) {
+ ServiceRegistrationImpl reg = new ServiceRegistrationImpl(this, instance, new String[] { clazz }, new Long(m_serviceId++), svcObj, dict);
+ m_regs.add(reg);
+ fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
+ return reg;
+ }
+ }
+
+ /**
+ * Register a service.
+ *
+ * @param instance : provider instance.
+ * @param clazzes : provided interfaces.
+ * @param svcObj : service object of service factory object.
+ * @param dict : service properties.
+ * @return the created service registration.
+ */
+ public ServiceRegistration registerService(ComponentInstance instance, String[] clazzes, Object svcObj, Dictionary dict) {
+ synchronized (m_regs) {
+ ServiceRegistrationImpl reg = new ServiceRegistrationImpl(this, instance, clazzes, new Long(m_serviceId++), svcObj, dict);
+ m_regs.add(reg);
+ fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
+ return reg;
+ }
+ }
+
+ /**
+ * Dispatch a service event.
+ * @param event : the service to dispatch
+ */
+ private void fireServiceChanged(ServiceEvent event) {
+ synchronized (m_listeners) {
+ // Iterate on the service listener list to notify service listener
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ListenerInfo info = (ListenerInfo) m_listeners.get(i);
+ ServiceReference ref = event.getServiceReference();
+ if (info.m_filter == null) {
+ info.m_listener.serviceChanged(event);
+ }
+ if (info.m_filter != null && info.m_filter.match(ref)) {
+ info.m_listener.serviceChanged(event);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get available (and accessible) service references.
+ *
+ * @param className : required interface
+ * @param expr : LDAP filter
+ * @return : the list of available service references.
+ * @throws InvalidSyntaxException
+ * occurs when the LDAP filter is malformed.
+ */
+ public ServiceReference[] getServiceReferences(String className, String expr) throws InvalidSyntaxException {
+ synchronized (m_regs) {
+ // Define filter if expression is not null.
+ Filter filter = null;
+ if (expr != null) {
+ filter = m_context.createFilter(expr);
+ }
+
+ List refs = new ArrayList();
+
+ for (int i = 0; i < m_regs.size(); i++) {
+ ServiceRegistrationImpl reg = (ServiceRegistrationImpl) m_regs.get(i);
+ // Determine if the registered services matches the search
+ // criteria.
+ boolean matched = false;
+
+ // If className is null, then look at filter only.
+ if ((className == null) && ((filter == null) || filter.match(reg.getReference()))) {
+ matched = true;
+ } else if (className != null) {
+ // If className is not null, then first match the
+ // objectClass property before looking at the
+ // filter.
+ String[] objectClass = (String[]) ((ServiceRegistrationImpl) reg).getProperty(Constants.OBJECTCLASS);
+ for (int classIdx = 0; classIdx < objectClass.length; classIdx++) {
+ if (objectClass[classIdx].equals(className) && ((filter == null) || filter.match(reg.getReference()))) {
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ // Add reference if it was a match.
+ if (matched) {
+ refs.add(reg.getReference());
+ }
+ }
+
+ if (! refs.isEmpty()) {
+ return (ServiceReference[]) refs.toArray(new ServiceReference[refs.size()]);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Look for a service reference.
+ *
+ * @param clazz : required interface.
+ * @return the first available provider or null if none available.
+ */
+ public ServiceReference getServiceReference(String clazz) {
+ synchronized (m_regs) {
+ try {
+ ServiceReference[] refs = getServiceReferences(clazz, null);
+ if (refs != null) {
+ return refs[0];
+ } // If the refs != null we are sure that it exists one reference or more.
+ } catch (InvalidSyntaxException ex) {
+ // Cannot happen : null filter.
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Get a service object.
+ * @param instance : component instance requiring the service.
+ * @param ref : the required reference.
+ * @return the service object.
+ */
+ public Object getService(ComponentInstance instance, ServiceReference ref) {
+ synchronized (m_regs) {
+ // Look for the service registration for this ref
+ ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
+ if (reg.isValid()) {
+ // Delegate the service providing to the service registration
+ return reg.getService();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Get all service references consistent with the given interface and
+ * filter.
+ * @param clazz : the required interface.
+ * @param filter : the LDAP filter.
+ * @return the list of all service reference or null if none available.
+ * @throws InvalidSyntaxException occurs when the LDAP filter is malformed.
+ */
+ public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
+ synchronized (m_regs) {
+ // Can delegate on getServiceReference, indeed their is no test on
+ // the "modularity" conflict.
+ return getServiceReferences(clazz, filter);
+ }
+ }
+
+ /**
+ * Add a service listener with a filter.
+ * @param listener : the service listener to add
+ * @param filter : LDAP filter
+ */
+ public void addServiceListener(ServiceListener listener, String filter) {
+ // If the filter is null, subscribe with no filter.
+ if (filter == null) {
+ addServiceListener(listener);
+ return;
+ }
+
+ try {
+ ListenerInfo info = new ListenerInfo();
+ info.m_listener = listener;
+ info.m_filter = m_context.createFilter(filter);
+ m_listeners.add(info);
+ } catch (InvalidSyntaxException ex) {
+ m_logger.log(Logger.ERROR, ex.getMessage(), ex);
+ }
+
+ }
+
+ /**
+ * Dispatch a service properties modified event.
+ * @param reg : the implicated service registration.
+ */
+ public void servicePropertiesModified(ServiceRegistrationImpl reg) {
+ fireServiceChanged(new ServiceEvent(ServiceEvent.MODIFIED, reg.getReference()));
+ }
+
+ /**
+ * Unregister a service.
+ * @param reg : the service registration to unregister
+ */
+ public void unregisterService(ServiceRegistrationImpl reg) {
+ m_regs.remove(reg);
+ fireServiceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()));
+ }
+
+ /**
+ * Reset the service registry.
+ */
+ public void reset() {
+ m_serviceId = 1L;
+ m_listeners = new ArrayList();
+ m_regs = new ArrayList();
+ }
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/StringMap.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/StringMap.java
similarity index 80%
rename from ipojo/core/src/main/java/org/apache/felix/ipojo/composite/StringMap.java
rename to ipojo/core/src/main/java/org/apache/felix/ipojo/context/StringMap.java
index bd057aa..31f7331 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/StringMap.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/context/StringMap.java
@@ -1,142 +1,142 @@
-/*
- * 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;
-
-import java.util.Comparator;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Simple utility class that creates a map for string-based keys by extending
- * <tt>TreeMap</tt>. This map can be set to use case-sensitive or
- * case-insensitive comparison when searching for the key. Any keys put into
- * this map will be converted to a <tt>String</tt> using the
- * <tt>toString()</tt> method, since it is only intended to compare strings.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class StringMap extends TreeMap {
-
- /**
- * serialVersionUID.
- */
- private static final long serialVersionUID = 6948801857034259744L;
-
- /**
- * Constructor.
- */
- public StringMap() {
- this(true);
- }
-
- /**
- * Constructor.
- *
- * @param caseSensitive : fix if the map if case sensitive or not.
- */
- public StringMap(boolean caseSensitive) {
- super(new StringComparator(caseSensitive));
- }
-
- /**
- * Constructor.
- *
- * @param map : initial properties.
- * @param caseSensitive : fix if the map if case sensitive or not.
- */
- public StringMap(Map map, boolean caseSensitive) {
- this(caseSensitive);
- putAll(map);
- }
-
- /**
- * Put a record in the map.
- * @param key : key
- * @param value : value
- * @return an object.
- * @see java.util.TreeMap#put(K, V)
- */
- public Object put(Object key, Object value) {
- return super.put(key.toString(), value);
- }
-
- /**
- * Check if the map is case-sensitive.
- * @return true if the map is case sensitive.
- */
- public boolean isCaseSensitive() {
- return ((StringComparator) comparator()).isCaseSensitive();
- }
-
- /**
- * Set the case sensitivity.
- *
- * @param b : the new case sensitivity.
- */
- public void setCaseSensitive(boolean b) {
- ((StringComparator) comparator()).setCaseSensitive(b);
- }
-
- private static class StringComparator implements Comparator {
- /**
- * Is the map case sensitive?
- */
- private boolean m_isCaseSensitive = true;
-
- /**
- * Constructor.
- *
- * @param b : true to enable the case sensitivity.
- */
- public StringComparator(boolean b) {
- m_isCaseSensitive = b;
- }
-
- /**
- * Compare to object.
- * @param o1 : first object to compare
- * @param o2 : second object to compare
- * @return the comparison result
- * @see java.util.Comparator#compare(T, T)
- */
- public int compare(Object o1, Object o2) {
- if (m_isCaseSensitive) {
- return o1.toString().compareTo(o2.toString());
- } else {
- return o1.toString().compareToIgnoreCase(o2.toString());
- }
- }
-
- /**
- * Check if the comparator is case sensitive.
- * @return true if the map is case sensitive.
- */
- public boolean isCaseSensitive() {
- return m_isCaseSensitive;
- }
-
- /**
- * Set the case sensitivity.
- *
- * @param b : true to enable the case sensitivity
- */
- public void setCaseSensitive(boolean b) {
- m_isCaseSensitive = b;
- }
- }
-}
+/*
+ * 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.context;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Simple utility class that creates a map for string-based keys by extending
+ * <tt>TreeMap</tt>. This map can be set to use case-sensitive or
+ * case-insensitive comparison when searching for the key. Any keys put into
+ * this map will be converted to a <tt>String</tt> using the
+ * <tt>toString()</tt> method, since it is only intended to compare strings.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class StringMap extends TreeMap {
+
+ /**
+ * serialVersionUID.
+ */
+ private static final long serialVersionUID = 6948801857034259744L;
+
+ /**
+ * Constructor.
+ */
+ public StringMap() {
+ this(true);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param caseSensitive : fix if the map if case sensitive or not.
+ */
+ public StringMap(boolean caseSensitive) {
+ super(new StringComparator(caseSensitive));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param map : initial properties.
+ * @param caseSensitive : fix if the map if case sensitive or not.
+ */
+ public StringMap(Map map, boolean caseSensitive) {
+ this(caseSensitive);
+ putAll(map);
+ }
+
+ /**
+ * Put a record in the map.
+ * @param key : key
+ * @param value : value
+ * @return an object.
+ * @see java.util.TreeMap#put(K, V)
+ */
+ public Object put(Object key, Object value) {
+ return super.put(key.toString(), value);
+ }
+
+ /**
+ * Check if the map is case-sensitive.
+ * @return true if the map is case sensitive.
+ */
+ public boolean isCaseSensitive() {
+ return ((StringComparator) comparator()).isCaseSensitive();
+ }
+
+ /**
+ * Set the case sensitivity.
+ *
+ * @param flag : the new case sensitivity.
+ */
+ public void setCaseSensitive(boolean flag) {
+ ((StringComparator) comparator()).setCaseSensitive(flag);
+ }
+
+ private static class StringComparator implements Comparator {
+ /**
+ * Is the map case sensitive?
+ */
+ private boolean m_isCaseSensitive = true;
+
+ /**
+ * Constructor.
+ *
+ * @param flag : true to enable the case sensitivity.
+ */
+ public StringComparator(boolean flag) {
+ m_isCaseSensitive = flag;
+ }
+
+ /**
+ * Compare to object.
+ * @param object1 : first object to compare
+ * @param object2 : second object to compare
+ * @return the comparison result
+ * @see java.util.Comparator#compare(T, T)
+ */
+ public int compare(Object object1, Object object2) {
+ if (m_isCaseSensitive) {
+ return object1.toString().compareTo(object2.toString());
+ } else {
+ return object1.toString().compareToIgnoreCase(object2.toString());
+ }
+ }
+
+ /**
+ * Check if the comparator is case sensitive.
+ * @return true if the map is case sensitive.
+ */
+ public boolean isCaseSensitive() {
+ return m_isCaseSensitive;
+ }
+
+ /**
+ * Set the case sensitivity.
+ *
+ * @param flag : true to enable the case sensitivity
+ */
+ public void setCaseSensitive(boolean flag) {
+ m_isCaseSensitive = flag;
+ }
+ }
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
index 1509cf6..6021c5a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
@@ -24,7 +24,6 @@
import org.apache.felix.ipojo.architecture.Architecture;
import org.apache.felix.ipojo.architecture.InstanceDescription;
import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
/**
* Architecture Handler : do reflection on your component.
@@ -52,6 +51,7 @@
* @see org.apache.felix.ipojo.Handler#stop()
*/
public void stop() {
+ // Nothing do do when stopping.
}
/**
@@ -59,7 +59,7 @@
* @see org.apache.felix.ipojo.Handler#start()
*/
public void start() {
- log(Logger.INFO, "Start architecture handler with " + m_name + " name");
+ info("Start architecture handler with " + m_name + " name");
}
/**
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
deleted file mode 100644
index 26db364..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * 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.handlers.configuration;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.parser.ParseUtils;
-import org.apache.felix.ipojo.util.Callback;
-import org.apache.felix.ipojo.util.Logger;
-
-/**
- * Configurable Property.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ConfigurableProperty {
-
- /**
- * Name of the property (filed name if not set).
- */
- private String m_name;
-
- /**
- * Field of the property.
- */
- private String m_field;
-
- /**
- * Method of the property.
- */
- private Callback m_method;
-
- /**
- * Value of the property.
- */
- private Object m_value;
-
- /**
- * Type of the property.
- */
- private Class m_type;
-
- /**
- * Configuration Handler managing this property.
- */
- private ConfigurationHandler m_handler;
-
- /**
- * Configurable Property Constructor. At least the method or the field need
- * to be referenced.
- *
- * @param name : name of the property (optional)
- * @param field : name of the field
- * @param method : method name
- * @param value : initial value of the property (optional)
- * @param type : the type of the property
- * @param ch : configuration handler managing this configurable property
- * @throws ConfigurationException : occurs when the property value cannot be set.
- */
- public ConfigurableProperty(String name, String field, String method, String value, String type, ConfigurationHandler ch) throws ConfigurationException {
- m_handler = ch;
-
- m_field = field;
-
- if (name != null) {
- m_name = name;
- } else {
- if (m_field != null) {
- m_name = field;
- } else {
- m_name = method;
- }
- }
- m_field = field;
-
- if (value != null) {
- setValue(value, type);
- } else {
- setType(type);
- }
-
- if (method != null) {
- m_method = new Callback(method, new String[] { m_type.getName() }, false, m_handler.getInstanceManager());
- }
-
- }
-
- /**
- * The set type method fix the property type according to the given type name.
- * @param type : the type name
- * @throws ConfigurationException if an error occurs when loading the type class for non-primitive types.
- */
- private void setType(String type) throws ConfigurationException {
- // Syntactic sugar to avoid writing java.lang.String
- if ("string".equals(type) || "String".equals(type)) {
- m_type = java.lang.String.class;
- return;
- }
- if (type.equals("boolean")) {
- m_type = Boolean.TYPE;
- return;
- }
- if ("byte".equals(type)) {
- m_type = Byte.TYPE;
- return;
- }
- if ("short".equals(type)) {
- m_type = Short.TYPE;
- return;
- }
- if ("int".equals(type)) {
- m_type = Integer.TYPE;
- return;
- }
- if ("long".equals(type)) {
- m_type = Long.TYPE;
- return;
- }
- if ("float".equals(type)) {
- m_type = Float.TYPE;
- return;
- }
- if ("double".equals(type)) {
- m_type = Double.TYPE;
- return;
- }
- if ("char".equals(type)) {
- m_type = Character.TYPE;
- return;
- }
-
- // Array :
- if (type.endsWith("[]")) {
- String internalType = type.substring(0, type.length() - 2);
- if ("string".equals(internalType) || "String".equals(internalType)) {
- m_type = new String[0].getClass();
- return;
- }
- if ("boolean".equals(internalType)) {
- m_type = new boolean[0].getClass();
- return;
- }
- if ("byte".equals(internalType)) {
- m_type = new byte[0].getClass();
- return;
- }
- if ("short".equals(internalType)) {
- m_type = new short[0].getClass();
- return;
- }
- if ("int".equals(internalType)) {
- m_type = new int[0].getClass();
- return;
- }
- if ("long".equals(internalType)) {
- m_type = new long[0].getClass();
- return;
- }
- if ("float".equals(internalType)) {
- m_type = new float[0].getClass();
- return;
- }
- if ("double".equals(internalType)) {
- m_type = new double[0].getClass();
- return;
- }
- if ("char".equals(internalType)) {
- m_type = new char[0].getClass();
- return;
- }
-
- // Complex array type.
- try {
- Class c = m_handler.getInstanceManager().getContext().getBundle().loadClass(internalType);
- Object[] ob = (Object[]) Array.newInstance(c, 0);
- m_type = ob.getClass();
- return;
- } catch (ClassNotFoundException e) {
- throw new ConfigurationException("Class not found exception in setValue on " + internalType);
- } catch (SecurityException e) {
- throw new ConfigurationException("Secutiry Exception in setValue on " + internalType);
- } catch (IllegalArgumentException e) {
- throw new ConfigurationException("Argument problem to call the constructor of the type " + internalType);
- }
- }
-
- // Non array, complex type.
- try {
- m_type = m_handler.getInstanceManager().getContext().getBundle().loadClass(type);
- } catch (ClassNotFoundException e) {
- throw new ConfigurationException("Class not found exception in setValue on " + type + " : " + e.getMessage());
- } catch (SecurityException e) {
- throw new ConfigurationException("Security excption in setValue on " + type + " : " + e.getMessage());
- } catch (IllegalArgumentException e) {
- throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
- }
- }
-
- /**
- * Set the value of the property.
- * @param strValue : value of the property (String)
- * @param type : type of the property
- * @throws ConfigurationException : occurs when the property value cannot be initialized.
- */
- private void setValue(String strValue, String type) throws ConfigurationException {
- Object value = null;
-
- // Syntactic sugar to avoid writing java.lang.String
- if ("string".equals(type) || "String".equals(type)) {
- value = new String(strValue);
- m_type = java.lang.String.class;
- }
- if (type.equals("boolean")) {
- value = new Boolean(strValue);
- m_type = Boolean.TYPE;
- }
- if ("byte".equals(type)) {
- value = new Byte(strValue);
- m_type = Byte.TYPE;
- }
- if ("short".equals(type)) {
- value = new Short(strValue);
- m_type = Short.TYPE;
- }
- if ("int".equals(type)) {
- value = new Integer(strValue);
- m_type = Integer.TYPE;
- }
- if ("long".equals(type)) {
- value = new Long(strValue);
- m_type = Long.TYPE;
- }
- if ("float".equals(type)) {
- value = new Float(strValue);
- m_type = Float.TYPE;
- }
- if ("double".equals(type)) {
- value = new Double(strValue);
- m_type = Double.TYPE;
- }
- if ("char".equals(type)) {
- value = new Character(strValue.charAt(0));
- m_type = Character.TYPE;
- }
-
- // Array :
- if (type.endsWith("[]")) {
- String internalType = type.substring(0, type.length() - 2);
- setArrayValue(internalType, ParseUtils.parseArrays(strValue));
- return;
- }
-
- if (value == null) {
- // Else it is a neither a primitive type neither a String -> create
- // the object by calling a constructor with a string in argument.
- try {
- m_type = m_handler.getInstanceManager().getContext().getBundle().loadClass(type);
- Constructor cst = m_type.getConstructor(new Class[] { String.class });
- value = cst.newInstance(new Object[] { strValue });
- } catch (ClassNotFoundException e) {
- throw new ConfigurationException("Class not found exception in setValue on " + type + " : " + e.getMessage());
- } catch (SecurityException e) {
- throw new ConfigurationException("Security excption in setValue on " + type + " : " + e.getMessage());
- } catch (NoSuchMethodException e) {
- throw new ConfigurationException("Constructor not found exeption in setValue on " + type + " : " + e.getMessage());
- } catch (IllegalArgumentException e) {
- throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
- } catch (InstantiationException e) {
- throw new ConfigurationException("Instantiation problem " + type);
- } catch (IllegalAccessException e) {
- throw new ConfigurationException("Illegal Access " + type);
- } catch (InvocationTargetException e) {
- throw new ConfigurationException("Invocation problem " + type + " : " + e.getTargetException().getMessage());
- }
- }
-
- m_value = value;
-
- }
-
- /**
- * Set array value to the current property.
- *
- * @param internalType : type of the property
- * @param values : new property value
- * @throws ConfigurationException occurs when the array cannot be initialized
- */
- private void setArrayValue(String internalType, String[] values) throws ConfigurationException {
- if ("string".equals(internalType) || "String".equals(internalType)) {
- String[] str = new String[values.length];
- for (int i = 0; i < values.length; i++) {
- str[i] = new String(values[i]);
- }
- m_value = str;
- m_type = new String[0].getClass();
- return;
- }
- if ("boolean".equals(internalType)) {
- boolean[] bool = new boolean[values.length];
- for (int i = 0; i < values.length; i++) {
- bool[i] = new Boolean(values[i]).booleanValue();
- }
- m_value = bool;
- m_type = new boolean[0].getClass();
- return;
- }
- if ("byte".equals(internalType)) {
- byte[] byt = new byte[values.length];
- for (int i = 0; i < values.length; i++) {
- byt[i] = new Byte(values[i]).byteValue();
- }
- m_value = byt;
- m_type = new byte[0].getClass();
- return;
- }
- if ("short".equals(internalType)) {
- short[] shor = new short[values.length];
- for (int i = 0; i < values.length; i++) {
- shor[i] = new Short(values[i]).shortValue();
- }
- m_value = shor;
- m_type = new short[0].getClass();
- return;
- }
- if ("int".equals(internalType)) {
- int[] in = new int[values.length];
- for (int i = 0; i < values.length; i++) {
- in[i] = new Integer(values[i]).intValue();
- }
- m_value = in;
- m_type = new int[0].getClass();
- return;
- }
- if ("long".equals(internalType)) {
- long[] ll = new long[values.length];
- for (int i = 0; i < values.length; i++) {
- ll[i] = new Long(values[i]).longValue();
- }
- m_value = ll;
- m_type = new long[0].getClass();
- return;
- }
- if ("float".equals(internalType)) {
- float[] fl = new float[values.length];
- for (int i = 0; i < values.length; i++) {
- fl[i] = new Float(values[i]).floatValue();
- }
- m_value = fl;
- m_type = new float[0].getClass();
- return;
- }
- if ("double".equals(internalType)) {
- double[] dl = new double[values.length];
- for (int i = 0; i < values.length; i++) {
- dl[i] = new Double(values[i]).doubleValue();
- }
- m_value = dl;
- m_type = new double[0].getClass();
- return;
- }
- if ("char".equals(internalType)) {
- char[] dl = new char[values.length];
- for (int i = 0; i < values.length; i++) {
- dl[i] = values[i].toCharArray()[0];
- }
- m_value = dl;
- m_type = new char[0].getClass();
- return;
- }
-
- // Else it is a neither a primitive type neither a String -> create the
- // object by calling a constructor with a string in argument.
- try {
- Class c = m_handler.getInstanceManager().getContext().getBundle().loadClass(internalType);
- Constructor cst = c.getConstructor(new Class[] { String.class });
- Object[] ob = (Object[]) Array.newInstance(c, values.length);
- for (int i = 0; i < values.length; i++) {
- ob[i] = cst.newInstance(new Object[] { values[i].trim() });
- }
- m_value = ob;
- m_type = ob.getClass();
- return;
- } catch (ClassNotFoundException e) {
- throw new ConfigurationException("Class not found exception in setValue on " + internalType);
- } catch (SecurityException e) {
- throw new ConfigurationException("Secutiry Exception in setValue on " + internalType);
- } catch (NoSuchMethodException e) {
- throw new ConfigurationException("Constructor not found exception in setValue on " + internalType);
- } catch (IllegalArgumentException e) {
- throw new ConfigurationException("Argument problem to call the constructor of the type " + internalType);
- } catch (InstantiationException e) {
- throw new ConfigurationException("Instantiation problem " + internalType);
- } catch (IllegalAccessException e) {
- throw new ConfigurationException("Illegal Access Exception in " + internalType);
- } catch (InvocationTargetException e) {
- throw new ConfigurationException("Invocation problem " + internalType + " : " + e.getTargetException().getMessage());
- }
- }
-
- public String getName() {
- return m_name;
- }
-
- public String getField() {
- return m_field;
- }
-
- /**
- * Get method name, null if no method.
- * @return the method name.
- */
- public String getMethod() {
- if (m_method == null) { return null; }
- return m_method.getMethod();
- }
-
- /**
- * Check if the property has a method callback.
- * @return true if the property has a method.
- */
- public boolean hasMethod() {
- return m_method != null;
- }
-
- /**
- * Check if the property has a field.
- * @return true if the property has a field.
- */
- public boolean hasField() {
- return m_field != null;
- }
-
- public Object getValue() {
- return m_value;
- }
-
- /**
- * Fix the value of the property.
- * @param value : the new value.
- */
- public void setValue(Object value) {
- // Is the object is directly assignable to the property, affect it.
- if (isAssignable(m_type, value)) {
- m_value = value;
- } else {
- // If the object is a String, we must recreate the object from the String form
- if (value instanceof String) {
- try {
- m_value = create(m_type, (String) value);
- } catch (ConfigurationException e) {
- throw new ClassCastException("Incompatible type for the property " + m_name + " : " + e.getMessage());
- }
- } else {
- // Error, the given property cannot be injected.
- throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type.getName() + " expected, " + value.getClass() + " received");
- }
- }
- }
-
- /**
- * Test if the given value is assignable to the given type.
- * @param type : class of the type
- * @param value : object to check
- * @return true if the object is assignable in the property of type 'type'.
- */
- public static boolean isAssignable(Class type, Object value) {
- if (type.isInstance(value)) {
- return true;
- } else if (type.isPrimitive()) {
- // Manage all boxing types.
- if (value instanceof Boolean && type.equals(Boolean.TYPE)) {
- return true;
- }
- if (value instanceof Byte && type.equals(Byte.TYPE)) {
- return true;
- }
- if (value instanceof Short && type.equals(Short.TYPE)) {
- return true;
- }
- if (value instanceof Integer && type.equals(Integer.TYPE)) {
- return true;
- }
- if (value instanceof Long && type.equals(Long.TYPE)) {
- return true;
- }
- if (value instanceof Float && type.equals(Float.TYPE)) {
- return true;
- }
- if (value instanceof Double && type.equals(Double.TYPE)) {
- return true;
- }
- if (value instanceof Character && type.equals(Character.TYPE)) {
- return true;
- }
- return false;
- } else {
- // Else return false.
- return false;
- }
- }
-
- /**
- * Create an object of the given type with the given String value.
- * @param type : type of the returned object
- * @param strValue : String value.
- * @return the object of type 'type' created from the String 'value'
- * @throws ConfigurationException occurs when the object cannot be created.
- */
- public static Object create(Class type, String strValue) throws ConfigurationException {
- if (type.equals(Boolean.TYPE)) { return new Boolean(strValue); }
- if (type.equals(Byte.TYPE)) { return new Byte(strValue); }
- if (type.equals(Short.TYPE)) { return new Short(strValue); }
- if (type.equals(Integer.TYPE)) { return new Integer(strValue); }
- if (type.equals(Long.TYPE)) { return new Long(strValue); }
- if (type.equals(Float.TYPE)) { return new Float(strValue); }
- if (type.equals(Double.TYPE)) { return new Double(strValue); }
- if (type.equals(Character.TYPE)) { return new Character(strValue.charAt(0)); }
-
- // Array :
- if (type.isArray()) { return createArrayObject(type.getComponentType(), ParseUtils.parseArrays(strValue)); }
- // Else it is a neither a primitive type neither a String -> create
- // the object by calling a constructor with a string in argument.
- try {
- Constructor cst = type.getConstructor(new Class[] { String.class });
- return cst.newInstance(new Object[] { strValue });
- } catch (SecurityException e) {
- throw new ConfigurationException("Security exception in create on " + type + " : " + e.getMessage());
- } catch (NoSuchMethodException e) {
- throw new ConfigurationException("Constructor not found exception in create on " + type + " : " + e.getMessage());
- } catch (IllegalArgumentException e) {
- throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
- } catch (InstantiationException e) {
- throw new ConfigurationException("Instantiation problem " + type);
- } catch (IllegalAccessException e) {
- throw new ConfigurationException("Illegal Access " + type);
- } catch (InvocationTargetException e) {
- throw new ConfigurationException("Invocation problem " + type + " : " + e.getTargetException().getMessage());
- }
-
- }
-
- /**
- * Create an array object containing the type 'interntype' from the String array 'values'.
- * @param interntype : internal type of the array.
- * @param values : String array
- * @return the array containing objects created from the 'values' array
- * @throws ConfigurationException occurs when the array cannot be created correctly
- */
- public static Object createArrayObject(Class interntype, String[] values) throws ConfigurationException {
- if (interntype.equals(Boolean.TYPE)) {
- boolean[] bool = new boolean[values.length];
- for (int i = 0; i < values.length; i++) {
- bool[i] = new Boolean(values[i]).booleanValue();
- }
- return bool;
- }
- if (interntype.equals(Byte.TYPE)) {
- byte[] byt = new byte[values.length];
- for (int i = 0; i < values.length; i++) {
- byt[i] = new Byte(values[i]).byteValue();
- }
- return byt;
- }
- if (interntype.equals(Short.TYPE)) {
- short[] shor = new short[values.length];
- for (int i = 0; i < values.length; i++) {
- shor[i] = new Short(values[i]).shortValue();
- }
- return shor;
- }
- if (interntype.equals(Integer.TYPE)) {
- int[] in = new int[values.length];
- for (int i = 0; i < values.length; i++) {
- in[i] = new Integer(values[i]).intValue();
- }
- return in;
- }
- if (interntype.equals(Long.TYPE)) {
- long[] ll = new long[values.length];
- for (int i = 0; i < values.length; i++) {
- ll[i] = new Long(values[i]).longValue();
- }
- return ll;
- }
- if (interntype.equals(Float.TYPE)) {
- float[] fl = new float[values.length];
- for (int i = 0; i < values.length; i++) {
- fl[i] = new Float(values[i]).floatValue();
- }
- return fl;
- }
- if (interntype.equals(Double.TYPE)) {
- double[] dl = new double[values.length];
- for (int i = 0; i < values.length; i++) {
- dl[i] = new Double(values[i]).doubleValue();
- }
- return dl;
- }
- if (interntype.equals(Character.TYPE)) {
- char[] dl = new char[values.length];
- for (int i = 0; i < values.length; i++) {
- dl[i] = values[i].toCharArray()[0];
- }
- return dl;
- }
-
- // Else it is a neither a primitive type -> create the
- // object by calling a constructor with a string in argument.
- try {
- Constructor cst = interntype.getConstructor(new Class[] { String.class });
- Object[] ob = (Object[]) Array.newInstance(interntype, values.length);
- for (int i = 0; i < values.length; i++) {
- ob[i] = cst.newInstance(new Object[] { values[i].trim() });
- }
- return ob;
- } catch (NoSuchMethodException e) {
- throw new ConfigurationException("Constructor not found exception in setValue on " + interntype.getName());
- } catch (IllegalArgumentException e) {
- throw new ConfigurationException("Argument problem to call the constructor of the type " + interntype.getName());
- } catch (InstantiationException e) {
- throw new ConfigurationException("Instantiation problem " + interntype.getName());
- } catch (IllegalAccessException e) {
- throw new ConfigurationException("Illegal Access Exception in " + interntype.getName());
- } catch (InvocationTargetException e) {
- throw new ConfigurationException("Invocation problem " + interntype.getName() + " : " + e.getTargetException().getMessage());
- }
- }
-
- /**
- * Invoke the method (if specified).
- * If the invocation failed, the instance is stopped.
- */
- public void invoke() {
- try {
- m_method.call(new Object[] { m_value });
- } catch (NoSuchMethodException e) {
- m_handler.log(Logger.ERROR, "The method " + m_method + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_handler.log(Logger.ERROR, "The method " + m_method + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_handler.log(Logger.ERROR, "The method " + m_method + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getTargetException().getMessage());
- m_handler.getInstanceManager().setState(ComponentInstance.INVALID);
- }
- }
-
- /**
- * Handler createInstance method. This method is override to allow delayed callback invocation.
- * If the invocation failed, the instance is stopped.
- * @param instance : the created object
- * @see org.apache.felix.ipojo.Handler#objectCreated(java.lang.Object)
- */
- public void invoke(Object instance) {
- try {
- m_method.call(instance, new Object[] { m_value });
- } catch (NoSuchMethodException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getTargetException().getMessage());
- m_handler.getInstanceManager().setState(ComponentInstance.INVALID);
- }
- }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index 186caa9..ef89f07 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -18,24 +18,23 @@
*/
package org.apache.felix.ipojo.handlers.configuration;
-import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
-import java.util.List;
import java.util.Properties;
import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.IPojoConfiguration;
+import org.apache.felix.ipojo.HandlerFactory;
import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.PrimitiveHandler;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.architecture.PropertyDescription;
import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.FieldMetadata;
-import org.apache.felix.ipojo.parser.ManipulationMetadata;
import org.apache.felix.ipojo.parser.MethodMetadata;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.apache.felix.ipojo.util.Property;
/**
* Handler managing the Configuration Admin.
@@ -46,7 +45,7 @@
/**
* List of the configurable fields.
*/
- private ConfigurableProperty[] m_configurableProperties = new ConfigurableProperty[0];
+ private Property[] m_configurableProperties = new Property[0];
/**
* ProvidedServiceHandler of the component. It is useful to propagate
@@ -71,16 +70,16 @@
/**
* Initialize the component type.
- * @param cd : component type description to populate.
+ * @param desc : 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.ComponentDescription, org.apache.felix.ipojo.metadata.Element)
+ * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element)
*/
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
+ public void initializeComponentFactory(ComponentTypeDescription desc, Element metadata) throws ConfigurationException {
Element[] confs = metadata.getElements("Properties", "");
- if (confs.length == 0) { return; }
+ if (confs == null) { return; }
Element[] configurables = confs[0].getElements("Property");
- for (int i = 0; i < configurables.length; i++) {
+ for (int i = 0; configurables != null && i < configurables.length; i++) {
String fieldName = configurables[i].getAttribute("field");
String methodName = configurables[i].getAttribute("method");
@@ -90,10 +89,10 @@
String name = configurables[i].getAttribute("name");
if (name == null) {
- if (fieldName != null) {
- name = fieldName;
- } else {
+ if (fieldName == null) {
name = methodName;
+ } else {
+ name = fieldName;
}
configurables[i].addAttribute(new Attribute("name", name)); // Add the type to avoid configure checking
}
@@ -101,35 +100,43 @@
String value = configurables[i].getAttribute("value");
// Detect the type of the property
- ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
+ PojoMetadata manipulation = getFactory().getPojoMetadata();
String type = null;
- if (fieldName != null) {
- FieldMetadata fm = manipulation.getField(fieldName);
- if (fm == null) { throw new ConfigurationException("Malformed property : The field " + fieldName + " does not exist in the implementation"); }
- type = fm.getFieldType();
- configurables[i].addAttribute(new Attribute("type", type)); // Add the type to avoid configure checking
- } else {
- MethodMetadata[] mm = manipulation.getMethods(methodName);
- if (mm.length != 0) {
- if (mm[0].getMethodArguments().length != 1) {
- throw new ConfigurationException("Malformed property : The method " + methodName + " does not have one argument");
- }
- if (type != null && !type.equals(mm[0].getMethodArguments()[0])) {
- throw new ConfigurationException("Malformed property : The field type (" + type + ") and the method type (" + mm[0].getMethodArguments()[0] + ") are not the same.");
- }
- type = mm[0].getMethodArguments()[0];
- configurables[i].addAttribute(new Attribute("type", type)); // Add the type to avoid configure checking
- } else {
+ if (fieldName == null) {
+ MethodMetadata[] method = manipulation.getMethods(methodName);
+ if (method.length == 0) {
type = configurables[i].getAttribute("type");
if (type == null) {
throw new ConfigurationException("Malformed property : The type of the property cannot be discovered, please add a 'type' attribute");
}
+ } else {
+ if (method[0].getMethodArguments().length != 1) {
+ throw new ConfigurationException("Malformed property : The method " + methodName + " does not have one argument");
+ }
+ if (type != null && !type.equals(method[0].getMethodArguments()[0])) {
+ throw new ConfigurationException("Malformed property : The field type (" + type + ") and the method type (" + method[0].getMethodArguments()[0] + ") are not the same.");
+ }
+ type = method[0].getMethodArguments()[0];
+ configurables[i].addAttribute(new Attribute("type", type)); // Add the type to avoid configure checking
}
- }
- if (value != null) {
- cd.addProperty(new PropertyDescription(name, type, value));
} else {
- cd.addProperty(new PropertyDescription(name, type, null));
+ FieldMetadata field = manipulation.getField(fieldName);
+ if (field == null) { throw new ConfigurationException("Malformed property : The field " + fieldName + " does not exist in the implementation"); }
+ type = field.getFieldType();
+ configurables[i].addAttribute(new Attribute("type", type)); // Add the type to avoid configure checking
+ }
+
+ // Is the property set to immutable
+ boolean immutable = false;
+ String imm = configurables[i].getAttribute("immutable");
+ if (imm != null && imm.equalsIgnoreCase("true")) {
+ immutable = true;
+ }
+
+ if (value == null) {
+ desc.addProperty(new PropertyDescription(name, type, null, false)); // Cannot be immutable if we have no value.
+ } else {
+ desc.addProperty(new PropertyDescription(name, type, value, immutable));
}
}
}
@@ -145,7 +152,7 @@
*/
public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
// Store the component manager
- m_configurableProperties = new ConfigurableProperty[0];
+ m_configurableProperties = new Property[0];
// Build the map
Element[] confs = metadata.getElements("Properties", "");
@@ -160,43 +167,32 @@
m_toPropagate = configuration;
}
- List ff = new ArrayList();
-
- for (int i = 0; i < configurables.length; i++) {
+ for (int i = 0; configurables != null && i < configurables.length; i++) {
String fieldName = configurables[i].getAttribute("field");
String methodName = configurables[i].getAttribute("method");
String name = configurables[i].getAttribute("name"); // The initialize method has fixed the property name.
String value = configurables[i].getAttribute("value");
- if (configuration.get(name) != null && configuration.get(name) instanceof String) {
- value = (String) configuration.get(name);
- } else {
- if (fieldName != null && configuration.get(fieldName) != null && configuration.get(fieldName) instanceof String) {
- value = (String) configuration.get(fieldName);
- }
- }
-
String type = configurables[i].getAttribute("type"); // The initialize method has fixed the property name.
- if (fieldName != null) {
- FieldMetadata fm = new FieldMetadata(fieldName, type);
- ff.add(fm);
- }
-
- ConfigurableProperty cp = new ConfigurableProperty(name, fieldName, methodName, value, type, this);
- addProperty(cp);
+ Property prop = new Property(name, fieldName, methodName, value, type, getInstanceManager(), this);
+ addProperty(prop);
// Check if the instance configuration contains value for the current property :
- if (configuration.get(name) != null && !(configuration.get(name) instanceof String)) {
- cp.setValue(configuration.get(name));
- } else {
- if (fieldName != null && configuration.get(fieldName) != null && !(configuration.get(fieldName) instanceof String)) {
- cp.setValue(configuration.get(fieldName));
+ if (configuration.get(name) == null) {
+ if (fieldName != null && configuration.get(fieldName) != null) {
+ prop.setValue(configuration.get(fieldName));
}
+ } else {
+ prop.setValue(configuration.get(name));
+ }
+
+ if (fieldName != null) {
+ FieldMetadata field = new FieldMetadata(fieldName, type);
+ getInstanceManager().register(field, prop);
}
}
- getInstanceManager().register(this, (FieldMetadata[]) ff.toArray(new FieldMetadata[ff.size()]), null);
}
/**
@@ -205,6 +201,7 @@
* @see org.apache.felix.ipojo.Handler#stop()
*/
public void stop() {
+ // Nothing to do.
}
/**
@@ -214,7 +211,7 @@
*/
public void start() {
// Get the provided service handler :
- m_providedServiceHandler = (ProvidedServiceHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":provides");
+ m_providedServiceHandler = (ProvidedServiceHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":provides");
// Propagation
if (m_isConfigurable) {
@@ -225,45 +222,47 @@
}
}
- /**
- * Setter Callback Method.
- * Check if the modified field is a configurable property to update the value.
- * @param fieldName : field name
- * @param value : new value
- * @see org.apache.felix.ipojo.Handler#setterCallback(java.lang.String, java.lang.Object)
- */
- public void setterCallback(String fieldName, Object value) {
- // Verify that the field name correspond to a configurable property
- for (int i = 0; i < m_configurableProperties.length; i++) {
- ConfigurableProperty cp = m_configurableProperties[i];
- if (cp.hasField() && cp.getField().equals(fieldName)) {
- // Check if the value has changed
- if (cp.getValue() == null || !cp.getValue().equals(value)) {
- cp.setValue(value); // Change the value
- }
- }
- }
- // Else do nothing
- }
-
- /**
- * Getter Callback Method.
- * Check if the field is a configurable property to push the stored value.
- * @param fieldName : field name
- * @param value : value pushed by the previous handler
- * @return the stored value or the previous value.
- * @see org.apache.felix.ipojo.Handler#getterCallback(java.lang.String,
- * java.lang.Object)
- */
- public Object getterCallback(String fieldName, Object value) {
- // Check if the field is a configurable property
- for (int i = 0; i < m_configurableProperties.length; i++) {
- if (fieldName.equals(m_configurableProperties[i].getField())) {
- return m_configurableProperties[i].getValue();
- }
- }
- return value;
- }
+// /**
+// * Setter Callback Method.
+// * Check if the modified field is a configurable property to update the value.
+// * @param pojo : the pojo object on which the field is accessed
+// * @param fieldName : field name
+// * @param value : new value
+// * @see org.apache.felix.ipojo.Handler#onSet(Object, java.lang.String, java.lang.Object)
+// */
+// public void onSet(Object pojo, String fieldName, Object value) {
+// // Verify that the field name correspond to a configurable property
+// for (int i = 0; i < m_configurableProperties.length; i++) {
+// Property prop = m_configurableProperties[i];
+// if (prop.hasField() && prop.getField().equals(fieldName)) {
+// // Check if the value has changed
+// if (prop.getValue() == null || !prop.getValue().equals(value)) {
+// prop.setValue(value); // Change the value
+// }
+// }
+// }
+// // Else do nothing
+// }
+//
+// /**
+// * Getter Callback Method.
+// * Check if the field is a configurable property to push the stored value.
+// * @param pojo : the pojo object on which the field is accessed
+// * @param fieldName : field name
+// * @param value : value pushed by the previous handler
+// * @return the stored value or the previous value.
+// * @see org.apache.felix.ipojo.Handler#onGet(Object,
+// * java.lang.String, java.lang.Object)
+// */
+// public Object onGet(Object pojo, String fieldName, Object value) {
+// // Check if the field is a configurable property
+// for (int i = 0; i < m_configurableProperties.length; i++) {
+// if (fieldName.equals(m_configurableProperties[i].getField())) {
+// return m_configurableProperties[i].getValue();
+// }
+// }
+// return value;
+// }
/**
* Handler state changed.
@@ -284,20 +283,20 @@
/**
* Add the given property metadata to the property metadata list.
*
- * @param p : property metadata to add
+ * @param prop : property metadata to add
*/
- protected void addProperty(ConfigurableProperty p) {
+ protected void addProperty(Property prop) {
for (int i = 0; (m_configurableProperties != null) && (i < m_configurableProperties.length); i++) {
- if (m_configurableProperties[i].getName().equals(p.getName())) { return; }
+ if (m_configurableProperties[i].getName().equals(prop.getName())) { return; }
}
if (m_configurableProperties.length > 0) {
- ConfigurableProperty[] newProp = new ConfigurableProperty[m_configurableProperties.length + 1];
+ Property[] newProp = new Property[m_configurableProperties.length + 1];
System.arraycopy(m_configurableProperties, 0, newProp, 0, m_configurableProperties.length);
- newProp[m_configurableProperties.length] = p;
+ newProp[m_configurableProperties.length] = prop;
m_configurableProperties = newProp;
} else {
- m_configurableProperties = new ConfigurableProperty[] { p };
+ m_configurableProperties = new Property[] { prop };
}
}
@@ -317,31 +316,31 @@
/**
* Reconfigure the component instance.
* Check if the new configuration modify the current configuration.
- * @param np : the new configuration
+ * @param configuration : the new configuration
* @see org.apache.felix.ipojo.Handler#reconfigure(java.util.Dictionary)
*/
- public void reconfigure(Dictionary np) {
+ public void reconfigure(Dictionary configuration) {
Properties toPropagate = new Properties();
- Enumeration keysEnumeration = np.keys();
+ Enumeration keysEnumeration = configuration.keys();
while (keysEnumeration.hasMoreElements()) {
String name = (String) keysEnumeration.nextElement();
- Object value = np.get(name);
+ Object value = configuration.get(name);
boolean found = false;
// Check if the name is a configurable property
- for (int i = 0; !found && i < m_configurableProperties.length; i++) {
+ for (int i = 0; i < m_configurableProperties.length; i++) {
if (m_configurableProperties[i].getName().equals(name)) {
// Check if the value has changed
if (m_configurableProperties[i].getValue() == null || !m_configurableProperties[i].getValue().equals(value)) {
if (m_configurableProperties[i].hasField()) {
- getInstanceManager().setterCallback(m_configurableProperties[i].getField(), value); // dispatch that the value has changed
+ getInstanceManager().onSet(null, m_configurableProperties[i].getField(), value); // dispatch that the value has changed
}
if (m_configurableProperties[i].hasMethod()) {
m_configurableProperties[i].setValue(value);
- m_configurableProperties[i].invoke();
+ m_configurableProperties[i].invoke(null); // Call on all created pojo objects.
}
}
found = true;
- // Else do nothing
+ break;
}
}
if (!found) {
@@ -366,9 +365,9 @@
* Handler createInstance method.
* This method is override to allow delayed callback invocation.
* @param instance : the created object
- * @see org.apache.felix.ipojo.Handler#objectCreated(java.lang.Object)
+ * @see org.apache.felix.ipojo.Handler#onCreation(java.lang.Object)
*/
- public void objectCreated(Object instance) {
+ public void onCreation(Object instance) {
for (int i = 0; i < m_configurableProperties.length; i++) {
if (m_configurableProperties[i].hasMethod()) {
m_configurableProperties[i].invoke(instance);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 7258e23..9b3c0e3 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -20,62 +20,28 @@
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.IPojoContext;
+import org.apache.felix.ipojo.FieldInterceptor;
import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.MethodInterceptor;
import org.apache.felix.ipojo.Nullable;
import org.apache.felix.ipojo.PolicyServiceContext;
-import org.apache.felix.ipojo.ServiceContext;
-import org.apache.felix.ipojo.composite.CompositeServiceContext;
-import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.ServiceReferenceRankingComparator;
-import org.apache.felix.ipojo.util.Tracker;
-import org.apache.felix.ipojo.util.TrackerCustomizer;
+import org.apache.felix.ipojo.handlers.dependency.ServiceUsage.Usage;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
* Represent a service dependency of the component instance.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class Dependency implements TrackerCustomizer {
-
- /**
- * Dependency State : RESOLVED.
- */
- public static final int RESOLVED = 1;
-
- /**
- * Dependency State : UNRESOLVED.
- */
- public static final int UNRESOLVED = 2;
-
- /**
- * Dependency State : BROKEN.
- * Broken means that a used service disappears for static dependency.
- */
- public static final int BROKEN = 3;
-
- /**
- * Dynamic Binding Policy (default).
- */
- public static final int DYNAMIC_POLICY = 0;
-
- /**
- * Dynamic Priority Binding Policy.
- */
- public static final int DYNAMIC_PRIORITY_POLICY = 1;
-
- /**
- * Static Binding Policy.
- */
- public static final int STATIC_POLICY = 2;
+public class Dependency extends DependencyModel implements FieldInterceptor, MethodInterceptor {
/**
* Reference on the Dependency Handler.
@@ -90,144 +56,88 @@
/**
* List of dependency callback.
*/
- private DependencyCallback[] m_callbacks = new DependencyCallback[0];
+ private DependencyCallback[] m_callbacks;
/**
- * Service Specification required by the dependency.
- */
- private String m_specification;
-
- /**
- * Dependency ID (declared ID, if not declare use the specification).
- */
- private String m_id;
-
- /**
- * Is the dependency a multiple dependency ?
- */
- private boolean m_isAggregate = false;
-
- /**
- * Is the Dependency an optional dependency ?
- */
- private boolean m_isOptional = false;
-
- /**
- * LDAP Filter of the Dependency (String form).
- */
- private String m_strFilter;
-
- /**
* Is the dependency a service level dependency.
*/
- private boolean m_isServiceLevelRequirement = false;
-
- /**
- * Resolution policy.
- */
- private int m_policy = PolicyServiceContext.LOCAL_AND_GLOBAL;
+ private boolean m_isServiceLevelRequirement;
/**
- * Array of service references.
- * m_ref : Array
+ * Is the provider set frozen ?
*/
- private List m_references = new ArrayList();
-
- /**
- * Array of service reference containing used service references.
- */
- private List m_usedReferences = new ArrayList();
+ private boolean m_isFrozen;
/**
- * State of the dependency. 0 : stopped, 1 : valid, 2 : invalid.
- * m_state : int
+ * Is the dependency started ?
*/
- private int m_state;
+ private boolean m_isStarted;
/**
- * Class of the dependency.
- * Useful to create in the case of multiple dependency
- */
- private Class m_clazz;
-
- /**
- * LDAP Filter of the dependency.
- */
- private Filter m_filter;
-
- /**
- * Service Context in which resolving the dependency.
- */
- private ServiceContext m_serviceContext;
-
- /**
* Thread Local.
*/
- private ServiceUsage m_usage = new ServiceUsage();
+ private ServiceUsage m_usage;
/**
- * Service Tracker.
- */
- private Tracker m_tracker;
-
- /**
- * IS the instance activated ?
- */
- private boolean m_activated = false;
-
- /**
- * Binding Policy.
- */
- private int m_bindingPolicy;
-
- /**
* Nullable object.
*/
private Object m_nullable;
-
+
/**
* Default-Implementation.
*/
private String m_di;
/**
+ * Id of the dependency.
+ */
+ private String m_id;
+
+ /**
* Dependency constructor. After the creation the dependency is not started.
*
- * @param dh : the dependency handler managing this dependency
+ * @param handler : the dependency handler managing this dependency
* @param field : field of the dependency
* @param spec : required specification
* @param filter : LDAP filter of the dependency
* @param isOptional : is the dependency an optional dependency ?
* @param isAggregate : is the dependency an aggregate dependency
- * @param id : id of the dependency, may be null
+ * @param identity : id of the dependency, may be null
+ * @param context : bundle context (or service context) to use.
* @param policy : resolution policy
- * @param bindingPolicy : binding policy
- * @param di : default-implementation class
+ * @param cmp : comparator to sort references
+ * @param defaultImplem : default-implementation class
*/
- public Dependency(DependencyHandler dh, String field, String spec, String filter, boolean isOptional, boolean isAggregate, String id, int policy, int bindingPolicy, String di) {
- m_handler = dh;
- m_field = field;
- m_specification = spec;
- m_isOptional = isOptional;
- m_di = di;
-
- m_strFilter = filter;
- m_isAggregate = isAggregate;
- if (m_id == null) {
- m_id = m_specification;
+ public Dependency(DependencyHandler handler, String field, Class spec, Filter filter, boolean isOptional, boolean isAggregate, String identity, BundleContext context, int policy, Comparator cmp, String defaultImplem) {
+ super(spec, isAggregate, isOptional, filter, cmp, policy, context, handler);
+ m_handler = handler;
+ if (field != null) {
+ m_field = field;
+ m_usage = new ServiceUsage();
+ }
+ m_di = defaultImplem;
+
+ if (identity == null) {
+ if (spec != null) {
+ m_id = spec.getName();
+ }
} else {
- m_id = id;
- }
- if (policy != -1) {
- m_policy = policy;
- }
-
- m_bindingPolicy = bindingPolicy;
-
- // Fix the policy according to the level
- if ((m_policy == PolicyServiceContext.LOCAL_AND_GLOBAL || m_policy == PolicyServiceContext.LOCAL) && ! ((((IPojoContext) m_handler.getInstanceManager().getContext()).getServiceContext()) instanceof CompositeServiceContext)) {
- // We are not in a composite : BOTH | STRICT => GLOBAL
- m_policy = PolicyServiceContext.GLOBAL;
+ m_id = identity;
+ }
+ // Else wait the setSpecification call.
+ }
+
+ /**
+ * Set the specification of the current dependency.
+ * In order to store the id of the dependency, this
+ * method is override.
+ * @param spec : request service Class
+ * @see org.apache.felix.ipojo.util.DependencyModel#setSpecification(java.lang.Class)
+ */
+ public void setSpecification(Class spec) {
+ super.setSpecification(spec);
+ if (m_id == null) {
+ m_id = spec.getName();
}
}
@@ -235,122 +145,76 @@
return m_field;
}
-
- public String getSpecification() {
- return m_specification;
- }
-
-
- public boolean isOptional() {
- return m_isOptional;
- }
-
-
- public boolean isAggregate() {
- return m_isAggregate;
- }
-
- /**
- * Set the dependency to aggregate.
- */
- protected void setAggregate() {
- m_isAggregate = true;
- }
-
- /**
- * Activate the dependency.
- * For static policy it freezes the service reference set.
- */
- void activate() {
- if (m_bindingPolicy == STATIC_POLICY) {
- m_activated = true;
- }
- }
-
- /**
- * Set the tracked specification for this dependency.
- * @param spec : the tracked specification (interface name)
- */
- protected void setSpecification(String spec) {
- m_specification = spec;
- }
-
/**
* Add a callback to the dependency.
- * @param cb : callback to add
+ * @param callback : callback to add
*/
- protected void addDependencyCallback(DependencyCallback cb) {
- if (m_callbacks.length > 0) {
+ protected void addDependencyCallback(DependencyCallback callback) {
+ if (m_callbacks == null) {
+ m_callbacks = new DependencyCallback[] { callback };
+ } else {
DependencyCallback[] newCallbacks = new DependencyCallback[m_callbacks.length + 1];
System.arraycopy(m_callbacks, 0, newCallbacks, 0, m_callbacks.length);
- newCallbacks[m_callbacks.length] = cb;
+ newCallbacks[m_callbacks.length] = callback;
m_callbacks = newCallbacks;
- } else {
- m_callbacks = new DependencyCallback[] { cb };
}
}
+ /**
+ * Stop the current dependency.
+ * @see org.apache.felix.ipojo.util.DependencyModel#stop()
+ */
+ public void stop() {
+ m_isStarted = false;
+ super.stop();
+ }
/**
* Get the string form of the filter.
* @return : the string form of the filter.
*/
- public String getFilter() {
- if (m_strFilter == null) { return ""; }
- return m_strFilter;
+ public String getStringFilter() {
+ return getFilter().toString();
}
-
public DependencyHandler getHandler() {
return m_handler;
}
- /**
- * Build the Set [service reference] of used services.
- * @return the used service.
- */
- public List getUsedServices() {
- return m_usedReferences;
+ public synchronized boolean isFrozen() {
+ return m_isFrozen;
}
/**
- * This method is called by the replaced code in the component
- * implementation class. Construct the service object list is necessary.
- *
- * @return null or a service object or a list of service object according to
- * the dependency.
+ * Call the bind method.
+ * @param pojo : pojo instance on which calling the bind method.
*/
- Object get() {
- // Initialize the thread local object is not already touched.
- if (m_usage.getObjects().isEmpty()) {
- if (isAggregate()) {
- synchronized (m_tracker) {
- for (int i = 0; i < m_references.size(); i++) {
- ServiceReference ref = (ServiceReference) m_references.get(i);
- m_usage.getReferences().add(ref);
- m_usage.getObjects().add(getService(ref));
- }
- }
- } else {
- if (m_references.size() == 0) {
- if (m_nullable == null) {
- m_handler.log(Logger.WARNING, "[" + m_handler.getInstanceManager().getInstanceName() + "] The dependency is not optional, however no service object can be injected in " + m_field + " -> " + m_specification);
- return null;
- }
- m_usage.getObjects().add(m_nullable);
- } else {
- ServiceReference ref = (ServiceReference) m_references.get(0);
- m_usage.getReferences().add(ref); // Get the first one
- m_usage.getObjects().add(getService(ref));
- }
- }
- m_usage.setStackLevel(1);
+ protected synchronized void onObjectCreation(Object pojo) {
+ if (!m_isStarted) { return; }
+
+ // We are notified of an instance creation, we have to freeze when the static policy is used
+ if (getBindingPolicy() == STATIC_BINDING_POLICY) {
+ m_isFrozen = true;
}
- if (m_isAggregate) { // Multiple dependency
- return (Object[]) m_usage.getObjects().toArray((Object[]) Array.newInstance(m_clazz, m_usage.getObjects().size()));
- } else {
- return m_usage.getObjects().get(0);
+ // Check optional case : nullable object case : do not call bind on nullable object
+ if (isOptional() && getSize() == 0) { return; }
+
+ // Call bind callback.
+ for (int j = 0; m_callbacks != null && j < m_callbacks.length; j++) {
+ if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
+ if (isAggregate()) {
+ ServiceReference[] refs = getServiceReferences();
+ for (int i = 0; i < refs.length; i++) {
+ invokeCallback(m_callbacks[j], refs[i], pojo);
+ }
+ } else {
+ ServiceReference ref = getServiceReference();
+ if (ref != null) {
+ invokeCallback(m_callbacks[j], ref, pojo);
+ }
+ }
+ }
}
}
@@ -360,95 +224,38 @@
*/
private void callUnbindMethod(ServiceReference ref) {
if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects() != null) {
- for (int i = 0; i < m_callbacks.length; i++) {
+ for (int i = 0; m_callbacks != null && i < m_callbacks.length; i++) {
if (m_callbacks[i].getMethodType() == DependencyCallback.UNBIND) {
- try {
- m_callbacks[i].call(ref, getService(ref));
- } catch (NoSuchMethodException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getTargetException().getMessage());
- m_handler.getInstanceManager().stop();
- }
+ invokeCallback(m_callbacks[i], ref, null); // Call on each created pojo objects.
}
}
}
}
/**
- * Get a service object for the given reference according to the resolving policy.
- * @param ref : service reference
- * @return the service object
+ * Helper method calling the given callback.
+ * @param callback : callback to call.
+ * @param ref : service reference.
+ * @param pojo : pojo on which calling the callback, if null call on each created pojo objects.
*/
- private synchronized Object getService(ServiceReference ref) {
- if (!m_usedReferences.contains(ref)) {
- m_usedReferences.add(ref);
- }
- return m_tracker.getService(ref);
- }
-
- /**
- * Unget the given service reference according to the resolving policy.
- * @param ref : service reference to unget
- */
- private void ungetService(ServiceReference ref) {
- m_tracker.ungetService(ref);
- }
-
- /**
- * Call the bind method.
- * @param instance : instance on which calling the bind method.
- */
- protected synchronized void callBindMethod(Object instance) {
- if (m_tracker == null) { return; }
- // Check optional case : nullable object case : do not call bind on nullable object
- if (m_isOptional && m_references.size() == 0) { return; }
-
- if (m_isAggregate) {
- for (int i = 0; i < m_references.size(); i++) {
- ServiceReference ref = (ServiceReference) m_references.get(i);
- for (int j = 0; j < m_callbacks.length; j++) {
- if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
- try {
- m_callbacks[j].callOnInstance(instance, ref, getService(ref));
- } catch (NoSuchMethodException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getTargetException().getMessage());
- m_handler.getInstanceManager().setState(ComponentInstance.INVALID);
- }
- }
- }
+ private void invokeCallback(DependencyCallback callback, ServiceReference ref, Object pojo) {
+ try {
+ if (pojo == null) {
+ callback.call(ref, getService(ref));
+ } else {
+ callback.callOnInstance(pojo, ref, getService(ref));
}
- } else {
- for (int j = 0; j < m_callbacks.length; j++) {
- if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
- try {
- ServiceReference ref = (ServiceReference) m_references.get(0);
- if (ref != null) {
- m_callbacks[j].callOnInstance(instance, ref, getService(ref));
- }
- } catch (NoSuchMethodException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getTargetException().getMessage());
- m_handler.getInstanceManager().setState(ComponentInstance.INVALID);
- }
- }
- }
+ } catch (NoSuchMethodException e) {
+ m_handler.error("The method " + callback.getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
+ m_handler.getInstanceManager().stop();
+ } catch (IllegalAccessException e) {
+ m_handler.error("The method " + callback.getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
+ m_handler.getInstanceManager().stop();
+ } catch (InvocationTargetException e) {
+ m_handler.error("The method " + callback.getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + " throws an exception : " + e.getTargetException().getMessage(), e.getTargetException());
+ m_handler.getInstanceManager().stop();
}
+
}
/**
@@ -459,112 +266,45 @@
// call bind method :
// if (m_handler.getInstanceManager().getState() == InstanceManager.VALID) {
if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects() != null) {
- for (int i = 0; i < m_callbacks.length; i++) {
+ for (int i = 0; m_callbacks != null && i < m_callbacks.length; i++) {
if (m_callbacks[i].getMethodType() == DependencyCallback.BIND) {
- try {
- m_callbacks[i].call(ref, getService(ref));
- ungetService(ref);
- } catch (NoSuchMethodException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- m_handler.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getTargetException().getMessage());
- m_handler.getInstanceManager().setState(ComponentInstance.INVALID);
- }
+ invokeCallback(m_callbacks[i], ref, null);
}
}
}
}
-
+
/**
* Start the dependency.
*/
- public void start() {
-
- m_serviceContext = new PolicyServiceContext(m_handler.getInstanceManager().getGlobalContext(), m_handler.getInstanceManager().getLocalServiceContext(), m_policy);
-
- // Construct the filter with the objectclass + filter
- String filter = "(objectClass=" + m_specification + ")";
- if (m_strFilter != null) {
- filter = "(&" + filter + m_strFilter + ")";
- }
-
- try {
- m_clazz = m_handler.getInstanceManager().getContext().getBundle().loadClass(m_specification);
- } catch (ClassNotFoundException e) {
- m_handler.log(Logger.ERROR, "Cannot load the interface class for the dependency " + m_field + " [" + m_specification + "]");
- }
-
- if (m_isOptional) {
- if (m_di != null) {
- try {
- Class c = getHandler().getInstanceManager().getContext().getBundle().loadClass(m_di);
- m_nullable = c.newInstance();
- } catch (IllegalAccessException e) {
- m_handler.log(Logger.ERROR, "Cannot load the default-implementation " + m_di + " : " + e.getMessage());
- } catch (InstantiationException e) {
- m_handler.log(Logger.ERROR, "Cannot load the default-implementation " + m_di + " : " + e.getMessage());
- } catch (ClassNotFoundException e) {
- m_handler.log(Logger.ERROR, "Cannot load the default-implementation " + m_di + " : " + e.getMessage());
- }
+ public void start() {
+ if (isOptional() && !isAggregate()) {
+ if (m_di == null) {
+ // To load the proxy we use the POJO class loader. Indeed, this classloader imports iPOJO (so can access to Nullable) and has access to the service specification.
+ m_nullable = Proxy.newProxyInstance(getHandler().getInstanceManager().getClazz().getClassLoader(), new Class[] { getSpecification(), Nullable.class }, new NullableObject()); // NOPMD
} else {
- m_nullable = Proxy.newProxyInstance(getHandler().getInstanceManager().getClazz().getClassLoader(), new Class[] {m_clazz, Nullable.class}, new NullableObject());
+ try {
+ Class clazz = getHandler().getInstanceManager().getContext().getBundle().loadClass(m_di);
+ m_nullable = clazz.newInstance();
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException("Cannot load the default-implementation " + m_di + " : " + e.getMessage());
+ } catch (InstantiationException e) {
+ throw new IllegalStateException("Cannot load the default-implementation " + m_di + " : " + e.getMessage());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Cannot load the default-implementation " + m_di + " : " + e.getMessage());
+ }
}
}
- m_state = UNRESOLVED;
+ super.start();
- try {
- m_filter = m_handler.getInstanceManager().getContext().createFilter(filter); // Store the filter
- } catch (InvalidSyntaxException e1) {
- m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] A filter is malformed : " + filter + " - " + e1.getMessage());
- m_handler.getInstanceManager().stop();
- }
- m_tracker = new Tracker(m_serviceContext, m_filter, this);
- m_tracker.open();
- if (m_tracker.size() == 0 && !m_isOptional) {
- m_state = UNRESOLVED;
- } else {
- m_state = RESOLVED;
- }
- }
-
- /**
- * Stop the dependency.
- */
- public void stop() {
- if (m_tracker != null) {
- m_tracker.close(); // Will unget all used reference.
- m_tracker = null;
+ if (getBindingPolicy() == STATIC_BINDING_POLICY && m_handler.getInstanceManager().getPojoObjects() != null) {
+ m_isFrozen = true;
}
- m_state = UNRESOLVED;
-
- m_activated = false;
- m_references.clear();
- m_usedReferences.clear();
- m_clazz = null;
+ m_isStarted = true;
}
- /**
- * Return the state of the dependency.
- * @return the state of the dependency (1 : valid, 2 : invalid)
- */
- public int getState() {
- return m_state;
- }
-
- /**
- * Return the list of used service reference.
- * @return the service reference list.
- */
- public List getServiceReferences() {
- return m_references;
- }
-
protected DependencyCallback[] getCallbacks() {
return m_callbacks;
}
@@ -572,136 +312,183 @@
/**
* Set that this dependency is a service level dependency.
* This forces the scoping policy to be STRICT.
- * @param b
*/
public void setServiceLevelDependency() {
m_isServiceLevelRequirement = true;
- m_policy = PolicyServiceContext.LOCAL;
+ setBundleContext(new PolicyServiceContext(m_handler.getInstanceManager().getGlobalContext(), m_handler.getInstanceManager().getLocalServiceContext(), PolicyServiceContext.LOCAL));
}
public String getId() {
return m_id;
}
-
+
public boolean isServiceLevelRequirement() {
return m_isServiceLevelRequirement;
}
- /**
- * Method called when a thread enters in a method.
- * @param method : method id.
- */
- public void entry(String method) {
- if (! m_usage.getObjects().isEmpty()) {
- int level = m_usage.getStackLevel();
- m_usage.setStackLevel(level++);
- }
- }
-
- /**
- * Method called when a thread exits a method.
- * @param method : the method id.
- */
- public void exit(String method) {
- if (! m_usage.getObjects().isEmpty()) {
- int level = m_usage.getStackLevel();
- level = level - 1;
- if (level == 0) {
- // Exit the method flow => Release all object
- m_usage.getObjects().clear();
- List refs = m_usage.getReferences();
- refs.clear();
- }
- }
- }
- /**
- * A new service is detected. This method check the reference against the stored filter.
- * @param ref : new service reference.
- * @return the service object, null is the service object is rejected.
- * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference ref) {
- if (! m_activated) {
- return true;
- }
- return false;
- }
-
/**
- * A new service reference has been added in the tracker.
- * Call the bind method if needed, and check the dependency context.
- * @param reference : added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+ * A new service has to be injected.
+ * @param reference : the new matching service reference.
+ * @see org.apache.felix.ipojo.util.DependencyModel#onServiceArrival(org.osgi.framework.ServiceReference)
*/
- public void addedService(ServiceReference reference) {
- m_references.add(reference);
- if (m_bindingPolicy == DYNAMIC_PRIORITY_POLICY) {
- Collections.sort(m_references, new ServiceReferenceRankingComparator());
- }
- m_state = RESOLVED;
- if (m_isAggregate || m_references.size() == 1) {
- callBindMethod(reference);
- }
-
- m_handler.checkContext();
+ public void onServiceArrival(ServiceReference reference) {
+ callBindMethod(reference);
+ //The method is only called when a new service arrives, or when the used one is replaced.
}
/**
- * A used service is modified.
- * @param ref : modified reference
- * @param arg1 : service object (returned when added)
- * @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
+ * A used (already injected) service disappears.
+ * @param ref : leaving service reference.
+ * @see org.apache.felix.ipojo.util.DependencyModel#onServiceDeparture(org.osgi.framework.ServiceReference)
*/
- public void modifiedService(ServiceReference ref, Object arg1) { }
+ public void onServiceDeparture(ServiceReference ref) {
+ callUnbindMethod(ref);
+ }
/**
- * A used service disappears.
- * @param ref : implicated service.
- * @param arg1 : service object.
- * @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+ * The dependency has been reconfigured.
+ * @param departs : service no more matching.
+ * @param arrivals : new services
+ * @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[])
*/
- public void removedService(ServiceReference ref, Object arg1) {
- // Call unbind method
- boolean hasChanged = false;
- m_references.remove(ref);
- if (m_usedReferences.remove(ref)) {
- callUnbindMethod(ref);
-
- // Null the ref in the instance manager map
- if (m_field != null) {
- m_handler.getInstanceManager().setterCallback(m_field, null);
- }
-
- // Unget the service reference
- ungetService(ref);
- hasChanged = true;
- }
-
- if (m_bindingPolicy == STATIC_POLICY) {
- if (hasChanged && m_activated) {
- m_state = BROKEN;
- }
+ public void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals) {
+ throw new UnsupportedOperationException("Dependency set change is not yet supported");
+ }
+
+ /**
+ * Get the used service references list.
+ * @return the used service reference or null if no service reference are available.
+ */
+ public List getServiceReferencesAsList() {
+ ServiceReference[] refs = super.getServiceReferences();
+ if (refs == null) {
+ return null;
} else {
- // Is the state valid or invalid, the reference is already removed
- if (m_references.size() == 0 && !m_isOptional) {
- m_state = UNRESOLVED;
- } else {
- m_state = RESOLVED;
- }
-
- // Is there any change ?
- if (!m_isAggregate) {
- if (hasChanged) { // The used reference has been removed
- if (m_references.size() != 0) {
- callBindMethod(m_references.get(0));
+ return Arrays.asList(refs);
+ }
+ }
+
+ /**
+ * This method is called by the replaced code in the component
+ * implementation class. Construct the service object list is necessary.
+ * @param pojo : POJO object.
+ * @param fieldName : field
+ * @param value : last value.
+ * @return the service object or a nullable / default implementation if defined.
+ * @see org.apache.felix.ipojo.FieldInterceptor#onGet(java.lang.Object, java.lang.String, java.lang.Object)
+ */
+ public Object onGet(Object pojo, String fieldName, Object value) {
+ // Initialize the thread local object is not already touched.
+ Usage usage = (Usage) m_usage.get();
+ if (usage.m_stack == 0) { // uninitialized usage.
+ ServiceReference[] refs = super.getServiceReferences();
+ if (isAggregate()) { // If we are aggregate we get the objects.
+ if (refs == null) {
+ usage.m_objects = (Object[]) Array.newInstance(getSpecification(), 0); // Create an empty array.
+ } else {
+ // Use a reflective construction to avoid class cast exception. This method allow to set the component type.
+ usage.m_objects = (Object[]) Array.newInstance(getSpecification(), refs.length);
+ for (int i = 0; refs != null && i < refs.length; i++) {
+ ServiceReference ref = refs[i];
+ usage.m_objects[i] = getService(ref);
}
}
+ } else { // We are singular.
+ // Use a reflective construction to avoid class cast exception. This method allow to set the component type.
+ usage.m_objects = (Object[]) Array.newInstance(getSpecification(), 1);
+ if (refs == null) {
+ if (m_nullable == null) {
+ m_handler.warn("[" + m_handler.getInstanceManager().getInstanceName() + "] The dependency is not optional, however no service object can be injected in " + m_field + " -> " + getSpecification().getName());
+ return null;
+ }
+ usage.m_objects[0] = m_nullable;
+ } else {
+ ServiceReference ref = getServiceReference();
+ usage.m_objects[0] = getService(ref);
+ }
+ }
+ usage.inc(); // Start the tracking, so fix the stack level to 1
+ m_usage.set(usage);
+ }
+
+ if (isAggregate()) { // Multiple dependency
+ return usage.m_objects;
+ } else {
+ return usage.m_objects[0];
+ }
+ }
+
+ /**
+ * The field was set.
+ * This method should not be call if the POJO is written correctly.
+ * @param pojo : POJO object
+ * @param fieldName : field name
+ * @param value : set value.
+ * @see org.apache.felix.ipojo.FieldInterceptor#onSet(java.lang.Object, java.lang.String, java.lang.Object)
+ */
+ public void onSet(Object pojo, String fieldName, Object value) {
+ // Nothing to do.
+ }
+
+ /**
+ * A POJO method will be invoked.
+ * @param pojo : Pojo object
+ * @param method : called method
+ * @param args : arguments
+ * @see org.apache.felix.ipojo.MethodInterceptor#onEntry(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
+ */
+ public void onEntry(Object pojo, Method method, Object[] args) {
+ if (m_usage != null) {
+ Usage usage = (Usage) m_usage.get();
+ if (usage.m_stack > 0) {
+ usage.inc();
+ m_usage.set(usage); // Set the Thread local as value has been modified
+ }
+ }
+ }
+
+ /**
+ * A POJO method has thrown an error.
+ * This method does nothing and wait for the finally.
+ * @param pojo : POJO object.
+ * @param method : Method object.
+ * @param throwable : thrown error
+ * @see org.apache.felix.ipojo.MethodInterceptor#onError(java.lang.Object, java.lang.reflect.Method, java.lang.Throwable)
+ */
+ public void onError(Object pojo, Method method, Throwable throwable) {
+ // Nothing to do : wait onFinally
+ }
+
+ /**
+ * A POJO method has returned.
+ * @param pojo : POJO object.
+ * @param method : Method object.
+ * @param returnedObj : returned object (null for void method)
+ * @see org.apache.felix.ipojo.MethodInterceptor#onExit(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
+ */
+ public void onExit(Object pojo, Method method, Object returnedObj) {
+ // Nothing to do : wait onFinally
+
+ }
+
+ /**
+ * A POJO method is finished.
+ * @param pojo : POJO object.
+ * @param method : Method object.
+ * @see org.apache.felix.ipojo.MethodInterceptor#onFinally(java.lang.Object, java.lang.reflect.Method)
+ */
+ public void onFinally(Object pojo, Method method) {
+ if (m_usage != null) {
+ Usage usage = (Usage) m_usage.get();
+ if (usage.m_stack > 0) {
+ if (usage.dec()) {
+ // Exit the method flow => Release all objects
+ usage.clear();
+ m_usage.set(usage); // Set the Thread local as value has been modified
+ }
}
}
-
- m_handler.checkContext();
- return;
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
index cb47c30..ad476c6 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
@@ -22,7 +22,6 @@
import java.lang.reflect.Method;
import org.apache.felix.ipojo.util.Callback;
-import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.ServiceReference;
/**
@@ -42,7 +41,6 @@
* Unbind method (called when a service disappears).
*/
public static final int UNBIND = 1;
-
/**
* Is the method a bind method or an unbind method ?
@@ -104,20 +102,25 @@
protected void searchMethod() {
if (m_argument != null) {
Method[] methods = m_dependency.getHandler().getInstanceManager().getClazz().getDeclaredMethods();
- for (int i = 0; m_methodObj == null && i < methods.length; i++) {
+ for (int i = 0; i < methods.length; i++) {
// First check the method name
if (methods[i].getName().equals(m_method)) {
// Check arguments
Class[] clazzes = methods[i].getParameterTypes();
- if (clazzes.length == m_argument.length) { // Test size to avoid useless loop
- boolean ok = true;
- for (int j = 0; ok && j < m_argument.length; j++) {
- if (!m_argument[j].equals(clazzes[j].getName())) {
- ok = false;
+ if (clazzes.length == m_argument.length) { // Test size to avoid useless loop // NOPMD
+ int argIndex = 0;
+ for (; argIndex < m_argument.length; argIndex++) {
+ if (!m_argument[argIndex].equals(clazzes[argIndex].getName())) {
+ break;
}
}
- if (ok) {
+ if (argIndex == m_argument.length) { // If the array was completely read.
m_methodObj = methods[i]; // It is the looked method.
+ if (! m_methodObj.isAccessible()) {
+ // If not accessible, try to set the accessibility.
+ m_methodObj.setAccessible(true);
+ }
+ return;
}
}
@@ -125,51 +128,64 @@
}
}
- if (m_methodObj == null) { //look at parent classes
- Method[] methods = m_dependency.getHandler().getInstanceManager().getClazz().getMethods();
- for (int i = 0; m_methodObj == null && i < methods.length; i++) {
- // First check the method name
- if (methods[i].getName().equals(m_method)) {
- // Check arguments
- Class[] clazzes = methods[i].getParameterTypes();
- switch(clazzes.length) {
- case 0 :
- // Callback with no arguments.
- m_methodObj = methods[i];
- m_argument = new String[0];
- break;
- case 1 :
- if (clazzes[0].getName().equals(ServiceReference.class.getName())) {
- // Callback with a service reference.
- m_methodObj = methods[i];
- m_argument = new String[] {ServiceReference.class.getName()};
- break;
- }
- if (clazzes[0].getName().equals(m_dependency.getSpecification())) {
- // Callback with the service object.
- m_methodObj = methods[i];
- m_argument = new String[] {m_dependency.getSpecification()};
- break;
- }
- case 2 :
- if (clazzes[0].getName().equals(m_dependency.getSpecification()) && clazzes[1].getName().equals(ServiceReference.class.getName())) {
- // Callback with two arguments.
- m_methodObj = methods[i];
- m_argument = new String[] {m_dependency.getSpecification(), ServiceReference.class.getName()};
- }
- break;
- default :
- break;
- }
- }
- }
- }
+ // Not found => Try parent method.
+ searchParentMethod();
if (m_methodObj == null) {
- m_dependency.getHandler().log(Logger.ERROR, "The method " + m_method + " cannot be called : method not found");
+ // If not found, stop the instance (fatal error)
+ m_dependency.getHandler().error("The method " + m_method + " cannot be called : method not found");
m_dependency.getHandler().getInstanceManager().stop();
} else {
- m_methodObj.setAccessible(true);
+ if (! m_methodObj.isAccessible()) {
+ // If not accessible, try to set the accessibility.
+ m_methodObj.setAccessible(true);
+ }
+ }
+ }
+
+ /**
+ * Introspect parent class to find the method.
+ */
+ private void searchParentMethod() {
+ // look at parent classes
+ Method[] methods = m_dependency.getHandler().getInstanceManager().getClazz().getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ // First check the method name
+ if (methods[i].getName().equals(m_method)) {
+ // Check arguments
+ Class[] clazzes = methods[i].getParameterTypes();
+ switch (clazzes.length) {
+ case 0:
+ // Callback with no arguments.
+ m_methodObj = methods[i];
+ m_argument = new String[0];
+ return;
+ case 1:
+ if (clazzes[0].getName().equals(ServiceReference.class.getName())) {
+ // Callback with a service reference.
+ m_methodObj = methods[i];
+ m_argument = new String[] { ServiceReference.class.getName() };
+ return;
+ }
+ if (clazzes[0].getName().equals(m_dependency.getSpecification().getName())) {
+ // Callback with the service object.
+ m_methodObj = methods[i];
+ m_argument = new String[] { m_dependency.getSpecification().getName() };
+ return;
+ }
+ break;
+ case 2:
+ if (clazzes[0].getName().equals(m_dependency.getSpecification().getName()) && clazzes[1].getName().equals(ServiceReference.class.getName())) {
+ // Callback with two arguments.
+ m_methodObj = methods[i];
+ m_argument = new String[] { m_dependency.getSpecification().getName(), ServiceReference.class.getName() };
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
index f9dea1b..6c09bd5 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
@@ -79,7 +79,6 @@
m_optional = optional;
m_filter = filter;
m_state = state;
- m_serviceReferences = new ArrayList();
}
public boolean isMultiple() { return m_multiple; }
@@ -106,9 +105,9 @@
/**
* Set the service reference array.
- * @param sr : the list of service reference
+ * @param refs : the list of service reference
*/
- public void setServiceReferences(List sr) { m_serviceReferences = sr; }
+ public void setServiceReferences(List refs) { m_serviceReferences = refs; }
/**
* Get the used service set.
@@ -118,10 +117,10 @@
/**
* Set the usedServices.
- * @param hm : the list of used service reference.
+ * @param usages : the list of used service reference.
*/
- public void setUsedServices(List hm) {
- m_usedServices = hm;
+ public void setUsedServices(List usages) {
+ m_usedServices = usages;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
index 433f0b1..5a0f4d8 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
@@ -18,27 +18,30 @@
*/
package org.apache.felix.ipojo.handlers.dependency;
-import java.util.ArrayList;
+import java.util.Comparator;
import java.util.Dictionary;
-import java.util.List;
-import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.IPojoContext;
import org.apache.felix.ipojo.PolicyServiceContext;
import org.apache.felix.ipojo.PrimitiveHandler;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.FieldMetadata;
-import org.apache.felix.ipojo.parser.ManipulationMetadata;
import org.apache.felix.ipojo.parser.MethodMetadata;
-import org.apache.felix.ipojo.util.Logger;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.apache.felix.ipojo.util.DependencyStateListener;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
* The dependency handler manages a list of service dependencies.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class DependencyHandler extends PrimitiveHandler {
+public class DependencyHandler extends PrimitiveHandler implements DependencyStateListener {
/**
* List of dependencies of the component.
@@ -46,12 +49,6 @@
private Dependency[] m_dependencies = new Dependency[0];
/**
- * State of the handler.
- * Lifecycle controller.
- */
- private boolean m_state;
-
- /**
* Is the handler started.
*/
private boolean m_started;
@@ -61,16 +58,18 @@
* @param dep : the dependency to add
*/
private void addDependency(Dependency dep) {
- for (int i = 0; i < m_dependencies.length; i++) {
- if (m_dependencies[i] == dep) { return; }
+ for (int i = 0; m_dependencies != null && i < m_dependencies.length; i++) {
+ if (m_dependencies[i] == dep) {
+ return;
+ }
}
- if (m_dependencies.length > 0) {
+ if (m_dependencies == null) {
+ m_dependencies = new Dependency[] { dep };
+ } else {
Dependency[] newDep = new Dependency[m_dependencies.length + 1];
System.arraycopy(m_dependencies, 0, newDep, 0, m_dependencies.length);
newDep[m_dependencies.length] = dep;
m_dependencies = newDep;
- } else {
- m_dependencies = new Dependency[] { dep };
}
}
@@ -83,36 +82,56 @@
}
/**
+ * Validate method. This method is invoked by an AbstractServiceDependency when this dependency becomes RESOLVED.
+ * @param dep : the dependency becoming RESOLVED.
+ * @see org.apache.felix.ipojo.util.DependencyStateListener#validate(org.apache.felix.ipojo.util.DependencyModel)
+ */
+ public void validate(DependencyModel dep) {
+ checkContext();
+ }
+
+ /**
+ * Invalidate method. This method is invoked by an AbstractServiceDependency when this dependency becomes UNRESOLVED or BROKEN.
+ * @param dep : the dependency becoming UNRESOLVED or BROKEN.
+ * @see org.apache.felix.ipojo.util.DependencyStateListener#invalidate(org.apache.felix.ipojo.util.DependencyModel)
+ */
+ public void invalidate(DependencyModel dep) {
+ setValidity(false);
+ }
+
+ /**
* Check the validity of the dependencies.
*/
protected void checkContext() {
- if (! m_started) { return; }
+ if (!m_started) {
+ return;
+ }
synchronized (m_dependencies) {
// Store the initial state
- boolean initialState = m_state;
+ boolean initialState = getValidity();
boolean valid = true;
for (int i = 0; i < m_dependencies.length; i++) {
Dependency dep = m_dependencies[i];
- if (dep.getState() > Dependency.RESOLVED) {
+ if (dep.getState() != Dependency.RESOLVED) {
valid = false;
break;
}
}
-
+
// Check the component dependencies
if (valid) {
// The dependencies are valid
if (!initialState) {
// There is a state change
- m_state = true;
+ setValidity(true);
}
// Else do nothing, the component state stay VALID
} else {
// The dependencies are not valid
if (initialState) {
// There is a state change
- m_state = false;
+ setValidity(false);
}
// Else do nothing, the component state stay UNRESOLVED
}
@@ -121,155 +140,197 @@
}
/**
- * Check if the dependency given is valid in the sense that metadata are
- * consistent.
+ * Check if the dependency given is valid in the sense that metadata are consistent.
* @param dep : the dependency to check
* @param manipulation : the component-type manipulation metadata
* @return true if the dependency is valid
* @throws ConfigurationException : the checked dependency is not correct
*/
- private boolean checkDependency(Dependency dep, ManipulationMetadata manipulation) throws ConfigurationException {
+ private boolean checkDependency(Dependency dep, PojoMetadata manipulation) throws ConfigurationException {
// Check the internal type of dependency
String field = dep.getField();
DependencyCallback[] callbacks = dep.getCallbacks();
- for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks == null && field == null) {
+ throw new ConfigurationException("A service requirement requires at least callbacks or a field");
+ }
+
+ for (int i = 0; callbacks != null && i < callbacks.length; i++) {
MethodMetadata[] mets = manipulation.getMethods(callbacks[i].getMethodName());
- if (mets.length != 0) {
+ if (mets.length == 0) {
+ info("A requirement callback " + callbacks[i].getMethodName() + " does not exist in the implementation, try the super classes");
+ } else {
if (mets[0].getMethodArguments().length > 2) {
- throw new ConfigurationException("Requirement Callback : A requirement callback " + callbacks[i].getMethodName() + " must have 0 or 1 or 2 arguments");
+ throw new ConfigurationException("Requirement Callback : A requirement callback "
+ + callbacks[i].getMethodName()
+ + " must have 0 or 1 or 2 arguments");
}
-
+
callbacks[i].setArgument(mets[0].getMethodArguments());
+
if (mets[0].getMethodArguments().length == 1) {
if (!mets[0].getMethodArguments()[0].equals(ServiceReference.class.getName())) {
- if (dep.getSpecification() == null) {
- dep.setSpecification(mets[0].getMethodArguments()[0]);
- }
- if (!dep.getSpecification().equals(mets[0].getMethodArguments()[0])) {
- log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + mets[0].getMethodArguments()[0] + "] and the needed service interface [" + dep.getSpecification() + "] are not the same");
- dep.setSpecification(mets[0].getMethodArguments()[0]);
- }
+ // The callback receives the service object.
+ setSpecification(dep, mets[0].getMethodArguments()[0], false); // Just warn if a mismatch is discovered.
}
} else if (mets[0].getMethodArguments().length == 2) {
- // Check that the second arguments is a service reference
+ // The callback receives service object, service reference. Check that the second argument is a service reference
if (!mets[0].getMethodArguments()[1].equals(ServiceReference.class.getName())) {
- String message = "The requirement callback " + callbacks[i].getMethodName() + " must have a ServiceReference as the second arguments";
+ String message =
+ "The requirement callback " + callbacks[i].getMethodName() + " must have a ServiceReference as the second argument";
throw new ConfigurationException(message);
}
- if (dep.getSpecification() == null) {
- dep.setSpecification(mets[0].getMethodArguments()[0]);
- } else {
- if (!dep.getSpecification().equals(mets[0].getMethodArguments()[0])) {
- log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + mets[0].getMethodArguments()[0] + "] and the needed service interface [" + dep.getSpecification() + "] are not the same");
- dep.setSpecification(mets[0].getMethodArguments()[0]);
- }
- }
+ setSpecification(dep, mets[0].getMethodArguments()[0], false); // Just warn if a mismatch is discovered.
}
- } else {
- log(Logger.INFO, "A requirement callback " + callbacks[i].getMethodName() + " does not exist in the implementation, try the super classes");
}
}
if (field != null) {
- FieldMetadata fm = manipulation.getField(field);
- if (fm == null) {
- throw new ConfigurationException("Requirement Callback : A requirement field " + field + " does not exist in the implementation class");
+ FieldMetadata meta = manipulation.getField(field);
+ if (meta == null) {
+ throw new ConfigurationException("Requirement Callback : A requirement field "
+ + field
+ + " does not exist in the implementation class");
}
- String type = fm.getFieldType();
+ String type = meta.getFieldType();
if (type.endsWith("[]")) {
// Set the dependency to multiple
- dep.setAggregate();
+ dep.setAggregate(true);
type = type.substring(0, type.length() - 2);
+ } else {
+ if (dep.isAggregate()) {
+ throw new ConfigurationException("A required service is not correct : the field "
+ + meta.getFieldName()
+ + " must be an array to support aggregate injections");
+ }
}
-
- if (dep.getSpecification() == null) {
- dep.setSpecification(type);
- }
-
- if (!dep.getSpecification().equals(type)) {
- log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + type + "] and the needed service interface [" + dep.getSpecification() + "] are not the same");
- dep.setSpecification(type);
- }
+ setSpecification(dep, type, true); // Throw an exception if the filed type mismatch.
}
- //Check that all required info are set
+ // Check that all required info are set
return dep.getSpecification() != null;
}
/**
+ * Check if we have to set the dependency specification with the given class name.
+ * @param dep : dependency to check
+ * @param className : class name
+ * @param error : set to true to throw an error if the set dependency specification and the given specification are different.
+ * @throws ConfigurationException : the specification class cannot be loaded correctly
+ */
+ private void setSpecification(Dependency dep, String className, boolean error) throws ConfigurationException {
+ // We have to set the dependency in two cases : either the dependency as no specification, or the specification is different from the given
+ // one
+ if (dep.getSpecification() == null || !dep.getSpecification().getName().equals(className)) {
+ if (dep.getSpecification() != null) {
+ if (error) {
+ throw new ConfigurationException("A required service is not correct : the discoevered type ["
+ + className
+ + "] and the specified (or already discovered) service interface ["
+ + dep.getSpecification().getName()
+ + "] are not the same");
+ } else {
+ // If the specification is different, warn that we will overide it.
+ warn("[DependencyHandler on "
+ + getInstanceManager().getInstanceName()
+ + "] The field type ["
+ + className
+ + "] and the needed service interface ["
+ + dep.getSpecification()
+ + "] are not the same");
+ }
+ }
+ try {
+ dep.setSpecification(getInstanceManager().getContext().getBundle().loadClass(className));
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("The required service interface cannot be loaded : " + e.getMessage());
+ }
+ }
+ }
+
+ /**
* Configure the handler.
* @param componentMetadata : the component type metadata
* @param configuration : the instance configuration
* @throws ConfigurationException : one dependency metadata is not correct.
- * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+ * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager, org.apache.felix.ipojo.metadata.Element,
+ * java.util.Dictionary)
*/
public void configure(Element componentMetadata, Dictionary configuration) throws ConfigurationException {
- m_dependencies = new Dependency[0];
-
- ManipulationMetadata manipulation = new ManipulationMetadata(componentMetadata);
- List fl = new ArrayList();
+ // getPojoMetadata();
+ PojoMetadata manipulation = getFactory().getPojoMetadata();
+ boolean atLeastOneField = false;
// Create the dependency according to the component metadata
Element[] deps = componentMetadata.getElements("Requires");
-
+
// Get instance filters.
Dictionary filtersConfiguration = (Dictionary) configuration.get("requires.filters");
-
- for (int i = 0; i < deps.length; i++) {
+
+ for (int i = 0; deps != null && i < deps.length; i++) {
// Create the dependency metadata
String field = deps[i].getAttribute("field");
String serviceSpecification = deps[i].getAttribute("interface");
String filter = deps[i].getAttribute("filter");
String opt = deps[i].getAttribute("optional");
boolean optional = opt != null && opt.equalsIgnoreCase("true");
- String di = deps[i].getAttribute("default-implementation");
-
+ String defaultImplem = deps[i].getAttribute("default-implementation");
+
String agg = deps[i].getAttribute("aggregate");
boolean aggregate = agg != null && agg.equalsIgnoreCase("true");
- String id = deps[i].getAttribute("id");
+ String identitity = deps[i].getAttribute("id");
- int scopePolicy = -1;
- String scope = deps[i].getAttribute("scope");
+ String scope = deps[i].getAttribute("scope");
+ BundleContext context = getInstanceManager().getContext(); // Get the default bundle context.
if (scope != null) {
- if (scope.equalsIgnoreCase("global")) {
- scopePolicy = PolicyServiceContext.GLOBAL;
+ // If we are not in a composite, the policy is set to global.
+ if (scope.equalsIgnoreCase("global") || ((((IPojoContext) getInstanceManager().getContext()).getServiceContext()) == null)) {
+ context =
+ new PolicyServiceContext(getInstanceManager().getGlobalContext(), getInstanceManager().getLocalServiceContext(),
+ PolicyServiceContext.GLOBAL);
} else if (scope.equalsIgnoreCase("composite")) {
- scopePolicy = PolicyServiceContext.LOCAL;
+ context =
+ new PolicyServiceContext(getInstanceManager().getGlobalContext(), getInstanceManager().getLocalServiceContext(),
+ PolicyServiceContext.LOCAL);
} else if (scope.equalsIgnoreCase("composite+global")) {
- scopePolicy = PolicyServiceContext.LOCAL_AND_GLOBAL;
+ context =
+ new PolicyServiceContext(getInstanceManager().getGlobalContext(), getInstanceManager().getLocalServiceContext(),
+ PolicyServiceContext.LOCAL_AND_GLOBAL);
}
}
// Get instance filter if available
- if (filtersConfiguration != null && id != null && filtersConfiguration.get(id) != null) {
- filter = (String) filtersConfiguration.get(id);
+ if (filtersConfiguration != null && identitity != null && filtersConfiguration.get(identitity) != null) {
+ filter = (String) filtersConfiguration.get(identitity);
}
-
-
- // Parse binding policy
- int bindingPolicy = Dependency.DYNAMIC_POLICY;
- String policy = deps[i].getAttribute("policy");
- if (policy != null) {
- if (policy.equalsIgnoreCase("static")) {
- bindingPolicy = Dependency.STATIC_POLICY;
- } else if (policy.equalsIgnoreCase("dynamic")) {
- bindingPolicy = Dependency.DYNAMIC_POLICY;
- } else if (policy.equalsIgnoreCase("dynamic-priority")) {
- bindingPolicy = Dependency.DYNAMIC_PRIORITY_POLICY;
+
+ Filter fil = null;
+ if (filter != null) {
+ try {
+ fil = getInstanceManager().getContext().createFilter(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new ConfigurationException("A requirement filter is invalid : " + filter + " - " + e.getMessage());
}
}
-
- Dependency dep = new Dependency(this, field, serviceSpecification, filter, optional, aggregate, id, scopePolicy, bindingPolicy, di);
+
+ Class spec = null;
+ if (serviceSpecification != null) {
+ spec = DependencyModel.loadSpecification(serviceSpecification, getInstanceManager().getContext());
+ }
+
+ int policy = DependencyModel.getPolicy(deps[i]);
+ Comparator cmp = DependencyModel.getComparator(deps[i], getInstanceManager().getGlobalContext());
+ Dependency dep = new Dependency(this, field, spec, fil, optional, aggregate, identitity, context, policy, cmp, defaultImplem);
// Look for dependency callback :
- for (int j = 0; j < (deps[i].getElements("Callback", "")).length; j++) {
- if (!(deps[i].getElements("Callback", "")[j].containsAttribute("method") && deps[i].getElements("Callback", "")[j].containsAttribute("type"))) {
- throw new ConfigurationException("Requirement Callback : a dependency callback must contain a method and a type attribute");
+ Element[] cbs = deps[i].getElements("Callback");
+ for (int j = 0; cbs != null && j < cbs.length; j++) {
+ if (!cbs[j].containsAttribute("method") && cbs[j].containsAttribute("type")) {
+ throw new ConfigurationException("Requirement Callback : a dependency callback must contain a method and a type attribute");
}
- String method = deps[i].getElements("Callback", "")[j].getAttribute("method");
- String type = deps[i].getElements("Callback", "")[j].getAttribute("type");
+ String method = cbs[j].getAttribute("method");
+ String type = cbs[j].getAttribute("type");
int methodType = 0;
if ("bind".equalsIgnoreCase(type)) {
methodType = DependencyCallback.BIND;
@@ -277,74 +338,49 @@
methodType = DependencyCallback.UNBIND;
}
- DependencyCallback dc = new DependencyCallback(dep, method, methodType);
- dep.addDependencyCallback(dc);
+ DependencyCallback callback = new DependencyCallback(dep, method, methodType);
+ dep.addDependencyCallback(callback);
}
// Check the dependency :
if (checkDependency(dep, manipulation)) {
addDependency(dep);
if (dep.getField() != null) {
- fl.add(manipulation.getField(dep.getField()));
+ getInstanceManager().register(manipulation.getField(dep.getField()), dep);
+ atLeastOneField = true;
}
}
}
- if (deps.length > 0) {
- getInstanceManager().register(this, (FieldMetadata[]) fl.toArray(new FieldMetadata[0]), manipulation.getMethods());
- } else {
- throw new ConfigurationException("No dependencies found in " + getInstanceManager().getInstanceName());
- }
- }
-
- /**
- * GetterCallback Method.
- * @param fieldName : the field name.
- * @param value : the value passed to the field (by the previous handler).
- * @return the object that the dependency handler want to push.
- * @see org.apache.felix.ipojo.Handler#getterCallback(java.lang.String, java.lang.Object)
- */
- public Object getterCallback(String fieldName, Object value) {
- for (int i = 0; i < m_dependencies.length; i++) {
- Dependency dep = m_dependencies[i];
- String field = dep.getField();
- if (field != null && field.equals(fieldName)) {
- // The field name is a dependency, return the get
- return dep.get();
- }
- }
- // Else return the value
- return value;
- }
-
- /**
- * Method Entry callback.
- * @param methodId : method Id.
- * @see org.apache.felix.ipojo.Handler#entryCallback(java.lang.String)
- */
- public void entryCallback(String methodId) {
- for (int i = 0; i < m_dependencies.length; i++) {
- Dependency dep = m_dependencies[i];
- if (dep.getField() != null) {
- dep.entry(methodId);
+ if (atLeastOneField) { // Does register only if we have fields
+ MethodMetadata[] methods = manipulation.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ for (int j = 0; j < m_dependencies.length; j++) {
+ getInstanceManager().register(methods[i], m_dependencies[j]);
+ }
}
}
}
- /**
- * Method Exit callback.
- * @param methodId : method id.
- * @param returnedObj : returned object.
- * @see org.apache.felix.ipojo.Handler#exitCallback(java.lang.String, java.lang.Object)
- */
- public void exitCallback(String methodId, Object returnedObj) {
- for (int i = 0; i < m_dependencies.length; i++) {
- Dependency dep = m_dependencies[i];
- if (dep.getField() != null) {
- dep.exit(methodId);
- }
- }
- }
+// /**
+// * GetterCallback Method.
+// * @param pojo : the pojo object on which the field is accessed
+// * @param fieldName : the field name.
+// * @param value : the value passed to the field (by the previous handler).
+// * @return the object that the dependency handler want to push.
+// * @see org.apache.felix.ipojo.Handler#onGet(Object, java.lang.String, java.lang.Object)
+// */
+// public Object onGet(Object pojo, String fieldName, Object value) {
+// for (int i = 0; i < m_dependencies.length; i++) {
+// Dependency dep = m_dependencies[i];
+// if (fieldName.equals(dep.getField())) {
+// // The field name is a dependency, return the get
+// return dep.get();
+// }
+// }
+// // Else return the value
+// return value;
+// }
/**
* Handler start method.
@@ -358,6 +394,7 @@
}
// Check the state
m_started = true;
+ setValidity(false);
checkContext();
}
@@ -373,27 +410,13 @@
}
/**
- * Handler createInstance method.
- * This method is override to allow delayed callback invocation.
+ * Handler createInstance method. This method is override to allow delayed callback invocation.
* @param instance : the created object
- * @see org.apache.felix.ipojo.Handler#objectCreated(java.lang.Object)
+ * @see org.apache.felix.ipojo.Handler#onCreation(java.lang.Object)
*/
- public void objectCreated(Object instance) {
+ public void onCreation(Object instance) {
for (int i = 0; i < m_dependencies.length; i++) {
- m_dependencies[i].callBindMethod(instance);
- }
- }
-
- /**
- * The instance state changes. If the new state is valid, we need to activate dependencies.
- * @param state : the new state
- * @see org.apache.felix.ipojo.Handler#stateChanged(int)
- */
- public void stateChanged(int state) {
- if (state == ComponentInstance.VALID) {
- for (int i = 0; i < m_dependencies.length; i++) {
- m_dependencies[i].activate();
- }
+ m_dependencies[i].onObjectCreation(instance);
}
}
@@ -407,10 +430,11 @@
for (int j = 0; j < getDependencies().length; j++) {
Dependency dep = getDependencies()[j];
// Create & add the dependency description
- DependencyDescription dd = new DependencyDescription(dep.getSpecification(), dep.isAggregate(), dep.isOptional(), dep.getFilter(), dep.getState());
- dd.setServiceReferences(dep.getServiceReferences());
- dd.setUsedServices(dep.getUsedServices());
- dhd.addDependency(dd);
+ DependencyDescription desc =
+ new DependencyDescription(dep.getSpecification().getName(), dep.isAggregate(), dep.isOptional(), dep.getFilter(), dep.getState());
+ desc.setServiceReferences(dep.getServiceReferencesAsList());
+ desc.setUsedServices(dep.getUsedServiceReferences());
+ dhd.addDependency(desc);
}
return dhd;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
index 1615521..aaf5baa 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
@@ -42,10 +42,10 @@
/**
* Constructor.
- * @param h : Handler.
+ * @param handler : Handler.
*/
- public DependencyHandlerDescription(Handler h) {
- super(h);
+ public DependencyHandlerDescription(Handler handler) {
+ super(handler);
}
/**
@@ -94,7 +94,7 @@
Element dep = new Element("Requires", "");
dep.addAttribute(new Attribute("Specification", m_dependencies[i].getInterface()));
- if (!"".equals(m_dependencies[i].getFilter())) {
+ if (m_dependencies[i].getFilter() != null) {
dep.addAttribute(new Attribute("Filter", m_dependencies[i].getFilter()));
}
@@ -112,16 +112,18 @@
dep.addAttribute(new Attribute("State", state));
List set = m_dependencies[i].getUsedServices();
- Iterator it = set.iterator();
- while (it.hasNext()) {
- Element use = new Element("Uses", "");
- ServiceReference ref = (ServiceReference) it.next();
- use.addAttribute(new Attribute("service.id", ref.getProperty(Constants.SERVICE_ID).toString()));
- String in = (String) ref.getProperty("instance.name");
- if (in != null) {
- use.addAttribute(new Attribute("instance.name", in));
+ if (set != null) {
+ Iterator iterator = set.iterator();
+ while (iterator.hasNext()) {
+ Element use = new Element("Uses", "");
+ ServiceReference ref = (ServiceReference) iterator.next();
+ use.addAttribute(new Attribute("service.id", ref.getProperty(Constants.SERVICE_ID).toString()));
+ String instance = (String) ref.getProperty("instance.name");
+ if (instance != null) {
+ use.addAttribute(new Attribute("instance.name", instance));
+ }
+ dep.addElement(use);
}
- dep.addElement(use);
}
deps.addElement(dep);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
index e0e4900..b11419f 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
@@ -26,41 +26,42 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class NullableObject implements InvocationHandler {
-
+
/**
* Default boolean value.
*/
private static final Boolean DEFAULT_BOOLEAN = Boolean.FALSE;
+
/**
* Default byte value.
*/
private static final Byte DEFAULT_BYTE = new Byte((byte) 0);
-
+
/**
* Default short value.
*/
private static final Short DEFAULT_SHORT = new Short((short) 0);
-
+
/**
* Default integer value.
*/
private static final Integer DEFAULT_INT = new Integer(0);
-
+
/**
* Default long value.
*/
private static final Long DEFAULT_LONG = new Long(0);
-
+
/**
* Default float value.
*/
private static final Float DEFAULT_FLOAT = new Float(0.0f);
-
+
/**
* Default double value.
*/
private static final Double DEFAULT_DOUBLE = new Double(0.0);
-
+
/**
* Invokes a method on this null object. The method will return a default
* value without doing anything.
@@ -72,19 +73,19 @@
*/
public Object invoke(Object proxy, Method method, Object[] args) {
Class returnType = method.getReturnType();
- if (returnType.equals(Boolean.TYPE)) {
+ if (Boolean.TYPE.equals(returnType)) {
return DEFAULT_BOOLEAN;
- } else if (returnType.equals(Byte.TYPE)) {
+ } else if (Byte.TYPE.equals(returnType)) {
return DEFAULT_BYTE;
- } else if (returnType.equals(Short.TYPE)) {
+ } else if (Short.TYPE.equals(returnType)) {
return DEFAULT_SHORT;
- } else if (returnType.equals(Integer.TYPE)) {
+ } else if (Integer.TYPE.equals(returnType)) {
return DEFAULT_INT;
- } else if (returnType.equals(Long.TYPE)) {
+ } else if (Long.TYPE.equals(returnType)) {
return DEFAULT_LONG;
- } else if (returnType.equals(Float.TYPE)) {
+ } else if (Float.TYPE.equals(returnType)) {
return DEFAULT_FLOAT;
- } else if (returnType.equals(Double.TYPE)) {
+ } else if (Double.TYPE.equals(returnType)) {
return DEFAULT_DOUBLE;
} else {
return null;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
index 822910b..7d289f1 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
@@ -18,8 +18,6 @@
*/
package org.apache.felix.ipojo.handlers.dependency;
-import java.util.ArrayList;
-import java.util.List;
/**
* Object managing thread local copy of required services.
@@ -31,19 +29,40 @@
/**
* Structure contained in the Thread Local.
*/
- private class Usage {
+ public class Usage {
+
/**
* Stack Size.
*/
- Integer m_stack = new Integer(0);
- /**
- * List of used service references.
- */
- List m_refs = new ArrayList();
+ int m_stack = 0;
/**
* List of used objects.
*/
- List m_objects = new ArrayList();
+ Object[] m_objects;
+
+ /**
+ * Increment the statck level.
+ */
+ public void inc() {
+ m_stack++;
+ }
+
+ /**
+ * Decrement the stack level.
+ * @return true if the stack is 0 after the decrement.
+ */
+ public boolean dec() {
+ m_stack--;
+ return m_stack == 0;
+ }
+
+ /**
+ * Clear the service object array.
+ */
+ public void clear() {
+ m_objects = null;
+ }
+
}
/**
@@ -53,45 +72,6 @@
*/
public Object initialValue() {
return new Usage();
- }
-
- /**
- * Get the list of stored references.
- * @return the list of stored references.
- */
- public List getReferences() {
- Usage use = (Usage) super.get();
- return use.m_refs;
- }
-
- /**
- * Get the lost of stored object.
- * @return the list of stored service objects.
- */
- public List getObjects() {
- Usage use = (Usage) super.get();
- return use.m_objects;
- }
-
- /**
- * Get the stack level.
- * @return the stack level.
- */
- public int getStackLevel() {
- Usage use = (Usage) super.get();
- return use.m_stack.intValue();
- }
-
- /**
- * Set the stack level.
- * @param level : the new stack level.
- */
- public void setStackLevel(int level) {
- Usage use = (Usage) super.get();
- use.m_stack = new Integer(level);
- }
-
-
-
+ }
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallback.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallback.java
index 15db443..cd86798 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallback.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallback.java
@@ -53,29 +53,29 @@
/**
* LifecycleCallback constructor.
*
- * @param hh : the callback handler calling the callback
+ * @param handler : the callback handler calling the callback
* @param transition : transition on which calling the callback
- * @param mm : method metadata to invoke
+ * @param method : method metadata to invoke
*/
- public LifecycleCallback(LifecycleCallbackHandler hh, int transition, MethodMetadata mm) {
+ public LifecycleCallback(LifecycleCallbackHandler handler, int transition, MethodMetadata method) {
m_transition = transition;
- m_callback = new Callback(mm, hh.getInstanceManager());
+ m_callback = new Callback(method, handler.getInstanceManager());
}
/**
* LifecycleCallback constructor.
*
- * @param hh : the callback handler calling the callback
+ * @param handler : the callback handler calling the callback
* @param transition : transition on which calling the callback
- * @param mm : method name to invoke
+ * @param method : method name to invoke
*/
- public LifecycleCallback(LifecycleCallbackHandler hh, int transition, String mm) {
+ public LifecycleCallback(LifecycleCallbackHandler handler, int transition, String method) {
m_transition = transition;
- m_callback = new Callback(mm, new String[0], false, hh.getInstanceManager());
+ m_callback = new Callback(method, new String[0], false, handler.getInstanceManager());
}
/**
- * Call the callback method when the transition from inital to final state is
+ * Call the callback method when the transition from inital tostate is
* detected.
*
* @throws NoSuchMethodException : Method is not found in the class
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java
index 7b153ef..85ca69a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java
@@ -26,9 +26,8 @@
import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.PrimitiveHandler;
import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.ManipulationMetadata;
import org.apache.felix.ipojo.parser.MethodMetadata;
-import org.apache.felix.ipojo.util.Logger;
+import org.apache.felix.ipojo.parser.PojoMetadata;
/**
* Lifecycle callback handler.
@@ -54,11 +53,11 @@
/**
* Add the given callback to the callback list.
*
- * @param hk : the element to add
+ * @param callback : the element to add
*/
- private void addCallback(LifecycleCallback hk) {
+ private void addCallback(LifecycleCallback callback) {
for (int i = 0; (m_callbacks != null) && (i < m_callbacks.length); i++) {
- if (m_callbacks[i] == hk) {
+ if (m_callbacks[i] == callback) {
return;
}
}
@@ -66,10 +65,10 @@
if (m_callbacks.length > 0) {
LifecycleCallback[] newHk = new LifecycleCallback[m_callbacks.length + 1];
System.arraycopy(m_callbacks, 0, newHk, 0, m_callbacks.length);
- newHk[m_callbacks.length] = hk;
+ newHk[m_callbacks.length] = callback;
m_callbacks = newHk;
} else {
- m_callbacks = new LifecycleCallback[] { hk };
+ m_callbacks = new LifecycleCallback[] { callback };
}
}
@@ -87,38 +86,38 @@
String imm = metadata.getAttribute("immediate");
m_immediate = imm != null && imm.equalsIgnoreCase("true");
- ManipulationMetadata mm = new ManipulationMetadata(metadata);
+ PojoMetadata meta = getFactory().getPojoMetadata();
Element[] hooksMetadata = metadata.getElements("callback");
- for (int i = 0; i < hooksMetadata.length; i++) {
+ for (int i = 0; hooksMetadata != null && i < hooksMetadata.length; i++) {
String method = hooksMetadata[i].getAttribute("method");
if (method == null) {
throw new ConfigurationException("Lifecycle callback : A callback needs to contains a method attribute");
}
- MethodMetadata met = mm.getMethod(method, new String[0]);
+ MethodMetadata met = meta.getMethod(method, new String[0]);
int transition = -1;
String trans = hooksMetadata[i].getAttribute("transition");
- if (trans != null) {
+ if (trans == null) {
+ throw new ConfigurationException("Lifecycle callback : the transition attribute is missing");
+ } else {
if (trans.equalsIgnoreCase("validate")) {
transition = LifecycleCallback.VALIDATE;
} else if (trans.equalsIgnoreCase("invalidate")) {
transition = LifecycleCallback.INVALIDATE;
} else {
- throw new ConfigurationException("Lifecycle callback : Unknown or malformed transition : " + transition);
+ throw new ConfigurationException("Lifecycle callback : Unknown or malformed transition : " + trans);
}
- } else {
- throw new ConfigurationException("Lifecycle callback : Unknown or malformed transition");
}
- LifecycleCallback hk = null;
- if (met != null) {
- hk = new LifecycleCallback(this, transition, met);
+ LifecycleCallback callback = null;
+ if (met == null) {
+ callback = new LifecycleCallback(this, transition, method);
} else {
- hk = new LifecycleCallback(this, transition, method);
+ callback = new LifecycleCallback(this, transition, met);
}
- addCallback(hk);
+ addCallback(callback);
}
}
@@ -127,7 +126,8 @@
* @see org.apache.felix.ipojo.Handler#start()
*/
public void start() {
- } // Do nothing during the start
+ // Do nothing during the start
+ }
/**
* Stop the handler.
@@ -162,13 +162,13 @@
try {
m_callbacks[i].call();
} catch (NoSuchMethodException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not found", e);
- getInstanceManager().stop();
+ error("[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not found");
+ throw new IllegalStateException(e.getMessage());
} catch (IllegalAccessException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not accessible", e);
- getInstanceManager().stop();
+ error("[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not accessible");
+ throw new IllegalStateException(e.getMessage());
} catch (InvocationTargetException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " has throws an exception : " + e.getTargetException().getMessage());
+ error("[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " has throws an exception : " + e.getTargetException().getMessage(), e.getTargetException());
getInstanceManager().setState(ComponentInstance.INVALID);
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
index 41b7250..6d00b3b 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
@@ -24,11 +24,10 @@
import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.PrimitiveHandler;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.FieldMetadata;
-import org.apache.felix.ipojo.parser.ManipulationMetadata;
-import org.apache.felix.ipojo.util.Logger;
+import org.apache.felix.ipojo.parser.PojoMetadata;
/**
* Lifecycle Controller handler.
@@ -51,9 +50,9 @@
* @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
*/
public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
- Element[] lc = metadata.getElements("controller");
- String field = lc[0].getAttribute("field");
- getInstanceManager().register(this, new FieldMetadata[] {new FieldMetadata(field, "boolean")}, null);
+ Element[] controller = metadata.getElements("controller");
+ String field = controller[0].getAttribute("field");
+ getInstanceManager().register(new FieldMetadata(field, "boolean"), this);
}
/**
@@ -70,38 +69,42 @@
* Nothing to do.
* @see org.apache.felix.ipojo.Handler#stop()
*/
- public void stop() { }
+ public void stop() {
+ // Nothing to do.
+ }
/**
* GetterCallback.
+ * @param pojo : the pojo object on which the field is accessed
* Return the stored value.
* @param field : field name.
- * @param o : value given by the previous handler.
+ * @param value : value given by the previous handler.
* @return : the handler state.
*/
- public Object getterCallback(String field, Object o) {
+ public Object onGet(Object pojo, String field, Object value) {
return new Boolean(m_state);
}
/**
* SetterCallback.
+ * @param pojo : the pojo object on which the field is accessed
* Store the new field value & invalidate / validate the handler is required.
* @param field : field name.
- * @param o : new value.
+ * @param value : new value.
*/
- public void setterCallback(String field, Object o) {
- if (o instanceof Boolean) {
- boolean nv = ((Boolean) o).booleanValue();
- if (nv != m_state) {
- m_state = nv;
+ public void onSet(Object pojo, String field, Object value) {
+ if (value instanceof Boolean) {
+ boolean newValue = ((Boolean) value).booleanValue();
+ if (newValue != m_state) {
+ m_state = newValue;
if (m_state) {
- ((InstanceManager) getInstance()).setState(ComponentInstance.VALID);
+ ((InstanceManager) getHandlerManager()).setState(ComponentInstance.VALID);
} else {
- ((InstanceManager) getInstance()).setState(ComponentInstance.INVALID);
+ ((InstanceManager) getHandlerManager()).setState(ComponentInstance.INVALID);
}
}
} else {
- log(Logger.ERROR, "Boolean expected for the lifecycle controller");
+ error("Boolean expected for the lifecycle controller");
getInstanceManager().stop();
}
}
@@ -109,28 +112,28 @@
/**
* Initialize the component factory.
* The controller field is checked to avoid configure check.
- * @param cd : component description
+ * @param desc : component description
* @param metadata : component type metadata
* @throws ConfigurationException : occurs if the controller field is not in the POJO class or is not a boolean.
- * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription, org.apache.felix.ipojo.metadata.Element)
+ * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element)
*/
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
+ public void initializeComponentFactory(ComponentTypeDescription desc, Element metadata) throws ConfigurationException {
String field = null;
- Element[] lc = metadata.getElements("controller");
+ Element[] controller = metadata.getElements("controller");
// Use only the first controller
- field = lc[0].getAttribute("field");
+ field = controller[0].getAttribute("field");
if (field == null) {
throw new ConfigurationException("Lifecycle controller : the controller element needs to have a field attribute");
}
- ManipulationMetadata mm = new ManipulationMetadata(metadata);
- FieldMetadata fm = mm.getField(field);
- if (fm == null) {
+ PojoMetadata method = getFactory().getPojoMetadata();
+ FieldMetadata fieldMetadata = method.getField(field);
+ if (fieldMetadata == null) {
throw new ConfigurationException("Lifecycle controller : The field " + field + " does not exist in the class");
}
- if (!fm.getFieldType().equalsIgnoreCase("boolean")) {
- throw new ConfigurationException("Lifecycle controller : The field " + field + " must be a boolean (" + fm.getFieldType() + " found)");
+ if (!fieldMetadata.getFieldType().equalsIgnoreCase("boolean")) {
+ throw new ConfigurationException("Lifecycle controller : The field " + field + " must be a boolean (" + fieldMetadata.getFieldType() + " found)");
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java
deleted file mode 100644
index f6b3b6f..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * 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.handlers.providedservice;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.parser.ParseUtils;
-import org.apache.felix.ipojo.util.Logger;
-
-/**
- * Represent a property i.e. a set : [name, type, value]. A property can be
- * attached to a field. The value of the property is thefield value. When the
- * value change, the published value change too.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class Property {
-
- /**
- * A property is link with a service. This field represent this provided
- * service. m_providedService : ProvidedService
- */
- private ProvidedService m_providedService;
-
- /**
- * Value of the property (before we know the type).
- */
- private Object m_value;
-
- /**
- * Field of the property.
- */
- private String m_field;
-
- /**
- * Name of the property.
- */
- private String m_name;
-
- /**
- * Type of the property.
- */
- private String m_type;
-
- /**
- * String value of the property (initial value).
- */
- private String m_initialValue;
-
- /**
- * Property constructor.
- *
- * @param ps : the provided service
- * @param name : name of the property
- * @param field : name of the field (if a field is attached to the property)
- * @param type : type of the property
- * @param value : initial value of the property
- */
- public Property(ProvidedService ps, String name, String field, String type, String value) {
- m_providedService = ps;
- m_name = name;
- m_field = field;
- m_type = type;
- m_initialValue = value;
-
- // Dynamic property case :
- if (m_field != null && m_name == null) {
- m_name = m_field;
- }
-
- if (m_initialValue != null) {
- setValue(m_initialValue);
- }
- }
-
- /**
- * Property constructor. This constructor is used only for non-field
- * property (property not attached to a field).
- *
- * @param ps : the provided service
- * @param name : the name of the property
- * @param value : the value of the property
- */
- public Property(ProvidedService ps, String name, Object value) {
- m_providedService = ps;
- m_name = name;
- m_type = value.getClass().getName();
- m_value = value;
- }
-
- /**
- * Get the property value.
- * @return the Object value of the property
- */
- protected Object get() {
- return m_value;
- }
-
- /**
- * This method is automaticaly called when the value of the property is
- * changed. Set the value of a property.
- *
- * @param s : the new value of the property (in String)
- */
- protected void set(String s) {
- setValue(s);
- }
-
- /**
- * This method is called when the value of the property is changed. Set the
- * value of a property.
- *
- * @param o : the new value of the property (object)
- */
- protected void set(Object o) {
- // Is the object is directly assignable to the property, affect it.
- if (!(o instanceof String) || m_type.equals("java.lang.String")) {
- m_value = o;
- } else {
- // If the object is a String, we must recreate the object from the String form
- if (o instanceof String) {
- setValue((String) o);
- } else {
- // Error, the given property cannot be injected.
- throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type + " expected");
- }
- }
- }
-
- /**
- * Set the provided service of this property.
- *
- * @param ps : the provided service to attached.
- */
- void setProvidedService(ProvidedService ps) {
- m_providedService = ps;
- }
-
- /**
- * Set the value of the property.
- *
- * @param value : value of the property (String)
- */
- private void setValue(String value) {
-
- // Array :
- if (m_type.endsWith("[]")) {
- String internalType = m_type.substring(0, m_type.length() - 2);
- setArrayValue(internalType, ParseUtils.parseArrays(value));
- return;
- }
-
- // Simple :
- if ("string".equals(m_type) || "String".equals(m_type)) {
- m_value = new String(value);
- return;
- }
- if ("boolean".equals(m_type)) {
- m_value = new Boolean(value);
- return;
- }
- if ("byte".equals(m_type)) {
- m_value = new Byte(value);
- return;
- }
- if ("short".equals(m_type)) {
- m_value = new Short(value);
- return;
- }
- if ("int".equals(m_type)) {
- m_value = new Integer(value);
- return;
- }
- if ("long".equals(m_type)) {
- m_value = new Long(value);
- return;
- }
- if ("float".equals(m_type)) {
- m_value = new Float(value);
- return;
- }
- if ("double".equals(m_type)) {
- m_value = new Double(value);
- return;
- }
-
- // Else it is a neither a primitive type neither a String -> create the
- // object by calling a constructor with a string in argument.
- try {
- Class c = m_providedService.getInstanceManager().getContext().getBundle().loadClass(m_type);
- // Class string =
- // m_providedService.getComponentManager().getContext().getBundle().loadClass("java.lang.String");
- Constructor cst = c.getConstructor(new Class[] { String.class });
- m_value = cst.newInstance(new Object[] { value });
- } catch (ClassNotFoundException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Class not found exception in setValue on " + m_type);
- m_providedService.getInstanceManager().stop();
- } catch (SecurityException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Security Exception in setValue on " + m_type);
- m_providedService.getInstanceManager().stop();
- } catch (NoSuchMethodException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Constructor not found exeption in setValue on " + m_type);
- m_providedService.getInstanceManager().stop();
- } catch (IllegalArgumentException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Argument problem to call the constructor of the type " + m_type);
- m_providedService.getInstanceManager().stop();
- } catch (InstantiationException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Instantiation problem " + m_type);
- m_providedService.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Illegal Access Exception in setValue on " + m_type);
- m_providedService.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Invocation problem " + m_type + " : " + e.getTargetException().getMessage());
- m_providedService.getInstanceManager().setState(ComponentInstance.INVALID);
- }
- }
-
- /**
- * Set a array value to the current property.
- *
- * @param internalType : internal array type
- * @param values : the new value
- */
- private void setArrayValue(String internalType, String[] values) {
- if ("string".equals(internalType) || "String".equals(internalType)) {
- m_value = values;
- return;
- }
- if ("boolean".equals(internalType)) {
- boolean[] bool = new boolean[values.length];
- for (int i = 0; i < values.length; i++) {
- bool[i] = new Boolean(values[i]).booleanValue();
- }
- m_value = bool;
- return;
- }
- if ("byte".equals(internalType)) {
- byte[] byt = new byte[values.length];
- for (int i = 0; i < values.length; i++) {
- byt[i] = new Byte(values[i]).byteValue();
- }
- m_value = byt;
- return;
- }
- if ("short".equals(internalType)) {
- short[] shor = new short[values.length];
- for (int i = 0; i < values.length; i++) {
- shor[i] = new Short(values[i]).shortValue();
- }
- m_value = shor;
- return;
- }
- if ("int".equals(internalType)) {
- int[] in = new int[values.length];
- for (int i = 0; i < values.length; i++) {
- in[i] = new Integer(values[i]).intValue();
- }
- m_value = in;
- return;
- }
- if ("long".equals(internalType)) {
- long[] ll = new long[values.length];
- for (int i = 0; i < values.length; i++) {
- ll[i] = new Long(values[i]).longValue();
- }
- m_value = ll;
- return;
- }
- if ("float".equals(internalType)) {
- float[] fl = new float[values.length];
- for (int i = 0; i < values.length; i++) {
- fl[i] = new Float(values[i]).floatValue();
- }
- m_value = fl;
- return;
- }
- if ("double".equals(internalType)) {
- double[] dl = new double[values.length];
- for (int i = 0; i < values.length; i++) {
- dl[i] = new Double(values[i]).doubleValue();
- }
- m_value = dl;
- return;
- }
-
- // Else it is a neither a primitive type neither a String -> create the
- // object by calling a constructor with a string in argument.
- try {
- Class c = m_providedService.getInstanceManager().getContext().getBundle().loadClass(internalType);
- Constructor cst = c.getConstructor(new Class[] { String.class });
- Object[] ob = (Object[]) Array.newInstance(c, values.length);
- for (int i = 0; i < values.length; i++) {
- ob[i] = cst.newInstance(new Object[] { values[i] });
- }
- m_value = ob;
- return;
- } catch (ClassNotFoundException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Class not found exception in setArrayValue on " + internalType);
- m_providedService.getInstanceManager().stop();
- } catch (SecurityException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Security Exception in setArrayValue on " + internalType);
- m_providedService.getInstanceManager().stop();
- } catch (NoSuchMethodException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Constructor not found exception in setArrayValue on " + internalType);
- m_providedService.getInstanceManager().stop();
- } catch (IllegalArgumentException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Argument problem to call the constructor of the type " + internalType);
- m_providedService.getInstanceManager().stop();
- } catch (InstantiationException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Instantiation problem " + internalType);
- m_providedService.getInstanceManager().stop();
- } catch (IllegalAccessException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Illegal Access Exception in setArrayValue on " + internalType);
- m_providedService.getInstanceManager().stop();
- } catch (InvocationTargetException e) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Invocation problem " + internalType + " : " + e.getTargetException().getMessage());
- m_providedService.getInstanceManager().setState(ComponentInstance.INVALID);
- }
- }
-
- /**
- * Get the stored value.
- * @return the value of the property.
- */
- public Object getValue() {
- return m_value;
- }
-
- /**
- * Get the property name.
- * @return the name of the property
- */
- public String getName() {
- return m_name;
- }
-
- /**
- * Get the property field.
- * @return the field name of the property (null if the property has no
- * field).
- */
- protected String getField() {
- return m_field;
- }
-
- /**
- * Set the type of the property.
- *
- * @param type : the type to attached to the property
- */
- public void setType(String type) {
- m_type = type;
- }
-
- /**
- * Get the property type.
- * @return the type of the property.
- */
- public String getType() {
- return m_type;
- }
-
- /**
- * Get the property initial value.
- * @return the initial value of the property.
- */
- public String getInitialValue() {
- return m_initialValue;
- }
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
index ee1248a..4f1d52c 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
@@ -22,8 +22,9 @@
import java.util.Enumeration;
import java.util.Properties;
+import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.InstanceManager;
-import org.apache.felix.ipojo.util.Logger;
+import org.apache.felix.ipojo.util.Property;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
@@ -55,6 +56,11 @@
* Factory policy : SERVICE_FACTORY.
*/
public static final int SERVICE_FACTORY = 1;
+
+ /**
+ * Factory policy : STATIC_FACTORY.
+ */
+ public static final int STATIC_FACTORY = 2;
/**
* At this time, it is only the java interface full name.
@@ -80,7 +86,7 @@
/**
* Properties Array.
*/
- private Property[] m_properties = new Property[0];
+ private Property[] m_properties;
/**
* Construct a provided service object.
@@ -96,8 +102,12 @@
m_factoryPolicy = factoryPolicy;
// Add instance name & factory name
- addProperty(new Property(this, "instance.name", handler.getInstanceManager().getInstanceName()));
- addProperty(new Property(this, "factory.name", handler.getInstanceManager().getFactory().getName()));
+ try {
+ addProperty(new Property("instance.name", null, null, handler.getInstanceManager().getInstanceName(), String.class.getName(), handler.getInstanceManager(), handler));
+ addProperty(new Property("factory.name", null, null, handler.getInstanceManager().getFactory().getFactoryName(), String.class.getName(), handler.getInstanceManager(), handler));
+ } catch (ConfigurationException e) {
+ m_handler.error("An exception occurs when adding instance.name and factory.name property : " + e.getMessage());
+ }
}
/**
@@ -113,22 +123,22 @@
/**
* Add the given property to the property list.
*
- * @param p : the element to add
+ * @param prop : the element to add
*/
- private synchronized void addProperty(Property p) {
+ private synchronized void addProperty(Property prop) {
for (int i = 0; (m_properties != null) && (i < m_properties.length); i++) {
- if (m_properties[i] == p) {
+ if (m_properties[i] == prop) {
return;
}
}
- if (m_properties.length > 0) {
+ if (m_properties == null) {
+ m_properties = new Property[] { prop };
+ } else {
Property[] newProp = new Property[m_properties.length + 1];
System.arraycopy(m_properties, 0, newProp, 0, m_properties.length);
- newProp[m_properties.length] = p;
+ newProp[m_properties.length] = prop;
m_properties = newProp;
- } else {
- m_properties = new Property[] { p };
}
}
@@ -148,7 +158,7 @@
if (idx >= 0) {
if ((m_properties.length - 1) == 0) {
- m_properties = new Property[0];
+ m_properties = null;
} else {
Property[] newPropertiesList = new Property[m_properties.length - 1];
System.arraycopy(m_properties, 0, newPropertiesList, 0, idx);
@@ -166,10 +176,10 @@
* service is not published).
*/
public ServiceReference getServiceReference() {
- if (m_serviceRegistration != null) {
- return m_serviceRegistration.getReference();
- } else {
+ if (m_serviceRegistration == null) {
return null;
+ } else {
+ return m_serviceRegistration.getReference();
}
}
@@ -189,9 +199,14 @@
case SERVICE_FACTORY:
svc = m_handler.getInstanceManager().createPojoObject();
break;
+ case STATIC_FACTORY:
+ // In this case, we need to try to create a new pojo object, the factory method will handle the creation.
+ svc = m_handler.getInstanceManager().createPojoObject();
+ break;
default:
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Unknown factory policy for " + m_serviceSpecification + " : " + m_factoryPolicy);
+ m_handler.error("[" + m_handler.getInstanceManager().getClassName() + "] Unknown factory policy for " + m_serviceSpecification + " : " + m_factoryPolicy);
getInstanceManager().stop();
+ break;
}
return svc;
}
@@ -258,8 +273,8 @@
// Contruct the service properties list
Properties serviceProperties = new Properties();
for (int i = 0; i < m_properties.length; i++) {
- if (m_properties[i].get() != null) {
- serviceProperties.put(m_properties[i].getName(), m_properties[i].get());
+ if (m_properties[i].getValue() != null) {
+ serviceProperties.put(m_properties[i].getName(), m_properties[i].getValue());
}
}
return serviceProperties;
@@ -278,18 +293,9 @@
* the service registry.
*/
public synchronized void update() {
- // Contruct the service properties list
- Properties serviceProperties = getServiceProperties();
-
- if (serviceProperties == null) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Cannot get the properties of the provided service");
- getInstanceManager().stop();
- return;
- }
-
// Update the service registration
if (m_serviceRegistration != null) {
- m_serviceRegistration.setProperties(serviceProperties);
+ m_serviceRegistration.setProperties(getServiceProperties());
}
}
@@ -302,8 +308,13 @@
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
Object value = props.get(key);
- Property prop = new Property(this, key, value);
- addProperty(prop);
+ Property prop;
+ try {
+ prop = new Property(key, null, null, value.toString(), value.getClass().getName(), getInstanceManager(), m_handler);
+ addProperty(prop);
+ } catch (ConfigurationException e) {
+ m_handler.error("The propagated property " + key + " cannot be pcreated correctly : " + e.getMessage());
+ }
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceDescription.java
index 59f2cda..d8fe68a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceDescription.java
@@ -69,13 +69,13 @@
*
* @param serviceSpecification : the provided contract
* @param state : state (UNREGITRED | REGISTRED)
- * @param sr : Service Registration (to obtain the reference), or null if
+ * @param ref : Service Registration (to obtain the reference), or null if
* state is UNREGISTRED
*/
- public ProvidedServiceDescription(String[] serviceSpecification, int state, ServiceReference sr) {
+ public ProvidedServiceDescription(String[] serviceSpecification, int state, ServiceReference ref) {
m_serviceSpecification = serviceSpecification;
m_state = state;
- m_serviceReference = sr;
+ m_serviceReference = ref;
// m_parent = parent;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
index a791797..1fc3e1d 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
@@ -19,7 +19,6 @@
package org.apache.felix.ipojo.handlers.providedservice;
import java.lang.reflect.Field;
-import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Iterator;
@@ -28,10 +27,10 @@
import java.util.Set;
import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.IPojoConfiguration;
+import org.apache.felix.ipojo.HandlerFactory;
import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.PrimitiveHandler;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.architecture.PropertyDescription;
import org.apache.felix.ipojo.handlers.dependency.Dependency;
@@ -40,9 +39,10 @@
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.FieldMetadata;
import org.apache.felix.ipojo.parser.ManifestMetadataParser;
-import org.apache.felix.ipojo.parser.ManipulationMetadata;
import org.apache.felix.ipojo.parser.ParseException;
import org.apache.felix.ipojo.parser.ParseUtils;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.apache.felix.ipojo.util.Property;
import org.osgi.framework.Bundle;
/**
@@ -60,21 +60,21 @@
/**
* Add a provided service to the list .
*
- * @param ps : the provided service to add
+ * @param svc : the provided service to add
*/
- private void addProvidedService(ProvidedService ps) {
+ private void addProvidedService(ProvidedService svc) {
// Verify that the provided service is not already in the array.
for (int i = 0; (m_providedServices != null) && (i < m_providedServices.length); i++) {
- if (m_providedServices[i] == ps) { return; }
+ if (m_providedServices[i] == svc) { return; }
}
if (m_providedServices.length > 0) {
ProvidedService[] newPS = new ProvidedService[m_providedServices.length + 1];
System.arraycopy(m_providedServices, 0, newPS, 0, m_providedServices.length);
- newPS[m_providedServices.length] = ps;
+ newPS[m_providedServices.length] = svc;
m_providedServices = newPS;
} else {
- m_providedServices = new ProvidedService[] { ps };
+ m_providedServices = new ProvidedService[] { svc };
}
}
@@ -97,7 +97,6 @@
m_providedServices = new ProvidedService[0];
// Create the dependency according to the component metadata
Element[] providedServices = componentMetadata.getElements("Provides");
- List fields = new ArrayList();
for (int i = 0; i < providedServices.length; i++) {
String[] serviceSpecifications = ParseUtils.parseArrays(providedServices[i].getAttribute("interface")); // Set by the initialize component factory.
@@ -107,62 +106,54 @@
if (fact != null && "service".equalsIgnoreCase(fact)) {
factory = ProvidedService.SERVICE_FACTORY;
}
-
- // Then create the provided service
- ProvidedService ps = new ProvidedService(this, serviceSpecifications, factory);
-
- Element[] props = providedServices[i].getElements("Property");
- Property[] properties = new Property[props.length];
- for (int j = 0; j < props.length; j++) {
- String name = props[j].getAttribute("name");
- String value = props[j].getAttribute("value");
- String type = props[j].getAttribute("type");
- String field = props[j].getAttribute("field");
-
- if (name != null && configuration.get(name) != null && configuration.get(name) instanceof String) {
- value = (String) configuration.get(name);
- } else {
- if (field != null && configuration.get(field) != null && configuration.get(field) instanceof String) {
- value = (String) configuration.get(field);
- }
- }
-
- Property prop = new Property(ps, name, field, type, value);
- properties[j] = prop;
-
- // Check if the instance configuration has a value for this property
- Object o = configuration.get(prop.getName());
- if (o != null && ! (o instanceof String)) {
- prop.set(o);
- } else {
- if (field != null) {
- o = configuration.get(field);
- if (o != null && !(o instanceof String)) {
- prop.set(configuration.get(field));
- }
- }
- }
-
- if (field != null) {
- fields.add(new FieldMetadata(field, type));
- }
+ if (fact != null && "method".equalsIgnoreCase(fact)) {
+ factory = ProvidedService.STATIC_FACTORY;
}
- // Attached to properties to the provided service
- ps.setProperties(properties);
+ // Then create the provided service
+ ProvidedService svc = new ProvidedService(this, serviceSpecifications, factory);
- if (checkProvidedService(ps)) {
- addProvidedService(ps);
+ Element[] props = providedServices[i].getElements("Property");
+ if (props != null) {
+ //Property[] properties = new Property[props.length];
+ Property[] properties = new Property[props.length];
+ for (int j = 0; j < props.length; j++) {
+ String name = props[j].getAttribute("name");
+ String value = props[j].getAttribute("value");
+ String type = props[j].getAttribute("type");
+ String field = props[j].getAttribute("field");
+
+ Property prop = new Property(name, field, null, value, type, getInstanceManager(), this);
+ properties[j] = prop;
+
+ // Check if the instance configuration has a value for this property
+ Object object = configuration.get(prop.getName());
+ if (object != null) {
+ prop.setValue(object);
+ }
+
+ if (field != null) {
+ getInstanceManager().register(new FieldMetadata(field, type), this);
+ // Cannot register the property as the interception is necessary to deal with registration update.
+ }
+ }
+
+ // Attach to properties to the provided service
+ svc.setProperties(properties);
+ }
+
+ if (checkProvidedService(svc)) {
+ addProvidedService(svc);
} else {
- String itfs = "";
+ StringBuffer itfs = new StringBuffer();
for (int j = 0; j < serviceSpecifications.length; j++) {
- itfs = itfs + " " + serviceSpecifications[j];
+ itfs.append(' ');
+ itfs.append(serviceSpecifications[j]);
}
throw new ConfigurationException("[" + getInstanceManager().getInstanceName() + "] The provided service" + itfs + " is not valid");
}
}
- getInstanceManager().register(this, (FieldMetadata[]) fields.toArray(new FieldMetadata[fields.size()]), null);
}
/**
@@ -185,8 +176,8 @@
// Look for parent class.
if (parent != null) {
- Class cl = bundle.loadClass(parent);
- collectInterfacesFromClass(cl, result, bundle);
+ Class clazz = bundle.loadClass(parent);
+ collectInterfacesFromClass(clazz, result, bundle);
}
return result;
@@ -195,78 +186,78 @@
/**
* Look for inherited interfaces.
* @param clazz : interface name to explore (class object)
- * @param l : set (accumulator)
- * @param b : bundle
+ * @param acc : set (accumulator)
+ * @param bundle : bundle
* @throws ClassNotFoundException : occurs when an interface cannot be loaded.
*/
- private void collectInterfaces(Class clazz, Set l, Bundle b) throws ClassNotFoundException {
+ private void collectInterfaces(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
Class[] clazzes = clazz.getInterfaces();
for (int i = 0; i < clazzes.length; i++) {
- l.add(clazzes[i].getName());
- collectInterfaces(clazzes[i], l, b);
+ acc.add(clazzes[i].getName());
+ collectInterfaces(clazzes[i], acc, bundle);
}
}
/**
* Collect interfaces for the given class.
* This method explores super class to.
- * @param cl : class object.
- * @param l : set of implemented interface (accumulator)
- * @param b : bundle.
+ * @param clazz : class object.
+ * @param acc : set of implemented interface (accumulator)
+ * @param bundle : bundle.
* @throws ClassNotFoundException : occurs if an interface cannot be load.
*/
- private void collectInterfacesFromClass(Class cl, Set l, Bundle b) throws ClassNotFoundException {
- Class[] clazzes = cl.getInterfaces();
+ private void collectInterfacesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+ Class[] clazzes = clazz.getInterfaces();
for (int i = 0; i < clazzes.length; i++) {
- l.add(clazzes[i].getName());
- collectInterfaces(clazzes[i], l, b);
+ acc.add(clazzes[i].getName());
+ collectInterfaces(clazzes[i], acc, bundle);
}
// Iterate on parent classes
- Class sup = cl.getSuperclass();
+ Class sup = clazz.getSuperclass();
if (sup != null) {
- collectInterfacesFromClass(sup, l, b);
+ collectInterfacesFromClass(sup, acc, bundle);
}
}
/**
* Check the provided service given in argument in the sense that the metadata are consistent.
- * @param ps : the provided service to check.
+ * @param svc : the provided service to check.
* @return true if the provided service is correct
* @throws ConfigurationException : the checked provided service is not correct.
*/
- private boolean checkProvidedService(ProvidedService ps) throws ConfigurationException {
- for (int i = 0; i < ps.getServiceSpecification().length; i++) {
- String specName = ps.getServiceSpecification()[i];
+ private boolean checkProvidedService(ProvidedService svc) throws ConfigurationException {
+ for (int i = 0; i < svc.getServiceSpecification().length; i++) {
+ String specName = svc.getServiceSpecification()[i];
// Check service level dependencies
try {
Class spec = getInstanceManager().getFactory().loadClass(specName);
Field specField = spec.getField("specification");
- Object o = specField.get(null);
- if (o instanceof String) {
- Element specification = ManifestMetadataParser.parse((String) o);
+ Object specif = specField.get(null);
+ if (specif instanceof String) {
+ Element specification = ManifestMetadataParser.parse((String) specif);
Element[] deps = specification.getElements("requires");
- for (int j = 0; j < deps.length; j++) {
- Dependency d = getAttachedDependency(deps[j]);
- if (d != null) {
+ for (int j = 0; deps != null && j < deps.length; j++) {
+ Dependency dep = getAttachedDependency(deps[j]);
+ if (dep != null) {
// Fix service-level dependency flag
- d.setServiceLevelDependency();
+ dep.setServiceLevelDependency();
}
- isDependencyCorrect(d, deps[j]);
+ isDependencyCorrect(dep, deps[j]);
}
} else {
- throw new ConfigurationException("Provides : The specification field of the service specification " + ps.getServiceSpecification()[i] + " need to be a String");
+ throw new ConfigurationException("Provides : The specification field of the service specification " + svc.getServiceSpecification()[i] + " need to be a String");
}
} catch (NoSuchFieldException e) {
return true; // No specification field
} catch (ClassNotFoundException e) {
- throw new ConfigurationException("Provides : The service specification " + ps.getServiceSpecification()[i] + " cannot be load");
+ throw new ConfigurationException("Provides : The service specification " + svc.getServiceSpecification()[i] + " cannot be load");
} catch (IllegalArgumentException e) {
- throw new ConfigurationException("Provides : The field 'specification' of the service specification " + ps.getServiceSpecification()[i] + " is not accessible : " + e.getMessage());
+ throw new ConfigurationException("Provides : The field 'specification' of the service specification " + svc.getServiceSpecification()[i] + " is not accessible : " + e.getMessage());
} catch (IllegalAccessException e) {
- throw new ConfigurationException("Provides : The field 'specification' of the service specification " + ps.getServiceSpecification()[i] + " is not accessible : " + e.getMessage());
+ throw new ConfigurationException("Provides : The field 'specification' of the service specification " + svc.getServiceSpecification()[i] + " is not accessible : " + e.getMessage());
} catch (ParseException e) {
- throw new ConfigurationException("Provides : The field 'specification' of the service specification " + ps.getServiceSpecification()[i] + " does not contain a valid String : " + e.getMessage());
+ throw new ConfigurationException("Provides : The field 'specification' of the service specification " + svc.getServiceSpecification()[i] + " does not contain a valid String : " + e.getMessage());
}
}
@@ -279,20 +270,20 @@
* @return the Dependency object, null if not found or if the DependencyHandler is not plugged to the instance
*/
private Dependency getAttachedDependency(Element element) {
- DependencyHandler dh = (DependencyHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":requires");
- if (dh == null) { return null; }
+ DependencyHandler handler = (DependencyHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":requires");
+ if (handler == null) { return null; }
- String id = element.getAttribute("id");
- if (id != null) {
+ String identity = element.getAttribute("id");
+ if (identity != null) {
// Look for dependency Id
- for (int i = 0; i < dh.getDependencies().length; i++) {
- if (dh.getDependencies()[i].getId().equals(id)) { return dh.getDependencies()[i]; }
+ for (int i = 0; i < handler.getDependencies().length; i++) {
+ if (handler.getDependencies()[i].getId().equals(identity)) { return handler.getDependencies()[i]; }
}
}
// If not found or no id, look for a dependency with the same specification
String requirement = element.getAttribute("specification");
- for (int i = 0; i < dh.getDependencies().length; i++) {
- if (dh.getDependencies()[i].getSpecification().equals(requirement)) { return dh.getDependencies()[i]; }
+ for (int i = 0; i < handler.getDependencies().length; i++) {
+ if (handler.getDependencies()[i].getSpecification().equals(requirement)) { return handler.getDependencies()[i]; }
}
return null;
@@ -334,6 +325,7 @@
* @see org.apache.felix.ipojo.Handler#stop()
*/
public void stop() {
+ //Nothing to do.
}
/**
@@ -341,31 +333,34 @@
*
* @see org.apache.felix.ipojo.Handler#start()
*/
- public void start() { }
+ public void start() {
+ // Nothing to do.
+ }
/**
* Setter Callback Method.
* Check if the modified field is a property to update the value.
+ * @param pojo : the pojo object on which the field is accessed
* @param fieldName : field name
* @param value : new value
- * @see org.apache.felix.ipojo.Handler#setterCallback(java.lang.String,
- * java.lang.Object)
+ * @see org.apache.felix.ipojo.Handler#onSet(Object,
+ * java.lang.String, java.lang.Object)
*/
- public void setterCallback(String fieldName, Object value) {
+ public void onSet(Object pojo, String fieldName, Object value) {
// Verify that the field name correspond to a dependency
for (int i = 0; i < m_providedServices.length; i++) {
- ProvidedService ps = m_providedServices[i];
+ ProvidedService svc = m_providedServices[i];
boolean update = false;
- for (int j = 0; j < ps.getProperties().length; j++) {
- Property prop = ps.getProperties()[j];
- if (fieldName.equals(prop.getField())) {
+ for (int j = 0; j < svc.getProperties().length; j++) {
+ Property prop = svc.getProperties()[j];
+ if (fieldName.equals(prop.getField()) && ! prop.getValue().equals(value)) {
// it is the associated property
- prop.set(value);
+ prop.setValue(value);
update = true;
}
}
if (update) {
- ps.update();
+ svc.update();
}
}
// Else do nothing
@@ -374,20 +369,21 @@
/**
* Getter Callback Method.
* Check if the field is a property to push the stored value.
+ * @param pojo : the pojo object on which the field is accessed
* @param fieldName : field name
* @param value : value pushed by the previous handler
* @return the stored value or the previous value.
- * @see org.apache.felix.ipojo.Handler#getterCallback(java.lang.String,
- * java.lang.Object)
+ * @see org.apache.felix.ipojo.Handler#onGet(Object,
+ * java.lang.String, java.lang.Object)
*/
- public Object getterCallback(String fieldName, Object value) {
+ public Object onGet(Object pojo, String fieldName, Object value) {
for (int i = 0; i < m_providedServices.length; i++) {
- ProvidedService ps = m_providedServices[i];
- for (int j = 0; j < ps.getProperties().length; j++) {
- Property prop = ps.getProperties()[j];
+ ProvidedService svc = m_providedServices[i];
+ for (int j = 0; j < svc.getProperties().length; j++) {
+ Property prop = svc.getProperties()[j];
if (fieldName.equals(prop.getField())) {
// it is the associated property
- return prop.get();
+ return prop.getValue();
}
}
}
@@ -452,12 +448,12 @@
ProvidedServiceHandlerDescription pshd = new ProvidedServiceHandlerDescription(this);
for (int j = 0; j < getProvidedService().length; j++) {
- ProvidedService ps = getProvidedService()[j];
- ProvidedServiceDescription psd = new ProvidedServiceDescription(ps.getServiceSpecification(), ps.getState(), ps.getServiceReference());
+ ProvidedService svc = getProvidedService()[j];
+ ProvidedServiceDescription psd = new ProvidedServiceDescription(svc.getServiceSpecification(), svc.getState(), svc.getServiceReference());
Properties props = new Properties();
- for (int k = 0; k < ps.getProperties().length; k++) {
- Property prop = ps.getProperties()[k];
+ for (int k = 0; k < svc.getProperties().length; k++) {
+ Property prop = svc.getProperties()[k];
if (prop.getValue() != null) {
props.put(prop.getName(), prop.getValue().toString());
}
@@ -475,36 +471,32 @@
*/
public void reconfigure(Dictionary dict) {
for (int j = 0; j < getProvidedService().length; j++) {
- ProvidedService ps = getProvidedService()[j];
- Property[] props = ps.getProperties();
+ ProvidedService svc = getProvidedService()[j];
+ Property[] props = svc.getProperties();
boolean update = false;
for (int k = 0; k < props.length; k++) {
if (dict.get(props[k].getName()) != null) {
update = true;
- if (dict.get(props[k].getName()) instanceof String) {
- props[k].set((String) dict.get(props[k].getName()));
- } else {
- props[k].set(dict.get(props[k].getName()));
- }
+ props[k].setValue(dict.get(props[k].getName()));
}
}
if (update) {
- ps.update();
+ svc.update();
}
}
}
/**
* Initialize the component type.
- * @param cd : component type description to populate.
+ * @param desc : component type description to populate.
* @param metadata : component type metadata.
* @throws ConfigurationException : occurs when the POJO does not implement any interfaces.
- * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription, org.apache.felix.ipojo.metadata.Element)
+ * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element)
*/
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
+ public void initializeComponentFactory(ComponentTypeDescription desc, Element metadata) throws ConfigurationException {
// Change ComponentInfo
Element[] provides = metadata.getElements("provides");
- ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
+ PojoMetadata manipulation = getFactory().getPojoMetadata();
for (int i = 0; i < provides.length; i++) {
// First : create the serviceSpecification list
@@ -512,7 +504,7 @@
String parent = manipulation.getSuperClass();
Set all = null;
try {
- all = computeInterfaces(serviceSpecification, parent, cd.getBundleContext().getBundle());
+ all = computeInterfaces(serviceSpecification, parent, desc.getBundleContext().getBundle());
} catch (ClassNotFoundException e) {
throw new ConfigurationException("A interface cannot be loaded : " + e.getMessage());
}
@@ -522,35 +514,37 @@
List itfs = ParseUtils.parseArraysAsList(serviceSpecificationStr);
for (int j = 0; j < itfs.size(); j++) {
if (! all.contains(itfs.get(j))) {
- throw new ConfigurationException("The specification " + itfs.get(j) + " is not implemented by " + cd.getClassName());
+ throw new ConfigurationException("The specification " + itfs.get(j) + " is not implemented by " + desc.getClassName());
}
}
all = new HashSet(itfs);
}
- if (all.size() == 0) {
+ if (all.isEmpty()) {
throw new ConfigurationException("Provides : Cannot instantiate a provided service : no specifications found (no interfaces implemented by the pojo)");
}
- String specs = null;
+ StringBuffer specs = null;
Set set = new HashSet(all);
- Iterator it = set.iterator();
- while (it.hasNext()) {
- String sp = (String) it.next();
- cd.addProvidedServiceSpecification(sp);
+ Iterator iterator = set.iterator();
+ while (iterator.hasNext()) {
+ String spec = (String) iterator.next();
+ desc.addProvidedServiceSpecification(spec);
if (specs == null) {
- specs = "{" + sp;
+ specs = new StringBuffer("{");
+ specs.append(spec);
} else {
- specs += "," + sp;
+ specs.append(',');
+ specs.append(spec);
}
}
- specs += "}";
+ specs.append('}');
- provides[i].addAttribute(new Attribute("interface", specs)); // Add interface attribute to avoid checking in the configure method
+ provides[i].addAttribute(new Attribute("interface", specs.toString())); // Add interface attribute to avoid checking in the configure method
Element[] props = provides[i].getElements("property");
- for (int j = 0; j < props.length; j++) {
+ for (int j = 0; props != null && j < props.length; j++) {
String name = props[j].getAttribute("name");
String value = props[j].getAttribute("value");
String type = props[j].getAttribute("type");
@@ -566,15 +560,22 @@
if (field == null) {
throw new ConfigurationException("The property " + name + " has neither type neither field.");
}
- FieldMetadata fm = manipulation.getField(field);
- if (fm == null) {
+ FieldMetadata fieldMeta = manipulation.getField(field);
+ if (fieldMeta == null) {
throw new ConfigurationException("A declared property was not found in the class : " + field);
}
- type = fm.getFieldType();
+ type = fieldMeta.getFieldType();
props[j].addAttribute(new Attribute("type", type));
}
+
+ // Is the property set to immutable
+ boolean immutable = false;
+ String imm = props[j].getAttribute("immutable");
+ if (imm != null && imm.equalsIgnoreCase("true")) {
+ immutable = true;
+ }
- cd.addProperty(new PropertyDescription(name, type, value));
+ desc.addProperty(new PropertyDescription(name, type, value, immutable));
}
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
index d2bb779..59601f9 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
@@ -40,10 +40,10 @@
/**
* Constructor.
- * @param h : handler.
+ * @param handler : handler.
*/
- public ProvidedServiceHandlerDescription(Handler h) {
- super(h);
+ public ProvidedServiceHandlerDescription(Handler handler) {
+ super(handler);
}
/**
@@ -83,17 +83,18 @@
public Element getHandlerInfo() {
Element services = super.getHandlerInfo();
for (int i = 0; i < m_providedServices.length; i++) {
- Element service = new Element("provides", "");
- String spec = "[";
+ Element service = new Element("provides", null);
+ StringBuffer spec = new StringBuffer("[");
for (int j = 0; j < m_providedServices[i].getServiceSpecification().length; j++) {
if (j == 0) {
- spec += m_providedServices[i].getServiceSpecification()[j];
+ spec.append(m_providedServices[i].getServiceSpecification()[j]);
} else {
- spec += ", " + m_providedServices[i].getServiceSpecification()[j];
+ spec.append(',');
+ spec.append(m_providedServices[i].getServiceSpecification()[j]);
}
}
- spec += "]";
- service.addAttribute(new Attribute("specifications", spec));
+ spec.append(']');
+ service.addAttribute(new Attribute("specifications", spec.toString()));
if (m_providedServices[i].getState() == ProvidedService.REGISTERED) {
service.addAttribute(new Attribute("state", "registered"));
@@ -102,12 +103,12 @@
service.addAttribute(new Attribute("state", "unregistered"));
}
- Iterator it = m_providedServices[i].getProperties().keySet().iterator();
- while (it.hasNext()) {
- Element prop = new Element("property", "");
- String k = (String) it.next();
- prop.addAttribute(new Attribute("name", k));
- prop.addAttribute(new Attribute("value", m_providedServices[i].getProperties().getProperty(k).toString()));
+ Iterator iterator = m_providedServices[i].getProperties().keySet().iterator();
+ while (iterator.hasNext()) {
+ Element prop = new Element("property", null);
+ String name = (String) iterator.next();
+ prop.addAttribute(new Attribute("name", name));
+ prop.addAttribute(new Attribute("value", m_providedServices[i].getProperties().getProperty(name).toString()));
service.addElement(prop);
}
services.addElement(service);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java
index 9c6ea8d..bc272d0 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java
@@ -62,45 +62,32 @@
public String getFieldType() { return m_type; }
/**
- * Get the 'reflective' type of the field.
+ * Get the 'reflective' type of the given type.
* The reflective type is the type used by the Java Reflection API.
+ * @param type : the type to analyze to find the Java reflective type.
* @return : the reflective type corresponding to this field.
*/
- public String getReflectionType() {
+ public static String getReflectionType(String type) {
// Primitive Array
- if (m_type.endsWith("[]") && m_type.indexOf(".") == -1) {
- String arr = "";
- for (int i = 0; i < m_type.length(); i++) {
- if (m_type.charAt(i) == '[') { arr += '['; }
- }
- int index = m_type.indexOf('[');
- String t = m_type.substring(0, index);
- return arr + getInternalPrimitiveType(t);
+ if (type.endsWith("[]") && type.indexOf('.') == -1) {
+ int index = type.indexOf('[');
+ return '[' + getInternalPrimitiveType(type.substring(0, index));
}
// Non-Primitive Array
- if (m_type.endsWith("[]") && m_type.indexOf(".") != -1) {
- String arr = "";
- for (int i = 0; i < m_type.length(); i++) {
- if (m_type.charAt(i) == '[') { arr += '['; }
- }
- int index = m_type.indexOf('[');
- String t = m_type.substring(0, index);
- return arr + "L" + t + ";";
+ if (type.endsWith("[]") && type.indexOf('.') != -1) {
+ int index = type.indexOf('[');
+ return "[L" + type.substring(0, index) + ";";
}
- // Simple type
- if (!m_type.endsWith("[]")) {
- return m_type;
- }
-
- return null;
+ // The type is not an array.
+ return type;
}
/**
* Get the internal notation for primitive type.
- * @param string : Stringform of the type
+ * @param string : String form of the type
* @return the internal notation or null if not found
*/
- private String getInternalPrimitiveType(String string) {
+ public static String getInternalPrimitiveType(String string) {
if (string.equalsIgnoreCase("boolean")) {
return "Z";
}
@@ -125,7 +112,39 @@
if (string.equalsIgnoreCase("double")) {
return "D";
}
- System.err.println("No primitive type found for " + m_type);
+ return null;
+ }
+
+ /**
+ * Get the iPOJO primitive type from the given primitive class.
+ * @param clazz : a primitive class
+ * @return the primitive type.
+ */
+ public static String getPrimitiveTypeByClass(Class clazz) {
+ if (clazz.equals(Boolean.TYPE)) {
+ return "boolean";
+ }
+ if (clazz.equals(Character.TYPE)) {
+ return "char";
+ }
+ if (clazz.equals(Byte.TYPE)) {
+ return "byte";
+ }
+ if (clazz.equals(Short.TYPE)) {
+ return "short";
+ }
+ if (clazz.equals(Integer.TYPE)) {
+ return "int";
+ }
+ if (clazz.equals(Float.TYPE)) {
+ return "float";
+ }
+ if (clazz.equals(Long.TYPE)) {
+ return "long";
+ }
+ if (clazz.equals(Double.TYPE)) {
+ return "double";
+ }
return null;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
index 172338a..ea0709e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
@@ -18,7 +18,9 @@
*/
package org.apache.felix.ipojo.parser;
+import java.util.ArrayList;
import java.util.Dictionary;
+import java.util.List;
import java.util.Properties;
import org.apache.felix.ipojo.metadata.Attribute;
@@ -32,11 +34,6 @@
public class ManifestMetadataParser {
/**
- * Manifest Headers.
- */
- private Dictionary m_headers;
-
- /**
* Element list.
*/
private Element[] m_elements = new Element[0];
@@ -47,24 +44,14 @@
* @throws ParseException when a parsing error occurs
*/
public Element[] getComponentsMetadata() throws ParseException {
- Element[] components = m_elements[0].getElements("Component");
- Element[] composites = m_elements[0].getElements("Composite");
- Element[] handlers = m_elements[0].getElements("Handler");
- Element[] all = new Element[components.length + composites.length + handlers.length];
- int l = 0;
- for (int i = 0; i < components.length; i++) {
- all[l] = components[i];
- l++;
+ Element[] elems = m_elements[0].getElements();
+ List list = new ArrayList();
+ for (int i = 0; i < elems.length; i++) {
+ if (!"instance".equals(elems[i].getName())) {
+ list.add(elems[i]);
+ }
}
- for (int i = 0; i < composites.length; i++) {
- all[l] = composites[i];
- l++;
- }
- for (int i = 0; i < handlers.length; i++) {
- all[l] = handlers[i];
- l++;
- }
- return all;
+ return (Element[]) list.toArray(new Element[list.size()]);
}
/**
@@ -73,7 +60,10 @@
* @throws ParseException : if the metadata cannot be parsed successfully
*/
public Dictionary[] getInstances() throws ParseException {
- Element[] configs = m_elements[0].getElements("Instance");
+ Element[] configs = m_elements[0].getElements("instance");
+ if (configs == null) {
+ return null;
+ }
Dictionary[] dicts = new Dictionary[configs.length];
for (int i = 0; i < configs.length; i++) {
dicts[i] = parseInstance(configs[i]);
@@ -95,17 +85,18 @@
if (name != null) {
dict.put("name", instance.getAttribute("name"));
}
-
+
if (comp == null) {
throw new ParseException("An instance does not have the 'component' attribute");
}
-
- dict.put("component", comp);
- for (int i = 0; i < instance.getElements("property").length; i++) {
- parseProperty(instance.getElements("property")[i], dict);
+ dict.put("component", comp);
+ Element[] props = instance.getElements("property");
+
+ for (int i = 0; props != null && i < props.length; i++) {
+ parseProperty(props[i], dict);
}
-
+
return dict;
}
@@ -122,10 +113,8 @@
if (name == null) {
throw new ParseException("A property does not have the 'name' attribute");
}
- // Final case : the property element has a 'value' attribute
- if (value != null) {
- dict.put(prop.getAttribute("name"), prop.getAttribute("value"));
- } else {
+ //case : the property element has a 'value' attribute
+ if (value == null) {
// Recursive case
// Check if there is 'property' element
Element[] subProps = prop.getElements("property");
@@ -137,6 +126,8 @@
parseProperty(subProps[i], dict2);
dict.put(name, dict2);
}
+ } else {
+ dict.put(prop.getAttribute("name"), prop.getAttribute("value"));
}
}
@@ -146,13 +137,13 @@
* @param elem : the element to add
*/
private void addElement(Element elem) {
- if (m_elements != null) {
+ if (m_elements == null) {
+ m_elements = new Element[] { elem };
+ } else {
Element[] newElementsList = new Element[m_elements.length + 1];
System.arraycopy(m_elements, 0, newElementsList, 0, m_elements.length);
newElementsList[m_elements.length] = elem;
m_elements = newElementsList;
- } else {
- m_elements = new Element[] { elem };
}
}
@@ -180,19 +171,18 @@
}
/**
- * Parse the given dictionnary and create the instance managers.
+ * Parse the given dictionary and create the instance managers.
*
* @param dict : the given headers of the manifest file
* @throws ParseException : if any error occurs
*/
public void parse(Dictionary dict) throws ParseException {
- m_headers = dict;
- String componentClassesStr = (String) m_headers.get("iPOJO-Components");
+ String componentClassesStr = (String) dict.get("iPOJO-Components");
// Add the ipojo element inside the element list
addElement(new Element("iPOJO", ""));
parseElements(componentClassesStr.trim());
}
-
+
/**
* Parse the given header and create the instance managers.
*
@@ -222,57 +212,61 @@
}
/**
- * Paser the given string.
+ * Parse the given string.
*
- * @param s : the string to parse
+ * @param elems : the string to parse
*/
- private void parseElements(String s) {
- char[] string = s.toCharArray();
+ private void parseElements(String elems) {
+ char[] string = elems.toCharArray();
for (int i = 0; i < string.length; i++) {
- char c = string[i];
+ char current = string[i];
- switch (c) {
+ switch (current) { //NOPMD
// Beginning of an attribute.
case '$':
- String attName = "";
- String attValue = "";
- String attNs = "";
+ StringBuffer attName = new StringBuffer();
+ StringBuffer attValue = new StringBuffer();
+ StringBuffer attNs = null;
i++;
- c = string[i];
- while (c != '=') {
- if (c == ':') {
+ current = string[i]; // Increment and get the new current char.
+ while (current != '=') {
+ if (current == ':') {
attNs = attName;
- attName = "";
+ attName = new StringBuffer();
} else {
- attName = attName + c;
+ attName.append(current);
}
- i = i + 1;
- c = string[i];
- }
- i++; // skip =
- i++; // skip "
- c = string[i];
- while (c != '"') {
- attValue = attValue + c;
i++;
- c = string[i];
+ current = string[i];
+ }
+ i = i + 2; // skip ="
+ current = string[i];
+ while (current != '"') {
+ attValue.append(current);
+ i++;
+ current = string[i]; // Increment and get the new current char.
}
i++; // skip "
- c = string[i];
+ current = string[i];
- Attribute att = new Attribute(attName, attNs, attValue);
+ Attribute att = null;
+ if (attNs == null) {
+ att = new Attribute(attName.toString(), attValue.toString());
+ } else {
+ att = new Attribute(attName.toString(), attNs.toString(), attValue.toString());
+ }
m_elements[m_elements.length - 1].addAttribute(att);
break;
// End of an element
case '}':
Element lastElement = removeLastElement();
- if (m_elements.length != 0) {
+ if (m_elements.length == 0) {
+ addElement(lastElement);
+ } else {
Element newQueue = m_elements[m_elements.length - 1];
newQueue.addElement(lastElement);
- } else {
- addElement(lastElement);
}
break;
@@ -282,19 +276,19 @@
// Default case
default:
- String name = "";
- String ns = "";
- c = string[i];
- while (c != ' ') {
- if (c == ':') {
- ns = name;
- name = "";
+ StringBuffer name = new StringBuffer();
+ StringBuffer namespace = null;
+ current = string[i];
+ while (current != ' ') {
+ if (current == ':') {
+ namespace = name;
+ name = new StringBuffer();
i++;
- c = string[i];
+ current = string[i];
} else {
- name = name + c;
+ name.append(current);
i++;
- c = string[i];
+ current = string[i]; // Increment and get the new current char.
}
}
// Skip spaces
@@ -302,8 +296,15 @@
i = i + 1;
}
i = i + 1; // skip {
- Element elem = new Element(name, ns);
+
+ Element elem = null;
+ if (namespace == null) {
+ elem = new Element(name.toString(), null);
+ } else {
+ elem = new Element(name.toString(), namespace.toString());
+ }
addElement(elem);
+
break;
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
index 1a8b482..302c2d4 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
@@ -18,6 +18,8 @@
*/
package org.apache.felix.ipojo.parser;
+import java.lang.reflect.Method;
+
import org.apache.felix.ipojo.metadata.Element;
/**
@@ -27,22 +29,22 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class MethodMetadata {
-
+
/**
* Name of the method.
*/
private String m_name;
-
+
/**
* Argument type array.
*/
private String[] m_arguments = new String[0];
-
+
/**
* Returned type.
*/
private String m_return = "void";
-
+
/**
* Constructor.
* @param metadata : method manipulation element.
@@ -50,37 +52,77 @@
MethodMetadata(Element metadata) {
m_name = metadata.getAttribute("name");
String arg = metadata.getAttribute("arguments");
- String rt = metadata.getAttribute("return");
+ String result = metadata.getAttribute("return");
if (arg != null) {
m_arguments = ParseUtils.parseArrays(arg);
}
- if (rt != null) {
- m_return = rt;
+ if (result != null) {
+ m_return = result;
}
}
-
- public String getMethodName() { return m_name; }
-
- public String[] getMethodArguments() { return m_arguments; }
-
- public String getMethodReturn() { return m_return; }
-
+
+ public String getMethodName() {
+ return m_name;
+ }
+
+ public String[] getMethodArguments() {
+ return m_arguments;
+ }
+
+ public String getMethodReturn() {
+ return m_return;
+ }
+
/**
* Get the method unique identifier. For internal usage only.
* @return the method identifier.
*/
public String getMethodIdentifier() {
- String id = m_name;
+ StringBuffer identifier = new StringBuffer(m_name);
for (int i = 0; i < m_arguments.length; i++) {
- String cn = m_arguments[i];
- if (cn.endsWith("[]")) {
- cn = cn.replace('[', '$');
- cn = cn.substring(0, cn.length() - 1);
+ String arg = m_arguments[i];
+ identifier.append('$');
+ if (arg.endsWith("[]")) {
+ arg = arg.substring(0, arg.length() - 2);
+ identifier.append(arg.replace('.', '_'));
+ identifier.append("__"); // Replace [] by __
+ } else {
+ identifier.append(arg.replace('.', '_'));
}
- cn = cn.replace('.', '_');
- id += cn;
}
- return id;
+ return identifier.toString();
+ }
+
+ /**
+ * Compute the method id for the given method.
+ * @param method : Method object.
+ * @return the method id.
+ */
+ public static String computeMethodId(Method method) {
+ StringBuffer identifier = new StringBuffer(method.getName());
+ Class[] args = method.getParameterTypes();
+ for (int i = 0; i < args.length; i++) {
+ identifier.append('$'); // Argument separator.
+ if (args[i].isArray()) {
+ if (args[i].getComponentType().isPrimitive()) {
+ // Primitive array
+ identifier.append(FieldMetadata.getPrimitiveTypeByClass(args[i].getComponentType()));
+ } else {
+ // Object array
+ identifier.append(args[i].getComponentType().getName().replace('.', '_')); // Replace '.' by '_'
+ }
+ identifier.append("__"); // Add __ (array)
+ } else {
+ if (args[i].isPrimitive()) {
+ // Primitive type
+ identifier.append(FieldMetadata.getPrimitiveTypeByClass(args[i]));
+ } else {
+ // Object type
+ identifier.append(args[i].getName().replace('.', '_')); // Replace '.' by '_'
+ }
+ }
+ }
+ return identifier.toString();
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ParseUtils.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ParseUtils.java
index 08ceccb..e1597a3 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ParseUtils.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ParseUtils.java
@@ -18,7 +18,7 @@
*/
package org.apache.felix.ipojo.parser;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
@@ -27,7 +27,7 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ParseUtils {
+public final class ParseUtils {
/**
* Parse the string form of an array as {a, b, c}.
@@ -37,18 +37,13 @@
*/
public static String[] parseArrays(String str) {
// Remove { and }
- if (str.startsWith("{") && str.endsWith("}")) {
- String m = str.substring(1, str.length() - 1);
+ if (str.charAt(0) == '{' && str.charAt(str.length() - 1) == '}') {
+ String internal = (str.substring(1, str.length() - 1)).trim();
// Check empty array
- m = m.trim();
- if (m.length() == 0) {
+ if (internal.length() == 0) {
return new String[0];
}
- String[] values = split(m, ",");
- for (int i = 0; i < values.length; i++) {
- values[i] = values[i].trim();
- }
- return values;
+ return split(internal, ",");
} else {
return new String[] { str };
}
@@ -61,40 +56,24 @@
* @return the resulting string array
*/
public static List parseArraysAsList(String str) {
- List result = new ArrayList();
- // Remove { and }
- if (str.startsWith("{") && str.endsWith("}")) {
- String m = str.substring(1, str.length() - 1);
- // Check empty array
- m = m.trim();
- if (m.length() == 0) {
- return result;
- }
- String[] values = split(m, ",");
- for (int i = 0; i < values.length; i++) {
- result.add(values[i].trim());
- }
- return result;
- } else {
- result.add(str);
- return result;
- }
+ return Arrays.asList(parseArrays(str));
}
/**
* Split method.
* This method is equivalent of the String.split in java 1.4
+ * The result array contains 'trimmed' String
* @param toSplit : String to split
* @param separator : separator
* @return the token array
*/
public static String[] split(String toSplit, String separator) {
- StringTokenizer st = new StringTokenizer(toSplit, separator);
- String[] result = new String[st.countTokens()];
- int i = 0;
- while (st.hasMoreElements()) {
- result[i] = st.nextToken();
- i++;
+ StringTokenizer tokenizer = new StringTokenizer(toSplit, separator);
+ String[] result = new String[tokenizer.countTokens()];
+ int index = 0;
+ while (tokenizer.hasMoreElements()) {
+ result[index] = tokenizer.nextToken().trim();
+ index++;
}
return result;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManipulationMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.java
similarity index 82%
rename from ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManipulationMetadata.java
rename to ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.java
index 3d08854..ee8c6fc 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManipulationMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.java
@@ -26,7 +26,7 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ManipulationMetadata {
+public class PojoMetadata {
/**
* List of implemented interfaces.
@@ -55,21 +55,21 @@
* parsing manipulation metadata.
* @param metadata : component type metadata
*/
- public ManipulationMetadata(Element metadata) {
+ public PojoMetadata(Element metadata) {
Element manip = metadata.getElements("manipulation", "")[0];
m_super = manip.getAttribute("super");
Element[] fields = manip.getElements("field");
- for (int i = 0; i < fields.length; i++) {
- FieldMetadata fm = new FieldMetadata(fields[i]);
- addField(fm);
+ for (int i = 0; fields != null && i < fields.length; i++) {
+ FieldMetadata field = new FieldMetadata(fields[i]);
+ addField(field);
}
Element[] methods = manip.getElements("method");
- for (int i = 0; i < methods.length; i++) {
- MethodMetadata fm = new MethodMetadata(methods[i]);
- addMethod(fm);
+ for (int i = 0; methods != null && i < methods.length; i++) {
+ MethodMetadata method = new MethodMetadata(methods[i]);
+ addMethod(method);
}
Element[] itfs = manip.getElements("interface");
- for (int i = 0; i < itfs.length; i++) {
+ for (int i = 0; itfs != null && i < itfs.length; i++) {
addInterface(itfs[i].getAttribute("name"));
}
}
@@ -167,13 +167,13 @@
public MethodMetadata getMethod(String name, String[] types) {
for (int i = 0; i < m_methods.length; i++) {
if (m_methods[i].getMethodName().equalsIgnoreCase(name) && m_methods[i].getMethodArguments().length == types.length) {
- boolean ok = true;
- for (int j = 0; ok && j < types.length; j++) {
- if (! types[j].equals(m_methods[i].getMethodArguments()[j])) {
- ok = false;
+ int argIndex = 0;
+ for (; argIndex < types.length; argIndex++) {
+ if (! types[argIndex].equals(m_methods[i].getMethodArguments()[argIndex])) {
+ break;
}
}
- if (ok) { return m_methods[i]; }
+ if (argIndex == types.length) { return m_methods[i]; } // No mismatch detected.
}
}
return null;
@@ -181,11 +181,11 @@
/**
* Add a method to the list.
- * @param mm : Method Metadata to add.
+ * @param method : Method Metadata to add.
*/
- private void addMethod(MethodMetadata mm) {
+ private void addMethod(MethodMetadata method) {
for (int i = 0; (m_methods != null) && (i < m_methods.length); i++) {
- if (m_methods[i] == mm) {
+ if (m_methods[i] == method) {
return;
}
}
@@ -193,20 +193,20 @@
if (m_methods.length > 0) {
MethodMetadata[] newInstances = new MethodMetadata[m_methods.length + 1];
System.arraycopy(m_methods, 0, newInstances, 0, m_methods.length);
- newInstances[m_methods.length] = mm;
+ newInstances[m_methods.length] = method;
m_methods = newInstances;
} else {
- m_methods = new MethodMetadata[] { mm };
+ m_methods = new MethodMetadata[] { method };
}
}
/**
* Add a field to the list.
- * @param mm : the Field Metadata to add.
+ * @param field : the Field Metadata to add.
*/
- private void addField(FieldMetadata mm) {
+ private void addField(FieldMetadata field) {
for (int i = 0; (m_fields != null) && (i < m_fields.length); i++) {
- if (m_fields[i] == mm) {
+ if (m_fields[i] == field) {
return;
}
}
@@ -214,20 +214,20 @@
if (m_fields.length > 0) {
FieldMetadata[] newInstances = new FieldMetadata[m_fields.length + 1];
System.arraycopy(m_fields, 0, newInstances, 0, m_fields.length);
- newInstances[m_fields.length] = mm;
+ newInstances[m_fields.length] = field;
m_fields = newInstances;
} else {
- m_fields = new FieldMetadata[] { mm };
+ m_fields = new FieldMetadata[] { field };
}
}
/**
* Add the interface to the list.
- * @param mm : the interface name to add.
+ * @param itf : the interface name to add.
*/
- private void addInterface(String mm) {
+ private void addInterface(String itf) {
for (int i = 0; (m_interfaces != null) && (i < m_interfaces.length); i++) {
- if (m_interfaces[i] == mm) {
+ if (m_interfaces[i] == itf) {
return;
}
}
@@ -235,10 +235,10 @@
if (m_interfaces.length > 0) {
String[] newInstances = new String[m_interfaces.length + 1];
System.arraycopy(m_interfaces, 0, newInstances, 0, m_interfaces.length);
- newInstances[m_interfaces.length] = mm;
+ newInstances[m_interfaces.length] = itf;
m_interfaces = newInstances;
} else {
- m_interfaces = new String[] { mm };
+ m_interfaces = new String[] { itf };
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java
index f19373c..a17326d 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java
@@ -22,15 +22,15 @@
import java.lang.reflect.Method;
import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.parser.FieldMetadata;
import org.apache.felix.ipojo.parser.MethodMetadata;
/**
* A callback allows calling a method on the component instances.
- *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class Callback {
-
+
/**
* Method object.
*/
@@ -50,7 +50,7 @@
* Reference on the instance manager.
*/
private InstanceManager m_manager;
-
+
/**
* Argument classes.
*/
@@ -58,193 +58,112 @@
/**
* Callback constructor.
- *
* @param method : the name of the method to call
* @param args : argument type name
* @param isStatic : is the method a static method
- * @param im : the instance manager of the component containing the method
+ * @param manager : the instance manager of the component containing the method
*/
- public Callback(String method, String[] args, boolean isStatic, InstanceManager im) {
+ public Callback(String method, String[] args, boolean isStatic, InstanceManager manager) {
m_method = method;
m_isStatic = isStatic;
- m_manager = im;
+ m_manager = manager;
if (args != null) {
- m_args = new String[args.length];
- for (int i = 0; i < args.length; i++) {
- // Primitive Array
- if (args[i].endsWith("[]") && args[i].indexOf(".") == -1) {
- String arr = "";
- for (int j = 0; j < args[i].length(); j++) {
- if (args[i].charAt(j) == '[') { arr += '['; }
- }
- int index = args[i].indexOf('[');
- m_args[i] = arr + getInternalPrimitiveType(args[i].substring(0, index));
- }
- // Non-Primitive Array
- if (args[i].endsWith("[]") && args[i].indexOf(".") != -1) {
- String arr = "";
- for (int j = 0; j < args[i].length(); j++) {
- if (args[i].charAt(j) == '[') { arr += '['; }
- }
- int index = args[i].indexOf('[');
- m_args[i] = arr + "L" + args[i].substring(0, index) + ";";
- }
- // Simple type
- if (!args[i].endsWith("[]")) {
- m_args[i] = args[i];
- }
- }
+ computeArguments(args);
}
-
}
-
+
/**
* Callback constructor.
- *
* @param method : the name of the method to call
* @param args : argument classes
* @param isStatic : is the method a static method
- * @param im : the instance manager of the component containing the method
+ * @param manager : the instance manager of the component containing the method
*/
- public Callback(String method, Class[] args, boolean isStatic, InstanceManager im) {
+ public Callback(String method, Class[] args, boolean isStatic, InstanceManager manager) {
m_method = method;
m_isStatic = isStatic;
- m_manager = im;
+ m_manager = manager;
m_args = new String[args.length];
for (int i = 0; i < args.length; i++) {
m_args[i] = args[i].getName();
}
}
-
+
/**
* Constructor.
- * @param mm : Method Metadata obtain form manipulation metadata.
- * @param im : instance manager.
+ * @param method : Method Metadata obtain form manipulation metadata.
+ * @param manager : instance manager.
*/
- public Callback(MethodMetadata mm, InstanceManager im) {
+ public Callback(MethodMetadata method, InstanceManager manager) {
m_isStatic = false;
- m_method = mm.getMethodName();
- m_manager = im;
- String[] args = mm.getMethodArguments();
+ m_method = method.getMethodName();
+ m_manager = manager;
+ computeArguments(method.getMethodArguments());
+ }
+
+ /**
+ * Compute arguments of the method.
+ * @param args : arguments of the method.
+ */
+ private void computeArguments(String[] args) {
m_args = new String[args.length];
for (int i = 0; i < args.length; i++) {
- // Primitive Array
- if (args[i].endsWith("[]") && args[i].indexOf(".") == -1) {
- String arr = "";
- for (int j = 0; j < args[i].length(); j++) {
- if (args[i].charAt(j) == '[') { arr += '['; }
- }
- int index = args[i].indexOf('[');
- m_args[i] = arr + getInternalPrimitiveType(args[i].substring(0, index));
- }
- // Non-Primitive Array
- if (args[i].endsWith("[]") && args[i].indexOf(".") != -1) {
- String arr = "";
- for (int j = 0; j < args[i].length(); j++) {
- if (args[i].charAt(j) == '[') { arr += '['; }
- }
- int index = args[i].indexOf('[');
- m_args[i] = arr + "L" + args[i].substring(0, index) + ";";
- }
- // Simple type
- if (!args[i].endsWith("[]")) {
- m_args[i] = args[i];
- }
+ m_args[i] = FieldMetadata.getReflectionType(args[i]);
}
}
/**
- * Get the internal notation for primitive type.
- * @param string : Stringform of the type
- * @return the internal notation or null if not found
+ * Search the looked method in the given method arrays.
+ * @param methods : method array in which we need to look
+ * @return the method object or null if not found
*/
- private String getInternalPrimitiveType(String string) {
- if (string.equalsIgnoreCase("boolean")) {
- return "Z";
- }
- if (string.equalsIgnoreCase("char")) {
- return "C";
- }
- if (string.equalsIgnoreCase("byte")) {
- return "B";
- }
- if (string.equalsIgnoreCase("short")) {
- return "S";
- }
- if (string.equalsIgnoreCase("int")) {
- return "I";
- }
- if (string.equalsIgnoreCase("float")) {
- return "F";
- }
- if (string.equalsIgnoreCase("long")) {
- return "J";
- }
- if (string.equalsIgnoreCase("double")) {
- return "D";
- }
- return null;
- }
-
- /**
- * Search the method object in the POJO by analyzing present method.
- * The name of the method and the argument type are checked.
- */
- protected void searchMethod() {
- Method[] methods = m_manager.getClazz().getDeclaredMethods();
- for (int i = 0; m_methodObj == null && i < methods.length; i++) {
+ private Method searchMethodInMethodArray(Method[] methods) {
+ for (int i = 0; i < methods.length; i++) {
// First check the method name
if (methods[i].getName().equals(m_method)) {
// Check arguments
Class[] clazzes = methods[i].getParameterTypes();
if (clazzes.length == m_args.length) { // Test size to avoid useless loop
- boolean ok = true;
- for (int j = 0; ok && j < m_args.length; j++) {
- if (!m_args[j].equals(clazzes[j].getName())) {
- ok = false;
+ int argIndex = 0;
+ for (; argIndex < m_args.length; argIndex++) {
+ if (!m_args[argIndex].equals(clazzes[argIndex].getName())) {
+ break;
}
}
- if (ok) {
- m_methodObj = methods[i]; // It is the looked method.
- }
+ if (argIndex == m_args.length) { // No mismatch detected.
+ return methods[i]; // It is the looked method.
+ }
}
+ }
+ }
+ return null;
+ }
- }
- }
-
- if (m_methodObj == null) { //look at parent classes
+ /**
+ * Search the method object in the POJO by analyzing present method. The name of the method and the argument type are checked.
+ * @throws NoSuchMethodException : occurs when the method cannot be found either in the pojo class either in parent classes.
+ */
+ protected void searchMethod() throws NoSuchMethodException {
+ Method[] methods = m_manager.getClazz().getDeclaredMethods();
+ m_methodObj = searchMethodInMethodArray(methods);
+
+ if (m_methodObj == null) { // look at parent classes
methods = m_manager.getClazz().getMethods();
- for (int i = 0; m_methodObj == null && i < methods.length; i++) {
- // First check the method name
- if (methods[i].getName().equals(m_method)) {
- // Check arguments
- Class[] clazzes = methods[i].getParameterTypes();
- if (clazzes.length == m_args.length) { // Test size to avoid useless loop
- boolean ok = true;
- for (int j = 0; ok && j < m_args.length; j++) {
- if (!m_args[j].equals(clazzes[j].getName())) {
- ok = false;
- }
- }
- if (ok) {
- m_methodObj = methods[i]; // It is the looked method.
- }
- }
- }
- }
+ m_methodObj = searchMethodInMethodArray(methods);
}
-
+
if (m_methodObj == null) {
- m_manager.getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " cannot be called : method not found");
- m_manager.stop();
+ throw new NoSuchMethodException(m_method);
} else {
- m_methodObj.setAccessible(true);
+ if (! m_methodObj.isAccessible()) {
+ // If not accessible, try to set the accessibility.
+ m_methodObj.setAccessible(true);
+ }
}
}
/**
* Call the method.
- *
* @return the result of the invocation, null for void method, the last result for multi-object instance
* @throws NoSuchMethodException : Method is not found in the class
* @throws InvocationTargetException : The method is not static
@@ -256,7 +175,6 @@
/**
* Call the current callback method on the instance given in parameter.
- *
* @param instance : instance on which call the callback
* @return the result of the invocation, null for void method
* @throws NoSuchMethodException : the method was not found
@@ -269,19 +187,17 @@
/**
* Call the callback on the method with the argument given in parameter.
- *
* @param arg : the parameters
* @return the result of the invocation, null for void method, the last result for multi-object instance
* @throws NoSuchMethodException : the callback method is not found
* @throws IllegalAccessException : the callback method cannot be called
- * @throws InvocationTargetException : an error occurs inside the called
- * method
+ * @throws InvocationTargetException : an error occurs inside the called method
*/
public Object call(Object[] arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
if (m_methodObj == null) {
searchMethod();
}
-
+
if (m_isStatic) {
return m_methodObj.invoke(null, arg);
} else {
@@ -291,35 +207,32 @@
if (m_manager.getPojoObjects() == null) {
return m_methodObj.invoke(m_manager.getPojoObject(), arg);
} else {
- Object r = null;
+ Object newObject = null;
for (int i = 0; i < m_manager.getPojoObjects().length; i++) {
- r = m_methodObj.invoke(m_manager.getPojoObjects()[i], arg);
+ newObject = m_methodObj.invoke(m_manager.getPojoObjects()[i], arg);
}
- return r;
+ return newObject;
}
}
}
/**
- * Call the callback on the method with the argument given in parameter and
- * with the arguments given in parameter too.
- *
+ * Call the callback on the method with the argument given in parameter and with the arguments given in parameter too.
* @param instance : instance on which call the callback
* @param arg : the argument array
* @return the result of the invocation, null for void method
* @throws NoSuchMethodException : the callback method is not found
* @throws IllegalAccessException : the callback method cannot be called
- * @throws InvocationTargetException : an error occurs inside the called
- * method
+ * @throws InvocationTargetException : an error occurs inside the called method
*/
public Object call(Object instance, Object[] arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
if (m_methodObj == null) {
searchMethod();
}
-
+
return m_methodObj.invoke(instance, arg);
}
-
+
public String getMethod() {
return m_method;
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
new file mode 100644
index 0000000..d644805
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
@@ -0,0 +1,792 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Abstract dependency model. This class is the parent class of every service dependency. It manages the most part of dependency management. This
+ * class creates an insterface between the service tracker and the concrete dependency.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class DependencyModel implements TrackerCustomizer {
+
+ /**
+ * Dependency state : BROKEN. A broken dependency cannot be fulfilled anymore. The dependency becomes broken when a used service disappears in the
+ * static binding policy.
+ */
+ public static final int BROKEN = -1;
+
+ /**
+ * Dependency state : UNRESOLVED. A dependency is unresolved if the dependency is not valid and no service providers are available.
+ */
+ public static final int UNRESOLVED = 0;
+
+ /**
+ * Dependency state : RESOLVED. A dependency is resolved if the dependency is optional or at least one provider is available.
+ */
+ public static final int RESOLVED = 1;
+
+ /**
+ * Binding policy : Dynamic. In this policy, services can appears and departs without special treatment.
+ */
+ public static final int DYNAMIC_BINDING_POLICY = 0;
+
+ /**
+ * Binding policy : Static. Once a service is used, if this service disappears the dependency becomes BROKEN. The instance needs to be recreated.
+ */
+ public static final int STATIC_BINDING_POLICY = 1;
+
+ /**
+ * Binding policy : Dynamic-Priority. In this policy, services can appears and departs. However, once a service with a highest ranking (according
+ * to the used comparator) appears, this new service is re-injected.
+ */
+ public static final int DYNAMIC_PRIORITY_BINDING_POLICY = 2;
+
+ /**
+ * Does the dependency bind several providers ?
+ */
+ private boolean m_aggregate;
+
+ /**
+ * Is the dependency optional ?
+ */
+ private boolean m_optional;
+
+ /**
+ * Required specification. Cannot change once set.
+ */
+ private Class m_specification;
+
+ /**
+ * Comparator to sort service references.
+ */
+ private Comparator m_comparator;
+
+ /**
+ * LDAP filter object selecting service references form the set of providers providing the required specification.
+ */
+ private Filter m_filter;
+
+ /**
+ * Bundle context used by the dependency. (could be a service context).
+ */
+ private BundleContext m_context;
+
+ /**
+ * Listener object on which invoking the validate and invalidate methods.
+ */
+ private final DependencyStateListener m_listener;
+
+ /**
+ * Actual state of the dependency.
+ */
+ private int m_state;
+
+ /**
+ * Binding policy of the dependency.
+ */
+ private int m_policy = DYNAMIC_BINDING_POLICY; // Is notas we have to handler policy change in a future version.
+
+ /**
+ * Service tracker used by this dependency.
+ */
+ private Tracker m_tracker;
+
+ /**
+ * List of matching service references. This list is a subset of tracked references. This set is compute according to the filter and the match
+ * method.
+ */
+ private final List m_matchingRefs = new ArrayList();
+
+ /**
+ * Constructor.
+ * @param specification : required specification
+ * @param aggregate : is the dependency aggregate ?
+ * @param optional : is the dependency optional ?
+ * @param filter : LDAP filter
+ * @param comparator : comparator object to sort references
+ * @param policy : binding policy
+ * @param context : bundle context (or service context)
+ * @param listener : dependency lifecycle listener to notify from dependency state changes.
+ */
+ public DependencyModel(Class specification, boolean aggregate, boolean optional, Filter filter, Comparator comparator, int policy,
+ BundleContext context, DependencyStateListener listener) {
+ m_specification = specification;
+ m_aggregate = aggregate;
+ m_optional = optional;
+ m_filter = filter;
+ m_comparator = comparator;
+ m_context = context;
+ m_policy = policy;
+ // If the dynamic priority policy is chosen, and we have no comparator, fix it to OSGi standard service reference comparator.
+ if (m_policy == DYNAMIC_PRIORITY_BINDING_POLICY && m_comparator == null) {
+ m_comparator = new ServiceReferenceRankingComparator();
+ }
+ m_state = UNRESOLVED;
+ m_listener = listener;
+ }
+
+ /**
+ * Open the tracking.
+ */
+ public void start() {
+ m_tracker = new Tracker(m_context, m_specification.getName(), this);
+ m_tracker.open();
+ computeDependencyState();
+ }
+
+ /**
+ * Close the tracking.
+ */
+ public void stop() {
+ if (m_tracker != null) {
+ m_tracker.close();
+ m_tracker = null;
+ }
+ m_state = UNRESOLVED;
+ }
+
+ /**
+ * Is the reference set frozen (cannot change anymore) ? This method must be override by concrete dependency to support the static binding policy.
+ * This method is just used by default. The method must always return false for non-static dependency.
+ * @return true if the reference set is frozen.
+ */
+ public boolean isFrozen() {
+ return false;
+ }
+
+ /**
+ * Does the service reference match ? This method must be override by concrete dependency if they need to advanced testing on service reference
+ * (that cannot be express in the LDAP filter). By default this method return true.
+ * @param ref : tested reference.
+ * @return true
+ */
+ public boolean match(ServiceReference ref) {
+ return true;
+ }
+
+ /**
+ * Compute the actual dependency state.
+ */
+ private void computeDependencyState() {
+ if (m_state == BROKEN) { return; } // The dependency is broken ...
+
+ boolean mustCallValidate = false;
+ boolean mustCallInvalidate = false;
+ synchronized (this) {
+ if (m_optional || !m_matchingRefs.isEmpty()) {
+ // The dependency is valid
+ if (m_state == UNRESOLVED) {
+ m_state = RESOLVED;
+ mustCallValidate = true;
+ }
+ } else {
+ // The dependency is invalid
+ if (m_state == RESOLVED) {
+ m_state = UNRESOLVED;
+ mustCallInvalidate = true;
+ }
+ }
+ }
+
+ // Invoke callback in a non-synchronized region
+ if (mustCallInvalidate) {
+ invalidate();
+ } else if (mustCallValidate) {
+ validate();
+ }
+
+ }
+
+ /**
+ * Service tracker adding service callback. We accept the service only if we aren't broken or frozen.
+ * @param ref : the new dependency.
+ * @return true if the reference must be tracked.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
+ */
+ public boolean addingService(ServiceReference ref) {
+ return !((m_state == BROKEN) || isFrozen());
+ }
+
+ /**
+ * Service Tracker added service callback. If the service matches, manage the arrival.
+ * @param ref : new references.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+ */
+ public void addedService(ServiceReference ref) {
+ if ((m_filter == null || m_filter.match(ref)) && match(ref)) {
+ manageArrival(ref);
+ }
+ // Do not store the service if it doesn't match.
+ }
+
+ /**
+ * Manage the arrival of a new service reference. The reference is valid and match the filter and the match method. This method has different
+ * behavior according to the binding policy.
+ * @param ref : the new reference
+ */
+ private void manageArrival(ServiceReference ref) {
+
+ // Create a local copy of the state and of the list size.
+ int state = m_state;
+ int size;
+
+ synchronized (this) {
+ m_matchingRefs.add(ref);
+
+ // Sort the collection if needed.
+ if (m_comparator != null) {
+ Collections.sort(m_matchingRefs, m_comparator);
+ }
+
+ size = m_matchingRefs.size();
+ }
+
+ if (m_aggregate) {
+ onServiceArrival(ref); // Always notify the arrival for aggregate dependencies.
+ if (state == UNRESOLVED) { // If we was unresolved, try to validate the dependency.
+ computeDependencyState();
+ }
+ } else { // We are not aggregate.
+ if (size == 1) {
+ onServiceArrival(ref); // It is the first service, so notify.
+ computeDependencyState();
+ } else {
+ // In the case of a dynamic priority binding, we have to test if we have to update the bound reference
+ if (m_policy == DYNAMIC_PRIORITY_BINDING_POLICY && m_matchingRefs.get(0) == ref) {
+ // We are sure that we have at least two references, so if the highest ranked references (first one) is the new received
+ // references,
+ // we have to unbind the used one and to bind the the new one.
+ onServiceDeparture((ServiceReference) m_matchingRefs.get(1));
+ onServiceArrival(ref);
+ }
+ }
+ }
+ // Ignore others cases
+ }
+
+ /**
+ * Service tracker removed service callback. A service goes away. The depart need to be managed only if the reference was used.
+ * @param ref : leaving service reference
+ * @param arg1 : service object if the service was get
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+ */
+ public void removedService(ServiceReference ref, Object arg1) {
+ if (m_matchingRefs.contains(ref)) {
+ manageDeparture(ref, arg1);
+ }
+ }
+
+ /**
+ * Manage the departure of a used service.
+ * @param ref : leaving service reference
+ * @param obj : service object if the service was get
+ */
+ private void manageDeparture(ServiceReference ref, Object obj) {
+ // If we already get this service and the binding policy is static, the dependency becomes broken
+ if (isFrozen() && obj != null) {
+ if (m_state != BROKEN) {
+ m_state = BROKEN;
+ invalidate();
+ }
+ } else {
+ synchronized (this) {
+ m_matchingRefs.remove(ref);
+ }
+ if (obj == null) {
+ computeDependencyState(); // check if the dependency stills valid.
+ } else {
+ onServiceDeparture(ref);
+ ServiceReference newRef = getServiceReference();
+ if (newRef == null) { // Check if there is another provider.
+ computeDependencyState(); // no more references.
+ } else {
+ if (!m_aggregate) {
+ onServiceArrival(newRef); // Injecting the new service reference for non aggregate dependencies.
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Service tracker modified service callback. This method must handle if the modified service should be considered as a depart or an arrival.
+ * According to the dependency filter, a service can now match or can no match anymore.
+ * @param ref : modified reference
+ * @param arg1 : service object if already get.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
+ */
+ public void modifiedService(ServiceReference ref, Object arg1) {
+ if (m_matchingRefs.contains(ref)) {
+ // It's a used service. Check if the service always match.
+ if (!(m_filter == null || m_filter.match(ref)) && match(ref)) {
+ // The service does not match anymore. Call removedService.
+ manageDeparture(ref, arg1);
+ } else {
+ onServiceModification(ref);
+ }
+ } else {
+ // The service was not used. Check if it matches.
+ if ((m_filter == null || m_filter.match(ref)) && match(ref)) {
+ manageArrival(ref);
+ }
+ // Else, the service does not match.
+ }
+ }
+
+ /**
+ * Get the next matching service reference.
+ * @return null if no more provider is available, else return the first reference from the matching set.
+ */
+ public ServiceReference getServiceReference() {
+ synchronized (this) {
+ if (m_matchingRefs.isEmpty()) {
+ return null;
+ } else {
+ return (ServiceReference) m_matchingRefs.get(0);
+ }
+ }
+ }
+
+ /**
+ * Get matching service references.
+ * @return the sorted (if a comparator is used) array of matching service references, null if no references are available.
+ */
+ public ServiceReference[] getServiceReferences() {
+ synchronized (this) {
+ if (m_matchingRefs.isEmpty()) { return null; }
+ return (ServiceReference[]) m_matchingRefs.toArray(new ServiceReference[m_matchingRefs.size()]);
+ }
+ }
+
+ /**
+ * Get the list of currently used service references.
+ * @return the list of used reference (according to the service tracker).
+ */
+ public List getUsedServiceReferences() {
+ synchronized (this) {
+ // The list must confront actual matching services with already get services from the tracker.
+
+ int size = m_matchingRefs.size();
+ List usedByTracker = m_tracker.getUsedServiceReferences();
+ if (size == 0 || usedByTracker == null) { return null; }
+
+ List list = new ArrayList(1);
+ for (int i = 0; i < size; i++) {
+ if (usedByTracker.contains(m_matchingRefs.get(i))) {
+ list.add(m_matchingRefs.get(i)); // Add the service in the list.
+ if (!isAggregate()) { // IF we are not multiple, return the list when the first element is found.
+ return list;
+ }
+ }
+ }
+
+ return list;
+ }
+ }
+
+ /**
+ * Get the number of actual matching references.
+ * @return the number of matching references
+ */
+ public int getSize() {
+ return m_matchingRefs.size();
+ }
+
+ /**
+ * Concrete dependency callback. This method is called when a new service need to be re-injected in the underlying concrete dependency.
+ * @param ref : service reference to inject.
+ */
+ public abstract void onServiceArrival(ServiceReference ref);
+
+ /**
+ * Concrete dependency callback. This method is called when a used service (already injected) is leaving.
+ * @param ref : the leaving service reference.
+ */
+ public abstract void onServiceDeparture(ServiceReference ref);
+
+ /**
+ * This method can be override by the concrete dependency to be notified of service modification. This modification is not an arrival or a
+ * departure.
+ * @param ref : modified service reference.
+ */
+ public void onServiceModification(ServiceReference ref) {
+ // Do nothing by default.
+ }
+
+ /**
+ * Concrete dependency callback. This method is called when the dependency is reconfigured and when this reconfiguration implies changes on the
+ * matching service set ( and by the way on the injected service).
+ * @param departs : service leaving the matching set.
+ * @param arrivals : service arriving in the matching set.
+ */
+ public abstract void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals);
+
+ /**
+ * Call the listener callback to notify the new state of the current dependency.
+ */
+ private void invalidate() {
+ m_listener.invalidate(this);
+ }
+
+ /**
+ * Call the listener callback to notify the new state of the current dependency.
+ */
+ private void validate() {
+ m_listener.validate(this);
+ }
+
+ /**
+ * Get the actual state of the dependency.
+ * @return : the state of the dependency.
+ */
+ public int getState() {
+ return m_state;
+ }
+
+ /**
+ * Get the tracked specification.
+ * @return the Class object tracked by the dependency.
+ */
+ public Class getSpecification() {
+ return m_specification;
+ }
+
+ /**
+ * Set the required specification of this service dependency. This operation is not supported if the dependency tracking has already begun.
+ * @param specification : required specification.
+ */
+ public void setSpecification(Class specification) {
+ if (m_tracker == null) {
+ m_specification = specification;
+ } else {
+ throw new UnsupportedOperationException("Dynamic specification change is not yet supported");
+ }
+ }
+
+ /**
+ * Set the filter of the dependency. This method recompute the matching set and call the onDependencyReconfiguration callback.
+ * @param filter : new LDAP filter.
+ */
+ public void setFilter(Filter filter) { //NOPMD
+ m_filter = filter;
+ if (m_tracker != null) { // Tracking started ...
+ List toRemove = new ArrayList();
+ List toAdd = new ArrayList();
+ ServiceReference usedRef = null;
+ synchronized (this) {
+
+ // Store the used service references.
+ if (!m_aggregate && !m_matchingRefs.isEmpty()) {
+ usedRef = (ServiceReference) m_matchingRefs.get(0);
+ }
+
+ // Get actually all tracked references.
+ ServiceReference[] refs = m_tracker.getServiceReferences();
+
+ if (refs == null) {
+ for (int j = 0; j < m_matchingRefs.size(); j++) {
+ // All references need to be removed.
+ toRemove.add(m_matchingRefs.get(j));
+ }
+ // No more matching dependency. Clear the matching reference set.
+ m_matchingRefs.clear();
+ } else {
+ // Compute matching services.
+ List matching = new ArrayList();
+ for (int i = 0; i < refs.length; i++) {
+ if (m_filter == null || m_filter.match(refs[i]) && match(refs[i])) {
+ matching.add(refs[i]);
+ }
+ }
+ // Now compare with used services.
+ for (int j = 0; j < m_matchingRefs.size(); j++) {
+ ServiceReference ref = (ServiceReference) m_matchingRefs.get(j);
+ // Check if the reference is inside the matching list:
+ if (!matching.contains(ref)) {
+ // The reference should be removed
+ toRemove.add(ref);
+ }
+ }
+
+ // Then remove services which do no more match.
+ m_matchingRefs.removeAll(toRemove);
+
+ // Then, add new matching services.
+
+ for (int k = 0; k < matching.size(); k++) {
+ if (!m_matchingRefs.contains(matching.get(k))) {
+ m_matchingRefs.add(matching.get(k));
+ toAdd.add(matching.get(k));
+ }
+ }
+
+ // Sort the collections if needed.
+ if (m_comparator != null) {
+ Collections.sort(m_matchingRefs, m_comparator);
+ Collections.sort(toAdd, m_comparator);
+ Collections.sort(toRemove, m_comparator);
+ }
+
+ }
+ }
+
+ // Call the callback outside the sync bloc.
+ if (m_aggregate) {
+ ServiceReference[] rem = null;
+ ServiceReference[] add = null;
+ if (!toAdd.isEmpty()) {
+ add = (ServiceReference[]) toAdd.toArray(new ServiceReference[toAdd.size()]);
+ }
+ if (!toRemove.isEmpty()) {
+ rem = (ServiceReference[]) toRemove.toArray(new ServiceReference[toRemove.size()]);
+ }
+ if (rem != null || add != null) { // Notify the change only when a change is made on the matching reference list.
+ onDependencyReconfiguration(rem, add);
+ }
+ } else {
+ // Create a local copy to avoid un-sync reference list access.
+ int size;
+ ServiceReference newRef = null;
+ synchronized (m_matchingRefs) {
+ size = m_matchingRefs.size();
+ if (size > 0) {
+ newRef = (ServiceReference) m_matchingRefs.get(0);
+ }
+ }
+ // Non aggregate case.
+ // If the used reference was not null
+ if (usedRef == null) {
+ // The used ref was null,
+ if (size > 0) {
+ onDependencyReconfiguration(null, new ServiceReference[] { newRef });
+ } // Don't notify the change, if the set is not touched by the reconfiguration.
+ } else {
+ // If the used ref disappears, inject a new service if available, else reinject null.
+ if (toRemove.contains(usedRef)) {
+ // We have to replace the service.
+ if (size > 0) {
+ onDependencyReconfiguration(new ServiceReference[] { usedRef }, new ServiceReference[] { newRef });
+ } else {
+ onDependencyReconfiguration(new ServiceReference[] { usedRef }, null);
+ }
+ } else if (m_policy == DYNAMIC_PRIORITY_BINDING_POLICY && newRef != usedRef) { //NOPMD
+ // In the case of dynamic-priority, check if the used ref is no more the highest reference
+ onDependencyReconfiguration(new ServiceReference[] { usedRef }, new ServiceReference[] { newRef });
+ }
+ }
+ }
+ // Now, compute the new dependency state.
+ computeDependencyState();
+ }
+ }
+
+ /**
+ * Return the dependency filter (String form).
+ * @return the String form of the LDAP filter used by this dependency, null if not set.
+ */
+ public String getFilter() {
+ if (m_filter == null) {
+ return null;
+ } else {
+ return m_filter.toString();
+ }
+ }
+
+ /**
+ * Set the aggregate attribute of the current dependency. If the tracking is open, it will call arrival and departure callbacks.
+ * @param isAggregate : new aggregate attribute value.
+ */
+ public synchronized void setAggregate(boolean isAggregate) {
+ if (m_tracker == null) { // Not started ...
+ m_aggregate = isAggregate;
+ } else {
+ // We become aggregate.
+ if (!m_aggregate && isAggregate) {
+ m_aggregate = true;
+ // Call the callback on all non already injected service.
+ if (m_state == RESOLVED) {
+
+ for (int i = 1; i < m_matchingRefs.size(); i++) { // The loop begin at 1, as the 0 is already injected.
+ onServiceArrival((ServiceReference) m_matchingRefs.get(i));
+ }
+ }
+ } else if (m_aggregate && !isAggregate) {
+ m_aggregate = false;
+ // We become non-aggregate.
+ if (m_state == RESOLVED) {
+ for (int i = 1; i < m_matchingRefs.size(); i++) { // The loop begin at 1, as the 0 stills injected.
+ onServiceDeparture((ServiceReference) m_matchingRefs.get(i));
+ }
+ }
+ }
+ // Else, do nothing.
+ }
+ }
+
+ public boolean isAggregate() {
+ return m_aggregate;
+ }
+
+ /**
+ * Set the optionality attribute of the current dependency.
+ * @param isOptional : the new optional attribute value.
+ */
+ public void setOptionality(boolean isOptional) {
+ if (m_tracker == null) { // Not started ...
+ m_optional = isOptional;
+ } else {
+ computeDependencyState();
+ }
+ }
+
+ public boolean isOptional() {
+ return m_optional;
+ }
+
+ /**
+ * Return the used binding policy.
+ * @return the current binding policy.
+ */
+ public int getBindingPolicy() {
+ return m_policy;
+ }
+
+ /**
+ * Set the binding policy. Not yet supported.
+ */
+ public void setBindingPolicy() {
+ throw new UnsupportedOperationException("Binding Policy change is not yet supported");
+ // TODO supporting dynamic policy change.
+ }
+
+ public void setComparator(Comparator cmp) {
+ m_comparator = cmp;
+ // NOTE: the array will be sorted at the next get.
+ }
+
+ /**
+ * Set the bundle context used by this dependency. This operation is not supported if the tracker is already opened.
+ * @param context : bundle context or service context to use
+ */
+ public void setBundleContext(BundleContext context) {
+ if (m_tracker == null) { // Not started ...
+ m_context = context;
+ } else {
+ throw new UnsupportedOperationException("Dynamic bundle (i.e. service) context change is not supported");
+ }
+ }
+
+ /**
+ * Get a service object for the given reference.
+ * @param ref : wanted service reference
+ * @return : the service object attached to the given reference
+ */
+ public Object getService(ServiceReference ref) {
+ return m_tracker.getService(ref);
+ }
+
+ /**
+ * Unget a used service reference.
+ * @param ref : reference to unget.
+ */
+ public void ungetService(ServiceReference ref) {
+ m_tracker.ungetService(ref);
+ }
+
+ /**
+ * Helper method parsing the comparator attribute and returning the comparator object. If the 'comparator' attribute is not set, this method
+ * returns null. If the 'comparator' attribute is set to 'osgi', this method returns the normal OSGi comparator. In other case, it tries to create
+ * an instance of the declared comparator class.
+ * @param dep : Element describing the dependency
+ * @param context : bundle context (to load the comparator class)
+ * @return the comparator object, null if not set.
+ * @throws ConfigurationException the comparator class cannot be load or the comparator cannot be instantiated correctly.
+ */
+ public static Comparator getComparator(Element dep, BundleContext context) throws ConfigurationException {
+ Comparator cmp = null;
+ String comp = dep.getAttribute("comparator");
+ if (comp != null) {
+ if (comp.equalsIgnoreCase("osgi")) {
+ cmp = new ServiceReferenceRankingComparator();
+ } else {
+ try {
+ Class cla = context.getBundle().loadClass(comp);
+ cmp = (Comparator) cla.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("Cannot load a customized comparator : " + e.getMessage());
+ } catch (IllegalAccessException e) {
+ throw new ConfigurationException("Cannot create a customized comparator : " + e.getMessage());
+ } catch (InstantiationException e) {
+ throw new ConfigurationException("Cannot create a customized comparator : " + e.getMessage());
+ }
+ }
+ }
+ return cmp;
+ }
+
+ /**
+ * Load the given specification class.
+ * @param specification : specification class name to load
+ * @param context : bundle context
+ * @return : the class object for the given specification
+ * @throws ConfigurationException : the class cannot be loaded correctly.
+ */
+ public static Class loadSpecification(String specification, BundleContext context) throws ConfigurationException {
+ Class spec = null;
+ try {
+ spec = context.getBundle().loadClass(specification);
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("A required specification cannot be loaded : " + specification);
+ }
+ return spec;
+ }
+
+ /**
+ * Helper method parsing the binding policy. If the 'policy' attribute is not set in the dependency, the method returns the 'DYNAMIC BINDING
+ * POLICY'. Accepted policy values are : dynamic, dynamic-priority and static.
+ * @param dep : Element describing the dependency
+ * @return : the policy attached to this dependency
+ * @throws ConfigurationException : an unknown biding policy was described.
+ */
+ public static int getPolicy(Element dep) throws ConfigurationException {
+ String policy = dep.getAttribute("policy");
+ if (policy == null || policy.equalsIgnoreCase("dynamic")) {
+ return DYNAMIC_BINDING_POLICY;
+ } else if (policy.equalsIgnoreCase("dynamic-priority")) {
+ return DYNAMIC_PRIORITY_BINDING_POLICY;
+ } else if (policy.equalsIgnoreCase("static")) {
+ return STATIC_BINDING_POLICY;
+ } else {
+ throw new ConfigurationException("Binding policy unknown : " + policy);
+ }
+ }
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyStateListener.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyStateListener.java
new file mode 100644
index 0000000..5131337
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyStateListener.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util;
+
+
+/**
+ * This interface allows a class to be notified of dependency state changes.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DependencyStateListener {
+
+ /**
+ * The given dependency becomes valid.
+ * @param dependency : dependency becoming valid.
+ */
+ void validate(DependencyModel dependency);
+
+ /**
+ * The given dependency becomes invalid.
+ * @param dependency : dependency becoming invalid.
+ */
+ void invalidate(DependencyModel dependency);
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
index 30a33a2..c8b8c26 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
@@ -28,6 +28,11 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class Logger {
+
+ /**
+ * Ipojo default log level property.
+ */
+ public static final String IPOJO_LOG_LEVEL = "ipojo.log.level";
/**
* Log Level ERROR.
@@ -67,14 +72,24 @@
/**
* Constructor.
*
- * @param bc : bundle context
+ * @param context : bundle context
* @param name : name of the logger
* @param level : trace level
*/
- public Logger(BundleContext bc, String name, int level) {
+ public Logger(BundleContext context, String name, int level) {
m_name = name;
m_level = level;
- m_context = bc;
+ m_context = context;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param context : bundle context
+ * @param name : name of the logger
+ */
+ public Logger(BundleContext context, String name) {
+ this(context, name, getDefaultLevel(context));
}
/**
@@ -85,7 +100,7 @@
*/
public void log(int level, String msg) {
if (m_level >= level) {
- dispatch(level, msg, null);
+ dispatch(level, msg);
}
}
@@ -94,26 +109,21 @@
*
* @param level : level of the message
* @param msg : message to log
- * @param ex : exception attached to the message
+ * @param exception : exception attached to the message
*/
- public void log(int level, String msg, Throwable ex) {
+ public void log(int level, String msg, Throwable exception) {
if (m_level >= level) {
- dispatch(level, msg, ex);
+ dispatch(level, msg, exception);
}
}
-
+
/**
* Internal log method.
*
* @param level : level of the message.
* @param msg : message to log
- * @param ex : exception attached to the message
*/
- private void dispatch(int level, String msg, Throwable ex) {
- String s = msg;
- if (ex != null) {
- s += " (" + ex.getMessage() + ")";
- }
+ private void dispatch(int level, String msg) {
ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
LogService log = null;
@@ -124,35 +134,35 @@
String message = null;
switch (level) {
case DEBUG:
- message = "[" + m_name + "] DEBUG: " + s;
+ message = "[" + m_name + "] DEBUG: " + msg;
if (log != null) {
log.log(LogService.LOG_DEBUG, message);
}
- System.err.println(message);
+ System.err.println(message); // NOPMD
break;
case ERROR:
- message = "[" + m_name + "] ERROR: " + s;
+ message = "[" + m_name + "] ERROR: " + msg;
if (log != null) {
log.log(LogService.LOG_ERROR, message);
}
- System.err.println(message);
+ System.err.println(message); //NOPMD
break;
case INFO:
- message = "[" + m_name + "] INFO: " + s;
+ message = "[" + m_name + "] INFO: " + msg;
if (log != null) {
log.log(LogService.LOG_INFO, message);
}
- System.err.println(message);
+ System.err.println(message); // NOPMD
break;
case WARNING:
- message = "[" + m_name + "] WARNING: " + s;
+ message = "[" + m_name + "] WARNING: " + msg;
if (log != null) {
log.log(LogService.LOG_WARNING, message);
}
- System.err.println(message);
+ System.err.println(message); // NOPMD
break;
default:
- System.err.println("[" + m_name + "] UNKNOWN[" + level + "]: " + s);
+ System.err.println("[" + m_name + "] UNKNOWN[" + level + "]: " + msg); // NOPMD
break;
}
@@ -160,4 +170,98 @@
m_context.ungetService(ref);
}
}
+
+ /**
+ * Internal log method.
+ *
+ * @param level : level of the message.
+ * @param msg : message to log
+ * @param exception : exception attached to the message
+ */
+ private void dispatch(int level, String msg, Throwable exception) {
+
+ ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
+ LogService log = null;
+ if (ref != null) {
+ log = (LogService) m_context.getService(ref);
+ }
+
+ String message = null;
+ switch (level) {
+ case DEBUG:
+ message = "[" + m_name + "] DEBUG: " + msg;
+ if (log != null) {
+ log.log(LogService.LOG_DEBUG, message, exception);
+ }
+ System.err.println(message); // NOPMD
+ exception.printStackTrace(); // NOPMD
+ break;
+ case ERROR:
+ message = "[" + m_name + "] ERROR: " + msg;
+ if (log != null) {
+ log.log(LogService.LOG_ERROR, message, exception);
+ }
+ System.err.println(message); // NOPMD
+ exception.printStackTrace(System.err); // NOPMD
+ break;
+ case INFO:
+ message = "[" + m_name + "] INFO: " + msg;
+ if (log != null) {
+ log.log(LogService.LOG_INFO, message, exception);
+ }
+ System.err.println(message); // NOPMD
+ exception.printStackTrace(System.err); // NOPMD
+ break;
+ case WARNING:
+ message = "[" + m_name + "] WARNING: " + msg;
+ if (log != null) {
+ log.log(LogService.LOG_WARNING, message, exception);
+ }
+ System.err.println(message); // NOPMD
+ exception.printStackTrace(System.err); // NOPMD
+ break;
+ default:
+ System.err.println("[" + m_name + "] UNKNOWN[" + level + "]: " + msg); // NOPMD
+ exception.printStackTrace(); // NOPMD
+ break;
+ }
+
+ if (log != null) {
+ m_context.ungetService(ref);
+ }
+ }
+
+ /**
+ * Get the default logger level.
+ * The property is searched inside the framework properties, the system properties,
+ * and in the manifest from the given bundle context. By default, set the level to WARNING.
+ * @param context : bundle context.
+ * @return the default log level.
+ */
+ private static int getDefaultLevel(BundleContext context) {
+ // First check in the framework and in the system properties
+ String level = context.getProperty(IPOJO_LOG_LEVEL);
+
+ // If null, look in bundle manifest
+ if (level == null) {
+ level = (String) context.getBundle().getHeaders().get(IPOJO_LOG_LEVEL);
+ }
+
+ if (level != null) {
+ if (level.equalsIgnoreCase("info")) {
+ return INFO;
+ } else if (level.equalsIgnoreCase("debug")) {
+ return DEBUG;
+ } else if (level.equalsIgnoreCase("warning")) {
+ return WARNING;
+ } else if (level.equalsIgnoreCase("error")) {
+ return ERROR;
+ }
+ }
+
+ // Either l is null, either the specified log level was unknown
+ // Set the default to WARNING
+ return WARNING;
+
+ }
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
new file mode 100644
index 0000000..948b66b
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
@@ -0,0 +1,472 @@
+/*
+ * 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.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.FieldInterceptor;
+import org.apache.felix.ipojo.Handler;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Property class managing a property.
+ * This class allows storing property value and calling setter method too.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Property implements FieldInterceptor {
+
+ /**
+ * Name of the property (filed name if not set).
+ */
+ private String m_name;
+
+ /**
+ * Field of the property.
+ */
+ private String m_field;
+
+ /**
+ * Setter method of the property.
+ */
+ private Callback m_method;
+
+ /**
+ * Value of the property.
+ */
+ private Object m_value;
+
+ /**
+ * Type of the property.
+ */
+ private Class m_type;
+
+ /**
+ * Handler object on to use the logger.
+ */
+ private Handler m_handler;
+
+ /**
+ * Instance Manager.
+ */
+ private InstanceManager m_manager;
+
+ /**
+ * Configurable Property Constructor. At least the method or the field need
+ * to be referenced.
+ *
+ * @param name : name of the property (optional)
+ * @param field : name of the field
+ * @param method : method name
+ * @param value : initial value of the property (optional)
+ * @param type : the type of the property
+ * @param manager : instance manager
+ * @param handler : handler object which manage this property.
+ * @throws ConfigurationException : occurs when the property value cannot be set.
+ */
+ public Property(String name, String field, String method, String value, String type, InstanceManager manager, Handler handler) throws ConfigurationException {
+ m_handler = handler;
+ m_manager = manager;
+ m_field = field;
+
+ if (name == null) {
+ if (m_field == null) {
+ m_name = method;
+ } else {
+ m_name = field;
+ }
+ } else {
+ m_name = name;
+ }
+
+ m_field = field;
+ m_type = computeType(type, manager.getGlobalContext());
+ if (value != null) {
+ m_value = create(m_type, value);
+ }
+
+ if (method != null) {
+ m_method = new Callback(method, new String[] { m_type.getName() }, false, manager);
+ }
+
+ }
+
+ /**
+ * The set type method computes and returns the property type according to the given type name.
+ * @param type : the type name
+ * @param context : bundle context (used to load classes)
+ * @return the class of the given type
+ * @throws ConfigurationException if an error occurs when loading the type class for non-primitive types.
+ */
+ public static Class computeType(String type, BundleContext context) throws ConfigurationException {
+ // Array :
+ if (type.endsWith("[]")) {
+ return computeArrayType(type, context);
+ } else {
+ // Syntactic sugar to avoid writing java.lang.String
+ if ("string".equals(type) || "String".equals(type)) {
+ return java.lang.String.class;
+ } else if ("boolean".equals(type)) {
+ return Boolean.TYPE;
+ } else if ("byte".equals(type)) {
+ return Byte.TYPE;
+ } else if ("short".equals(type)) {
+ return Short.TYPE;
+ } else if ("int".equals(type)) {
+ return Integer.TYPE;
+ } else if ("long".equals(type)) {
+ return Long.TYPE;
+ } else if ("float".equals(type)) {
+ return Float.TYPE;
+ } else if ("double".equals(type)) {
+ return Double.TYPE;
+ } else if ("char".equals(type)) {
+ return Character.TYPE;
+ } else {
+ // Non array, complex type.
+ try {
+ return context.getBundle().loadClass(type);
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("Class not found exception in setValue on " + type + " : " + e.getMessage());
+ } catch (SecurityException e) {
+ throw new ConfigurationException("Security excption in setValue on " + type + " : " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the Class object of a type array.
+ * @param type : the string descriptor of the type (must end by [] )
+ * @param context : bundle context (used to load classes)
+ * @return the Class object of the given type array.
+ * @throws ConfigurationException : if the class cannot be loaded
+ */
+ private static Class computeArrayType(String type, BundleContext context) throws ConfigurationException {
+ String internalType = type.substring(0, type.length() - 2);
+ if ("string".equals(internalType) || "String".equals(internalType)) {
+ return new String[0].getClass();
+ }
+ if ("boolean".equals(internalType)) {
+ return new boolean[0].getClass();
+ }
+ if ("byte".equals(internalType)) {
+ return new byte[0].getClass();
+ }
+ if ("short".equals(internalType)) {
+ return new short[0].getClass();
+ }
+ if ("int".equals(internalType)) {
+ return new int[0].getClass();
+ }
+ if ("long".equals(internalType)) {
+ return new long[0].getClass();
+ }
+ if ("float".equals(internalType)) {
+ return new float[0].getClass();
+ }
+ if ("double".equals(internalType)) {
+ return new double[0].getClass();
+ }
+ if ("char".equals(internalType)) {
+ return new char[0].getClass();
+ }
+
+ // Complex array type.
+ try {
+ Class clazz = context.getBundle().loadClass(internalType);
+ Object[] object = (Object[]) Array.newInstance(clazz, 0);
+ return object.getClass();
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("Class not found exception in setValue on " + internalType);
+ } catch (SecurityException e) {
+ throw new ConfigurationException("Secutiry Exception in setValue on " + internalType);
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + internalType);
+ }
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public String getField() {
+ return m_field;
+ }
+
+ /**
+ * Get method name, null if no method.
+ * @return the method name.
+ */
+ public String getMethod() {
+ if (m_method == null) { return null; }
+ return m_method.getMethod();
+ }
+
+ /**
+ * Check if the property has a method callback.
+ * @return true if the property has a method.
+ */
+ public boolean hasMethod() {
+ return m_method != null;
+ }
+
+ /**
+ * Check if the property has a field.
+ * @return true if the property has a field.
+ */
+ public boolean hasField() {
+ return m_field != null;
+ }
+
+ public Object getValue() {
+ return m_value;
+ }
+
+ /**
+ * Fix the value of the property.
+ * @param value : the new value.
+ */
+ public void setValue(Object value) {
+ // Is the object is directly assignable to the property, affect it.
+ if (isAssignable(m_type, value)) {
+ m_value = value;
+ } else {
+ // If the object is a String, we must recreate the object from the String form
+ if (value instanceof String) {
+ try {
+ m_value = create(m_type, (String) value);
+ } catch (ConfigurationException e) {
+ throw new ClassCastException("Incompatible type for the property " + m_name + " : " + e.getMessage());
+ }
+ } else {
+ // Error, the given property cannot be injected.
+ throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type.getName() + " expected, " + value.getClass() + " received");
+ }
+ }
+ }
+
+ /**
+ * Test if the given value is assignable to the given type.
+ * @param type : class of the type
+ * @param value : object to check
+ * @return true if the object is assignable in the property of type 'type'.
+ */
+ public static boolean isAssignable(Class type, Object value) {
+ if (value == null || type.isInstance(value)) { // When the value is null, the assign works necessary.
+ return true;
+ } else if (type.isPrimitive()) {
+ // Manage all boxing types.
+ if (value instanceof Boolean && Boolean.TYPE.equals(type)) { return true; }
+ if (value instanceof Byte && Byte.TYPE.equals(type)) { return true; }
+ if (value instanceof Short && Short.TYPE.equals(type)) { return true; }
+ if (value instanceof Integer && Integer.TYPE.equals(type)) { return true; }
+ if (value instanceof Long && Long.TYPE.equals(type)) { return true; }
+ if (value instanceof Float && Float.TYPE.equals(type)) { return true; }
+ if (value instanceof Double && Double.TYPE.equals(type)) { return true; }
+ if (value instanceof Character && Character.TYPE.equals(type)) { return true; }
+ return false;
+ } else {
+ // Else return false.
+ return false;
+ }
+ }
+
+ /**
+ * Create an object of the given type with the given String value.
+ * @param type : type of the returned object
+ * @param strValue : String value.
+ * @return the object of type 'type' created from the String 'value'
+ * @throws ConfigurationException occurs when the object cannot be created.
+ */
+ public static Object create(Class type, String strValue) throws ConfigurationException {
+ if (Boolean.TYPE.equals(type)) { return new Boolean(strValue); }
+ if (Byte.TYPE.equals(type)) { return new Byte(strValue); }
+ if (Short.TYPE.equals(type)) { return new Short(strValue); }
+ if (Integer.TYPE.equals(type)) { return new Integer(strValue); }
+ if (Long.TYPE.equals(type)) { return new Long(strValue); }
+ if (Float.TYPE.equals(type)) { return new Float(strValue); }
+ if (Double.TYPE.equals(type)) { return new Double(strValue); }
+ if (Character.TYPE.equals(type)) { return new Character(strValue.charAt(0)); }
+
+ // Array :
+ if (type.isArray()) { return createArrayObject(type.getComponentType(), ParseUtils.parseArrays(strValue)); }
+ // Else it is a neither a primitive type neither a String -> create
+ // the object by calling a constructor with a string in argument.
+ try {
+ Constructor cst = type.getConstructor(new Class[] { String.class });
+ return cst.newInstance(new Object[] { strValue });
+ } catch (SecurityException e) {
+ throw new ConfigurationException("Security exception in create on " + type + " : " + e.getMessage());
+ } catch (NoSuchMethodException e) {
+ throw new ConfigurationException("Constructor not found exception in create on " + type + " : " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
+ } catch (InstantiationException e) {
+ throw new ConfigurationException("Instantiation problem " + type);
+ } catch (IllegalAccessException e) {
+ throw new ConfigurationException("Illegal Access " + type);
+ } catch (InvocationTargetException e) {
+ throw new ConfigurationException("Invocation problem " + type + " : " + e.getTargetException().getMessage());
+ }
+
+ }
+
+ /**
+ * Create an array object containing the type 'interntype' from the String array 'values'.
+ * @param interntype : internal type of the array.
+ * @param values : String array
+ * @return the array containing objects created from the 'values' array
+ * @throws ConfigurationException occurs when the array cannot be created correctly
+ */
+ public static Object createArrayObject(Class interntype, String[] values) throws ConfigurationException {
+ if (Boolean.TYPE.equals(interntype)) {
+ boolean[] bool = new boolean[values.length];
+ for (int i = 0; i < values.length; i++) {
+ bool[i] = new Boolean(values[i]).booleanValue();
+ }
+ return bool;
+ }
+ if (Byte.TYPE.equals(interntype)) {
+ byte[] byt = new byte[values.length];
+ for (int i = 0; i < values.length; i++) {
+ byt[i] = new Byte(values[i]).byteValue();
+ }
+ return byt;
+ }
+ if (Short.TYPE.equals(interntype)) {
+ short[] shor = new short[values.length];
+ for (int i = 0; i < values.length; i++) {
+ shor[i] = new Short(values[i]).shortValue();
+ }
+ return shor;
+ }
+ if (Integer.TYPE.equals(interntype)) {
+ int[] ints = new int[values.length];
+ for (int i = 0; i < values.length; i++) {
+ ints[i] = new Integer(values[i]).intValue();
+ }
+ return ints;
+ }
+ if (Long.TYPE.equals(interntype)) {
+ long[] longs = new long[values.length];
+ for (int i = 0; i < values.length; i++) {
+ longs[i] = new Long(values[i]).longValue();
+ }
+ return longs;
+ }
+ if (Float.TYPE.equals(interntype)) {
+ float[] floats = new float[values.length];
+ for (int i = 0; i < values.length; i++) {
+ floats[i] = new Float(values[i]).floatValue();
+ }
+ return floats;
+ }
+ if (Double.TYPE.equals(interntype)) {
+ double[] doubles = new double[values.length];
+ for (int i = 0; i < values.length; i++) {
+ doubles[i] = new Double(values[i]).doubleValue();
+ }
+ return doubles;
+ }
+ if (Character.TYPE.equals(interntype)) {
+ char[] chars = new char[values.length];
+ for (int i = 0; i < values.length; i++) {
+ chars[i] = values[i].toCharArray()[0];
+ }
+ return chars;
+ }
+
+ // Else it is a neither a primitive type -> create the
+ // object by calling a constructor with a string in argument.
+ try {
+ Constructor cst = interntype.getConstructor(new Class[] { String.class });
+ Object[] object = (Object[]) Array.newInstance(interntype, values.length);
+ for (int i = 0; i < values.length; i++) {
+ object[i] = cst.newInstance(new Object[] { values[i].trim() });
+ }
+ return object;
+ } catch (NoSuchMethodException e) {
+ throw new ConfigurationException("Constructor not found exception in setValue on " + interntype.getName());
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + interntype.getName());
+ } catch (InstantiationException e) {
+ throw new ConfigurationException("Instantiation problem " + interntype.getName());
+ } catch (IllegalAccessException e) {
+ throw new ConfigurationException("Illegal Access Exception in " + interntype.getName());
+ } catch (InvocationTargetException e) {
+ throw new ConfigurationException("Invocation problem " + interntype.getName() + " : " + e.getTargetException().getMessage());
+ }
+ }
+
+ /**
+ * Invoke the setter method on the given pjo object. If no specified pojo object, will call on each created pojo object.
+ * @param instance : the created object (could be null
+ * @see org.apache.felix.ipojo.Handler#onCreation(java.lang.Object)
+ */
+ public void invoke(Object instance) {
+ try {
+ if (instance == null) {
+ m_method.call(new Object[] { m_value });
+ } else {
+ m_method.call(instance, new Object[] { m_value });
+ }
+ } catch (NoSuchMethodException e) {
+ m_handler.error("The method " + m_method + " does not exist in the class " + m_manager.getClassName());
+ m_manager.stop();
+ } catch (IllegalAccessException e) {
+ m_handler.error("The method " + m_method + " is not accessible in the class " + m_manager.getClassName());
+ m_manager.stop();
+ } catch (InvocationTargetException e) {
+ m_handler.error("The method " + m_method + " in the class " + m_manager.getClassName() + "throws an exception : " + e.getTargetException().getMessage(), e.getTargetException());
+ m_manager.setState(ComponentInstance.INVALID);
+ }
+ }
+
+ /**
+ * A field value is required by the object 'pojo'.
+ * @param pojo : POJO object
+ * @param fieldName : field
+ * @param value : last value
+ * @return the value if the handler want to inject this value.
+ * @see org.apache.felix.ipojo.FieldInterceptor#onGet(java.lang.Object, java.lang.String, java.lang.Object)
+ */
+ public Object onGet(Object pojo, String fieldName, Object value) {
+ return getValue();
+ }
+
+ /**
+ * The field 'field' receives a new value.
+ * @param pojo : pojo
+ * @param fieldName : field name
+ * @param value : new value
+ * @see org.apache.felix.ipojo.FieldInterceptor#onSet(java.lang.Object, java.lang.String, java.lang.Object)
+ */
+ public void onSet(Object pojo, String fieldName, Object value) {
+ setValue(value);
+
+ }
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java
index 1c8ae1d..7dd3349 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java
@@ -42,7 +42,7 @@
/**
* Bundle context against which this Tracker object is tracking.
*/
- protected final BundleContext m_context;
+ protected BundleContext m_context;
/**
* Filter specifying search criteria for the services to track.
@@ -52,22 +52,22 @@
/**
* TrackerCustomizer object for this tracker.
*/
- final TrackerCustomizer m_customizer;
+ protected TrackerCustomizer m_customizer;
/**
* Filter string for use when adding the ServiceListener. If this field is set, then certain optimizations can be taken since we don't have a user supplied filter.
*/
- final String m_listenerFilter;
+ protected String m_listenerFilter;
/**
* Class name to be tracked. If this field is set, then we are tracking by class name.
*/
- private final String m_trackClass;
+ private String m_trackClass;
/**
* Reference to be tracked. If this field is set, then we are tracking a single ServiceReference.
*/
- private final ServiceReference m_trackReference;
+ private ServiceReference m_trackReference;
/**
* Tracked services: ServiceReference object -> customized. Object and ServiceListener object
@@ -126,13 +126,13 @@
} else {
m_customizer = customizer;
}
- this.m_listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz.toString() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ this.m_listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz + ")";
try {
this.m_filter = context.createFilter(m_listenerFilter);
} catch (InvalidSyntaxException e) { // we could only get this exception
// if the clazz argument was
// malformed
- throw new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage()); //$NON-NLS-1$
+ throw new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
}
}
@@ -157,7 +157,7 @@
m_customizer = customizer;
}
if ((context == null) || (filter == null)) { // we throw a NPE here to be consistent with the other constructors
- throw new NullPointerException();
+ throw new NullPointerException(); // NOPMD by clement on 29/02/08 14:12
}
}
@@ -188,7 +188,7 @@
// the initial
// references
} catch (InvalidSyntaxException e) {
- throw new RuntimeException("unexpected InvalidSyntaxException: " + e.getMessage()); //$NON-NLS-1$
+ throw new IllegalStateException("unexpected InvalidSyntaxException: " + e.getMessage()); //$NON-NLS-1$
}
}
/* Call tracked outside of synchronized region */
@@ -220,8 +220,8 @@
try {
m_context.removeServiceListener(outgoing);
- } catch (IllegalStateException e) {
- System.err.println("Context stopped");
+ } catch (IllegalStateException e) { //NOPMD
+ //System.err.println("Context stopped");
/* In case the context was stopped. */
}
if (references != null) {
@@ -254,7 +254,7 @@
* @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
*/
public void addedService(ServiceReference reference) {
-
+ // Nothing to do.
}
/**
@@ -266,6 +266,7 @@
* @see TrackerCustomizer
*/
public void modifiedService(ServiceReference reference, Object service) {
+ // Nothing to do.
}
/**
@@ -326,8 +327,7 @@
Iterator keys = tracked.keySet().iterator();
for (int i = 0; i < length; i++) {
references[i] = (ServiceReference) keys.next();
- }
- // The resulting array is sorted by ranking.
+ }
return references;
}
}
@@ -353,6 +353,31 @@
return references;
}
}
+
+ /**
+ * Return the list of references used by the tracker.
+ * A reference becomes used when the dependency has already
+ * call getService on this reference.
+ * @return : the list of used references.
+ */
+ public List/*<ServiceReference>*/getUsedServiceReferences() {
+ Tracked tracked = this.m_tracked; // use local var since we are not synchronized
+ if (tracked == null || tracked.size() == 0) { // if Tracker is not open or empty
+ return null;
+ }
+ synchronized (tracked) {
+ int length = tracked.size();
+ List references = new ArrayList();
+ Iterator keys = tracked.keySet().iterator();
+ for (int i = 0; i < length; i++) {
+ Object key = keys.next();
+ if (tracked.get(key) != null) {
+ references.add(key);
+ }
+ }
+ return references;
+ }
+ }
/**
* Returns a ServiceReference object for one of the services being tracked by this Tracker object.
@@ -388,11 +413,13 @@
Object object = null;
synchronized (tracked) {
object = tracked.get(reference);
- if (object != null) { // The object was already get.
- return object;
- } else if (tracked.containsKey(reference)) { // Not already get
- object = m_context.getService(reference);
- tracked.put(reference, object);
+ if (object == null) {
+ if (tracked.containsKey(reference)) { // Not already get but already tracked.
+ object = m_context.getService(reference);
+ tracked.put(reference, object);
+ return object;
+ }
+ } else { // The object was already get.
return object;
}
// Not already tracked.
@@ -430,10 +457,10 @@
synchronized (tracked) {
ServiceReference[] references = getServiceReferences();
int length = 0;
- if (references != null) {
- length = references.length;
- } else {
+ if (references == null) {
return null;
+ } else {
+ length = references.length;
}
Object[] objects = new Object[length];
for (int i = 0; i < length; i++) {
@@ -541,7 +568,7 @@
while (true) {
ServiceReference reference;
synchronized (this) {
- if (m_initial.size() == 0) { // if there are no more inital services
+ if (m_initial.isEmpty()) { // if there are no more inital services
return; // we are done
}
@@ -580,14 +607,14 @@
switch (event.getType()) {
case ServiceEvent.REGISTERED:
case ServiceEvent.MODIFIED:
- if (m_listenerFilter != null) { // constructor supplied filter
- track(reference);
- } else { // user supplied filter
+ if (m_listenerFilter == null) { // user supplied filter
if (m_filter.match(reference)) {
track(reference); // Arrival
} else {
untrack(reference); // Departure
}
+ } else { // constructor supplied filter
+ track(reference);
}
break;
case ServiceEvent.UNREGISTERING:
diff --git a/ipojo/core/src/main/resources/metadata.xml b/ipojo/core/src/main/resources/metadata.xml
index 9d02336..3163416 100644
--- a/ipojo/core/src/main/resources/metadata.xml
+++ b/ipojo/core/src/main/resources/metadata.xml
@@ -1,41 +1,27 @@
<ipojo>
-<!-- Primitives handler -->
-<handler classname="org.apache.felix.ipojo.handlers.lifecycle.controller.ControllerHandler" name="controller" architecture="false"/>
-<handler classname="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler" name="callback" level="1" architecture="false"/>
-<handler classname="org.apache.felix.ipojo.handlers.dependency.DependencyHandler" name="requires" level="0" architecture="false">
- <controller field="m_state"/>
-</handler>
-<handler classname="org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler" name="provides" level="3" architecture="false"/>
-<handler classname="org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler" name="properties" level="1" architecture="false"/>
-<handler classname="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler" name="architecture" architecture="false">
- <provides>
- <property field="m_name" name="instance.name" value=""/>
- </provides>
-</handler>
-
-<!-- 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)(factory.name=*))" field="m_factories" optional="true" architecture="false">
- <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>
+ <!-- Primitives handler -->
+ <handler
+ classname="org.apache.felix.ipojo.handlers.lifecycle.controller.ControllerHandler"
+ name="controller" architecture="false" />
+ <handler
+ classname="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler"
+ name="callback" level="1" architecture="false" />
+ <handler
+ classname="org.apache.felix.ipojo.handlers.dependency.DependencyHandler"
+ name="requires" level="0" architecture="false">
+ <!-- <controller field="m_state"/> -->
+ </handler>
+ <handler
+ classname="org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler"
+ name="provides" level="3" architecture="false" />
+ <handler
+ classname="org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler"
+ name="properties" level="1" architecture="false" />
+ <handler
+ classname="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler"
+ name="architecture" architecture="false">
+ <provides>
+ <property field="m_name" name="instance.name" value="" />
+ </provides>
+ </handler>
</ipojo>
\ No newline at end of file