Add static and dynamic-priority binding policy.
Fix log access in initializeComponentFactory
Improve bytecode manipulation
Improve exception handling
Improve service tracking
Manage super interfaces (interface extended by the implemented interfaces and by the super-class)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@585146 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/arch/src/main/resources/metadata.xml b/ipojo/arch/src/main/resources/metadata.xml
index 6dcfb62..f605ec4 100644
--- a/ipojo/arch/src/main/resources/metadata.xml
+++ b/ipojo/arch/src/main/resources/metadata.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<iPOJO>
- <Component className="org.apache.felix.ipojo.arch.ArchCommandImpl">
+ <Component className="org.apache.felix.ipojo.arch.ArchCommandImpl" factory="false">
<Provides/>
<Requires field="m_archs" optional="true"/>
<Requires field="m_factories" optional="true" filter="(!(handler.name=*))"/>
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 02a907a..d5ff230 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
@@ -31,7 +31,6 @@
import java.util.Properties;
import org.apache.felix.ipojo.architecture.ComponentDescription;
-import org.apache.felix.ipojo.architecture.PropertyDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.Logger;
import org.apache.felix.ipojo.util.Tracker;
@@ -168,10 +167,8 @@
computeFactoryName();
m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
- m_isPublic = true;
- if (cm.containsAttribute("factory") && cm.getAttribute("factory").equals("false")) {
- m_isPublic = false;
- }
+ String fac = cm.getAttribute("factory");
+ m_isPublic = fac == null || ! fac.equalsIgnoreCase("false");
computeRequiredHandlers();
@@ -200,10 +197,10 @@
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.getPriority();
+ int oldP = hi.m_level;
hi.setReference(reference);
// If the priority has changed, sort the list.
- if (oldP != hi.getPriority()) {
+ if (oldP != hi.m_level) {
Collections.sort(m_handlerIdentifiers);
}
return true;
@@ -218,7 +215,14 @@
* @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
*/
public void addedService(ServiceReference reference) {
- computeFactoryState();
+ 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();
+ }
+ }
}
/**
@@ -228,12 +232,12 @@
* @return true if the metadata are correct
*/
public boolean check(Element cm) {
- if (cm.containsAttribute("className")) {
- m_componentClassName = cm.getAttribute("className");
- return true;
- } else {
+ m_componentClassName = cm.getAttribute("className");
+ if (m_componentClassName == null) {
System.err.println("A component needs a class name : " + cm);
return false;
+ } else {
+ return true;
}
}
@@ -264,11 +268,7 @@
* @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 == INVALID) {
- throw new MissingHandlerException(getMissingHandlers());
- }
-
+ public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
if (configuration == null) {
configuration = new Properties();
}
@@ -284,16 +284,14 @@
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);
}
-
- if (m_instancesName.contains(n)) {
- throw new UnacceptableConfiguration("Name already used : " + n);
- } else {
- m_instancesName.add(n);
- }
+ m_instancesName.add(n);
BundleContext context = null;
if (serviceContext == null) {
@@ -301,14 +299,19 @@
} 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[0]));
- instance.configure(m_componentMetadata, configuration);
+ 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();
@@ -322,9 +325,8 @@
* @param b : byte array of the class
* @param domain : protection domain of the class
* @return the defined class object
- * @throws Exception : an exception occur during the definition
*/
- public Class defineClass(String name, byte[] b, ProtectionDomain domain) throws Exception {
+ public Class defineClass(String name, byte[] b, ProtectionDomain domain) {
if (m_classLoader == null) {
m_classLoader = new FactoryClassloader();
}
@@ -360,7 +362,7 @@
* @see org.apache.felix.ipojo.Factory#getDescription()
*/
public Element getDescription() {
- if (m_componentDesc == null) { return new Element("No description available for " + getName(), ""); }
+ if (m_componentDesc == null) { return new Element("No description available for " + m_factoryName, ""); }
return m_componentDesc.getDescription();
}
@@ -412,6 +414,14 @@
return l;
}
+ public String getClassName() {
+ return m_componentClassName;
+ }
+
+ public int getState() {
+ return m_state;
+ }
+
/**
* Return the URL of a resource.
* @param resName : resource name
@@ -491,8 +501,8 @@
return; // The instance does not exist.
} else {
checkAcceptability(properties); // Test if the configuration is acceptable
+ cm.reconfigure(properties); // re-configure the component
}
- cm.reconfigure(properties); // re-configure the component
}
/**
@@ -503,15 +513,19 @@
*/
public void removedService(ServiceReference reference, Object service) {
// Look for the implied reference and invalid the handler identifier
- boolean touched = false;
for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
if (reference.equals(hi.getReference())) {
- hi.setReference(null); // This method will unget the service.
- touched = true;
+ 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.
}
}
- if (touched) { computeFactoryState(); }
}
/**
@@ -533,21 +547,28 @@
return;
}
- try {
- String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
- + "(" + Handler.HANDLER_NAME_PROPERTY + "=*)" + "(" + Handler.HANDLER_NAMESPACE_PROPERTY + "=*)" /* Look only for handlers */
- + "(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")"
- + "(factory.state=1)"
- + ")";
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
+ 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;
+ }
+ }
- } catch (InvalidSyntaxException e) {
- m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
+ 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;
}
-
- computeFactoryState();
if (m_isPublic) {
// Exposition of the factory service
@@ -582,10 +603,7 @@
// Release each handler
for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (hi.getReference() != null) {
- hi.setReference(null);
- }
+ ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
}
m_tracker = null;
@@ -641,18 +659,15 @@
* @throws MissingHandlerException : the factory is not valid.
*/
protected void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
- computeFactoryState();
-
if (m_state == Factory.INVALID) {
throw new MissingHandlerException(getMissingHandlers());
}
- final PropertyDescription[] props = m_componentDesc.getProperties();
- for (int i = 0; i < props.length; i++) {
- final PropertyDescription pd = props[i];
+ 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 (pd.getValue() == null && conf.get(pd.getName()) == null) {
- throw new UnacceptableConfiguration("The configuration does not contains the \"" + pd.getName() + "\" property");
+ if (conf.get(props.get(i)) == null) {
+ throw new UnacceptableConfiguration("The configuration does not contains the \"" + props.get(i) + "\" property");
}
}
}
@@ -663,21 +678,20 @@
* @throws org.apache.felix.ipojo.ConfigurationException if one handler has rejected the configuration.
*/
protected void computeDescription() throws org.apache.felix.ipojo.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(getName(), m_componentClassName, m_state, l, getMissingHandlers(), m_context.getBundle().getBundleId());
+ 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();
+ 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);
+ }
}
}
@@ -685,69 +699,71 @@
* Compute the factory name.
*/
protected void computeFactoryName() {
- if (m_componentMetadata.containsAttribute("name")) {
- m_factoryName = m_componentMetadata.getAttribute("name");
- } else if (m_componentMetadata.containsAttribute("factory") && ! m_componentMetadata.getAttribute("factory").equalsIgnoreCase("false")) {
+ m_factoryName = m_componentMetadata.getAttribute("name");
+ if (m_factoryName == null) { // No factory name, try with factory attribute
m_factoryName = m_componentMetadata.getAttribute("factory");
- } else {
- m_factoryName = m_componentMetadata.getAttribute("className");
+ 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() {
+ 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 && m_componentDesc == null) {
- try {
- computeDescription();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
+
+ 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;
}
- }
-
- 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()) {
- InstanceManager ci = (InstanceManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
+ } 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);
}
- m_instancesName.remove(ci.getInstanceName());
- }
- m_componentInstances.clear();
+ // 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);
+ }
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
+ m_componentInstances.clear();
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ // Update service properties TODO : really useful ?
+ if (m_sr != null) {
+ m_sr.setProperties(getProperties());
+ }
+
+ return;
}
- return;
}
}
@@ -763,15 +779,17 @@
if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
}
- // Add architecture if needed
- HandlerIdentifier hi = new HandlerIdentifier("architecture", "");
- if (! m_handlerIdentifiers.contains(hi) && m_componentMetadata.containsAttribute("architecture") && m_componentMetadata.getAttribute("architecture").equalsIgnoreCase("true")) {
+ // 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", "");
- if (! m_handlerIdentifiers.contains(hi2) && m_componentMetadata.containsAttribute("immediate") && m_componentMetadata.getAttribute("immediate").equalsIgnoreCase("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);
}
}
@@ -781,8 +799,9 @@
* @param ci : the destroyed instance
*/
protected void disposed(ComponentInstance ci) {
- m_instancesName.remove(ci.getInstanceName());
- m_componentInstances.remove(ci.getInstanceName());
+ String name = ci.getInstanceName();
+ m_instancesName.remove(name);
+ m_componentInstances.remove(name);
}
/**
@@ -790,10 +809,10 @@
* @return an non already used name
*/
protected synchronized String generateName() {
- String name = getName() + "-" + m_index;
+ String name = m_factoryName + "-" + m_index;
while (m_instancesName.contains(name)) {
m_index = m_index + 1;
- name = getName() + "-" + m_index;
+ name = m_factoryName + "-" + m_index;
}
return name;
}
@@ -802,7 +821,7 @@
* Return the bundle context.
* @return the Bundle Context.
*/
- protected BundleContext getBundleContext() {
+ public BundleContext getBundleContext() {
return m_context;
}
@@ -831,7 +850,6 @@
props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
props.put("component.properties", m_componentDesc.getProperties());
props.put("component.description", m_componentDesc);
- props.put("component.desc", m_componentDesc.toString());
}
// Add factory state
@@ -850,30 +868,31 @@
String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
- 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) {
- Factory factory = hi.getFactory();
try {
- return (HandlerManager) factory.createComponentInstance(null, sc);
+ 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;
}
}
@@ -925,10 +944,11 @@
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object o) {
- if (o instanceof HandlerIdentifier) {
- return ((HandlerIdentifier) o).getName().equalsIgnoreCase(m_name) && ((HandlerIdentifier) o).getNamespace().equalsIgnoreCase(m_namespace);
- }
- return false;
+ 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);
+ }
}
/**
@@ -951,7 +971,7 @@
* @return the handler full name
*/
public String getFullName() {
- if ("".equals(m_namespace)) {
+ if (m_namespace == null) {
return IPojoConfiguration.IPOJO_NAMESPACE + ":" + m_name;
} else {
return m_namespace + ":" + m_name;
@@ -970,32 +990,32 @@
return m_reference;
}
- public int getPriority() {
+ 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) {
- // First release the previous reference
- if (m_reference != null) {
- m_tracker.ungetService(m_reference);
- m_factory = null;
- m_level = Integer.MAX_VALUE; // Reset the reference to
- }
-
+ public void setReference(ServiceReference ref) {
m_reference = ref;
- // If the given reference is not null, set the priority.
- if (m_reference != null) {
- Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
- if (p != null) {
- m_level = p.intValue();
- }
+ Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
+ if (p != null) {
+ m_level = p.intValue();
}
-
}
/**
@@ -1032,14 +1052,12 @@
/**
* The defineClass method.
- *
* @param name : name of the class
* @param b : the byte array of the class
* @param domain : the protection domain
* @return : the defined class.
- * @throws Exception : if a problem is detected during the loading
*/
- public Class defineClass(String name, byte[] b, ProtectionDomain domain) throws Exception {
+ public Class defineClass(String name, byte[] b, ProtectionDomain domain) {
if (m_definedClasses.containsKey(name)) {
return (Class) m_definedClasses.get(name);
}
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
index e7dc233..a87015e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
@@ -65,13 +65,12 @@
* @see org.apache.felix.ipojo.ComponentFactory#check(org.apache.felix.ipojo.metadata.Element)
*/
public boolean check(Element cm) {
- // Get the name
- if (cm.containsAttribute("name")) {
- m_factoryName = cm.getAttribute("name");
- return true;
- } else {
+ m_factoryName = cm.getAttribute("name");
+ if (m_factoryName == null) {
System.err.println("A composite needs a name");
return false;
+ } else {
+ return true;
}
}
@@ -89,13 +88,14 @@
if ("composite".equals(type)) {
if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
- ns = "";
+ return name.equals(hi.getName()) && hi.getNamespace() == null;
}
return name.equals(hi.getName()) && ns.equals(hi.getNamespace());
} else {
return false;
}
}
+
/**
* Compute required handlers.
@@ -108,9 +108,10 @@
if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
}
- // Add architecture if needed
- if (m_componentMetadata.containsAttribute("architecture") && m_componentMetadata.getAttribute("architecture").equalsIgnoreCase("true")) {
- HandlerIdentifier hi = new HandlerIdentifier("architecture", "");
+ // 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); }
}
}
@@ -119,7 +120,9 @@
* Stop all the instance managers.
*/
public synchronized void stop() {
- m_tracker.close();
+ if (m_tracker != null) {
+ m_tracker.close();
+ }
final Collection col = m_componentInstances.values();
final Iterator it = col.iterator();
@@ -148,22 +151,29 @@
if (m_componentDesc != null) { // Already started.
return;
}
- try {
- String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
- + "(" + Handler.HANDLER_NAME_PROPERTY + "=*)" + "(" + Handler.HANDLER_NAMESPACE_PROPERTY + "=*)" /* Look only for handlers */
+ 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());
+ 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;
}
- computeFactoryState();
-
// Check if the factory should be exposed
if (m_isPublic) {
// Exposition of the factory service
@@ -184,7 +194,6 @@
props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
props.put("component.properties", m_componentDesc.getProperties());
props.put("component.description", m_componentDesc);
- props.put("component.desc", m_componentDesc.toString());
}
// Add factory state
@@ -194,6 +203,10 @@
return props;
}
+
+ public String getClassName() {
+ return "composite";
+ }
/**
@@ -224,10 +237,6 @@
* @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
*/
public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
- if (m_state == INVALID) {
- throw new MissingHandlerException(getMissingHandlers());
- }
-
if (configuration == null) {
configuration = new Properties();
}
@@ -301,8 +310,9 @@
/**
* Compute factory state.
+ * @throws ConfigurationException : occurs if the component type cannot be initialized correctly.
*/
- protected void computeFactoryState() {
+ 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);
@@ -310,13 +320,7 @@
}
if (isValid && m_componentDesc == null) {
- try {
- computeDescription();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- return;
- }
+ computeDescription();
}
if (isValid && m_state == INVALID) {
@@ -367,7 +371,7 @@
l.add(hi.getFullName());
}
- m_componentDesc = new ComponentDescription(getName(), "composite", m_state, l, getMissingHandlers(), m_context.getBundle().getBundleId());
+ m_componentDesc = new ComponentDescription(this);
for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
@@ -391,12 +395,15 @@
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
index 7ac7487..bf243e9 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeHandler.java
@@ -42,32 +42,14 @@
* This method me be called only once time.
* @param cm : the composite manager.
*/
- public final void attach(ComponentInstance cm) {
+ protected final void attach(ComponentInstance cm) {
m_manager = (CompositeManager) cm;
+ setLogger(m_manager.getFactory().getLogger());
}
public final CompositeManager getCompositeManager() {
return m_manager;
}
-
- /**
- * Log method.
- * @param level : message level (Logger class constant)
- * @param message : message to log
- */
- public void log(int level, String message) {
- m_manager.getFactory().getLogger().log(level, message);
- }
-
- /**
- * Log method.
- * @param level : message level (Logger class constant)
- * @param message : message to log
- * @param ex : exception to attach to the message
- */
- public void log(int level, String message, Throwable ex) {
- m_manager.getFactory().getLogger().log(level, message, ex);
- }
/**
* Get a plugged handler of the same container.
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 5f0c2c7..90c9ba4 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
@@ -45,18 +45,30 @@
* @param mes : message
* @param typ : component type
*/
- public ConfigurationException(String mes, String typ) {
+ ConfigurationException(String mes, String typ) {
m_type = typ;
m_message = mes;
}
/**
+ * Constructor.
+ * @param mes : message
+ */
+ public ConfigurationException(String mes) {
+ m_message = mes;
+ }
+
+ /**
* Get the error message.
* @return the error message.
* @see java.lang.Throwable#getMessage()
*/
public String getMessage() {
- return "The configuration is not correct for the type " + m_type + " : " + m_message;
+ if (m_type != null) {
+ return "The configuration is not correct for the type " + m_type + " : " + m_message;
+ } else {
+ return m_message;
+ }
}
}
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 9d309bf..bcc2d55 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
@@ -23,6 +23,7 @@
import org.apache.felix.ipojo.architecture.ComponentDescription;
import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
/**
* Component Type Factory Service. This service is exposed by a instance manager factory, and allows the dynamic creation of component instance.
@@ -118,4 +119,23 @@
*/
List getRequiredHandlers();
+ /**
+ * Return the classname of the component type.
+ * For factories which does not contains a class, return "composite"
+ * @return the class name of the component type or "composite"
+ */
+ String getClassName();
+
+ /**
+ * Return the state of the factory.
+ * @return the state of the factory
+ */
+ int getState();
+
+ /**
+ * Get the bundle context of the factory.
+ * @return the bundle context of the factory.
+ */
+ BundleContext getBundleContext();
+
}
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 4293a98..48cb786 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
@@ -53,11 +53,26 @@
public static final String HANDLER_LEVEL_PROPERTY = "handler.level";
/**
+ * Handler logger.
+ */
+ private Logger m_logger;
+
+ /**
+ * Set the logger use by this handler.
+ * @param logger : the logger object to use.
+ */
+ final void setLogger(Logger logger) {
+ m_logger = logger;
+ }
+
+ /**
* Log method.
* @param level : message level (Logger class constant)
* @param message : message to log
*/
- public abstract void log(int level, String message);
+ public final void log(int level, String message) {
+ m_logger.log(level, message);
+ }
/**
* Log method.
@@ -65,7 +80,9 @@
* @param message : message to log
* @param ex : exception to attach to the message
*/
- public abstract void log(int level, String message, Throwable ex);
+ public final void log(int level, String message, Throwable ex) {
+ m_logger.log(level, message, ex);
+ }
/**
* Get a plugged handler of the same container.
@@ -90,12 +107,7 @@
* @return true if the handler is valid.
*/
public final boolean isValid() {
- if (this instanceof Pojo) {
- return ((Pojo) this).getComponentInstance().getState() == ComponentInstance.VALID;
- } else {
- log(Logger.ERROR, "The handler is not a POJO : " + this.getClass().getName());
- return false;
- }
+ return ((Pojo) this).getComponentInstance().getState() == ComponentInstance.VALID;
}
@@ -104,12 +116,7 @@
* @return : the component instance.
*/
public final ComponentInstance getInstance() {
- if (this instanceof Pojo) {
- return ((Pojo) this).getComponentInstance();
- } else {
- log(Logger.ERROR, "The handler is not a POJO : " + this.getClass().getName());
- return null;
- }
+ return ((Pojo) this).getComponentInstance();
}
/**
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 6acf1a9..04bc706 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
@@ -19,15 +19,17 @@
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.ServiceRegistration;
@@ -72,25 +74,27 @@
super(bc, cm);
// Get the name
- if (cm.containsAttribute("name")) {
- m_factoryName = cm.getAttribute("name").toLowerCase();
- } else {
+ m_factoryName = cm.getAttribute("name").toLowerCase();
+ if (m_factoryName == null) {
System.err.println("An Handler needs a name");
return;
}
// Get the type
- if (cm.containsAttribute("type")) {
- m_type = cm.getAttribute("type");
+ String t = cm.getAttribute("type");
+ if (t != null) {
+ m_type = t;
}
- if (cm.containsAttribute("level")) {
- m_level = new Integer(cm.getAttribute("level")).intValue();
+ String l = cm.getAttribute("level");
+ if (l != null) {
+ m_level = new Integer(l).intValue();
}
// Get the namespace
- if (cm.containsAttribute("namespace")) {
- m_namespace = cm.getAttribute("namespace").toLowerCase();
+ String ns = cm.getAttribute("namespace");
+ if (ns != null) {
+ m_namespace = ns.toLowerCase();
}
}
@@ -114,27 +118,33 @@
* Start all the instance managers.
*/
public synchronized void start() {
- if (m_componentDesc != null) { // Already started.
- return;
- }
-
- try {
- String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
- + "(" + Handler.HANDLER_NAME_PROPERTY + "=*)" + "(" + Handler.HANDLER_NAMESPACE_PROPERTY + "=*)" /* Look only for handlers */
- + "(" + 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());
+ if (m_sr != null) { // Already started.
return;
}
-
- computeFactoryState();
- // Exposition of the factory service
+ 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());
}
@@ -149,20 +159,18 @@
m_sr = null;
}
- m_tracker.close();
+ if (m_tracker != null) {
+ m_tracker.close();
+ m_tracker = null;
+ }
// Release each handler
for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (hi.getReference() != null) {
- hi.setReference(null);
- }
+ ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
}
m_handlerIdentifiers.clear();
m_listeners.clear();
- m_tracker = null;
- m_componentDesc = null;
m_state = INVALID;
}
@@ -174,7 +182,10 @@
* @see org.apache.felix.ipojo.ComponentFactory#getProperties()
*/
protected Properties getProperties() {
- final Properties props = super.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);
@@ -187,6 +198,73 @@
}
/**
+ * 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.
@@ -199,7 +277,7 @@
* @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 == INVALID) {
+ if (m_state == Factory.INVALID) {
throw new MissingHandlerException(getMissingHandlers());
}
@@ -207,14 +285,6 @@
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");
@@ -257,17 +327,19 @@
* @return the Handler object.
*/
private HandlerManager getHandlerInstance(HandlerIdentifier hi, ServiceContext sc) {
- Factory factory = hi.getFactory();
try {
- return (HandlerManager) factory.createComponentInstance(null, sc);
+ 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;
}
}
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 0d5fa79..d87ecdd 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
@@ -151,9 +151,4 @@
m_handler = null;
}
-
-
-
-
-
}
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 f4b37c8..c356b2a 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
@@ -188,10 +188,13 @@
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();
}
}
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 6a59d0f..03bfa83 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
@@ -106,6 +106,11 @@
* 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();
/**
* Construct a new Component Manager.
@@ -258,6 +263,7 @@
m_handlers[i].dispose();
}
+ m_map.clear();
m_handlers = new HandlerManager[0];
m_fieldRegistration = new HashMap();
m_methodRegistration = new HashMap();
@@ -286,6 +292,7 @@
m_handlers[i].dispose();
}
+ m_map.clear();
m_handlers = new HandlerManager[0];
m_fieldRegistration = new HashMap();
m_methodRegistration = new HashMap();
@@ -393,6 +400,7 @@
m_clazz = m_factory.loadClass(m_className);
} catch (ClassNotFoundException e) {
m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "] Class not found during the loading phase : " + e.getMessage());
+ stop();
return;
}
}
@@ -488,19 +496,24 @@
} 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());
+ 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.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
@@ -661,26 +674,37 @@
*
* @param fieldName : the field name on which the GETFIELD instruction is
* called
- * @param initialValue : the value of the field in the code
* @return the value decided by the last asked handler (throw a warning if
* two fields decide two different values)
*/
- public synchronized Object getterCallback(String fieldName, Object initialValue) {
- Object result = null;
+ public synchronized Object getterCallback(String fieldName) {
+ Object initialValue = m_map.get(fieldName);
+ Object result = initialValue;
// Get the list of registered handlers
PrimitiveHandler[] list = (PrimitiveHandler[]) m_fieldRegistration.get(fieldName);
for (int i = 0; list != null && i < list.length; i++) {
Object handlerResult = list[i].getterCallback(fieldName, initialValue);
- if (handlerResult != 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());
+ }
+ }
result = handlerResult;
}
}
-
- if (result != null) {
- return result;
- } else {
- return initialValue;
+
+ if ((result != null && ! result.equals(initialValue)) || (result == null && initialValue != null)) {
+ // A change occurs => notify the change
+ m_map.put(fieldName, result);
+ for (int i = 0; list != null && i < list.length; i++) {
+ list[i].setterCallback(fieldName, result);
+ }
}
+
+ return result;
}
/**
@@ -717,11 +741,13 @@
* @param objectValue : the value of the field
*/
public synchronized void setterCallback(String fieldName, Object objectValue) {
- // Get the list of registered handlers
- PrimitiveHandler[] list = (PrimitiveHandler[]) m_fieldRegistration.get(fieldName);
-
- for (int i = 0; list != null && i < list.length; i++) {
- list[i].setterCallback(fieldName, 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);
+ for (int i = 0; list != null && i < list.length; i++) {
+ list[i].setterCallback(fieldName, objectValue);
+ }
}
}
@@ -793,11 +819,6 @@
}
setState(VALID);
return;
- }
-
- if (newState == DISPOSED) {
- dispose();
- }
-
+ }
}
}
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 cbfad6e..25a9eda 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,8 @@
*/
package org.apache.felix.ipojo;
+
+
/**
* Abstract class to extends for primitive handler.
*
@@ -42,6 +44,7 @@
*/
protected final void attach(ComponentInstance im) {
m_manager = (InstanceManager) im;
+ setLogger(m_manager.getFactory().getLogger());
}
public InstanceManager getInstanceManager() {
@@ -49,25 +52,6 @@
}
/**
- * Log method.
- * @param level : message level (Logger class constant)
- * @param message : message to log
- */
- public void log(int level, String message) {
- m_manager.getFactory().getLogger().log(level, message);
- }
-
- /**
- * Log method.
- * @param level : message level (Logger class constant)
- * @param message : message to log
- * @param ex : exception to attach to the message
- */
- public void log(int level, String message, Throwable ex) {
- m_manager.getFactory().getLogger().log(level, message, ex);
- }
-
- /**
* 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
@@ -84,12 +68,14 @@
* @param fieldName : the field name
* @param value : the value passed to the field
*/
- public void setterCallback(String fieldName, Object value) { }
+ public void setterCallback(String fieldName, Object value) {
+ return;
+ }
/**
* This method is called when a GETFIELD operation is detected.
* @param fieldName : the field name
- * @param value : the value passed to the field (by the previous handler)
+ * @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) {
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/ComponentDescription.java
index 01ad8c7..1e6c94f 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/ComponentDescription.java
@@ -18,11 +18,14 @@
*/
package org.apache.felix.ipojo.architecture;
+import java.util.ArrayList;
import java.util.List;
+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;
/**
* Component Type description.
@@ -36,56 +39,32 @@
private String[] m_providedServiceSpecification = new String[0];
/**
- * Component Type implementation class.
- */
- private String m_className;
-
- /**
* 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();
+
/**
- * Get the name of this component type.
+ * Represented factory.
*/
- private String m_name;
-
- /**
- * Bundle Id of the bundle containing this type.
- */
- private long m_bundleId;
-
- /**
- * State of the factory.
- */
- private int m_state;
-
- /**
- * Required handler list.
- */
- private List m_rh;
-
- /**
- * Missing handler list.
- */
- private List m_mh;
-
+ private Factory m_factory;
+
/**
* Constructor.
- * @param name : name.
- * @param className : implementation class or "composite"
- * @param state : state of the type (valid or invalid)
- * @param rh : required handler list
- * @param mh : missing handler list
- * @param bundle : bundle containing the type
+ * @param factory : represented factory.
*/
- public ComponentDescription(String name, String className, int state, List rh, List mh, long bundle) {
- m_name = name;
- m_className = className;
- m_bundleId = bundle;
- m_state = state;
- m_rh = rh;
- m_mh = mh;
+ public ComponentDescription(Factory factory) {
+ m_factory = factory;
+ }
+
+ public List getRequiredProperties() {
+ return m_requiredProperties;
}
/**
@@ -102,7 +81,7 @@
* @return the component type implementation class name.
*/
public String getClassName() {
- return m_className;
+ return m_factory.getClassName();
}
/**
@@ -128,18 +107,27 @@
* @param pd : the property to add
*/
public void addProperty(PropertyDescription pd) {
- if ("name".equals(pd.getName())) {
- pd = new PropertyDescription(pd.getName(), pd.getType(), null); // Erase the instance name
+ String n = pd.getName();
+ if ("name".equals(n)) {
+ pd = new PropertyDescription(n, pd.getType(), null); // Instance name case.
}
-
+
+ // Check if the property is not already in the array
for (int i = 0; i < m_properties.length; i++) {
- if (m_properties[i].getName().equals(pd.getName())) { return; }
+ PropertyDescription desc = m_properties[i];
+ if (desc.getName().equals(n)) {
+ 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);
+ }
}
/**
@@ -166,7 +154,7 @@
* @return the name of this component type
*/
public String getName() {
- return m_name;
+ return m_factory.getName();
}
/**
@@ -176,26 +164,27 @@
public Element getDescription() {
Element desc = new Element("Factory", "");
- desc.addAttribute(new Attribute("name", m_name));
- desc.addAttribute(new Attribute("bundle", "" + m_bundleId));
+ desc.addAttribute(new Attribute("name", m_factory.getName()));
+ desc.addAttribute(new Attribute("bundle", "" + ((ComponentFactory) m_factory).getBundleContext().getBundle().getBundleId()));
- if (m_className != null) {
- desc.addAttribute(new Attribute("Implementation-Class", m_className));
- } else {
+ String cn = getClassName();
+ if (cn == null) {
desc.addAttribute(new Attribute("Composite", "true"));
+ } else {
+ desc.addAttribute(new Attribute("Implementation-Class", getClassName()));
}
String state = "valid";
- if (m_state == Factory.INVALID) {
+ if (m_factory.getState() == Factory.INVALID) {
state = "invalid";
}
desc.addAttribute(new Attribute("state", state));
// Display required & missing handlers
Element rh = new Element("RequiredHandlers", "");
- rh.addAttribute(new Attribute("list", m_rh.toString()));
+ rh.addAttribute(new Attribute("list", m_factory.getRequiredHandlers().toString()));
Element mh = new Element("MissingHandlers", "");
- mh.addAttribute(new Attribute("list", m_mh.toString()));
+ mh.addAttribute(new Attribute("list", m_factory.getMissingHandlers().toString()));
desc.addElement(rh);
desc.addElement(mh);
@@ -220,4 +209,8 @@
return desc;
}
+ public BundleContext getBundleContext() {
+ return m_factory.getBundleContext();
+ }
+
}
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
index 283b1e4..73a61e7 100644
--- 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
@@ -30,6 +30,7 @@
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.
@@ -161,4 +162,16 @@
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/instance/InstanceHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
index df22f6f..b4f82b9 100644
--- 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
@@ -241,7 +241,7 @@
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(), getCompositeManager().getFactory().getName());
+ throw new ConfigurationException("An instance cannot be parsed correctly : " + e.getMessage());
}
m_configurations[i] = new ManagedConfiguration(conf);
}
@@ -255,12 +255,17 @@
*/
private Dictionary parseInstance(Element instance) throws ParseException {
Dictionary dict = new Properties();
- if (instance.containsAttribute("name")) {
- dict.put("name", instance.getAttribute("name"));
+ String name = instance.getAttribute("name");
+ if (name != null) {
+ dict.put("name", name);
}
- if (!instance.containsAttribute("component")) { throw new ParseException("An instance does not have the 'component' attribute"); }
-
- dict.put("component", instance.getAttribute("component"));
+
+ 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);
@@ -277,10 +282,12 @@
*/
private void parseProperty(Element prop, Dictionary dict) throws ParseException {
// Check that the property has a name
- if (!prop.containsAttribute("name")) { throw new ParseException("A property does not have the 'name' attribute"); }
+ 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 (prop.containsAttribute("value")) {
- dict.put(prop.getAttribute("name"), prop.getAttribute("value"));
+ if (value != null) {
+ dict.put(name, value);
} else {
// Recursive case
// Check if there is 'property' element
@@ -301,7 +308,7 @@
public void start() {
for (int j = 0; j < m_factories.length; j++) {
String factName = m_factories[j].getName();
- String className = m_factories[j].getComponentDescription().getClassName();
+ 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]);
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
index 186b984..707dac8 100644
--- 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
@@ -28,7 +28,6 @@
import org.apache.felix.ipojo.architecture.ComponentDescription;
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;
/**
@@ -64,15 +63,19 @@
* 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) {
+ 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++) {
- if (exp[i].containsAttribute("specification")) { // Malformed exports
- String specification = exp[i].getAttribute("specification");
- cd.addProvidedServiceSpecification(specification);
+ String spec = exp[i].getAttribute("specification");
+ if (spec != null) {
+ cd.addProvidedServiceSpecification(spec);
+ } else {
+ // Malformed exports
+ throw new ConfigurationException("Malformed exports - Missing the specification attribute");
}
}
}
@@ -94,32 +97,21 @@
for (int i = 0; i < exp.length; i++) {
boolean optional = false;
boolean aggregate = false;
- String specification = null;
+ 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");
- if (exp[i].containsAttribute("specification")) {
- specification = exp[i].getAttribute("specification");
- String filter = "(objectClass=" + specification + ")";
- if (exp[i].containsAttribute("optional") && exp[i].getAttribute("optional").equalsIgnoreCase("true")) {
- optional = true;
- }
- if (exp[i].containsAttribute("aggregate") && exp[i].getAttribute("aggregate").equalsIgnoreCase("true")) {
- aggregate = true;
- }
- if (exp[i].containsAttribute("filter")) {
- String classnamefilter = "(objectClass=" + specification + ")";
- filter = null;
- if ("".equals(exp[i].getAttribute("filter"))) {
- filter = classnamefilter;
- } else {
- filter = "(&" + classnamefilter + exp[i].getAttribute("filter") + ")";
- }
- }
- ServiceExporter si = new ServiceExporter(specification, filter, aggregate, optional, m_scope, m_context, this);
- m_exporters.add(si);
- } else { // Malformed exports
- log(Logger.ERROR, "Malformed exports : the specification attribute is mandatory");
- throw new ConfigurationException("Malformed exports : the specification attribute is mandatory", getCompositeManager().getFactory().getName());
+ 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);
}
}
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
index c9b26bf..b54397f 100644
--- 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
@@ -73,7 +73,6 @@
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
@@ -85,35 +84,31 @@
for (int i = 0; i < imp.length; i++) {
boolean optional = false;
boolean aggregate = false;
- String specification = null;
+ String specification = imp[i].getAttribute("specification");
- if (imp[i].containsAttribute("specification")) {
- 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
- if (imp[i].containsAttribute("optional") && imp[i].getAttribute("optional").equalsIgnoreCase("true")) {
- optional = true;
- }
- if (imp[i].containsAttribute("aggregate") && imp[i].getAttribute("aggregate").equalsIgnoreCase("true")) {
- aggregate = true;
- }
- if (imp[i].containsAttribute("filter")) {
- if (!"".equals(imp[i].getAttribute("filter"))) {
- filter = "(&" + filter + imp[i].getAttribute("filter") + ")";
- }
+ String f = imp[i].getAttribute("filter");
+ if (f != null) {
+ filter = "(&" + filter + f + ")";
}
- String id = null;
- if (imp[i].containsAttribute("id")) {
- id = imp[i].getAttribute("id");
- }
+ String id = imp[i].getAttribute("id");
int scopePolicy = -1;
- if (imp[i].containsAttribute("scope")) {
- if (imp[i].getAttribute("scope").equalsIgnoreCase("global")) {
+ String scope = imp[i].getAttribute("scope");
+ if (scope != null) {
+ if (scope.equalsIgnoreCase("global")) {
scopePolicy = PolicyServiceContext.GLOBAL;
- } else if (imp[i].getAttribute("scope").equalsIgnoreCase("composite")) {
+ } else if (scope.equalsIgnoreCase("composite")) {
scopePolicy = PolicyServiceContext.LOCAL;
- } else if (imp[i].getAttribute("scope").equalsIgnoreCase("composite+global")) {
+ } else if (scope.equalsIgnoreCase("composite+global")) {
scopePolicy = PolicyServiceContext.LOCAL_AND_GLOBAL;
}
}
@@ -127,7 +122,7 @@
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", getCompositeManager().getFactory().getName());
+ throw new ConfigurationException("Malformed imports : the specification attribute is mandatory");
}
}
}
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
index 324a85e..b0f1bac 100644
--- 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
@@ -25,7 +25,6 @@
import org.apache.felix.ipojo.CompositeHandler;
import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.metadata.Element;
@@ -60,19 +59,14 @@
public void configure(Element metadata, Dictionary conf) throws ConfigurationException {
Element[] services = metadata.getElements("service");
for (int i = 0; i < services.length; i++) {
- if (!services[i].containsAttribute("specification")) {
- throw new ConfigurationException("Malformed service : the specification attribute is mandatory", getCompositeManager().getFactory().getName());
- }
String spec = services[i].getAttribute("specification");
- String filter = "(&(objectClass=" + Factory.class.getName() + ")(!(factory.name=" + getCompositeManager().getFactory().getComponentDescription().getName() + "))(factory.state=1))"; // Cannot reinstantiate yourself
- if (services[i].containsAttribute("filter")) {
- String classnamefilter = "(&(objectClass=" + Factory.class.getName() + ")(!(factory.name=" + getCompositeManager().getFactory().getComponentDescription().getName() + "))(factory.state=1))"; // Cannot reinstantiate yourself
- filter = null;
- if ("".equals(services[i].getAttribute("filter"))) {
- filter = classnamefilter;
- } else {
- filter = "(&" + classnamefilter + services[i].getAttribute("filter") + ")";
- }
+ 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++) {
@@ -80,14 +74,12 @@
String value = services[i].getElements("property")[k].getAttribute("value");
prop.put(key, value);
}
- boolean agg = false;
- if (services[i].containsAttribute("aggregate") && services[i].getAttribute("aggregate").equalsIgnoreCase("true")) {
- agg = true;
- }
- boolean opt = false;
- if (services[i].containsAttribute("optional") && services[i].getAttribute("optional").equalsIgnoreCase("true")) {
- opt = true;
- }
+ 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);
}
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
index e573d4a..ef86839 100644
--- 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
@@ -87,11 +87,11 @@
public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
Element[] provides = metadata.getElements("provides", "");
for (int i = 0; i < provides.length; i++) {
- if (provides[i].containsAttribute("specification")) {
- String spec = provides[i].getAttribute("specification");
+ String spec = provides[i].getAttribute("specification");
+ if (spec != null) {
cd.addProvidedServiceSpecification(spec);
} else {
- throw new ConfigurationException("Malformed provides : the specification attribute is mandatory", getCompositeManager().getFactory().getName());
+ throw new ConfigurationException("Malformed provides : the specification attribute is mandatory");
}
}
}
@@ -264,9 +264,9 @@
ImportHandler ih = (ImportHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":requires");
if (ih == null) { return null; }
- if (element.containsAttribute("id")) {
+ String id = element.getAttribute("id");
+ if (id != null) {
// Look for dependency Id
- String id = element.getAttribute("id");
for (int i = 0; i < ih.getRequirements().size(); i++) {
ServiceImporter imp = (ServiceImporter) ih.getRequirements().get(i);
if (imp.getId().equals(id)) { return imp; }
@@ -289,15 +289,11 @@
* @throws CompositionException : occurs if the requirement does not match with service-level specification requirement
*/
private void checkRequirement(ServiceImporter imp, Element elem) throws CompositionException {
- boolean opt = false;
- if (elem.containsAttribute("optional") && elem.getAttribute("optional").equalsIgnoreCase("true")) {
- opt = true;
- }
+ String op = elem.getAttribute("optional");
+ boolean opt = op != null && op.equalsIgnoreCase("true");
- boolean agg = false;
- if (elem.containsAttribute("aggregate") && elem.getAttribute("aggregate").equalsIgnoreCase("true")) {
- agg = true;
- }
+ String ag = elem.getAttribute("aggregate");
+ boolean agg = ag != null && ag.equalsIgnoreCase("true");
if (imp == null) {
// Add the missing requirement
@@ -324,10 +320,9 @@
}
String spec = elem.getAttribute("specification");
String filter = "(&(objectClass=" + spec + ")(!(instance.name=" + getCompositeManager().getInstanceName() + ")))"; // Cannot import yourself
- if (elem.containsAttribute("filter")) {
- if (!"".equals(elem.getAttribute("filter"))) {
- filter = "(&" + filter + elem.getAttribute("filter") + ")";
- }
+ 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);
@@ -342,8 +337,8 @@
throw new CompositionException("The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");
}
- if (elem.containsAttribute("filter")) {
- String filter = elem.getAttribute("filter");
+ 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");
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 afa138e..1509cf6 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
@@ -28,7 +28,6 @@
/**
* Architecture Handler : do reflection on your component.
- *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ArchitectureHandler extends PrimitiveHandler implements Architecture {
@@ -40,7 +39,6 @@
/**
* Configure the handler.
- *
* @param metadata : the metadata of the component
* @param configuration : the instance configuration
* @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
@@ -53,13 +51,14 @@
* Stop method.
* @see org.apache.felix.ipojo.Handler#stop()
*/
- public void stop() { }
+ public void stop() {
+ }
/**
* Start method.
* @see org.apache.felix.ipojo.Handler#start()
*/
- public void start() {
+ public void start() {
log(Logger.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
index 822fb69..56882c4 100644
--- 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
@@ -22,6 +22,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+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;
@@ -73,8 +74,9 @@
* @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) {
+ public ConfigurableProperty(String name, String field, String method, String value, String type, ConfigurationHandler ch) throws ConfigurationException {
m_handler = ch;
m_field = field;
@@ -104,8 +106,9 @@
* 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) {
+ private void setValue(String strValue, String type) throws ConfigurationException {
Object value = null;
// Syntactic sugar to avoid writing java.lang.String
@@ -161,26 +164,19 @@
Constructor cst = m_type.getConstructor(new Class[] { String.class });
value = cst.newInstance(new Object[] { strValue });
} catch (ClassNotFoundException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Class not found exception in setValue on " + type + " : " + e.getMessage());
- return;
+ throw new ConfigurationException("Class not found exception in setValue on " + type + " : " + e.getMessage());
} catch (SecurityException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Security excption in setValue on " + type + " : " + e.getMessage());
- return;
+ throw new ConfigurationException("Security excption in setValue on " + type + " : " + e.getMessage());
} catch (NoSuchMethodException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Constructor not found exeption in setValue on " + type + " : " + e.getMessage());
- return;
+ throw new ConfigurationException("Constructor not found exeption in setValue on " + type + " : " + e.getMessage());
} catch (IllegalArgumentException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Argument problem to call the constructor of the type " + type);
- return;
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
} catch (InstantiationException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Instantiation problem " + type);
- return;
+ throw new ConfigurationException("Instantiation problem " + type);
} catch (IllegalAccessException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Illegal Access " + type);
- return;
+ throw new ConfigurationException("Illegal Access " + type);
} catch (InvocationTargetException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Invocation problem " + type);
- return;
+ throw new ConfigurationException("Invocation problem " + type);
}
}
@@ -193,8 +189,9 @@
*
* @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) {
+ 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++) {
@@ -290,19 +287,19 @@
m_type = ob.getClass();
return;
} catch (ClassNotFoundException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Class not found exception in setValue on " + internalType);
+ throw new ConfigurationException("Class not found exception in setValue on " + internalType);
} catch (SecurityException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Secutiry Exception in setValue on " + internalType);
+ throw new ConfigurationException("Secutiry Exception in setValue on " + internalType);
} catch (NoSuchMethodException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Constructor not found exception in setValue on " + internalType);
+ throw new ConfigurationException("Constructor not found exception in setValue on " + internalType);
} catch (IllegalArgumentException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Argument problem to call the constructor of the type " + internalType);
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + internalType);
} catch (InstantiationException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Instantiation problem " + internalType);
+ throw new ConfigurationException("Instantiation problem " + internalType);
} catch (IllegalAccessException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Illegal Access Exception in " + internalType);
+ throw new ConfigurationException("Illegal Access Exception in " + internalType);
} catch (InvocationTargetException e) {
- m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "Invocation problem " + internalType);
+ throw new ConfigurationException("Invocation problem " + internalType);
}
}
@@ -354,24 +351,26 @@
/**
* 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.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
- return;
+ 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.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
- return;
+ 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.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " in the class " + m_handler.getInstanceManager().getClassName() + "thorws an exception : " + e.getMessage());
- return;
+ m_handler.log(Logger.ERROR, "The method " + m_method + " in the class " + m_handler.getInstanceManager().getClassName() + "thorws an exception : " + e.getMessage());
+ m_handler.getInstanceManager().stop();
}
}
/**
- * Handler createInstance method. This method is overided to allow delayed callback invocation.
+ * 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)
*/
@@ -380,13 +379,13 @@
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());
- return;
+ 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());
- return;
+ 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.getMessage());
- return;
+ m_handler.getInstanceManager().stop();
}
}
}
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 6c9e76e..186caa9 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
@@ -31,11 +31,11 @@
import org.apache.felix.ipojo.architecture.ComponentDescription;
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.util.Logger;
/**
* Handler managing the Configuration Admin.
@@ -81,69 +81,55 @@
if (confs.length == 0) { return; }
Element[] configurables = confs[0].getElements("Property");
for (int i = 0; i < configurables.length; i++) {
- String fieldName = null;
- String methodName = null;
-
- if (configurables[i].containsAttribute("field")) {
- fieldName = configurables[i].getAttribute("field");
- }
- if (configurables[i].containsAttribute("method")) {
- methodName = configurables[i].getAttribute("method");
+ String fieldName = configurables[i].getAttribute("field");
+ String methodName = configurables[i].getAttribute("method");
+
+ if (fieldName == null && methodName == null) {
+ throw new ConfigurationException("Malformed property : The property need to contain at least a field or a method");
}
- if (fieldName != null || methodName != null) {
- String name = null;
- if (configurables[i].containsAttribute("name")) {
- name = configurables[i].getAttribute("name");
- } else {
- if (fieldName != null) {
- name = fieldName;
- } else {
- name = methodName;
- }
- }
- String value = null;
- if (configurables[i].containsAttribute("value")) {
- value = configurables[i].getAttribute("value");
- }
-
- // Detect the type of the property
- ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
- String type = null;
+ String name = configurables[i].getAttribute("name");
+ if (name == 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", getInstanceManager().getFactory().getName()); }
- type = fm.getFieldType();
+ name = fieldName;
} else {
- MethodMetadata[] mm = manipulation.getMethods(methodName);
- if (mm.length != 0) {
- if (mm[0].getMethodArguments().length != 1) {
- log(Logger.ERROR, "[" + getInstanceManager().getClassName() + "] The method " + methodName + " does not have one argument");
- throw new ConfigurationException("Malformed property : The method " + methodName + " does not have one argument", getInstanceManager().getFactory().getName());
- }
- if (type != null && !type.equals(mm[0].getMethodArguments()[0])) {
- log(Logger.ERROR, "[" + getInstanceManager().getClassName() + "] The field type (" + type + ") and the method type (" + mm[0].getMethodArguments()[0] + ") are not the same.");
- throw new ConfigurationException("Malformed property : The field type (" + type + ") and the method type (" + mm[0].getMethodArguments()[0] + ") are not the same.", getInstanceManager().getFactory().getName());
- }
- type = mm[0].getMethodArguments()[0];
- } else {
- // Else, the method is in a super class, look for the type attribute to get the type (if not already discovered)
- if (type == null && configurables[i].containsAttribute("type")) {
- type = configurables[i].getAttribute("type");
- } else {
- log(Logger.ERROR, "The type of the property cannot be discovered, please add a 'type' attribute");
- return;
- }
+ name = methodName;
+ }
+ configurables[i].addAttribute(new Attribute("name", name)); // Add the type to avoid configure checking
+ }
+
+ String value = configurables[i].getAttribute("value");
+
+ // Detect the type of the property
+ ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
+ 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 {
+ 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");
}
}
-
- if (value != null) {
- cd.addProperty(new PropertyDescription(name, type, value));
- } else {
- cd.addProperty(new PropertyDescription(name, type, null));
- }
+ }
+ if (value != null) {
+ cd.addProperty(new PropertyDescription(name, type, value));
} else {
- throw new ConfigurationException("Malformed property : The property need to contain at least a field or a method", getInstanceManager().getFactory().getName());
+ cd.addProperty(new PropertyDescription(name, type, null));
}
}
}
@@ -163,58 +149,27 @@
// Build the map
Element[] confs = metadata.getElements("Properties", "");
- if (confs.length == 0) { return; }
+ Element[] configurables = confs[0].getElements("Property");
// Check if the component is dynamically configurable
m_isConfigurable = false;
- // DEPRECATED BLOCK
- if (confs[0].containsAttribute("configurable") && confs[0].getAttribute("configurable").equalsIgnoreCase("true")) {
- log(Logger.WARNING, "The configurable attribute is deprecated, please use the propagation attribute");
+
+ String propa = confs[0].getAttribute("propagation");
+ if (propa != null && propa.equalsIgnoreCase("true")) {
m_isConfigurable = true;
m_toPropagate = configuration;
}
- // END
- if (confs[0].containsAttribute("propagation") && confs[0].getAttribute("propagation").equalsIgnoreCase("true")) {
- m_isConfigurable = true;
- m_toPropagate = configuration;
- }
-
- Element[] configurables = confs[0].getElements("Property");
List ff = new ArrayList();
for (int i = 0; i < configurables.length; i++) {
- String fieldName = null;
- String methodName = null;
+ String fieldName = configurables[i].getAttribute("field");
+ String methodName = configurables[i].getAttribute("method");
- if (configurables[i].containsAttribute("field")) {
- fieldName = configurables[i].getAttribute("field");
- }
- if (configurables[i].containsAttribute("method")) {
- 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 (fieldName == null && methodName == null) {
- log(Logger.ERROR, "A configurable property need to have at least a field or a method");
- throw new ConfigurationException("Malformed property : The property need to contain at least a field or a method", getInstanceManager().getFactory().getName());
- }
-
- String name = null;
- if (configurables[i].containsAttribute("name")) {
- name = configurables[i].getAttribute("name");
- } else {
- if (fieldName != null) {
- name = fieldName;
- } else {
- name = methodName;
- }
- }
- String value = null;
- if (configurables[i].containsAttribute("value")) {
- value = configurables[i].getAttribute("value");
- }
-
- if (name != null && configuration.get(name) != null && configuration.get(name) instanceof String) {
+ 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) {
@@ -222,60 +177,26 @@
}
}
- // Detect the type of the property
- ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
- String type = null;
+ String type = configurables[i].getAttribute("type"); // The initialize method has fixed the property name.
+
if (fieldName != null) {
- FieldMetadata fm = manipulation.getField(fieldName);
- if (fm == null) {
- log(Logger.ERROR, "[" + getInstanceManager().getClassName() + "] The field " + fieldName + " does not exist in the implementation");
- throw new ConfigurationException("Malformed property : The field " + fieldName + " does not exist in the implementation", getInstanceManager().getFactory().getName());
- }
- type = fm.getFieldType();
+ FieldMetadata fm = new FieldMetadata(fieldName, type);
ff.add(fm);
- } else {
- MethodMetadata[] mm = manipulation.getMethods(methodName);
- if (mm.length != 0) {
- if (mm[0].getMethodArguments().length != 1) {
- log(Logger.ERROR, "[" + getInstanceManager().getClassName() + "] The method " + methodName + " does not have one argument");
- throw new ConfigurationException("Malformed property : The method " + methodName + " does not have one argument", getInstanceManager().getFactory().getName());
- }
- if (type != null && !type.equals(mm[0].getMethodArguments()[0])) {
- log(Logger.ERROR, "[" + getInstanceManager().getClassName() + "] The field type (" + type + ") and the method type (" + mm[0].getMethodArguments()[0] + ") are not the same.");
- throw new ConfigurationException("Malformed property : The field type (" + type + ") and the method type (" + mm[0].getMethodArguments()[0] + ") are not the same.", getInstanceManager().getFactory().getName());
- }
- type = mm[0].getMethodArguments()[0];
- } else {
- // Else, the method is in a super class, look for the type attribute to get the type (if not already discovered)
- if (type == null && configurables[i].containsAttribute("type")) {
- type = configurables[i].getAttribute("type");
- } else {
- log(Logger.ERROR, "The type of the property cannot be discovered, please add a 'type' attribute");
- return;
- }
- }
}
-
+
ConfigurableProperty cp = new ConfigurableProperty(name, fieldName, methodName, value, type, this);
addProperty(cp);
- }
- if (configurables.length > 0) {
- for (int k = 0; k < m_configurableProperties.length; k++) {
- // Check if the instance configuration contains value for the
- // current property :
- String name = m_configurableProperties[k].getName();
- String fieldName = m_configurableProperties[k].getField();
- if (name != null && configuration.get(name) != null && !(configuration.get(name) instanceof String)) {
- m_configurableProperties[k].setValue(configuration.get(name));
- } else {
- if (fieldName != null && configuration.get(fieldName) != null && !(configuration.get(fieldName) instanceof String)) {
- m_configurableProperties[k].setValue(configuration.get(fieldName));
- }
+ // 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));
}
}
- getInstanceManager().register(this, (FieldMetadata[]) ff.toArray(new FieldMetadata[0]), null);
}
+ getInstanceManager().register(this, (FieldMetadata[]) ff.toArray(new FieldMetadata[ff.size()]), null);
}
/**
@@ -337,7 +258,9 @@
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 (m_configurableProperties[i].hasField() && m_configurableProperties[i].getField().equals(fieldName)) { return m_configurableProperties[i].getValue(); }
+ if (fieldName.equals(m_configurableProperties[i].getField())) {
+ return m_configurableProperties[i].getValue();
+ }
}
return value;
}
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 9c890b2..13d8c02 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
@@ -21,6 +21,7 @@
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.felix.ipojo.IPojoContext;
@@ -29,6 +30,7 @@
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.osgi.framework.Filter;
@@ -51,6 +53,27 @@
* 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;
/**
* Reference on the Dependency Handler.
@@ -106,7 +129,7 @@
* Array of service references.
* m_ref : Array
*/
- //private List m_references = new ArrayList();
+ private List m_references = new ArrayList();
/**
* Array of service reference containing used service references.
@@ -144,6 +167,16 @@
* Service Tracker.
*/
private Tracker m_tracker;
+
+ /**
+ * IS the instance activated ?
+ */
+ private boolean m_activated = false;
+
+ /**
+ * Biding Policy.
+ */
+ private int m_bindingPolicy;
/**
* Dependency constructor. After the creation the dependency is not started.
@@ -156,8 +189,9 @@
* @param isAggregate : is the dependency an aggregate dependency
* @param id : id of the dependency, may be null
* @param policy : resolution policy
+ * @param bindingPolicy : binding policy
*/
- public Dependency(DependencyHandler dh, String field, String spec, String filter, boolean isOptional, boolean isAggregate, String id, int policy) {
+ public Dependency(DependencyHandler dh, String field, String spec, String filter, boolean isOptional, boolean isAggregate, String id, int policy, int bindingPolicy) {
m_handler = dh;
m_field = field;
m_specification = spec;
@@ -172,7 +206,8 @@
if (policy != -1) {
m_policy = policy;
}
- // TODO : Add binding policy too
+
+ 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)) {
@@ -206,10 +241,19 @@
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) {
@@ -218,7 +262,6 @@
/**
* Add a callback to the dependency.
- *
* @param cb : callback to add
*/
protected void addDependencyCallback(DependencyCallback cb) {
@@ -233,12 +276,17 @@
}
+ /**
+ * 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 DependencyHandler getDependencyHandler() {
+ public DependencyHandler getHandler() {
return m_handler;
}
@@ -247,13 +295,7 @@
* @return the used service.
*/
public List getUsedServices() {
- List set = new ArrayList();
- for (int i = 0; i < m_usedReferences.size(); i++) {
- if (! set.contains(m_usedReferences.get(i))) {
- set.add(m_usedReferences.get(i));
- }
- }
- return set;
+ return m_usedReferences;
}
/**
@@ -264,26 +306,24 @@
* the dependency.
*/
Object get() {
- //TODO in static policy, the set of used service is frozen.
-
// Initialize the thread local object is not already touched.
if (m_usage.getObjects().isEmpty()) {
if (isAggregate()) {
synchronized (m_tracker) {
- ServiceReference[] refs = m_tracker.getServiceReferences();
- for (int i = 0; refs != null && i < refs.length; i++) {
- m_usage.getReferences().add(refs[i]);
- m_usage.getObjects().add(getService(refs[i]));
+ 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_tracker.getServiceReferences() == null) {
+ if (m_references.size() == 0) {
// Load the nullable class
String className = m_specification + "Nullable";
Class nullableClazz = m_handler.getNullableClass(className);
if (nullableClazz == null) {
- m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Cannot load the nullable class to return a dependency object for " + m_field + " -> " + m_specification);
+ m_handler.log(Logger.WARNING, "[" + m_handler.getInstanceManager().getClassName() + "] Cannot load the nullable class to return a dependency object for " + m_field + " -> " + m_specification);
return null;
}
@@ -294,27 +334,28 @@
} catch (IllegalAccessException e) {
// There is a problem in the dependency resolving (like in stopping method)
if (m_isAggregate) {
- m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Return an empty array, an exception was throwed in the get method", e);
+ m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getInstanceName() + "] Return an empty array, an exception was throwed in the get method", e);
return Array.newInstance(m_clazz, 0);
} else {
- m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Return null, an exception was throwed in the get method", e);
+ m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getInstanceName() + "] Return null, an exception was throwed in the get method", e);
return null;
}
} catch (InstantiationException e) {
// There is a problem in the dependency resolving (like in stopping
// method)
if (m_isAggregate) {
- m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Return an empty array, an exception was throwed in the get method", e);
+ m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getInstanceName() + "] Return an empty array, an exception was throwed in the get method", e);
return Array.newInstance(m_clazz, 0);
} else {
- m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Return null, an exception was throwed in the get method", e);
+ m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getInstanceName() + "] Return null, an exception was throwed in the get method", e);
return null;
}
}
m_usage.getObjects().add(instance);
} else {
- m_usage.getReferences().add(m_tracker.getServiceReference());
- m_usage.getObjects().add(getService(m_tracker.getServiceReference()));
+ 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);
@@ -338,17 +379,14 @@
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());
- return;
+ 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());
- return;
+ 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.getMessage());
- return;
+ m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getMessage());
+ m_handler.getInstanceManager().stop();
}
}
}
@@ -382,24 +420,24 @@
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_tracker.getServiceReferences() == null) { return; }
+ if (m_isOptional && m_references.size() == 0) { return; }
if (m_isAggregate) {
- ServiceReference[] refs = m_tracker.getServiceReferences();
- for (int i = 0; refs != null && i < refs.length; i++) {
+ 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, refs[i], getService(refs[i]));
+ 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());
- return;
+ 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());
- return;
+ 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() + "thorws an exception : " + e.getMessage());
- return;
+ m_handler.getInstanceManager().stop();
}
}
}
@@ -408,19 +446,19 @@
for (int j = 0; j < m_callbacks.length; j++) {
if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
try {
- ServiceReference ref = m_tracker.getServiceReference();
+ 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());
- return;
+ 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());
- return;
+ 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.getMessage());
- return;
+ m_handler.getInstanceManager().stop();
}
}
}
@@ -442,13 +480,13 @@
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());
- return;
+ 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());
- return;
+ 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.getMessage());
- return;
+ m_handler.getInstanceManager().stop();
}
}
}
@@ -463,12 +501,9 @@
m_serviceContext = new PolicyServiceContext(m_handler.getInstanceManager().getGlobalContext(), m_handler.getInstanceManager().getLocalServiceContext(), m_policy);
// Construct the filter with the objectclass + filter
- String classnamefilter = "(objectClass=" + m_specification + ")";
- String filter = "";
- if ("".equals(m_strFilter)) {
- filter = classnamefilter;
- } else {
- filter = "(&" + classnamefilter + m_strFilter + ")";
+ String filter = "(objectClass=" + m_specification + ")";
+ if (m_strFilter != null) {
+ filter = "(&" + filter + m_strFilter + ")";
}
m_state = UNRESOLVED;
@@ -477,16 +512,15 @@
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 + "]");
- return;
+ m_handler.getInstanceManager().stop();
}
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());
- return;
- }
- //TODO : Add binding (dynamic priority against normal) policy, i.e. comparator.
+ m_handler.getInstanceManager().stop();
+ }
m_tracker = new Tracker(m_serviceContext, m_filter, this);
m_tracker.open();
if (m_tracker.size() == 0 && !m_isOptional) {
@@ -504,37 +538,29 @@
m_tracker.close(); // Will unget all used reference.
m_tracker = null;
}
- m_handler.log(Logger.INFO, "[" + m_handler.getInstanceManager().getInstanceName() + "] Stop a dependency on : " + m_specification + " with " + m_strFilter + " (" + m_handler.getInstanceManager() + ")");
+
m_state = UNRESOLVED;
+ m_activated = false;
+ m_references.clear();
m_usedReferences.clear();
m_clazz = null;
}
/**
* Return the state of the dependency.
- *
* @return the state of the dependency (1 : valid, 2 : invalid)
*/
public int getState() {
- if (m_isOptional) {
- return RESOLVED;
- } else {
- return m_state;
- }
+ return m_state;
}
/**
* Return the list of used service reference.
- *
* @return the service reference list.
*/
public List getServiceReferences() {
- if (m_tracker.size() != 0) {
- return m_tracker.getServiceReferencesList();
- } else {
- return new ArrayList();
- }
+ return m_references;
}
protected DependencyCallback[] getCallbacks() {
@@ -594,8 +620,7 @@
* @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
*/
public boolean addingService(ServiceReference ref) {
- //TODO : according to the policy, do not add the new reference. Indeed in static policy is references are already used, new ones are ignored
- if (m_filter.match(ref)) {
+ if (! m_activated && m_filter.match(ref)) {
return true;
}
return false;
@@ -608,8 +633,12 @@
* @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(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_tracker.getServiceReferences() != null) {
+ if (m_isAggregate || m_references.size() == 1) {
callBindMethod(reference);
}
@@ -633,27 +662,38 @@
public void removedService(ServiceReference ref, Object arg1) {
// Call unbind method
boolean hasChanged = false;
- if (m_usedReferences.contains(ref)) {
+ 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);
- m_usedReferences.remove(ref);
hasChanged = true;
- //TODO in static policy, invalidate the instance, and close the tracking
}
-
- // Is the state valid or invalid, the reference is already removed
- if (m_tracker.getServiceReferences() == null && !m_isOptional) {
- m_state = UNRESOLVED;
+
+ if (m_bindingPolicy == STATIC_POLICY) {
+ if (hasChanged && m_activated) {
+ m_state = BROKEN;
+ }
} else {
- m_state = RESOLVED;
- }
-
- // Is there any change ?
- if (!m_isAggregate) {
- if (hasChanged) { // The used reference has been removed
- if (m_tracker.size() != 0) {
- callBindMethod(m_tracker.getServiceReference());
+ // 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));
+ }
}
}
}
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 ef62ef7..d354456 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
@@ -73,7 +73,7 @@
* method
*/
public DependencyCallback(Dependency dep, String method, int methodType) {
- super(method, (String[]) null, false, dep.getDependencyHandler().getInstanceManager());
+ super(method, (String[]) null, false, dep.getHandler().getInstanceManager());
m_methodType = methodType;
m_dependency = dep;
m_method = method;
@@ -103,7 +103,7 @@
*/
protected void searchMethod() {
if (m_argument != null) {
- Method[] methods = m_dependency.getDependencyHandler().getInstanceManager().getClazz().getDeclaredMethods();
+ Method[] methods = m_dependency.getHandler().getInstanceManager().getClazz().getDeclaredMethods();
for (int i = 0; m_methodObj == null && i < methods.length; i++) {
// First check the method name
if (methods[i].getName().equals(m_method)) {
@@ -126,7 +126,7 @@
}
if (m_methodObj == null) { //look at parent classes
- Method[] methods = m_dependency.getDependencyHandler().getInstanceManager().getClazz().getMethods();
+ 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)) {
@@ -166,8 +166,8 @@
}
if (m_methodObj == null) {
- m_dependency.getDependencyHandler().log(Logger.ERROR, "The method " + m_method + " cannot be called : method not found");
- return;
+ m_dependency.getHandler().log(Logger.ERROR, "The method " + m_method + " cannot be called : method not found");
+ m_dependency.getHandler().getInstanceManager().stop();
} else {
m_methodObj.setAccessible(true);
}
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 c7db95e..2e38641 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
@@ -23,6 +23,7 @@
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.PolicyServiceContext;
import org.apache.felix.ipojo.PrimitiveHandler;
@@ -58,12 +59,17 @@
private boolean m_state;
/**
+ * Is the handler started.
+ */
+ private boolean m_started;
+
+ /**
* Add a dependency.
*
* @param dep : the dependency to add
*/
private void addDependency(Dependency dep) {
- for (int i = 0; (m_dependencies != null) && (i < m_dependencies.length); i++) {
+ for (int i = 0; i < m_dependencies.length; i++) {
if (m_dependencies[i] == dep) { return; }
}
if (m_dependencies.length > 0) {
@@ -107,12 +113,22 @@
* Check the validity of the dependencies.
*/
protected void checkContext() {
+ if (! m_started) { return; }
synchronized (m_dependencies) {
// Store the initial state
boolean initialState = m_state;
+ boolean valid = true;
+ for (int i = 0; i < m_dependencies.length; i++) {
+ Dependency dep = m_dependencies[i];
+ if (dep.getState() > Dependency.RESOLVED) {
+ valid = false;
+ break;
+ }
+ }
+
// Check the component dependencies
- if (validateComponentDependencies()) {
+ if (valid) {
// The dependencies are valid
if (!initialState) {
// There is a state change
@@ -148,8 +164,7 @@
MethodMetadata[] mets = manipulation.getMethods(callbacks[i].getMethodName());
if (mets.length != 0) {
if (mets[0].getMethodArguments().length > 2) {
- log(Logger.ERROR, "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", getInstanceManager().getFactory().getName());
+ 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());
@@ -159,8 +174,7 @@
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");
+ 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]);
}
}
@@ -168,15 +182,13 @@
// Check that the second arguments 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";
- log(Logger.ERROR, message);
- throw new ConfigurationException(message, getInstanceManager().getFactory().getName());
+ 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");
+ 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]);
}
}
@@ -190,8 +202,7 @@
if (field != null) {
FieldMetadata fm = manipulation.getField(field);
if (fm == null) {
- log(Logger.ERROR, "A requirement field " + field + " does not exist in the implementation class");
- throw new ConfigurationException("Requirement Callback : A requirement field " + field + " does not exist in the implementation class", getInstanceManager().getFactory().getName());
+ throw new ConfigurationException("Requirement Callback : A requirement field " + field + " does not exist in the implementation class");
}
String type = fm.getFieldType();
if (type.endsWith("[]")) {
@@ -231,56 +242,28 @@
// Create the dependency according to the component metadata
Element[] deps = componentMetadata.getElements("Requires");
- // DEPRECATED BLOCK :
- if (deps.length == 0) {
- deps = componentMetadata.getElements("Dependency");
- if (deps.length != 0) {
- log(Logger.WARNING, "Dependency is deprecated, please use 'requires' instead of 'dependency'");
- }
- }
- // END OF DEPRECATED BLOCK
-
// Get instance filters.
- Dictionary filtersConfiguration = null;
- if (configuration.get("requires.filters") != null) {
- filtersConfiguration = (Dictionary) configuration.get("requires.filters");
- }
+ Dictionary filtersConfiguration = (Dictionary) configuration.get("requires.filters");
for (int i = 0; i < deps.length; i++) {
// Create the dependency metadata
- String field = null;
- if (deps[i].containsAttribute("field")) {
- field = deps[i].getAttribute("field");
- }
- String serviceSpecification = null;
- if (deps[i].containsAttribute("interface")) {
- serviceSpecification = deps[i].getAttribute("interface");
- }
- String filter = "";
- if (deps[i].containsAttribute("filter")) {
- filter = deps[i].getAttribute("filter");
- }
- boolean optional = false;
- if (deps[i].containsAttribute("optional") && "true".equals(deps[i].getAttribute("optional"))) {
- optional = true;
- }
- boolean aggregate = false;
- if (deps[i].containsAttribute("aggregate") && "true".equals(deps[i].getAttribute("aggregate"))) {
- aggregate = true;
- }
-
- String id = null;
- if (deps[i].containsAttribute("id")) {
- id = deps[i].getAttribute("id");
- }
+ 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 agg = deps[i].getAttribute("aggregate");
+ boolean aggregate = agg != null && agg.equalsIgnoreCase("true");
+ String id = deps[i].getAttribute("id");
int scopePolicy = -1;
- if (deps[i].containsAttribute("scope")) {
- if (deps[i].getAttribute("scope").equalsIgnoreCase("global")) {
+ String scope = deps[i].getAttribute("scope");
+ if (scope != null) {
+ if (scope.equalsIgnoreCase("global")) {
scopePolicy = PolicyServiceContext.GLOBAL;
- } else if (deps[i].getAttribute("scope").equalsIgnoreCase("composite")) {
+ } else if (scope.equalsIgnoreCase("composite")) {
scopePolicy = PolicyServiceContext.LOCAL;
- } else if (deps[i].getAttribute("scope").equalsIgnoreCase("composite+global")) {
+ } else if (scope.equalsIgnoreCase("composite+global")) {
scopePolicy = PolicyServiceContext.LOCAL_AND_GLOBAL;
}
}
@@ -290,12 +273,26 @@
filter = (String) filtersConfiguration.get(id);
}
- Dependency dep = new Dependency(this, field, serviceSpecification, filter, optional, aggregate, id, scopePolicy);
+
+ // 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;
+ }
+ }
+
+ Dependency dep = new Dependency(this, field, serviceSpecification, filter, optional, aggregate, id, scopePolicy, bindingPolicy);
// 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", getInstanceManager().getFactory().getName());
+ 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");
@@ -316,56 +313,36 @@
if (dep.getField() != null) {
fl.add(manipulation.getField(dep.getField()));
}
- } else {
- log(Logger.ERROR, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The dependency on " + dep.getField() + " is not valid");
}
}
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());
}
}
/**
* Create a nullable class for the given dependency.
- *
* @param dep : the dependency
*/
private void createNullableClass(Dependency dep) {
- log(Logger.INFO, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] Try to load the nullable class for " + dep.getSpecification());
- // String[] segment =
- // dep.getMetadata().getServiceSpecification().split("[.]");
- // String className = "org/apache/felix/ipojo/" + segment[segment.length
- // - 1] + "Nullable";
String className = dep.getSpecification() + "Nullable";
String resource = dep.getSpecification().replace('.', '/') + ".class";
URL url = getInstanceManager().getContext().getBundle().getResource(resource);
- try {
- byte[] b = NullableObjectWriter.dump(url, dep.getSpecification());
- Class c = null;
- try {
- c = getInstanceManager().getFactory().defineClass(className, b, null);
- } catch (Exception e) {
- log(Logger.ERROR, "Cannot define the nullable class : " + e.getMessage());
- e.printStackTrace();
- return;
- }
- addNullableClass(c);
- log(Logger.INFO, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] Nullable class created for " + dep.getSpecification());
- } catch (Exception e2) {
- log(Logger.ERROR, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] Cannot load the nullable class for " + dep.getSpecification(), e2);
- }
+ byte[] b = NullableObjectWriter.dump(url, dep.getSpecification());
+ Class c = getInstanceManager().getFactory().defineClass(className, b, null);
+ addNullableClass(c);
}
/**
* Return the nullable class corresponding to the given name.
- *
* @param name the needed type
- * @return the class correspondig to the name, or null if the class does not
- * exist.
+ * @return the class correspondig to the name, or null if the class does not exist.
*/
protected Class getNullableClass(String name) {
for (int i = 0; i < m_nullableClasses.length; i++) {
@@ -385,7 +362,8 @@
public Object getterCallback(String fieldName, Object value) {
for (int i = 0; i < m_dependencies.length; i++) {
Dependency dep = m_dependencies[i];
- if (dep.getField().equals(fieldName)) {
+ String field = dep.getField();
+ if (field != null && field.equals(fieldName)) {
// The field name is a dependency, return the get
return dep.get();
}
@@ -402,7 +380,9 @@
public void entryCallback(String methodId) {
for (int i = 0; i < m_dependencies.length; i++) {
Dependency dep = m_dependencies[i];
- dep.entry(methodId);
+ if (dep.getField() != null) {
+ dep.entry(methodId);
+ }
}
}
@@ -415,7 +395,9 @@
public void exitCallback(String methodId, Object returnedObj) {
for (int i = 0; i < m_dependencies.length; i++) {
Dependency dep = m_dependencies[i];
- dep.exit(methodId);
+ if (dep.getField() != null) {
+ dep.exit(methodId);
+ }
}
}
@@ -434,6 +416,7 @@
dep.start();
}
// Check the state
+ m_started = true;
checkContext();
}
@@ -442,15 +425,15 @@
* @see org.apache.felix.ipojo.Handler#stop()
*/
public void stop() {
+ m_started = false;
for (int i = 0; i < m_dependencies.length; i++) {
m_dependencies[i].stop();
}
- m_nullableClasses = new Class[0];
}
/**
* Handler createInstance method.
- * This method is overided to allow delayed callback invocation.
+ * This method is override to allow delayed callback invocation.
* @param instance : the created object
* @see org.apache.felix.ipojo.Handler#objectCreated(java.lang.Object)
*/
@@ -459,19 +442,18 @@
m_dependencies[i].callBindMethod(instance);
}
}
-
+
/**
- * Check if dependencies are resolved.
- * @return true if all dependencies are resolved.
+ * 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)
*/
- private boolean validateComponentDependencies() {
- boolean valid = true;
- for (int i = 0; i < m_dependencies.length; i++) {
- Dependency dep = m_dependencies[i];
- valid = valid & dep.getState() == Dependency.RESOLVED;
- if (!valid) { return false; }
+ public void stateChanged(int state) {
+ if (state == ComponentInstance.VALID) {
+ for (int i = 0; i < m_dependencies.length; i++) {
+ m_dependencies[i].activate();
+ }
}
- return valid;
}
/**
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 db62073..1615521 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
@@ -88,6 +88,9 @@
if (m_dependencies[i].getState() == 2) {
state = "unresolved";
}
+ if (m_dependencies[i].getState() == 3) {
+ state = "broken";
+ }
Element dep = new Element("Requires", "");
dep.addAttribute(new Attribute("Specification", m_dependencies[i].getInterface()));
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 bec6709..7214d83 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
@@ -84,54 +84,39 @@
public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
m_callbacks = new LifecycleCallback[0];
- if (metadata.containsAttribute("immediate") && metadata.getAttribute("immediate").equalsIgnoreCase("true")) {
- m_immediate = true;
- }
+ String imm = metadata.getAttribute("immediate");
+ m_immediate = imm != null && imm.equalsIgnoreCase("true");
ManipulationMetadata mm = new ManipulationMetadata(metadata);
Element[] hooksMetadata = metadata.getElements("callback");
for (int i = 0; i < hooksMetadata.length; i++) {
- if (! hooksMetadata[i].containsAttribute("method")) {
- throw new ConfigurationException("Lifecycle callback : A callback needs to contains a method attribute", getInstanceManager().getFactory().getName());
+ String method = hooksMetadata[i].getAttribute("method");
+ if (method == null) {
+ throw new ConfigurationException("Lifecycle callback : A callback needs to contains a method attribute");
}
- String methodName = hooksMetadata[i].getAttribute("method");
- MethodMetadata met = mm.getMethod(methodName, new String[0]);
+ MethodMetadata met = mm.getMethod(method, new String[0]);
int transition = -1;
- if (hooksMetadata[i].containsAttribute("transition")) {
- if (hooksMetadata[i].getAttribute("transition").equalsIgnoreCase("validate")) {
+ String trans = hooksMetadata[i].getAttribute("transition");
+ if (trans != null) {
+ if (trans.equalsIgnoreCase("validate")) {
transition = LifecycleCallback.VALIDATE;
- }
- if (hooksMetadata[i].getAttribute("transition").equalsIgnoreCase("invalidate")) {
+ } else if (trans.equalsIgnoreCase("invalidate")) {
transition = LifecycleCallback.INVALIDATE;
+ } else {
+ throw new ConfigurationException("Lifecycle callback : Unknown or malformed transition : " + transition);
}
- }
-
- //DEPRECATED BLOCK
- if (hooksMetadata[i].containsAttribute("initial")) {
- log(Logger.WARNING, "initial & final are deprecated, please use 'transition=validate|invalidate' instead.");
- if (hooksMetadata[i].containsAttribute("final")) {
- if (hooksMetadata[i].getAttribute("initial").equalsIgnoreCase("valid") && hooksMetadata[i].getAttribute("final").equalsIgnoreCase("invalid")) {
- transition = LifecycleCallback.INVALIDATE;
- } else {
- transition = LifecycleCallback.VALIDATE;
- }
- }
- }
- //END OF DEPRECATED BLOCK
-
- if (transition == -1) {
- log(Logger.ERROR, "Unknown or malformed transition");
- throw new ConfigurationException("Lifecycle callback : Unknown or malformed transition", getInstanceManager().getFactory().getName());
+ } else {
+ throw new ConfigurationException("Lifecycle callback : Unknown or malformed transition");
}
LifecycleCallback hk = null;
if (met != null) {
hk = new LifecycleCallback(this, transition, met);
} else {
- hk = new LifecycleCallback(this, transition, methodName);
+ hk = new LifecycleCallback(this, transition, method);
}
addCallback(hk);
}
@@ -177,16 +162,14 @@
try {
m_callbacks[i].call();
} catch (NoSuchMethodException e) {
- log(Logger.ERROR,
- "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not found", e);
+ log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not found", e);
+ getInstanceManager().stop();
} catch (IllegalAccessException e) {
- log(Logger.ERROR,
- "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not accessible", e);
+ log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " is not accessible", e);
+ getInstanceManager().stop();
} catch (InvocationTargetException e) {
- log(
- Logger.ERROR,
- "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " has throws an exception : "
- + e.getMessage());
+ log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The callback method " + m_callbacks[i].getMethod() + " has throws an exception : " + e.getMessage());
+ getInstanceManager().stop();
}
}
}
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 03f9eee..41b7250 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,6 +24,7 @@
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.metadata.Element;
import org.apache.felix.ipojo.parser.FieldMetadata;
import org.apache.felix.ipojo.parser.ManipulationMetadata;
@@ -50,33 +51,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 {
- String field = null;
Element[] lc = metadata.getElements("controller");
- if (lc.length > 0) {
- // Use only the first controller
- if (lc[0].containsAttribute("field")) {
- field = lc[0].getAttribute("field");
- } else {
- log(Logger.ERROR, "A lifecycle controler needs to contain a field attribute");
- throw new ConfigurationException("Lifecycle controller : the controller element needs to have a field attribute", getInstanceManager().getFactory().getName());
- }
- } else {
- return;
- }
-
- ManipulationMetadata mm = new ManipulationMetadata(metadata);
- FieldMetadata fm = mm.getField(field);
- if (fm == null) {
- log(Logger.ERROR, "The field " + field + " does not exist in the class");
- throw new ConfigurationException("Lifecycle controller : The field " + field + " does not exist in the class", getInstanceManager().getFactory().getName());
- }
-
- if (!fm.getFieldType().equalsIgnoreCase("boolean")) {
- log(Logger.ERROR, "The field " + field + " must be a boolean (" + fm.getFieldType() + " found)");
- throw new ConfigurationException("Lifecycle controller : The field " + field + " must be a boolean (" + fm.getFieldType() + " found)", getInstanceManager().getFactory().getName());
- }
-
- getInstanceManager().register(this, new FieldMetadata[] {fm}, null);
+ String field = lc[0].getAttribute("field");
+ getInstanceManager().register(this, new FieldMetadata[] {new FieldMetadata(field, "boolean")}, null);
}
/**
@@ -124,7 +101,36 @@
}
}
} else {
- log(Logger.ERROR, "Boolean expected");
+ log(Logger.ERROR, "Boolean expected for the lifecycle controller");
+ getInstanceManager().stop();
+ }
+ }
+
+ /**
+ * Initialize the component factory.
+ * The controller field is checked to avoid configure check.
+ * @param cd : 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)
+ */
+ public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
+ String field = null;
+ Element[] lc = metadata.getElements("controller");
+ // Use only the first controller
+ field = lc[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) {
+ 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)");
}
}
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
index fa46d2e..c54e47f 100644
--- 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
@@ -22,8 +22,6 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import org.apache.felix.ipojo.parser.FieldMetadata;
-import org.apache.felix.ipojo.parser.ManipulationMetadata;
import org.apache.felix.ipojo.parser.ParseUtils;
import org.apache.felix.ipojo.util.Logger;
@@ -75,9 +73,8 @@
* @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
- * @param manipulation : manipulation metadata
*/
- public Property(ProvidedService ps, String name, String field, String type, String value, ManipulationMetadata manipulation) {
+ public Property(ProvidedService ps, String name, String field, String type, String value) {
m_providedService = ps;
m_name = name;
m_field = field;
@@ -85,25 +82,8 @@
m_initialValue = value;
// Dynamic property case :
- if (m_field != null) {
- if (m_name == null) {
- m_name = m_field;
- }
- }
-
- // Check type if not already set
- if (m_type == null) {
- if (field == null) {
- ps.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "The property " + m_name + " has neither type neither field.");
- return;
- }
- FieldMetadata fm = manipulation.getField(field);
- if (fm == null) {
- m_providedService.getInstanceManager().getFactory().getLogger().log(Logger.ERROR,
- "[" + ps.getInstanceManager().getClassName() + "] A declared property was not found in the class : " + m_field);
- return;
- }
- m_type = fm.getFieldType();
+ if (m_field != null && m_name == null) {
+ m_name = m_field;
}
if (m_initialValue != null) {
@@ -221,18 +201,25 @@
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);
+ m_providedService.getInstanceManager().stop();
}
}
@@ -317,20 +304,25 @@
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().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().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);
+ m_providedService.getInstanceManager().stop();
}
}
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 1962ae7..0a2bfea 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
@@ -94,7 +94,7 @@
m_serviceSpecification = specification;
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()));
@@ -175,32 +175,25 @@
/**
* Return a service object for the dependency.
- *
- * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle,
- * org.osgi.framework.ServiceRegistration)
+ * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration)
* @param bundle : the bundle
* @param registration : the service registration of the registred service
- * @return : a new service object or a already created service object (in
- * the case of singleton)
+ * @return : a new service object or a already created service object (in the case of singleton)
*/
public Object getService(Bundle bundle, ServiceRegistration registration) {
-
+ Object svc = null;
switch (m_factoryPolicy) {
-
case SINGLETON_FACTORY:
- return m_handler.getInstanceManager().getPojoObject();
-
+ svc = m_handler.getInstanceManager().getPojoObject();
+ break;
case SERVICE_FACTORY:
- return m_handler.getInstanceManager().createPojoObject();
-
+ 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);
- return null;
+ m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Unknown factory policy for " + m_serviceSpecification + " : " + m_factoryPolicy);
+ getInstanceManager().stop();
}
-
+ return svc;
}
/**
@@ -296,6 +289,8 @@
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
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 b66f917..a791797 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,8 +19,13 @@
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;
+import java.util.List;
import java.util.Properties;
+import java.util.Set;
import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.IPojoConfiguration;
@@ -31,13 +36,14 @@
import org.apache.felix.ipojo.architecture.PropertyDescription;
import org.apache.felix.ipojo.handlers.dependency.Dependency;
import org.apache.felix.ipojo.handlers.dependency.DependencyHandler;
+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.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.util.Logger;
+import org.osgi.framework.Bundle;
/**
* Composite Provided Service Handler.
@@ -88,56 +94,30 @@
* @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 {
-
- ManipulationMetadata manipulation = new ManipulationMetadata(componentMetadata);
-
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++) {
- // Create a ProvidedServiceMetadata object
-
- // First : create the serviceSpecification array
- String[] serviceSpecification = new String[0];
- if (providedServices[i].containsAttribute("interface")) {
- String serviceSpecificationStr = providedServices[i].getAttribute("interface");
- serviceSpecification = ParseUtils.parseArrays(serviceSpecificationStr);
- } else {
- serviceSpecification = manipulation.getInterfaces();
- }
- if (serviceSpecification.length == 0) {
- log(Logger.ERROR, "Cannot instantiate a provided service : no specifications found (no interfaces implemented by the pojo)");
- throw new ConfigurationException("Provides : Cannot instantiate a provided service : no specifications found (no interfaces implemented by the pojo)", getInstanceManager().getFactory().getName());
- }
-
+ String[] serviceSpecifications = ParseUtils.parseArrays(providedServices[i].getAttribute("interface")); // Set by the initialize component factory.
+
// Get the factory policy
int factory = ProvidedService.SINGLETON_FACTORY;
- if (providedServices[i].containsAttribute("factory") && "service".equals(providedServices[i].getAttribute("factory"))) {
+ String fact = providedServices[i].getAttribute("factory");
+ if (fact != null && "service".equalsIgnoreCase(fact)) {
factory = ProvidedService.SERVICE_FACTORY;
}
// Then create the provided service
- ProvidedService ps = new ProvidedService(this, serviceSpecification, factory);
+ 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 = null;
- if (props[j].containsAttribute("name")) {
- name = props[j].getAttribute("name");
- }
- String value = null;
- if (props[j].containsAttribute("value")) {
- value = props[j].getAttribute("value");
- }
- String type = null;
- if (props[j].containsAttribute("type")) {
- type = props[j].getAttribute("type");
- }
- String field = null;
- if (props[j].containsAttribute("field")) {
- field = props[j].getAttribute("field");
- }
+ 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);
@@ -147,75 +127,120 @@
}
}
- Property prop = new Property(ps, name, field, type, value, manipulation);
+ 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));
+ }
}
// Attached to properties to the provided service
ps.setProperties(properties);
- if (checkProvidedService(ps, manipulation)) {
+ if (checkProvidedService(ps)) {
addProvidedService(ps);
} else {
String itfs = "";
- for (int j = 0; j < serviceSpecification.length; j++) {
- itfs = itfs + " " + serviceSpecification[j];
+ for (int j = 0; j < serviceSpecifications.length; j++) {
+ itfs = itfs + " " + serviceSpecifications[j];
}
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The provided service" + itfs + " is not valid");
- return;
+ throw new ConfigurationException("[" + getInstanceManager().getInstanceName() + "] The provided service" + itfs + " is not valid");
}
}
+ getInstanceManager().register(this, (FieldMetadata[]) fields.toArray(new FieldMetadata[fields.size()]), null);
+ }
+
+ /**
+ * Collect interfaces implemented by the POJO.
+ * @param specs : implemented interfaces.
+ * @param parent : parent class.
+ * @param bundle : Bundle object.
+ * @return the set of implemented interfaces.
+ * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+ */
+ private Set computeInterfaces(String[] specs, String parent, Bundle bundle) throws ClassNotFoundException {
+ Set result = new HashSet();
+ // First iterate on found specification in manipulation metadata
+ for (int i = 0; i < specs.length; i++) {
+ result.add(specs[i]);
+ // Iterate on interfaces implemented by the current interface
+ Class clazz = bundle.loadClass(specs[i]);
+ collectInterfaces(clazz, result, bundle);
+ }
- if (providedServices.length > 0) {
- FieldMetadata[] fields = new FieldMetadata[0];
- 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];
+ // Look for parent class.
+ if (parent != null) {
+ Class cl = bundle.loadClass(parent);
+ collectInterfacesFromClass(cl, result, bundle);
+ }
- // Check if the instance configuration has a value for this
- // property
- if (prop.getName() != null && configuration.get(prop.getName()) != null && !(configuration.get(prop.getName()) instanceof String)) {
- prop.set(configuration.get(prop.getName()));
- } else {
- if (prop.getField() != null && configuration.get(prop.getField()) != null && !(configuration.get(prop.getField()) instanceof String)) {
- prop.set(configuration.get(prop.getField()));
- }
- }
- if (prop.getField() != null) {
- FieldMetadata[] newFields = new FieldMetadata[fields.length + 1];
- System.arraycopy(fields, 0, newFields, 0, fields.length);
- newFields[fields.length] = manipulation.getField(prop.getField());
- fields = newFields;
- }
- }
- }
- getInstanceManager().register(this, fields, null);
+ return result;
+ }
+
+ /**
+ * Look for inherited interfaces.
+ * @param clazz : interface name to explore (class object)
+ * @param l : set (accumulator)
+ * @param b : bundle
+ * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+ */
+ private void collectInterfaces(Class clazz, Set l, Bundle b) throws ClassNotFoundException {
+ Class[] clazzes = clazz.getInterfaces();
+ for (int i = 0; i < clazzes.length; i++) {
+ l.add(clazzes[i].getName());
+ collectInterfaces(clazzes[i], l, b);
+ }
+ }
+
+ /**
+ * 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.
+ * @throws ClassNotFoundException : occurs if an interface cannot be load.
+ */
+ private void collectInterfacesFromClass(Class cl, Set l, Bundle b) throws ClassNotFoundException {
+ Class[] clazzes = cl.getInterfaces();
+ for (int i = 0; i < clazzes.length; i++) {
+ l.add(clazzes[i].getName());
+ collectInterfaces(clazzes[i], l, b);
+ }
+ // Iterate on parent classes
+ Class sup = cl.getSuperclass();
+ if (sup != null) {
+ collectInterfacesFromClass(sup, l, b);
}
}
/**
- * Check the provided service given in argument in the sense that the
- * metadata are consistent.
- *
+ * Check the provided service given in argument in the sense that the metadata are consistent.
* @param ps : the provided service to check.
- * @param manipulation : component-type manipulation metadata.
* @return true if the provided service is correct
* @throws ConfigurationException : the checked provided service is not correct.
*/
- private boolean checkProvidedService(ProvidedService ps, ManipulationMetadata manipulation) throws ConfigurationException {
+ private boolean checkProvidedService(ProvidedService ps) throws ConfigurationException {
for (int i = 0; i < ps.getServiceSpecification().length; i++) {
- // Check the implementation of the specification
- if (!manipulation.isInterfaceImplemented(ps.getServiceSpecification()[i])) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The service specification " + ps.getServiceSpecification()[i] + " is not implemented by the component class");
- throw new ConfigurationException("Provides : The service specification " + ps.getServiceSpecification()[i] + " is not implemented by the component class", getInstanceManager().getFactory().getName());
-
- }
-
+ String specName = ps.getServiceSpecification()[i];
+
// Check service level dependencies
try {
- Class spec = getInstanceManager().getFactory().loadClass(ps.getServiceSpecification()[i]);
+ Class spec = getInstanceManager().getFactory().loadClass(specName);
Field specField = spec.getField("specification");
Object o = specField.get(null);
if (o instanceof String) {
@@ -230,24 +255,18 @@
isDependencyCorrect(d, deps[j]);
}
} else {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] 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 " + ps.getServiceSpecification()[i] + " need to be a String", getInstanceManager().getFactory().getName());
+ throw new ConfigurationException("Provides : The specification field of the service specification " + ps.getServiceSpecification()[i] + " need to be a String");
}
} catch (NoSuchFieldException e) {
return true; // No specification field
} catch (ClassNotFoundException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The service specification " + ps.getServiceSpecification()[i] + " cannot be load");
- throw new ConfigurationException("Provides : The service specification " + ps.getServiceSpecification()[i] + " cannot be load", getInstanceManager().getFactory().getName());
+ throw new ConfigurationException("Provides : The service specification " + ps.getServiceSpecification()[i] + " cannot be load");
} catch (IllegalArgumentException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] 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 " + ps.getServiceSpecification()[i] + " is not accessible : " + e.getMessage(), getInstanceManager().getFactory().getName());
+ throw new ConfigurationException("Provides : The field 'specification' of the service specification " + ps.getServiceSpecification()[i] + " is not accessible : " + e.getMessage());
} catch (IllegalAccessException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] 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 " + ps.getServiceSpecification()[i] + " is not accessible : " + e.getMessage(), getInstanceManager().getFactory().getName());
+ throw new ConfigurationException("Provides : The field 'specification' of the service specification " + ps.getServiceSpecification()[i] + " is not accessible : " + e.getMessage());
} catch (ParseException e) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] 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 " + ps.getServiceSpecification()[i] + " does not contain a valid String : " + e.getMessage(), getInstanceManager().getFactory()
- .getName());
+ throw new ConfigurationException("Provides : The field 'specification' of the service specification " + ps.getServiceSpecification()[i] + " does not contain a valid String : " + e.getMessage());
}
}
@@ -263,14 +282,13 @@
DependencyHandler dh = (DependencyHandler) getHandler(IPojoConfiguration.IPOJO_NAMESPACE + ":requires");
if (dh == null) { return null; }
- if (element.containsAttribute("id")) {
+ String id = element.getAttribute("id");
+ if (id != null) {
// Look for dependency Id
- String id = element.getAttribute("id");
for (int i = 0; i < dh.getDependencies().length; i++) {
if (dh.getDependencies()[i].getId().equals(id)) { return dh.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++) {
@@ -287,34 +305,25 @@
* @throws ConfigurationException : the service level dependency and the implementation dependency does not match.
*/
private void isDependencyCorrect(Dependency dep, Element elem) throws ConfigurationException {
- boolean opt = false;
- if (elem.containsAttribute("optional") && elem.getAttribute("optional").equalsIgnoreCase("true")) {
- opt = true;
- }
+ String optional = elem.getAttribute("optional");
+ boolean opt = optional != null && optional.equalsIgnoreCase("true");
- boolean agg = false;
- if (elem.containsAttribute("aggregate") && elem.getAttribute("aggregate").equalsIgnoreCase("true")) {
- agg = true;
- }
+ String aggregate = elem.getAttribute("aggregate");
+ boolean agg = aggregate != null && aggregate.equalsIgnoreCase("true");
if (dep == null && !opt) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The requirement " + elem.getAttribute("specification") + " is not present in the implementation and is declared as a mandatory service-level requirement");
- throw new ConfigurationException("Provides : The requirement " + elem.getAttribute("specification") + " is not present in the implementation and is declared as a mandatory service-level requirement", getInstanceManager().getFactory()
- .getName());
+ throw new ConfigurationException("Provides : The requirement " + elem.getAttribute("specification") + " is not present in the implementation and is declared as a mandatory service-level requirement");
}
if (dep != null && dep.isAggregate() && !agg) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");
- throw new ConfigurationException("Provides : The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement", getInstanceManager().getFactory()
- .getName());
+ throw new ConfigurationException("Provides : The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");
}
- if (dep != null && elem.containsAttribute("filter")) {
- String filter = elem.getAttribute("filter");
+ String filter = elem.getAttribute("filter");
+ if (dep != null && filter != null) {
String filter2 = dep.getFilter();
if (filter2 == null || !filter2.equalsIgnoreCase(filter)) {
- log(Logger.ERROR, "[" + getInstanceManager().getInstanceName() + "] The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement");
- throw new ConfigurationException("Provides : The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement", getInstanceManager().getFactory().getName());
+ throw new ConfigurationException("Provides : The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement");
}
}
}
@@ -332,8 +341,7 @@
*
* @see org.apache.felix.ipojo.Handler#start()
*/
- public void start() {
- }
+ public void start() { }
/**
* Setter Callback Method.
@@ -490,48 +498,63 @@
* Initialize the component type.
* @param cd : 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)
*/
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) {
+ public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {
// Change ComponentInfo
Element[] provides = metadata.getElements("provides");
- ManipulationMetadata mm = new ManipulationMetadata(metadata);
+ ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
for (int i = 0; i < provides.length; i++) {
- String[] serviceSpecification = new String[0];
- if (provides[i].containsAttribute("interface")) {
- String serviceSpecificationStr = provides[i].getAttribute("interface");
- serviceSpecification = ParseUtils.parseArrays(serviceSpecificationStr);
- } else {
- serviceSpecification = mm.getInterfaces();
+ // First : create the serviceSpecification list
+ String[] serviceSpecification = manipulation.getInterfaces();
+ String parent = manipulation.getSuperClass();
+ Set all = null;
+ try {
+ all = computeInterfaces(serviceSpecification, parent, cd.getBundleContext().getBundle());
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("A interface cannot be loaded : " + e.getMessage());
}
- if (serviceSpecification.length == 0) {
- log(Logger.ERROR, "Cannot instantiate a provided service : no specifications found (no interfaces implemented by the pojo)");
- return;
+
+ String serviceSpecificationStr = provides[i].getAttribute("interface");
+ if (serviceSpecificationStr != null) {
+ 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());
+ }
+ }
+ all = new HashSet(itfs);
+ }
+
+ if (all.size() == 0) {
+ throw new ConfigurationException("Provides : Cannot instantiate a provided service : no specifications found (no interfaces implemented by the pojo)");
}
- for (int j = 0; j < serviceSpecification.length; j++) {
- cd.addProvidedServiceSpecification(serviceSpecification[j]);
+ String specs = null;
+ Set set = new HashSet(all);
+ Iterator it = set.iterator();
+ while (it.hasNext()) {
+ String sp = (String) it.next();
+ cd.addProvidedServiceSpecification(sp);
+ if (specs == null) {
+ specs = "{" + sp;
+ } else {
+ specs += "," + sp;
+ }
}
+
+ specs += "}";
+
+ provides[i].addAttribute(new Attribute("interface", specs)); // Add interface attribute to avoid checking in the configure method
Element[] props = provides[i].getElements("property");
for (int j = 0; j < props.length; j++) {
- String name = null;
- if (props[j].containsAttribute("name")) {
- name = props[j].getAttribute("name");
- }
- String value = null;
- if (props[j].containsAttribute("value")) {
- value = props[j].getAttribute("value");
- }
- String type = null;
- if (props[j].containsAttribute("type")) {
- type = props[j].getAttribute("type");
- }
- String field = null;
- if (props[j].containsAttribute("field")) {
- field = props[j].getAttribute("field");
- }
+ String name = props[j].getAttribute("name");
+ String value = props[j].getAttribute("value");
+ String type = props[j].getAttribute("type");
+ String field = props[j].getAttribute("field");
// Get property name :
if (field != null && name == null) {
@@ -541,15 +564,14 @@
// Check type if not already set
if (type == null) {
if (field == null) {
- System.err.println("The property " + name + " has neither type neither field.");
- return;
+ throw new ConfigurationException("The property " + name + " has neither type neither field.");
}
- FieldMetadata fm = mm.getField(field);
+ FieldMetadata fm = manipulation.getField(field);
if (fm == null) {
- System.err.println("A declared property was not found in the class : " + field);
- return;
+ throw new ConfigurationException("A declared property was not found in the class : " + field);
}
type = fm.getFieldType();
+ props[j].addAttribute(new Attribute("type", type));
}
cd.addProperty(new PropertyDescription(name, type, value));
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 939f6da..9c6ea8d 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
@@ -47,6 +47,16 @@
m_type = metadata.getAttribute("type");
}
+ /**
+ * Constructor.
+ * @param field : field name.
+ * @param type : type of the field.
+ */
+ public FieldMetadata(String field, String type) {
+ m_name = field;
+ m_type = type;
+ }
+
public String getFieldName() { return m_name; }
public String getFieldType() { return m_type; }
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 f993a2e..172338a 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
@@ -90,19 +90,22 @@
*/
private Dictionary parseInstance(Element instance) throws ParseException {
Dictionary dict = new Properties();
- if (instance.containsAttribute("name")) {
+ String name = instance.getAttribute("name");
+ String comp = instance.getAttribute("component");
+ if (name != null) {
dict.put("name", instance.getAttribute("name"));
}
- if (!instance.containsAttribute("component")) {
+
+ if (comp == null) {
throw new ParseException("An instance does not have the 'component' attribute");
}
- dict.put("component", instance.getAttribute("component"));
+ dict.put("component", comp);
for (int i = 0; i < instance.getElements("property").length; i++) {
parseProperty(instance.getElements("property")[i], dict);
}
-
+
return dict;
}
@@ -114,11 +117,13 @@
*/
private void parseProperty(Element prop, Dictionary dict) throws ParseException {
// Check that the property has a name
- if (!prop.containsAttribute("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 (prop.containsAttribute("value")) {
+ if (value != null) {
dict.put(prop.getAttribute("name"), prop.getAttribute("value"));
} else {
// Recursive case
@@ -130,7 +135,7 @@
Dictionary dict2 = new Properties();
for (int i = 0; i < subProps.length; i++) {
parseProperty(subProps[i], dict2);
- dict.put(prop.getAttribute("name"), dict2);
+ dict.put(name, dict2);
}
}
}
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/ManipulationMetadata.java
index 702793e..3d08854 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/ManipulationMetadata.java
@@ -42,6 +42,11 @@
* List of methods.
*/
private MethodMetadata[] m_methods = new MethodMetadata[0];
+
+ /**
+ * Super class (if not java.lang.object).
+ */
+ private String m_super;
/**
@@ -52,6 +57,7 @@
*/
public ManipulationMetadata(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]);
@@ -236,4 +242,8 @@
}
}
+ public String getSuperClass() {
+ return m_super;
+ }
+
}
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 61245eb..1a8b482 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
@@ -49,11 +49,13 @@
*/
MethodMetadata(Element metadata) {
m_name = metadata.getAttribute("name");
- if (metadata.containsAttribute("arguments")) {
- m_arguments = ParseUtils.parseArrays(metadata.getAttribute("arguments"));
+ String arg = metadata.getAttribute("arguments");
+ String rt = metadata.getAttribute("return");
+ if (arg != null) {
+ m_arguments = ParseUtils.parseArrays(arg);
}
- if (metadata.containsAttribute("return")) {
- m_return = metadata.getAttribute("return");
+ if (rt != null) {
+ m_return = rt;
}
}
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 546f359..08ceccb 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,6 +18,8 @@
*/
package org.apache.felix.ipojo.parser;
+import java.util.ArrayList;
+import java.util.List;
import java.util.StringTokenizer;
/**
@@ -53,6 +55,33 @@
}
/**
+ * Parse the string form of an array as {a, b, c}.
+ *
+ * @param str : the string form
+ * @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;
+ }
+ }
+
+ /**
* Split method.
* This method is equivalent of the String.split in java 1.4
* @param toSplit : String to split
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 a4daa34..02450d3 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
@@ -236,7 +236,7 @@
if (m_methodObj == null) {
m_manager.getFactory().getLogger().log(Logger.ERROR, "The method " + m_method + " cannot be called : method not found");
- return;
+ m_manager.stop();
} else {
m_methodObj.setAccessible(true);
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/ServiceReferenceRankingComparator.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/ServiceReferenceRankingComparator.java
new file mode 100644
index 0000000..6263c63
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/ServiceReferenceRankingComparator.java
@@ -0,0 +1,82 @@
+/*
+ * 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.Comparator;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Service Reference Comparator.
+ * This comparator follow OSGi Ranking policy.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceReferenceRankingComparator implements Comparator {
+
+ /**
+ * Compare two service reference.
+ * @param ref1 : reference 1
+ * @param ref2 : reference 2
+ * @return -1 if the reference 1 is 'higher' than the reference 2, 1 otherwise. (higher is term of ranking means a lower index)
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object ref1, Object ref2) {
+ if (ref1.equals(ref2)) { return 0; }
+
+ if (ref1 instanceof ServiceReference && ref2 instanceof ServiceReference) {
+ Object property1 = ((ServiceReference) ref1).getProperty(Constants.SERVICE_RANKING);
+ Object property2 = ((ServiceReference) ref2).getProperty(Constants.SERVICE_RANKING);
+
+ int rank1 = 0;
+ int rank2 = 0;
+ if (property1 instanceof Integer) {
+ rank1 = ((Integer) property1).intValue();
+ }
+ if (property2 instanceof Integer) {
+ rank2 = ((Integer) property2).intValue();
+ }
+
+ if (rank1 == rank2) {
+ // Check service.id
+ Object sid1 = ((ServiceReference) ref1).getProperty(Constants.SERVICE_ID);
+ Object sid2 = ((ServiceReference) ref2).getProperty(Constants.SERVICE_ID);
+
+ long rankId1 = ((Long) sid1).longValue();
+ long rankId2 = ((Long) sid2).longValue();
+
+ if (rankId1 == rankId2) {
+ return 0;
+ } else if (rankId1 < rankId2) {
+ return -1;
+ } else {
+ return 1;
+ }
+
+ } else if (rank1 > rank2) {
+ return 1;
+ } else {
+ return -1;
+ }
+
+ } else {
+ return 0;
+ }
+ }
+}
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 b7e146e..1c8ae1d 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
@@ -19,11 +19,10 @@
package org.apache.felix.ipojo.util;
import java.util.ArrayList;
-import java.util.Comparator;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.TreeMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -116,7 +115,7 @@
* @param context BundleContext object against which the tracking is done.
* @param clazz Class name of the services to be tracked.
* @param customizer The customizer object to call when services are added, modified, or removed in this Tracker object. If customizer is null, then this Tracker object will be used as
- * the TrackerCustomizer object and the Tracker object will call the TrackerCustomizer methods on itself.
+ * the TrackerCustomizer object and the Tracker object will call the TrackerCustomizer methods on itself.
*/
public Tracker(BundleContext context, String clazz, TrackerCustomizer customizer) {
this.m_context = context;
@@ -144,8 +143,7 @@
* @param context BundleContext object against which the tracking is done.
* @param filter Filter object to select the services to be tracked.
* @param customizer The customizer object to call when services are added, modified, or removed in this Tracker object. If customizer is null, then this Tracker object will be used as the
- * TrackerCustomizer object and the Tracker object will call the TrackerCustomizer methods on itself.
- * @since 1.1
+ * TrackerCustomizer object and the Tracker object will call the TrackerCustomizer methods on itself.
*/
public Tracker(BundleContext context, Filter filter, TrackerCustomizer customizer) {
this.m_context = context;
@@ -489,7 +487,7 @@
* class is the ServiceListener object for the tracker. This class is used to synchronize access to the tracked services. This is not a public class. It is only for use by the implementation of the Tracker
* class.
*/
- class Tracked extends TreeMap implements ServiceListener {
+ class Tracked extends HashMap implements ServiceListener {
/**
* UID.
*/
@@ -518,8 +516,7 @@
* Tracked constructor.
*/
protected Tracked() {
- //TODO : set the comparator according to the binding policy.
- super(new ReferenceComparator());
+ super();
m_closed = false;
m_adding = new ArrayList(6);
m_initial = new LinkedList();
@@ -706,63 +703,5 @@
m_cachedReference = null; /* clear cached value */
m_cachedService = null; /* clear cached value */
}
-
}
-
- /**
- * Service Reference Comparator.
- */
- private class ReferenceComparator implements Comparator {
-
- /**
- * Compare two service reference.
- * @param ref1 : reference 1
- * @param ref2 : reference 2
- * @return -1 if the reference 1 is 'higher' than the reference 2, 1 otherwise. (higher is term of ranking means a lower index)
- * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
- */
- public int compare(Object ref1, Object ref2) {
- if (ref1.equals(ref2)) { return 0; }
-
- if (ref1 instanceof ServiceReference && ref2 instanceof ServiceReference) {
- Object property1 = ((ServiceReference) ref1).getProperty(Constants.SERVICE_RANKING);
- Object property2 = ((ServiceReference) ref2).getProperty(Constants.SERVICE_RANKING);
-
- int rank1 = 0;
- int rank2 = 0;
- if (property1 instanceof Integer) {
- rank1 = ((Integer) property1).intValue();
- }
- if (property2 instanceof Integer) {
- rank2 = ((Integer) property2).intValue();
- }
-
- if (rank1 == rank2) {
- // Check service.id
- Object sid1 = ((ServiceReference) ref1).getProperty(Constants.SERVICE_ID);
- Object sid2 = ((ServiceReference) ref2).getProperty(Constants.SERVICE_ID);
-
- long rankId1 = ((Long) sid1).longValue();
- long rankId2 = ((Long) sid2).longValue();
-
- if (rankId1 == rankId2) {
- return 0;
- } else if (rankId1 < rankId2) {
- return -1;
- } else {
- return 1;
- }
-
- } else if (rank1 > rank2) {
- return 1;
- } else {
- return -1;
- }
-
- } else {
- return 0;
- }
- }
- }
-
}
diff --git a/ipojo/core/src/main/resources/metadata.xml b/ipojo/core/src/main/resources/metadata.xml
index 1095057..9d02336 100644
--- a/ipojo/core/src/main/resources/metadata.xml
+++ b/ipojo/core/src/main/resources/metadata.xml
@@ -1,39 +1,39 @@
<ipojo>
<!-- Primitives handler -->
-<handler classname="org.apache.felix.ipojo.handlers.lifecycle.controller.ControllerHandler" name="controller"/>
-<handler classname="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler" name="callback" level="1"/>
-<handler classname="org.apache.felix.ipojo.handlers.dependency.DependencyHandler" name="requires" level="0">
+<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"/>
-<handler classname="org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler" name="properties" level="1"/>
-<handler classname="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler" name="architecture">
+<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">
+<handler classname="org.apache.felix.ipojo.composite.instance.InstanceHandler" name="instance" type="composite" architecture="false">
<controller field="m_isValid"/>
- <requires filter="(factory.state=1)" field="m_factories" optional="true">
+ <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">
+<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">
+<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">
+<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">
+<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">
+<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>
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
index 2309f23..16c7f61 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
@@ -45,7 +45,7 @@
/**
* Interfaces implemented by the component.
*/
- private String[] m_itfs = new String[0];
+ private List m_itfs = new ArrayList();
/**
* Field map [field name, type] discovered in the component class.
@@ -56,6 +56,11 @@
* Method List of method descriptor discovered in the component class.
*/
private List m_methods = new ArrayList()/* <MethodDesciptor> */;
+
+ /**
+ * Super class if not java.lang.Object.
+ */
+ private String m_superClass;
/**
* Check if the _cm field already exists.
@@ -115,8 +120,16 @@
*/
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
- // Store the interfaces :
- m_itfs = interfaces;
+
+ if (! superName.equals("java/lang/Object")) {
+ m_superClass = superName.replace('/', '.');
+ }
+
+ for (int i = 0; i < interfaces.length; i++) {
+ if (! interfaces[i].equals("org/apache/felix/ipojo/Pojo")) {
+ m_itfs.add(interfaces[i].replace('/', '.'));
+ }
+ }
}
/**
@@ -132,8 +145,20 @@
*/
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
- if (!name.equals("<init>") && !name.equals("<clinit>")) {
- m_methods.add(new MethodDescriptor(name, desc));
+ if (!name.equals("<clinit>")) {
+
+ if (name.equals("<init>")) {
+ m_methods.add(new MethodDescriptor("$init", desc));
+ } else {
+ // Avoid constructors.
+ if (!(name.startsWith("_get") || // Avoid getter method
+ name.startsWith("_set") || // Avoid setter method
+ name.equals("_setComponentManager") || // Avoid the set method
+ name.equals("getComponentInstance"))) { // Avoid the getComponentInstance method
+ m_methods.add(new MethodDescriptor(name, desc));
+ }
+ }
+
}
return null;
}
@@ -142,7 +167,7 @@
* Get collected interfaces.
* @return the interfaces implemented by the component class.
*/
- public String[] getInterfaces() {
+ public List getInterfaces() {
return m_itfs;
}
@@ -161,5 +186,9 @@
public List getMethods() {
return m_methods;
}
+
+ public String getSuperClass() {
+ return m_superClass;
+ }
}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ConstructorCodeAdapter.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ConstructorCodeAdapter.java
index b153751..1a25c4e 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ConstructorCodeAdapter.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ConstructorCodeAdapter.java
@@ -21,16 +21,17 @@
import java.util.Set;
import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
/**
* Constructor Adapter : add a component manager argument inside a constructor.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ConstructorCodeAdapter extends MethodAdapter implements Opcodes {
+public class ConstructorCodeAdapter extends GeneratorAdapter implements Opcodes {
/**
* The class containing the field.
@@ -47,6 +48,11 @@
* Set of contained fields.
*/
private Set m_fields;
+
+ /**
+ * Constructor description.
+ */
+ private String m_desc;
/**
* PropertyCodeAdapter constructor.
@@ -54,12 +60,16 @@
* @param mv MethodVisitor
* @param owner Name of the class
* @param fields List of contained fields
+ * @param access Access
+ * @param desc : constructor descriptor
+ * @param name : name
*/
- public ConstructorCodeAdapter(final MethodVisitor mv, final String owner, Set fields) {
- super(mv);
+ public ConstructorCodeAdapter(final MethodVisitor mv, final String owner, Set fields, int access, String name, String desc) {
+ super(mv, access, name, desc);
m_owner = owner;
m_superDetected = false;
m_fields = fields;
+ m_desc = desc;
}
@@ -115,6 +125,10 @@
mv.visitVarInsn(ALOAD, 1); // CM is always the first argument
// 3) Initialize the field
mv.visitMethodInsn(INVOKESPECIAL, m_owner, "_setComponentManager", "(Lorg/apache/felix/ipojo/InstanceManager;)V");
+
+ // Add the entry callback call.
+ methodEntry();
+
// insertion finished
} else {
mv.visitMethodInsn(opcode, owner, name, desc);
@@ -181,8 +195,104 @@
* @see org.objectweb.asm.MethodAdapter#visitMaxs(int, int)
*/
public void visitMaxs(int maxStack, int maxLocals) {
- mv.visitMaxs(maxStack, maxLocals + 1);
+ mv.visitMaxs(maxStack + 1, maxLocals + 2);
}
+
+ /**
+ * Visit zero argument instruction.
+ * This allow to catch RETURN instruction in order to insert the invocation to exit callback.
+ * @param opcode : instruction code
+ * @see org.objectweb.asm.MethodAdapter#visitInsn(int)
+ */
+ public void visitInsn(int opcode) {
+ switch(opcode) {
+ case RETURN:
+ onMethodExit(opcode);
+ break;
+ default :
+ break;
+ }
+ super.visitInsn(opcode);
+ }
+
+ /**
+ * Method injecting call at the entry of each method.
+ */
+ private void methodEntry() {
+ Type[] args = Type.getArgumentTypes(m_desc);
+ String name = "$init";
+
+ for (int i = 0; i < args.length; i++) {
+ String cn = args[i].getClassName();
+ if (cn.endsWith("[]")) {
+ cn = cn.replace('[', '$');
+ cn = cn.substring(0, cn.length() - 1);
+ }
+ cn = cn.replace('.', '_');
+ name += cn;
+ }
+
+ String flag = "_M" + name;
+
+ Label l0 = new Label();
+ mv.visitLabel(l0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, m_owner, flag, "Z");
+ Label l1 = new Label();
+ mv.visitJumpInsn(IFEQ, l1);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
+ mv.visitLdcInsn(name);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "entryCallback", "(Ljava/lang/String;)V");
+ mv.visitLabel(l1);
+ }
+
+ /**
+ * Method injecting call at the exit of each method.
+ * @param opcode : returned opcode (ARETURN, IRETURN, ATHROW ...)
+ * @see org.objectweb.asm.commons.AdviceAdapter#onMethodExit(int)
+ */
+ protected void onMethodExit(int opcode) {
+ Type[] args = Type.getArgumentTypes(m_desc);
+ String name = "$init";
+
+ for (int i = 0; i < args.length; i++) {
+ String cn = args[i].getClassName();
+ if (cn.endsWith("[]")) {
+ cn = cn.replace('[', '$');
+ cn = cn.substring(0, cn.length() - 1);
+ }
+ cn = cn.replace('.', '_');
+ name += cn;
+ }
+
+ String flag = "_M" + name;
+
+ int local = newLocal(Type.getType(Object.class));
+ local++;
+ visitInsn(ACONST_NULL);
+
+ mv.visitVarInsn(ASTORE, local);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, m_owner, flag, "Z");
+ Label l5 = new Label();
+ mv.visitJumpInsn(IFEQ, l5);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
+ mv.visitLdcInsn(name);
+ mv.visitVarInsn(ALOAD, local);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "exitCallback", "(Ljava/lang/String;Ljava/lang/Object;)V");
+
+ mv.visitLabel(l5);
+ }
+
+
+ /**
+ * Do nothing.
+ * @see org.objectweb.asm.commons.AdviceAdapter#onMethodEnter()
+ */
+ protected void onMethodEnter() { }
+
}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java
index e3b6628..fec3d3e 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java
@@ -119,7 +119,7 @@
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
Label l2 = new Label();
mv.visitJumpInsn(IFNE, l2);
- //TODO move in
+
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, m_owner, name, internalType);
@@ -162,41 +162,10 @@
mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
- // mv.visitFieldInsn(GETFIELD, m_owner, name, "["+type.getInternalName()+";");
- mv.visitFieldInsn(GETFIELD, m_owner, name, internalType);
- mv.visitVarInsn(ASTORE, 1);
-
- mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitLdcInsn(name);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
- mv.visitVarInsn(ASTORE, 2);
-
- mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;)Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, internalType);
- mv.visitVarInsn(ASTORE, 3);
-
- Label l3a = new Label();
- mv.visitLabel(l3a);
-
- mv.visitVarInsn(ALOAD, 1);
- Label l4a = new Label();
- mv.visitJumpInsn(IFNULL, l4a);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitVarInsn(ALOAD, 3);
- Label l5a = new Label();
- mv.visitJumpInsn(IF_ACMPEQ, l5a); // Test equality on object.
-
- // Invoke the _set method
- mv.visitLabel(l4a);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(ALOAD, 3);
- mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(" + internalType + ")V");
-
- // End of the method
- mv.visitLabel(l5a);
- mv.visitVarInsn(ALOAD, 3);
mv.visitInsn(ARETURN);
// End
@@ -240,46 +209,17 @@
mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
- mv.visitVarInsn(type.getOpcode(ISTORE), 1);
-
- mv.visitTypeInsn(NEW, boxingType);
- mv.visitInsn(DUP);
- mv.visitVarInsn(type.getOpcode(ILOAD), 1);
- mv.visitMethodInsn(INVOKESPECIAL, boxingType, "<init>", "(" + internalName + ")V");
- mv.visitVarInsn(ASTORE, 2);
-
- mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitLdcInsn(name);
- mv.visitVarInsn(ALOAD, 2);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
- mv.visitVarInsn(ASTORE, 3);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;)Ljava/lang/Object;");
+ mv.visitVarInsn(ASTORE, 1);
- mv.visitVarInsn(ALOAD, 3);
+ mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, boxingType);
- mv.visitVarInsn(ASTORE, 4);
+ mv.visitVarInsn(ASTORE, 2);
- mv.visitVarInsn(ALOAD, 4);
+ mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, boxingType, unboxingMethod, "()" + internalName);
- mv.visitVarInsn(type.getOpcode(ISTORE), 5);
-
- Label l5 = new Label();
- mv.visitLabel(l5);
-
- mv.visitVarInsn(type.getOpcode(ILOAD), 1);
- mv.visitVarInsn(type.getOpcode(ILOAD), 5);
- Label l6 = new Label();
- mv.visitJumpInsn(type.getOpcode(IF_ICMPEQ), l6);
-
- Label l7 = new Label();
- mv.visitLabel(l7);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(type.getOpcode(ILOAD), 5);
- mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(" + internalName + ")V");
- mv.visitLabel(l6);
-
- mv.visitVarInsn(type.getOpcode(ILOAD), 5);
mv.visitInsn(type.getOpcode(IRETURN));
break;
@@ -288,59 +228,29 @@
boxingType = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][1];
unboxingMethod = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][2];
- Label l00 = new Label();
- mv.visitLabel(l00);
+ l0 = new Label();
+ mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
- Label l10 = new Label();
- mv.visitJumpInsn(IFNE, l10);
+ l1 = new Label();
+ mv.visitJumpInsn(IFNE, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
mv.visitInsn(LRETURN);
- mv.visitLabel(l10);
-
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
- mv.visitVarInsn(LSTORE, 1);
-
- mv.visitTypeInsn(NEW, boxingType);
- mv.visitInsn(DUP);
- mv.visitVarInsn(LLOAD, 1);
- mv.visitMethodInsn(INVOKESPECIAL, boxingType, "<init>", "(" + internalName + ")V");
- mv.visitVarInsn(ASTORE, 3); // Double Space
+ mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitLdcInsn(name);
- mv.visitVarInsn(ALOAD, 3);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
- mv.visitVarInsn(ASTORE, 4);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;)Ljava/lang/Object;");
+ mv.visitVarInsn(ASTORE, 1);
- mv.visitVarInsn(ALOAD, 4);
+ mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, boxingType);
- mv.visitVarInsn(ASTORE, 5);
+ mv.visitVarInsn(ASTORE, 2);
- mv.visitVarInsn(ALOAD, 5);
+ mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, boxingType, unboxingMethod, "()" + internalName);
- mv.visitVarInsn(LSTORE, 6);
-
- l5 = new Label();
- mv.visitLabel(l5);
-
- mv.visitVarInsn(LLOAD, 1);
- mv.visitVarInsn(LLOAD, 6);
- mv.visitInsn(LCMP);
- l6 = new Label();
- mv.visitJumpInsn(IFEQ, l6);
-
- l7 = new Label();
- mv.visitLabel(l7);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(LLOAD, 6);
- mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(" + internalName + ")V");
- mv.visitLabel(l6);
-
- mv.visitVarInsn(LLOAD, 6);
mv.visitInsn(LRETURN);
break;
@@ -350,59 +260,29 @@
boxingType = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][1];
unboxingMethod = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][2];
- Label l01 = new Label();
- mv.visitLabel(l01);
+ l0 = new Label();
+ mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
- Label l11 = new Label();
- mv.visitJumpInsn(IFNE, l11);
+ l1 = new Label();
+ mv.visitJumpInsn(IFNE, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
mv.visitInsn(DRETURN);
- mv.visitLabel(l11);
-
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
- mv.visitVarInsn(DSTORE, 1);
-
- mv.visitTypeInsn(NEW, boxingType);
- mv.visitInsn(DUP);
- mv.visitVarInsn(DLOAD, 1);
- mv.visitMethodInsn(INVOKESPECIAL, boxingType, "<init>", "(" + internalName + ")V");
- mv.visitVarInsn(ASTORE, 3); // Double Space
+ mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitLdcInsn(name);
- mv.visitVarInsn(ALOAD, 3);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
- mv.visitVarInsn(ASTORE, 4);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;)Ljava/lang/Object;");
+ mv.visitVarInsn(ASTORE, 1);
- mv.visitVarInsn(ALOAD, 4);
+ mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, boxingType);
- mv.visitVarInsn(ASTORE, 5);
+ mv.visitVarInsn(ASTORE, 2);
- mv.visitVarInsn(ALOAD, 5);
+ mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, boxingType, unboxingMethod, "()" + internalName);
- mv.visitVarInsn(DSTORE, 6);
-
- l5 = new Label();
- mv.visitLabel(l5);
-
- mv.visitVarInsn(DLOAD, 1);
- mv.visitVarInsn(DLOAD, 6);
- mv.visitInsn(DCMPL);
- l6 = new Label();
- mv.visitJumpInsn(IFEQ, l6);
-
- l7 = new Label();
- mv.visitLabel(l7);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(DLOAD, 6);
- mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(" + internalName + ")V");
- mv.visitLabel(l6);
-
- mv.visitVarInsn(DLOAD, 6);
mv.visitInsn(DRETURN);
break;
@@ -412,110 +292,50 @@
boxingType = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][1];
unboxingMethod = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][2];
- Label l02 = new Label();
- mv.visitLabel(l02);
+ l0 = new Label();
+ mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
- Label l12 = new Label();
- mv.visitJumpInsn(IFNE, l12);
+ l1 = new Label();
+ mv.visitJumpInsn(IFNE, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
mv.visitInsn(FRETURN);
- mv.visitLabel(l12);
-
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, m_owner, name, internalName);
- mv.visitVarInsn(FSTORE, 1);
-
- mv.visitTypeInsn(NEW, boxingType);
- mv.visitInsn(DUP);
- mv.visitVarInsn(FLOAD, 1);
- mv.visitMethodInsn(INVOKESPECIAL, boxingType, "<init>", "(" + internalName + ")V");
- mv.visitVarInsn(ASTORE, 2); // One Space
+ mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitLdcInsn(name);
- mv.visitVarInsn(ALOAD, 2);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
- mv.visitVarInsn(ASTORE, 3);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;)Ljava/lang/Object;");
+ mv.visitVarInsn(ASTORE, 1);
- mv.visitVarInsn(ALOAD, 3);
+ mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, boxingType);
- mv.visitVarInsn(ASTORE, 4);
+ mv.visitVarInsn(ASTORE, 2);
- mv.visitVarInsn(ALOAD, 4);
+ mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, boxingType, unboxingMethod, "()" + internalName);
- mv.visitVarInsn(FSTORE, 5);
-
- l5 = new Label();
- mv.visitLabel(l5);
-
- mv.visitVarInsn(FLOAD, 1);
- mv.visitVarInsn(FLOAD, 5);
- mv.visitInsn(FCMPL);
- l6 = new Label();
- mv.visitJumpInsn(IFEQ, l6);
-
- l7 = new Label();
- mv.visitLabel(l7);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(FLOAD, 5);
- mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(" + internalName + ")V");
- mv.visitLabel(l6);
-
- mv.visitVarInsn(FLOAD, 5);
mv.visitInsn(FRETURN);
break;
case Type.OBJECT:
- Label l03 = new Label();
- mv.visitLabel(l03);
+ l0 = new Label();
+ mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
- Label l13 = new Label();
- mv.visitJumpInsn(IFNE, l13);
+ l1 = new Label();
+ mv.visitJumpInsn(IFNE, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, name, "L" + type.getInternalName() + ";");
mv.visitInsn(ARETURN);
- mv.visitLabel(l13);
-
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, m_owner, name, "L" + type.getInternalName() + ";");
- mv.visitVarInsn(ASTORE, 1);
+ mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitLdcInsn(name);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
- mv.visitVarInsn(ASTORE, 2);
-
- mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getterCallback", "(Ljava/lang/String;)Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, type.getInternalName());
- mv.visitVarInsn(ASTORE, 3);
-
- Label l3b = new Label();
- mv.visitLabel(l3b);
-
- mv.visitVarInsn(ALOAD, 1);
- Label l4b = new Label();
- mv.visitJumpInsn(IFNULL, l4b);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitVarInsn(ALOAD, 3);
-
- Label l5b = new Label();
- mv.visitJumpInsn(IF_ACMPEQ, l5b); // Test equality on object.
-
- mv.visitLabel(l4b);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(ALOAD, 3);
- mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(L" + type.getInternalName() + ";)V");
-
- // End of the getter method, return the object
- mv.visitLabel(l5b);
- mv.visitVarInsn(ALOAD, 3);
mv.visitInsn(ARETURN);
break;
@@ -555,7 +375,7 @@
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
Label l22 = new Label();
mv.visitJumpInsn(IFNE, l22);
- //TODO move in
+
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(type.getOpcode(ILOAD), 1);
mv.visitFieldInsn(PUTFIELD, m_owner, name, internalName);
@@ -593,7 +413,7 @@
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
Label l23 = new Label();
mv.visitJumpInsn(IFNE, l23);
- //TODO move in
+
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(type.getOpcode(ILOAD), 1);
mv.visitFieldInsn(PUTFIELD, m_owner, name, internalName);
@@ -624,7 +444,7 @@
mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");
Label l24 = new Label();
mv.visitJumpInsn(IFNE, l24);
- //TODO move in
+
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, m_owner, name, "L" + type.getInternalName() + ";");
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
index acb18fc..1917582 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
@@ -24,8 +24,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -44,17 +42,22 @@
/**
* Store the visited fields : [name of the field, type of the field].
*/
- private Map m_fields = new HashMap();
+ private Map m_fields;
/**
* Store the interface implemented by the class.
*/
- private String[] m_interfaces = new String[0];
+ private List m_interfaces;
/**
* Store the methods list.
*/
- private List m_methods = new ArrayList();
+ private List m_methods;
+
+ /**
+ * Pojo super class.
+ */
+ private String m_superClass;
/**
* Manipulate the class.
@@ -65,12 +68,6 @@
* @throws Exception : occurs if the manipulation failed.
*/
public boolean manipulate(String name, File outputDirectory) throws Exception {
-
- // Initialize fields, interfaces and methods
- m_fields = new HashMap();
- m_interfaces = new String[0];
- m_methods = new ArrayList();
-
// gets an input stream to read the byte code of the class
String path = outputDirectory + "/" + name.replace('.', '/') + ".class";
File clazz = new File(path);
@@ -92,33 +89,14 @@
ckReader.accept(ck, ClassReader.SKIP_FRAMES);
is1.close();
- m_fields = ck.getFields(); // GEt visited fields (contains only POJO fields)
+ m_fields = ck.getFields(); // Get visited fields (contains only POJO fields)
- // Get interface and remove POJO interface is presents
- String[] its = ck.getInterfaces();
- List l = new ArrayList();
- for (int i = 0; i < its.length; i++) {
- l.add(its[i]);
- }
- l.remove("org/apache/felix/ipojo/Pojo");
+ // Get interfaces and super class.
+ m_interfaces = ck.getInterfaces();
+ m_superClass = ck.getSuperClass();
- m_interfaces = new String[l.size()];
- for (int i = 0; i < m_interfaces.length; i++) {
- m_interfaces[i] = ((String) l.get(i)).replace('/', '.');
- }
-
- // Get the method list
- // Remove iPOJO methods
- for (int i = 0; i < ck.getMethods().size(); i++) {
- MethodDescriptor method = (MethodDescriptor) ck.getMethods().get(i);
- if (!(method.getName().startsWith("_get") || // Avoid getter method
- method.getName().startsWith("_set") || // Avoid setter method
- method.getName().equals("_setComponentManager") || // Avoid the set method
- method.getName().equals("getComponentInstance"))) { // Avoid the getComponentInstance method
- System.err.println(" Add the method : " + method);
- m_methods.add(method);
- }
- }
+ // Get the methods list
+ m_methods = ck.getMethods();
if (!ck.isalreadyManipulated()) {
@@ -163,30 +141,14 @@
ckReader.accept(ck, ClassReader.SKIP_FRAMES);
is1.close();
- m_fields = ck.getFields();
+ m_fields = ck.getFields(); // Get visited fields (contains only POJO fields)
- // Get interface and remove POJO interface is presents
- String[] its = ck.getInterfaces();
- List l = new ArrayList();
- for (int i = 0; i < its.length; i++) {
- l.add(its[i]);
- }
- l.remove("org/apache/felix/ipojo/Pojo");
+ // Get interfaces and super class.
+ m_interfaces = ck.getInterfaces();
+ m_superClass = ck.getSuperClass();
- m_interfaces = new String[l.size()];
- for (int i = 0; i < m_interfaces.length; i++) {
- m_interfaces[i] = ((String) l.get(i)).replace('/', '.');
- }
-
- for (int i = 0; i < ck.getMethods().size(); i++) {
- MethodDescriptor method = (MethodDescriptor) ck.getMethods().get(i);
- if (!(method.getName().startsWith("_get") || // Avoid getter method
- method.getName().startsWith("_set") || // Avoid setter method
- method.getName().equals("_setComponentManager") || // Avoid the set method
- method.getName().equals("getComponentInstance"))) { // Avoid the getComponentInstance method
- m_methods.add(method);
- }
- }
+ // Get the methods list
+ m_methods = ck.getMethods();
ClassWriter finalWriter = null;
if (!ck.isalreadyManipulated()) {
@@ -215,12 +177,18 @@
*/
public Element getManipulationMetadata() {
Element elem = new Element("Manipulation", "");
- for (int j = 0; j < m_interfaces.length; j++) {
+
+ if (m_superClass != null) {
+ elem.addAttribute(new Attribute("super", m_superClass));
+ }
+
+ for (int j = 0; j < m_interfaces.size(); j++) {
Element itf = new Element("Interface", "");
- Attribute att = new Attribute("name", m_interfaces[j]);
+ Attribute att = new Attribute("name", m_interfaces.get(j).toString());
itf.addAttribute(att);
elem.addElement(itf);
}
+
for (Iterator it = m_fields.keySet().iterator(); it.hasNext();) {
Element field = new Element("Field", "");
String name = (String) it.next();
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
index 06bb461..f58cc6b 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
@@ -145,7 +145,7 @@
*/
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
// Add the field to the list.
- if ((access & ACC_STATIC) == 0) {
+ if (((access & ACC_STATIC) == 0) && (!name.startsWith("class$"))) {
addFlagField(name);
m_getterSetterCreator.visitField(access, name, desc, signature, value);
}
@@ -179,24 +179,45 @@
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
// Avoid manipulating special method
if (name.equals("<clinit>") || name.equals("class$")) { return super.visitMethod(access, name, desc, signature, exceptions); }
- // The constructor is manipulated separatly
- if (name.equals("<init>")) {
+ // The constructor is manipulated separately
+ if (name.equals("<init>")) {
+
// 1) change the constructor descriptor (add a component manager arg as first argument)
String newDesc = desc.substring(1);
newDesc = "(Lorg/apache/felix/ipojo/InstanceManager;" + newDesc;
// Insert the new constructor
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, "<init>", newDesc, null, null);
+
+ Type[] args = Type.getArgumentTypes(newDesc);
+ String id = "$init";
+ for (int i = 0; i < args.length; i++) {
+ String cn = args[i].getClassName();
+ if (cn.endsWith("[]")) {
+ cn = cn.replace('[', '$');
+ cn = cn.substring(0, cn.length() - 1);
+ }
+ cn = cn.replace('.', '_');
+ id += cn;
+ }
+
+ String flag = "_M" + id;
+ m_methods.add(id);
+
+ FieldVisitor flagField = cv.visitField(Opcodes.ACC_PRIVATE, flag, "Z", null, null);
+ if (flagField != null) {
+ flagField.visitEnd();
+ }
if (mv == null) {
return null;
} else {
- // return new ConstructorCodeAdapter(mv, access, desc, m_owner);
- return new ConstructorCodeAdapter(mv, m_owner, m_fields);
+ return new ConstructorCodeAdapter(mv, m_owner, m_fields, access, name, newDesc);
}
} else { // "Normal methods"
// avoid manipulating static methods.
if ((access & ACC_STATIC) == ACC_STATIC) { return super.visitMethod(access, name, desc, signature, exceptions); }
+
Type[] args = Type.getArgumentTypes(desc);
String id = name;
for (int i = 0; i < args.length; i++) {
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
index f6ecd63..7b68f69 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
@@ -280,7 +280,8 @@
Element[] props = m_parent.getElements("Property");
Element prop = null;
for (int i = 0; prop == null && i < props.length; i++) {
- if (props[i].containsAttribute("name") && props[i].getAttribute("name").equals(m_name)) {
+ String name = props[i].getAttribute("name");
+ if (name != null && name.equals(m_name)) {
prop = props[i];
}
}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
index 2ffa9da..9859888 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
@@ -335,7 +335,8 @@
Element[] props = m_parent.getElements("Property");
Element prop = null;
for (int i = 0; prop == null && i < props.length; i++) {
- if (props[i].containsAttribute("name") && props[i].getAttribute("name").equals(m_name)) {
+ String name = props[i].getAttribute("name");
+ if (name != null && name.equals(m_name)) {
prop = props[i];
}
}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
index 15f6e32..18b025a 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
@@ -349,14 +349,8 @@
private List getDeclaredComponents(Element[] meta) {
List componentClazzes = new ArrayList();
for (int i = 0; i < meta.length; i++) {
- if (meta[i].getName().equalsIgnoreCase("component") && meta[i].containsAttribute("className")) {
- String name = meta[i].getAttribute("classname");
- name = name.replace('.', '/');
- name += ".class";
- componentClazzes.add(new ComponentInfo(name, meta[i]));
- }
- if (meta[i].getName().equalsIgnoreCase("handler") && meta[i].containsAttribute("className")) {
- String name = meta[i].getAttribute("classname");
+ String name = meta[i].getAttribute("classname");
+ if (name != null) { // Only handler and component have a classname attribute
name = name.replace('.', '/');
name += ".class";
componentClazzes.add(new ComponentInfo(name, meta[i]));
@@ -626,7 +620,7 @@
*/
private String buildManifestMetadata(Element element, String actual) {
String result = "";
- if (element.getNameSpace().equals("")) {
+ if (element.getNameSpace() == null) {
result = actual + element.getName() + " { ";
} else {
result = actual + element.getNameSpace() + ":" + element.getName() + " { ";
@@ -635,7 +629,7 @@
Attribute[] atts = element.getAttributes();
for (int i = 0; i < atts.length; i++) {
Attribute current = (Attribute) atts[i];
- if (current.getNameSpace().equals("")) {
+ if (current.getNameSpace() == null) {
result = result + "$" + current.getName() + "=\"" + current.getValue() + "\" ";
} else {
result = result + "$" + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\" ";
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java
index 906ea05..bea964a 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java
@@ -224,7 +224,6 @@
*/
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
Element elem = new Element(localName, namespaceURI);
-
for (int i = 0; i < atts.getLength(); i++) {
String name = (String) atts.getLocalName(i);
String ns = (String) atts.getURI(i);
diff --git a/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Attribute.java b/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Attribute.java
index 44fd7e7..5ffba50 100644
--- a/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Attribute.java
+++ b/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Attribute.java
@@ -48,7 +48,6 @@
public Attribute(String name, String value) {
m_name = name.toLowerCase();
m_value = value;
- m_nameSpace = "";
}
/**
@@ -60,7 +59,9 @@
public Attribute(String name, String ns, String value) {
m_name = name.toLowerCase();
m_value = value;
- m_nameSpace = ns;
+ if (ns != null && ns.length() > 0) {
+ m_nameSpace = ns;
+ }
}
/**
diff --git a/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Element.java b/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Element.java
index 25aab36..7b59150 100644
--- a/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Element.java
+++ b/ipojo/metadata/src/main/java/org/apache/felix/ipojo/metadata/Element.java
@@ -64,7 +64,9 @@
*/
public Element(String name, String ns) {
m_name = name.toLowerCase();
- m_nameSpace = ns.toLowerCase();
+ if (ns != null && ns.length() > 0) {
+ m_nameSpace = ns.toLowerCase();
+ }
}
/**
@@ -139,7 +141,7 @@
* @return the qualified name of the current element.
*/
private String getQualifiedName() {
- if (m_nameSpace.equals("")) {
+ if (m_nameSpace == null) {
return m_name;
} else {
return m_nameSpace + ":" + m_name;
@@ -200,7 +202,7 @@
*/
public void addAttribute(Attribute att) {
String name = att.getName().toLowerCase();
- if (!att.getNameSpace().equals("")) {
+ if (att.getNameSpace() != null) {
name = att.getNameSpace().toLowerCase() + ":" + name;
}
m_attributes.put(name, att);
@@ -212,7 +214,7 @@
*/
public void removeAttribute(Attribute att) {
String name = att.getName();
- if (!att.getNameSpace().equals("")) {
+ if (att.getNameSpace() != null) {
name = att.getNameSpace() + ":" + name;
}
m_attributes.remove(name);
@@ -224,8 +226,7 @@
* @return the resulting element array (empty if the search failed)
*/
public Element[] getElements(String name) {
- name = name.toLowerCase();
- Element[] elems = (Element[]) m_elements.get(name);
+ Element[] elems = (Element[]) m_elements.get(name.toLowerCase());
if (elems == null) {
return new Element[0];
} else {
@@ -300,7 +301,7 @@
tabs += "\t";
}
- if ("".equals(m_nameSpace)) {
+ if (m_nameSpace == null) {
xml = tabs + "<" + m_name;
} else {
xml = tabs + "<" + m_nameSpace + ":" + m_name;
@@ -310,7 +311,7 @@
Iterator it = keys.iterator();
while (it.hasNext()) {
Attribute current = (Attribute) m_attributes.get(it.next());
- if ("".equals(current.getNameSpace())) {
+ if (current.getNameSpace() == null) {
xml += " " + current.getName() + "=\"" + current.getValue() + "\"";
} else {
xml += " " + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\"";
@@ -358,7 +359,7 @@
tabs += "\t";
}
- if ("".equals(m_nameSpace)) {
+ if (m_nameSpace == null) {
xml = tabs + m_name;
} else {
xml = tabs + m_nameSpace + ":" + m_name;
@@ -368,7 +369,7 @@
Iterator it = keys.iterator();
while (it.hasNext()) {
Attribute current = (Attribute) m_attributes.get(it.next());
- if ("".equals(current.getNameSpace())) {
+ if (current.getNameSpace() == null) {
xml += " " + current.getName() + "=\"" + current.getValue() + "\"";
} else {
xml += " " + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\"";
diff --git a/ipojo/pom.xml b/ipojo/pom.xml
index 53d3897..3b735e7 100644
--- a/ipojo/pom.xml
+++ b/ipojo/pom.xml
@@ -12,11 +12,11 @@
<version>0.7.5-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
- <module>../ipojo/metadata</module>
- <module>../ipojo/manipulator</module>
- <module>../ipojo/plugin</module>
- <module>../ipojo/core</module>
- <module>../ipojo/arch</module>
- <module>../ipojo/ant</module>
+ <module>metadata</module>
+ <module>manipulator</module>
+ <module>plugin</module>
+ <module>core</module>
+ <module>arch</module>
+ <module>ant</module>
</modules>
</project>
\ No newline at end of file