/**
  * 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;
  }
Exemple #6
0
  /**
   * 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;
 }