Applied patch to fix FELIX-3326:
Accessing IPojo-Component's all inherited classes and all implemented interfaces in PrimitiveTypeDescription
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1242268 13f79535-47bb-0310-9956-ffa450edef68
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 98fc075..a79d8c4 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
@@ -24,8 +24,10 @@
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Attribute;
@@ -508,12 +510,35 @@
*/
private final class PrimitiveTypeDescription extends ComponentTypeDescription {
+ /*
+ * Set to keep component's all super-class class-names.
+ */
+ private Set m_superClasses = new HashSet();
+
+ /*
+ * Set to keep component's all interface class-names.
+ */
+ private Set m_interfaces = new HashSet();
+
/**
* Creates a PrimitiveTypeDescription object.
* @param factory the factory attached to this component type description.
*/
public PrimitiveTypeDescription(IPojoFactory factory) {
super(factory);
+
+ try
+ {
+ // Read inherited classes and interfaces into given Sets.
+ new InheritanceInspector(getPojoMetadata(), getBundleContext().getBundle()).
+ computeInterfacesAndSuperClasses(m_interfaces, m_superClasses);
+ }
+ catch (ClassNotFoundException e)
+ {
+ m_interfaces.clear();
+ m_superClasses.clear();
+ }
+
}
/**
@@ -538,7 +563,126 @@
public Element getDescription() {
Element elem = super.getDescription();
elem.addAttribute(new Attribute("Implementation-Class", m_classname));
+
+ /* Adding interfaces and super-classes of component into description */
+ Element inheritance = new Element("Inherited", "");
+
+ inheritance.addAttribute(new Attribute("Interfaces",m_interfaces.toString()));
+ inheritance.addAttribute(new Attribute("SuperClasses",m_superClasses.toString()));
+
+ elem.addElement(inheritance);
+
return elem;
}
+
+ /**
+ * This class is used to collect interfaces and super-classes of given component in specified Sets.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+ private final class InheritanceInspector{
+ /*
+ * PojoMetadata of target Component.
+ */
+ private PojoMetadata m_pojoMetadata;
+
+ /*
+ * Bundle exposing target component.
+ */
+ private Bundle m_bundle;
+
+
+ /**
+ * Creates a TypeCollector object
+ * @param pojoMetadata PojoMetadata describing Component.
+ * @param bundle Bundle which has been exposed the intended Component.
+ */
+ public InheritanceInspector(PojoMetadata pojoMetadata,Bundle bundle)
+ {
+ m_pojoMetadata = pojoMetadata;
+ m_bundle = bundle;
+ }
+
+ /**
+ * Collect interfaces implemented by the POJO into given Sets.
+ * @param interfaces : the set of implemented interfaces
+ * @param classes : the set of extended classes
+ * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+ */
+ public void computeInterfacesAndSuperClasses(Set interfaces, Set classes) throws ClassNotFoundException {
+
+ String[] immediateInterfaces = m_pojoMetadata.getInterfaces();
+ String parentClass = m_pojoMetadata.getSuperClass();
+
+ // First iterate on found specification in manipulation metadata
+ for (int i = 0; i < immediateInterfaces.length; i++) {
+ interfaces.add(immediateInterfaces[i]);
+ // Iterate on interfaces implemented by the current interface
+ Class clazz = m_bundle.loadClass(immediateInterfaces[i]);
+ collectInterfaces(clazz, interfaces, m_bundle);
+ }
+
+ // Look for parent class.
+ if (parentClass != null) {
+ Class clazz = m_bundle.loadClass(parentClass);
+ collectInterfacesFromClass(clazz, interfaces, m_bundle);
+ classes.add(parentClass);
+ collectParentClassesFromClass(clazz, classes, m_bundle);
+ }
+
+ // Removing Object Class from the inherited classes list.
+ classes.remove(Object.class.getName());
+ }
+
+ /**
+ * Look for inherited interfaces.
+ * @param clazz : interface name to explore (class object)
+ * @param acc : set (accumulator)
+ * @param bundle : bundle
+ * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+ */
+ private void collectInterfaces(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+ Class[] clazzes = clazz.getInterfaces();
+ for (int i = 0; i < clazzes.length; i++) {
+ acc.add(clazzes[i].getName());
+ collectInterfaces(clazzes[i], acc, bundle);
+ }
+ }
+
+ /**
+ * Collect interfaces for the given class.
+ * This method explores super class to.
+ * @param clazz : class object.
+ * @param acc : set of implemented interface (accumulator)
+ * @param bundle : bundle.
+ * @throws ClassNotFoundException : occurs if an interface cannot be load.
+ */
+ private void collectInterfacesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+ Class[] clazzes = clazz.getInterfaces();
+ for (int i = 0; i < clazzes.length; i++) {
+ acc.add(clazzes[i].getName());
+ collectInterfaces(clazzes[i], acc, bundle);
+ }
+ // Iterate on parent classes
+ Class sup = clazz.getSuperclass();
+ if (sup != null) {
+ collectInterfacesFromClass(sup, acc, bundle);
+ }
+ }
+
+ /**
+ * Collect parent classes for the given class.
+ * @param clazz : class object.
+ * @param acc : set of extended classes (accumulator)
+ * @param bundle : bundle.
+ * @throws ClassNotFoundException : occurs if an interface cannot be load.
+ */
+ private void collectParentClassesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+ Class parent = clazz.getSuperclass();
+ if (parent != null) {
+ acc.add(parent.getName());
+ collectParentClassesFromClass(parent, acc, bundle);
+ }
+ }
+ }
}
}