| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.felix.ipojo; |
| |
| import org.apache.felix.ipojo.architecture.ComponentTypeDescription; |
| import org.apache.felix.ipojo.metadata.Attribute; |
| import org.apache.felix.ipojo.metadata.Element; |
| import org.apache.felix.ipojo.parser.PojoMetadata; |
| import org.osgi.framework.Bundle; |
| |
| import java.util.Dictionary; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * This class defines the description of primitive (non-composite) component |
| * types. An instance of this class will be returned when invoking the |
| * {@link org.apache.felix.ipojo.ComponentFactory#getComponentDescription()} method. |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| final class PrimitiveTypeDescription extends ComponentTypeDescription { |
| |
| /** |
| * Set to keep component's all super-class class-names. |
| */ |
| private Set<String> m_superClasses = new HashSet<String>(); |
| |
| /** |
| * Set to keep component's all interface class-names. |
| */ |
| private Set<String> m_interfaces = new HashSet<String>(); |
| |
| /** |
| * The described component factory. |
| */ |
| private ComponentFactory m_factory; |
| |
| /** |
| * Creates a PrimitiveTypeDescription object. |
| * |
| * @param factory the m_factory attached to this component type description. |
| */ |
| public PrimitiveTypeDescription(ComponentFactory factory) { |
| super(factory); |
| this.m_factory = factory; |
| |
| try { |
| // The inspection can be done only for primitive components |
| if (factory.getClassName() != null) { |
| // Read inherited classes and interfaces into given Sets. |
| new InheritanceInspector(factory.getPojoMetadata(), getBundleContext().getBundle()). |
| computeInterfacesAndSuperClasses(m_interfaces, m_superClasses); |
| } |
| } catch (ClassNotFoundException e) { |
| m_interfaces.clear(); |
| m_superClasses.clear(); |
| } |
| |
| } |
| |
| /** |
| * Computes the properties to publish. |
| * The <code>component.class</code> property contains the implementation class name. |
| * |
| * @return the dictionary of properties to publish |
| * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish() |
| */ |
| public Dictionary<String, Object> getPropertiesToPublish() { |
| Dictionary<String, Object> dict = super.getPropertiesToPublish(); |
| if (m_factory.getClassName() != null) { |
| dict.put("component.class", m_factory.getClassName()); |
| } |
| return dict; |
| } |
| |
| /** |
| * Adds the "implementation-class" attribute to the type description. |
| * |
| * @return the component type description. |
| * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getDescription() |
| */ |
| public Element getDescription() { |
| Element elem = super.getDescription(); |
| elem.addAttribute(new Attribute("Implementation-Class", m_factory.getClassName())); |
| |
| /* 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<String> interfaces, Set<String> classes) throws ClassNotFoundException { |
| String[] immediateInterfaces = m_pojoMetadata.getInterfaces(); |
| String parentClass = m_pojoMetadata.getSuperClass(); |
| |
| // First iterate on found specification in manipulation metadata |
| for (String immediateInterface : immediateInterfaces) { |
| interfaces.add(immediateInterface); |
| // Iterate on interfaces implemented by the current interface |
| Class<?> clazz = m_bundle.loadClass(immediateInterface); |
| 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<String> acc, Bundle bundle) throws ClassNotFoundException { |
| Class[] clazzes = clazz.getInterfaces(); |
| for (Class clazze : clazzes) { |
| acc.add(clazze.getName()); |
| collectInterfaces(clazze, 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<String> acc, |
| Bundle bundle) throws ClassNotFoundException { |
| Class[] clazzes = clazz.getInterfaces(); |
| for (Class clazze : clazzes) { |
| acc.add(clazze.getName()); |
| collectInterfaces(clazze, 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<String> acc, Bundle bundle) throws ClassNotFoundException { |
| Class<?> parent = clazz.getSuperclass(); |
| if (parent != null) { |
| acc.add(parent.getName()); |
| collectParentClassesFromClass(parent, acc, bundle); |
| } |
| } |
| } |
| } |