/** * Allows a factory to check if the given element is well-formed. A component factory metadata is * correct if they contain the 'classname' attribute. As this method is called from the * (single-threaded) constructor, no synchronization is needed. * * @param element the metadata describing the component * @throws ConfigurationException if the element describing the factory is malformed. */ public void check(Element element) throws ConfigurationException { m_classname = element.getAttribute("classname"); if (m_classname == null) { throw new ConfigurationException("A component needs a class name : " + element); } m_manipulation = new PojoMetadata(m_componentMetadata); }
@SuppressWarnings("rawtypes") public void loadMetadata(Element metadata, Dictionary configuration) { if (metadata.containsAttribute(ProviderMetadata.PROFILE_POLICY)) { this.policy = metadata.getAttribute(ProviderMetadata.PROFILE_POLICY); } if (metadata.containsElement(ProviderMetadata.RESOURCE)) { Element[] tagResource = metadata.getElements(ProviderMetadata.RESOURCE); for (Element e_resource : tagResource) { Resource resource = new Resource(); resource.loadMetadata(e_resource, configuration); resources.add(resource); } } }
/** * Computes required handlers. This method does not manipulate any non-immutable fields, so does * not need to be synchronized. * * @return the required handler list. */ public List getRequiredHandlerList() { List list = new ArrayList(); Element[] elems = m_componentMetadata.getElements(); for (int i = 0; i < elems.length; i++) { Element current = elems[i]; if (!"manipulation".equals(current.getName())) { RequiredHandler req = new RequiredHandler(current.getName(), current.getNameSpace()); if (!list.contains(req)) { list.add(req); } } } // Add architecture if architecture != 'false' String arch = m_componentMetadata.getAttribute("architecture"); if (arch == null || arch.equalsIgnoreCase("true")) { list.add(new RequiredHandler("architecture", null)); } // Determine if the component must be immediate. // A component becomes immediate if it doesn't provide a service, // and does not specified that the component is not immediate. if (m_componentMetadata.getElements("provides") == null) { String imm = m_componentMetadata.getAttribute("immediate"); if (imm == null) { // immediate not specified, set the immediate attribute to true getLogger() .log(Logger.INFO, "The component type " + getFactoryName() + " becomes immediate"); m_componentMetadata.addAttribute(new Attribute("immediate", "true")); } } // Add lifecycle callback if immediate = true RequiredHandler reqCallback = new RequiredHandler("callback", null); String imm = m_componentMetadata.getAttribute("immediate"); if (!list.contains(reqCallback) && imm != null && imm.equalsIgnoreCase("true")) { list.add(reqCallback); } return list; }
public void testMandatoryPropertyWithValue() { Property prop = new Property() .setField("field") .setMandatory(true) .setName("prop") .setValue("foo") .setImmutable(true); Element elem = prop.getElement(); assertEquals(null, elem.getAttribute("constructor-parameter")); assertEquals("field", elem.getAttribute("field")); assertEquals("prop", elem.getAttribute("name")); assertEquals("foo", elem.getAttribute("value")); assertEquals("true", elem.getAttribute("mandatory")); assertEquals("true", elem.getAttribute("immutable")); }
/** * Build service instantiator handler description. * * @return the handler description * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo() */ public Element getHandlerInfo() { Element services = super.getHandlerInfo(); for (int i = 0; i < m_imports.size(); i++) { ServiceImporter imp = (ServiceImporter) m_imports.get(i); Element impo = new Element("Requires", ""); impo.addAttribute(new Attribute("Specification", imp.getSpecification().getName())); if (imp.getFilter() != null) { impo.addAttribute(new Attribute("Filter", imp.getFilter())); } if (imp.getState() == DependencyModel.RESOLVED) { impo.addAttribute(new Attribute("State", "resolved")); for (int j = 0; j < imp.getProviders().size(); j++) { Element prov = new Element("Provider", ""); prov.addAttribute(new Attribute("name", (String) imp.getProviders().get(j))); impo.addElement(prov); } } else { impo.addAttribute(new Attribute("State", "unresolved")); } services.addElement(impo); } for (int i = 0; i < m_instances.size(); i++) { SvcInstance inst = (SvcInstance) m_instances.get(i); Element service = new Element("Service", ""); service.addAttribute(new Attribute("Specification", inst.getServiceSpecification())); String state = "unresolved"; if (inst.getState() == DependencyModel.RESOLVED) { state = "resolved"; } service.addAttribute(new Attribute("State", state)); Map map = inst.getMatchingFactories(); Set keys = map.keySet(); Iterator iterator = keys.iterator(); while (iterator.hasNext()) { ServiceReference ref = (ServiceReference) iterator.next(); Object object = map.get(ref); if (object != null) { Element fact = new Element("Factory", ""); fact.addAttribute( new Attribute("Name", ((ComponentInstance) object).getFactory().getName())); service.addElement(fact); } } services.addElement(service); } return services; }
/** * Constructs the structure JmxConfigFieldMap and the Dynamic Mbean. * * @param metadata the component metadata * @param dict the instance configuration */ public void configure(Element metadata, Dictionary dict) { PojoMetadata manipulation = getPojoMetadata(); m_instanceManager = getInstanceManager(); m_jmxConfigFieldMap = new JmxConfigFieldMap(); // Build the hashmap Element[] mbeans = metadata.getElements(JMX_CONFIG_ELT, m_namespace); if (mbeans == null || mbeans.length == 0) { mbeans = metadata.getElements(JMX_CONFIG_ALT_ELT, m_namespace); } if (mbeans.length != 1) { error( "A component must have exactly one " + JMX_CONFIG_ELT + " or " + JMX_CONFIG_ALT_ELT + " element."); error("The JMX handler configuration is ignored."); return; } Element mbean = mbeans[0]; // retrieve kind of MBeanServer to use m_usesMOSGi = Boolean.parseBoolean(mbean.getAttribute(JMX_USES_MOSGI_ELT)); // retrieve object name m_completeObjNameElt = mbean.getAttribute(JMX_OBJ_NAME_ELT); m_domainElt = mbean.getAttribute(JMX_OBJ_NAME_DOMAIN_ELT); m_objNameWODomainElt = mbean.getAttribute(JMX_OBJ_NAME_WO_DOMAIN_ELT); // test if Pojo is interested in registration callbacks m_registerCallbacks = manipulation.isInterfaceImplemented(MBeanRegistration.class.getName()); if (m_registerCallbacks) { // don't need to check that methods exist, the pojo implements // MBeanRegistration interface String[] preRegisterParams = {MBeanServer.class.getName(), ObjectName.class.getName()}; m_preRegisterMeth = manipulation.getMethod(PRE_REGISTER_METH_NAME, preRegisterParams); String[] postRegisterParams = {Boolean.class.getName()}; m_postRegisterMeth = manipulation.getMethod(POST_REGISTER_METH_NAME, postRegisterParams); m_preDeregisterMeth = manipulation.getMethod(PRE_DEREGISTER_METH_NAME, new String[0]); m_postDeregisterMeth = manipulation.getMethod(POST_DEREGISTER_METH_NAME, new String[0]); } // set property Element[] attributes = mbean.getElements(JMX_PROPERTY_ELT, m_namespace); Element[] attributesAlt = mbean.getElements(JMX_PROPERTY_ELT_ALT, m_namespace); List<Element> listOfAttributes = new ArrayList<Element>(); if (attributes != null) { listOfAttributes.addAll(Arrays.asList(attributes)); } if (attributesAlt != null) { listOfAttributes.addAll(Arrays.asList(attributesAlt)); } Element[] attributesOld = mbeans[0].getElements(JMX_PROPERTY_ELT); if (attributesOld != null) { warn("The JMX property element should use the '" + m_namespace + "' namespace."); listOfAttributes.addAll(Arrays.asList(attributesOld)); } for (Element attribute : listOfAttributes) { boolean notif = false; String rights; String name; String field = attribute.getAttribute(JMX_FIELD_ELT); if (attribute.containsAttribute(JMX_NAME_ELT)) { name = attribute.getAttribute(JMX_NAME_ELT); } else { name = field; } if (attribute.containsAttribute(JMX_RIGHTS_ELT)) { rights = attribute.getAttribute(JMX_RIGHTS_ELT); } else { rights = "r"; } PropertyField property = new PropertyField(name, field, rights, getTypeFromAttributeField(field, manipulation)); if (attribute.containsAttribute(JMX_NOTIFICATION_ELT)) { notif = Boolean.parseBoolean(attribute.getAttribute(JMX_NOTIFICATION_ELT)); } property.setNotifiable(notif); if (notif) { // add the new notifiable property in structure NotificationField notification = new NotificationField(name, this.getClass().getName() + "." + field, null); m_jmxConfigFieldMap.addNotificationFromName(name, notification); } m_jmxConfigFieldMap.addPropertyFromName(name, property); getInstanceManager().register(manipulation.getField(field), this); info( "property exposed:" + name + " " + field + ":" + getTypeFromAttributeField(field, manipulation) + " " + rights + ", Notif=" + notif); } // set methods Element[] methods = mbean.getElements(JMX_METHOD_ELT, m_namespace); Element[] methodsAlt = mbean.getElements(JMX_METHOD_ELT_ALT, m_namespace); List<Element> listOfMethods = new ArrayList<Element>(); if (methods != null) { listOfMethods.addAll(Arrays.asList(methods)); } if (methodsAlt != null) { listOfMethods.addAll(Arrays.asList(methodsAlt)); } Element[] methodsOld = mbeans[0].getElements(JMX_PROPERTY_ELT); if (methodsOld != null) { warn("The JMX method element should use the '" + m_namespace + "' namespace."); listOfMethods.addAll(Arrays.asList(methodsOld)); } for (Element method : listOfMethods) { String name = method.getAttribute(JMX_NAME_ELT); if (name == null) { name = method.getAttribute("method"); } String description = null; if (method.containsAttribute(JMX_DESCRIPTION_ELT)) { description = method.getAttribute(JMX_DESCRIPTION_ELT); } MethodField[] meth = getMethodsFromName(name, manipulation, description); for (int j = 0; j < meth.length; j++) { m_jmxConfigFieldMap.addMethodFromName(name, meth[j]); info("method exposed:" + meth[j].getReturnType() + " " + name); } } }
/** * Computes required handlers. This method does not manipulate any non-immutable fields, so does * not need to be synchronized. This method checks the {@link * ComponentFactory#HANDLER_AUTO_PRIMITIVE} system property to add the listed handlers to the * required handler set. * * @return the required handler list. */ public List<RequiredHandler> getRequiredHandlerList() { List<RequiredHandler> list = new ArrayList<RequiredHandler>(); Element[] elems = m_componentMetadata.getElements(); for (Element current : elems) { if (!"manipulation".equals(current.getName())) { // Remove the manipulation element RequiredHandler req = new RequiredHandler(current.getName(), current.getNameSpace()); if (!list.contains(req)) { list.add(req); } } } // Add architecture if architecture != 'false' String arch = m_componentMetadata.getAttribute("architecture"); if (arch == null || arch.equalsIgnoreCase("true")) { list.add(new RequiredHandler("architecture", null)); } // Determine if the component must be immediate. // A component becomes immediate if it doesn't provide a service, // and does not specified that the component is not immediate. if (m_componentMetadata.getElements("provides") == null) { String imm = m_componentMetadata.getAttribute("immediate"); if (imm == null) { // immediate not specified, set the immediate attribute to true getLogger() .log(Logger.INFO, "The component type " + getFactoryName() + " becomes immediate"); m_componentMetadata.addAttribute(new Attribute("immediate", "true")); } } // Add lifecycle callback if immediate = true RequiredHandler reqCallback = new RequiredHandler("callback", null); String imm = m_componentMetadata.getAttribute("immediate"); if (!list.contains(reqCallback) && imm != null && imm.equalsIgnoreCase("true")) { list.add(reqCallback); } // Manage auto attached handler. String v = System.getProperty(HANDLER_AUTO_PRIMITIVE); if (v != null && v.length() != 0) { String[] hs = ParseUtils.split(v, ","); for (String h1 : hs) { String h = h1.trim(); String[] segments = ParseUtils.split(h, ":"); RequiredHandler rq = null; if (segments.length == 2) { // External handler rq = new RequiredHandler(segments[1], segments[0]); } else if (segments.length == 1) { // Core handler rq = new RequiredHandler(segments[1], null); } // Others case are ignored. if (rq != null) { // Check it's not already contained if (!list.contains(rq)) { list.add(rq); } } } } return list; }
public void testField() { Property prop = new Property().setField("field"); Element elem = prop.getElement(); assertEquals(null, elem.getAttribute("constructor-parameter")); assertEquals("field", elem.getAttribute("field")); }
public void testConstructorParameter() { Property prop = new Property().setConstructorParameter(1); Element elem = prop.getElement(); assertEquals("1", elem.getAttribute("constructor-parameter")); }
/** * Creates Pojo metadata. Manipulation Metadata object are created from component type metadata by * parsing manipulation metadata. * * @param metadata the component type metadata * @throws ConfigurationException if the manipulation metadata cannot be found */ public PojoMetadata(Element metadata) throws ConfigurationException { Element[] elems = metadata.getElements("manipulation", ""); if (elems == null) { throw new ConfigurationException( "The component " + metadata.getAttribute("classname") + " has no manipulation metadata"); } Element manip = elems[0]; m_className = manip.getAttribute("classname"); m_super = manip.getAttribute("super"); Element[] fields = manip.getElements("field"); if (fields != null) { for (Element field : fields) { addField(new FieldMetadata(field)); } } Element[] methods = manip.getElements("method"); if (methods != null) { for (Element method : methods) { m_methods.add(new MethodMetadata(method)); } } Element[] itfs = manip.getElements("interface"); if (itfs != null) { for (Element itf : itfs) { addInterface(itf.getAttribute("name")); } } Element[] inners = manip.getElements("inner"); if (inners != null) { for (Element inner : inners) { String name = inner.getAttribute("name"); List<MethodMetadata> list = m_innerClasses.get(name); if (list == null) { list = new ArrayList<MethodMetadata>(); m_innerClasses.put(name, list); } methods = inner.getElements("method"); if (methods != null) { for (Element m : methods) { list.add(new MethodMetadata(m)); } } } } }
/** * Configures the handler. Access to field does not require synchronization as this method is * executed before any thread access to this object. * * @param metadata the metadata of the component * @param configuration the instance configuration * @throws ConfigurationException one property metadata is not correct * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager, * org.apache.felix.ipojo.metadata.Element) */ public void configure(Element metadata, Dictionary configuration) throws ConfigurationException { // Build the map Element[] confs = metadata.getElements("Properties", ""); Element[] configurables = confs[0].getElements("Property"); // Check if the component is dynamically configurable m_mustPropagate = false; String propa = confs[0].getAttribute("propagation"); if (propa != null && propa.equalsIgnoreCase("true")) { m_mustPropagate = true; m_toPropagate = configuration; // Instance configuration to propagate. } // Check if the component support ConfigurationADmin reconfiguration m_managedServicePID = confs[0].getAttribute("pid"); // Look inside the component type description String instanceMSPID = (String) configuration.get("managed.service.pid"); // Look inside the instance configuration. if (instanceMSPID != null) { m_managedServicePID = instanceMSPID; } // updated method String upd = confs[0].getAttribute("updated"); if (upd != null) { m_updated = new Callback(upd, new Class[] {Dictionary.class}, false, getInstanceManager()); } for (int i = 0; configurables != null && i < configurables.length; i++) { String fieldName = configurables[i].getAttribute("field"); String methodName = configurables[i].getAttribute("method"); String name = configurables[i].getAttribute( "name"); // The initialize method has fixed the property name. String value = configurables[i].getAttribute("value"); String type = configurables[i].getAttribute( "type"); // The initialize method has fixed the property name. Property prop = new Property(name, fieldName, methodName, value, type, getInstanceManager(), this); addProperty(prop); // Check if the instance configuration contains value for the current property : if (configuration.get(name) == null) { if (fieldName != null && configuration.get(fieldName) != null) { prop.setValue(configuration.get(fieldName)); } } else { prop.setValue(configuration.get(name)); } if (fieldName != null) { FieldMetadata field = new FieldMetadata(fieldName, type); getInstanceManager().register(field, prop); } } m_description = new ConfigurationHandlerDescription(this, m_configurableProperties, m_managedServicePID); }
/** * Initialize the component type. * * @param desc : component type description to populate. * @param metadata : component type metadata. * @throws ConfigurationException : metadata are incorrect. * @see * org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, * org.apache.felix.ipojo.metadata.Element) */ public void initializeComponentFactory(ComponentTypeDescription desc, Element metadata) throws ConfigurationException { Element[] confs = metadata.getElements("Properties", ""); if (confs == null) { return; } Element[] configurables = confs[0].getElements("Property"); for (int i = 0; configurables != null && i < configurables.length; i++) { String fieldName = configurables[i].getAttribute("field"); String methodName = configurables[i].getAttribute("method"); if (fieldName == null && methodName == null) { throw new ConfigurationException( "Malformed property : The property needs to contain at least a field or a method"); } String name = configurables[i].getAttribute("name"); if (name == null) { if (fieldName == null) { name = methodName; } else { name = fieldName; } 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 PojoMetadata manipulation = getFactory().getPojoMetadata(); String type = null; if (fieldName == null) { MethodMetadata[] method = manipulation.getMethods(methodName); if (method.length == 0) { type = configurables[i].getAttribute("type"); if (type == null) { throw new ConfigurationException( "Malformed property : The type of the property cannot be discovered, add a 'type' attribute"); } } else { if (method[0].getMethodArguments().length != 1) { throw new ConfigurationException( "Malformed property : The method " + methodName + " does not have one argument"); } type = method[0].getMethodArguments()[0]; configurables[i].addAttribute( new Attribute("type", type)); // Add the type to avoid configure checking } } else { FieldMetadata field = manipulation.getField(fieldName); if (field == null) { throw new ConfigurationException( "Malformed property : The field " + fieldName + " does not exist in the implementation class"); } type = field.getFieldType(); configurables[i].addAttribute( new Attribute("type", type)); // Add the type to avoid configure checking } // Is the property set to immutable boolean immutable = false; String imm = configurables[i].getAttribute("immutable"); immutable = imm != null && imm.equalsIgnoreCase("true"); boolean mandatory = false; String man = configurables[i].getAttribute("mandatory"); mandatory = man != null && man.equalsIgnoreCase("true"); PropertyDescription pd = null; if (value == null) { pd = new PropertyDescription( name, type, null, false); // Cannot be immutable if we have no value. } else { pd = new PropertyDescription(name, type, value, immutable); } if (mandatory) { pd.setMandatory(); } desc.addProperty(pd); } }
/** * 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_classname)); return elem; }