Search in sources :

Example 1 with PropertyDescription

use of org.apache.felix.scrplugin.description.PropertyDescription in project sling by apache.

the class SlingHealthCheckProcessor method generatePropertyDescriptor.

/** Generates a property descriptor of type {@link PropertyType} */
private void generatePropertyDescriptor(final ClassAnnotation cad, final ClassDescription classDescription, final boolean metatype, final String propertyName, final String propertyDescriptorName, PropertyType propertyType, String label, String description, boolean isArray) {
    final PropertyDescription pd = new PropertyDescription(cad);
    pd.setName(propertyDescriptorName);
    pd.setLabel(label);
    pd.setDescription(description);
    pd.setType(propertyType);
    if (isArray) {
        final String[] values = (String[]) cad.getValue(propertyName);
        pd.setMultiValue(values);
        pd.setUnbounded(PropertyUnbounded.ARRAY);
        pd.setCardinality(Integer.MAX_VALUE);
    } else {
        final Object propertyVal = cad.getValue(propertyName);
        String pdValue = (propertyVal instanceof String) ? (String) propertyVal : propertyVal != null ? propertyVal.toString() : null;
        pd.setValue(pdValue);
        pd.setUnbounded(PropertyUnbounded.DEFAULT);
    }
    if (!metatype) {
        pd.setPrivate(true);
    }
    classDescription.add(pd);
}
Also used : PropertyDescription(org.apache.felix.scrplugin.description.PropertyDescription)

Example 2 with PropertyDescription

use of org.apache.felix.scrplugin.description.PropertyDescription in project felix by apache.

the class DSAnnotationProcessor method createComponent.

/**
 * Create a component description.
 *
 * @param cad The component annotation for the class.
 * @param scannedClass The scanned class.
 */
private ComponentDescription createComponent(final ClassAnnotation cad, final ClassDescription describedClass, final ScannedClass scannedClass) throws SCRDescriptorException {
    final ComponentDescription component = new ComponentDescription(cad);
    describedClass.add(component);
    // Although not defined in the spec, we support abstract classes.
    final boolean classIsAbstract = Modifier.isAbstract(scannedClass.getClass().getModifiers());
    component.setAbstract(classIsAbstract);
    // name
    component.setName(cad.getStringValue("name", scannedClass.getScannedClass().getName()));
    // services
    final List<String> listedInterfaces = new ArrayList<String>();
    if (cad.hasValue("service")) {
        final String[] interfaces = (String[]) cad.getValue("service");
        if (interfaces != null) {
            for (final String t : interfaces) {
                listedInterfaces.add(t);
            }
        }
    } else {
        // scan directly implemented interfaces
        this.searchInterfaces(listedInterfaces, scannedClass.getScannedClass());
    }
    if (listedInterfaces.size() > 0) {
        final ServiceDescription serviceDesc = new ServiceDescription(cad);
        describedClass.add(serviceDesc);
        for (final String name : listedInterfaces) {
            serviceDesc.addInterface(name);
        }
        serviceDesc.setServiceFactory(cad.getBooleanValue("servicefactory", false));
    }
    // factory
    component.setFactory(cad.getStringValue("factory", null));
    // enabled
    if (cad.getValue("enabled") != null) {
        component.setEnabled(cad.getBooleanValue("enabled", true));
    }
    // immediate
    if (cad.getValue("immediate") != null) {
        component.setImmediate(cad.getBooleanValue("immediate", false));
    }
    // property
    final String[] property = (String[]) cad.getValue("property");
    if (property != null) {
        // TODO - what do we do if the value is invalid?
        for (final String propDef : property) {
            final int pos = propDef.indexOf('=');
            if (pos != -1) {
                final String prefix = propDef.substring(0, pos);
                final String value = propDef.substring(pos + 1);
                final int typeSep = prefix.indexOf(':');
                final String key = (typeSep == -1 ? prefix : prefix.substring(0, typeSep));
                final String type = (typeSep == -1 ? PropertyType.String.name() : prefix.substring(typeSep + 1));
                final PropertyType propType = PropertyType.valueOf(type);
                // FELIX-4159 : check if this is a multi value prop
                final List<PropertyDescription> existingProps = describedClass.getDescriptions(PropertyDescription.class);
                PropertyDescription found = null;
                for (final PropertyDescription current : existingProps) {
                    if (current.getName().equals(key)) {
                        found = current;
                        break;
                    }
                }
                if (found == null) {
                    final PropertyDescription pd = new PropertyDescription(cad);
                    describedClass.add(pd);
                    pd.setName(key);
                    pd.setValue(value);
                    pd.setType(propType);
                    pd.setUnbounded(PropertyUnbounded.DEFAULT);
                } else {
                    if (propType != found.getType()) {
                        throw new SCRDescriptorException("Multi value property '" + key + "' has different types: " + found.getType() + " & " + propType, describedClass.getSource());
                    }
                    if (found.getValue() != null) {
                        final String[] values = new String[2];
                        values[0] = found.getValue();
                        values[1] = value;
                        found.setMultiValue(values);
                    } else {
                        final String[] oldValues = found.getMultiValue();
                        final String[] newValues = new String[oldValues.length + 1];
                        System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
                        newValues[oldValues.length] = value;
                        found.setMultiValue(newValues);
                    }
                }
            }
        }
    }
    // xmlns
    if (cad.getValue("xmlns") != null) {
        final SpecVersion spec = SpecVersion.fromNamespaceUrl(cad.getValue("xmlns").toString());
        if (spec == null) {
            throw new SCRDescriptorException("Unknown xmlns attribute value: " + cad.getValue("xmlns"), describedClass.getSource());
        }
        component.setSpecVersion(spec);
    }
    // configuration policy
    component.setConfigurationPolicy(ComponentConfigurationPolicy.valueOf(cad.getEnumValue("configurationPolicy", ComponentConfigurationPolicy.OPTIONAL.name())));
    // configuration pid
    Object configPid = cad.getValue("configurationPid");
    if (configPid instanceof String) {
        component.setConfigurationPid((String) configPid);
    } else if (configPid instanceof String[] && ((String[]) configPid).length == 1) {
        component.setConfigurationPid(((String[]) configPid)[0]);
    } else {
        component.setConfigurationPid(null);
    }
    component.setCreatePid(false);
    // no inheritance
    component.setInherit(false);
    return component;
}
Also used : ComponentDescription(org.apache.felix.scrplugin.description.ComponentDescription) ServiceDescription(org.apache.felix.scrplugin.description.ServiceDescription) ArrayList(java.util.ArrayList) PropertyType(org.apache.felix.scrplugin.description.PropertyType) PropertyDescription(org.apache.felix.scrplugin.description.PropertyDescription) SpecVersion(org.apache.felix.scrplugin.SpecVersion) SCRDescriptorException(org.apache.felix.scrplugin.SCRDescriptorException)

Example 3 with PropertyDescription

use of org.apache.felix.scrplugin.description.PropertyDescription in project felix by apache.

the class SCRDescriptorGenerator method processGlobalProperties.

/**
 * Add global properties (if not already defined in the component)
 */
private void processGlobalProperties(final ClassDescription desc, final Map<String, PropertyDescription> allProperties) {
    // apply pre configured global properties
    if (this.options.getProperties() != null) {
        for (final Map.Entry<String, String> entry : this.options.getProperties().entrySet()) {
            final String propName = entry.getKey();
            final String value = entry.getValue();
            // check if the service already provides this property
            if (value != null && !allProperties.containsKey(propName)) {
                final PropertyDescription p = new PropertyDescription(null);
                p.setName(propName);
                p.setValue(value);
                p.setType(PropertyType.String);
                allProperties.put(propName, p);
            }
        }
    }
}
Also used : PropertyDescription(org.apache.felix.scrplugin.description.PropertyDescription) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 4 with PropertyDescription

use of org.apache.felix.scrplugin.description.PropertyDescription in project felix by apache.

the class Validator method validate.

/**
 * Validate the component description. If errors occur a message is added to
 * the issues list, warnings can be added to the warnings list.
 */
public void validate() throws SCRDescriptorException {
    final ComponentDescription component = this.container.getComponentDescription();
    // nothing to check if this is ignored
    if (!component.isCreateDs()) {
        return;
    }
    final int currentIssueCount = iLog.getNumberOfErrors();
    // if the component is abstract, we do not validate everything
    if (!component.isAbstract()) {
        // if configuration pid is set and different from name, we need 1.2
        if (component.getConfigurationPid() != null && !component.getConfigurationPid().equals(component.getName()) && options.getSpecVersion().ordinal() < SpecVersion.VERSION_1_2.ordinal()) {
            this.logError(component, "Different configuration pid requires " + SpecVersion.VERSION_1_2.getName() + " or higher.");
        }
        // ensure non-abstract, public class
        if (!Modifier.isPublic(this.container.getClassDescription().getDescribedClass().getModifiers())) {
            this.logError(component, "Class must be public: " + this.container.getClassDescription().getDescribedClass().getName());
        }
        if (Modifier.isAbstract(this.container.getClassDescription().getDescribedClass().getModifiers()) || this.container.getClassDescription().getDescribedClass().isInterface()) {
            this.logError(component, "Class must be concrete class (not abstract or interface) : " + this.container.getClassDescription().getDescribedClass().getName());
        }
        // no errors so far, let's continue
        if (iLog.getNumberOfErrors() == currentIssueCount) {
            final String activateName = component.getActivate() == null ? "activate" : component.getActivate();
            final String deactivateName = component.getDeactivate() == null ? "deactivate" : component.getDeactivate();
            // check activate and deactivate methods
            this.checkLifecycleMethod(activateName, true, component.getActivate() != null);
            this.checkLifecycleMethod(deactivateName, false, component.getDeactivate() != null);
            if (component.getModified() != null) {
                if (this.options.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal()) {
                    this.checkLifecycleMethod(component.getModified(), true, true);
                } else {
                    this.logError(component, "If modified version is specified, spec version must be " + SpecVersion.VERSION_1_1.name() + " or higher : " + component.getModified());
                }
            }
            // ensure public default constructor
            boolean constructorFound = true;
            Constructor<?>[] constructors = this.container.getClassDescription().getDescribedClass().getDeclaredConstructors();
            for (int i = 0; constructors != null && i < constructors.length; i++) {
                // if public default, succeed
                if (Modifier.isPublic(constructors[i].getModifiers()) && (constructors[i].getParameterTypes() == null || constructors[i].getParameterTypes().length == 0)) {
                    constructorFound = true;
                    break;
                }
                // non-public/non-default constructor found, must have
                // explicit
                constructorFound = false;
            }
            if (!constructorFound) {
                this.logError(component, "Class must have public default constructor: " + this.container.getClassDescription().getDescribedClass().getName());
            }
            // verify properties
            for (final PropertyDescription prop : this.container.getProperties().values()) {
                this.validateProperty(prop);
            }
            // verify service
            boolean isServiceFactory = false;
            if (this.container.getServiceDescription() != null) {
                if (this.container.getServiceDescription().getInterfaces().size() == 0) {
                    this.logError(component, "Service interface information is missing!");
                }
                this.validateService(this.container.getServiceDescription());
                isServiceFactory = this.container.getServiceDescription().isServiceFactory();
            }
            // serviceFactory must not be true for immediate of component factory
            if (isServiceFactory && component.getImmediate() != null && component.getImmediate().booleanValue() && component.getFactory() != null) {
                this.logError(component, "Component must not be a ServiceFactory, if immediate and/or component factory: " + this.container.getClassDescription().getDescribedClass().getName());
            }
            // immediate must not be true for component factory
            if (component.getImmediate() != null && component.getImmediate().booleanValue() && component.getFactory() != null) {
                this.logError(component, "Component must not be immediate if component factory: " + this.container.getClassDescription().getDescribedClass().getName());
            }
        }
        // additional check for metatype (FELIX-4035)
        if (this.container.getMetatypeContainer() != null) {
            if (this.container.getMetatypeContainer().getProperties().size() == 0) {
                this.logError(component, "Component is defined to generate metatype information, however no properties or only private properties have been " + "defined; in case no properties or only private properties are wanted, consider to use 'metatype=false'");
            }
        }
        if (iLog.getNumberOfErrors() == currentIssueCount) {
            // verify references
            for (final ReferenceDescription ref : this.container.getReferences().values()) {
                this.validateReference(ref, component.isAbstract());
            }
        }
    }
}
Also used : PropertyDescription(org.apache.felix.scrplugin.description.PropertyDescription) ComponentDescription(org.apache.felix.scrplugin.description.ComponentDescription) Constructor(java.lang.reflect.Constructor) ReferenceDescription(org.apache.felix.scrplugin.description.ReferenceDescription)

Example 5 with PropertyDescription

use of org.apache.felix.scrplugin.description.PropertyDescription in project felix by apache.

the class SCRAnnotationProcessor method createProperties.

/**
 * Create properties descriptions
 *
 * @throws SCRDescriptorException
 * @throws SCRDescriptorFailureException
 */
private void createProperties(final List<? extends ScannedAnnotation> descs, final ClassDescription describedClass) throws SCRDescriptorFailureException, SCRDescriptorException {
    for (final ScannedAnnotation ad : descs) {
        final PropertyDescription prop = new PropertyDescription(ad);
        // check for field annotation
        final FieldAnnotation fieldAnnotation;
        if (ad instanceof FieldAnnotation) {
            fieldAnnotation = (FieldAnnotation) ad;
        } else {
            fieldAnnotation = null;
        }
        // Detect values from annotation
        String type = null;
        String[] values = null;
        int index = 0;
        while (type == null && index < PROPERTY_VALUE_PROCESSING.length) {
            final String propType = PROPERTY_VALUE_PROCESSING[index];
            final String propName = PROPERTY_VALUE_PROCESSING[index + 1];
            final Object propValue = ad.getValue(propName);
            if (propValue != null && propValue.getClass().isArray()) {
                type = propType;
                values = new String[Array.getLength(propValue)];
                for (int i = 0; i < values.length; i++) {
                    values[i] = Array.get(propValue, i).toString();
                }
            }
            index += 2;
        }
        String name = ad.getStringValue("name", null);
        if (values != null) {
            prop.setType(PropertyType.valueOf(type));
            if (values.length == 1) {
                prop.setValue(values[0]);
            } else {
                prop.setMultiValue(values);
            }
            if (name == null) {
                final Object value = fieldAnnotation.getAnnotatedFieldValue();
                if (value != null) {
                    name = value.toString();
                }
            }
        } else if (fieldAnnotation != null) {
            // Detect values from field
            if (name != null) {
                final Object value = fieldAnnotation.getAnnotatedFieldValue();
                if (value != null) {
                    if (value.getClass().isArray()) {
                        final String[] newValues = new String[Array.getLength(value)];
                        for (int i = 0; i < newValues.length; i++) {
                            newValues[i] = Array.get(value, i).toString();
                        }
                        prop.setMultiValue(newValues);
                        prop.setType(PropertyType.from(fieldAnnotation.getAnnotatedField().getType().getComponentType()));
                    } else {
                        prop.setType(PropertyType.from(value.getClass()));
                        prop.setValue(value.toString());
                    }
                }
            } else {
                if (Modifier.isStatic(fieldAnnotation.getAnnotatedField().getModifiers())) {
                    final Object value = fieldAnnotation.getAnnotatedFieldValue();
                    if (value != null) {
                        name = value.toString();
                    }
                } else {
                    // non static, no name, no value (FELIX-4393)
                    name = fieldAnnotation.getAnnotatedField().getName();
                    final Object value = fieldAnnotation.getAnnotatedFieldValue();
                    if (value != null) {
                        if (value.getClass().isArray()) {
                            final String[] newValues = new String[Array.getLength(value)];
                            for (int i = 0; i < newValues.length; i++) {
                                newValues[i] = Array.get(value, i).toString();
                            }
                            prop.setMultiValue(newValues);
                            prop.setType(PropertyType.from(fieldAnnotation.getAnnotatedField().getType().getComponentType()));
                        } else {
                            prop.setType(PropertyType.from(value.getClass()));
                            prop.setValue(value.toString());
                        }
                    }
                }
            }
        }
        prop.setName(name);
        prop.setLabel(ad.getStringValue("label", null));
        prop.setDescription(ad.getStringValue("description", null));
        // check type
        if (prop.getType() == null) {
            prop.setType(PropertyType.String);
        }
        // private
        if (ad.getValue("propertyPrivate") != null) {
            prop.setPrivate(ad.getBooleanValue("propertyPrivate", false));
        }
        // cardinality handling
        final PropertyUnbounded pu = PropertyUnbounded.valueOf(ad.getEnumValue("unbounded", PropertyUnbounded.DEFAULT.name()));
        prop.setUnbounded(pu);
        if (pu == PropertyUnbounded.DEFAULT) {
            prop.setCardinality(ad.getIntegerValue("cardinality", 0));
            if (prop.getMultiValue() != null && prop.getCardinality() == 0) {
                prop.setUnbounded(PropertyUnbounded.ARRAY);
            }
        } else {
            prop.setCardinality(0);
        }
        if (prop.getValue() != null) {
            if (prop.getUnbounded() == PropertyUnbounded.ARRAY || prop.getUnbounded() == PropertyUnbounded.VECTOR) {
                prop.setMultiValue(new String[] { prop.getValue() });
            } else if (prop.getCardinality() < -1 || prop.getCardinality() > 1) {
                prop.setMultiValue(new String[] { prop.getValue() });
            }
        }
        // options
        final ScannedAnnotation[] options = (ScannedAnnotation[]) ad.getValue("options");
        if (options != null) {
            final List<String> propertyOptions = new ArrayList<String>();
            for (final ScannedAnnotation po : options) {
                propertyOptions.add(po.getStringValue("name", ""));
                propertyOptions.add(po.getStringValue("value", ""));
            }
            prop.setOptions(propertyOptions.toArray(new String[propertyOptions.size()]));
        }
        describedClass.add(prop);
    }
}
Also used : PropertyDescription(org.apache.felix.scrplugin.description.PropertyDescription) FieldAnnotation(org.apache.felix.scrplugin.annotations.FieldAnnotation) ArrayList(java.util.ArrayList) ScannedAnnotation(org.apache.felix.scrplugin.annotations.ScannedAnnotation) PropertyUnbounded(org.apache.felix.scrplugin.description.PropertyUnbounded)

Aggregations

PropertyDescription (org.apache.felix.scrplugin.description.PropertyDescription)9 ComponentDescription (org.apache.felix.scrplugin.description.ComponentDescription)4 ArrayList (java.util.ArrayList)2 LinkedHashMap (java.util.LinkedHashMap)2 ReferenceDescription (org.apache.felix.scrplugin.description.ReferenceDescription)2 ServiceDescription (org.apache.felix.scrplugin.description.ServiceDescription)2 Constructor (java.lang.reflect.Constructor)1 Map (java.util.Map)1 SCRDescriptorException (org.apache.felix.scrplugin.SCRDescriptorException)1 SpecVersion (org.apache.felix.scrplugin.SpecVersion)1 FieldAnnotation (org.apache.felix.scrplugin.annotations.FieldAnnotation)1 ScannedAnnotation (org.apache.felix.scrplugin.annotations.ScannedAnnotation)1 PropertyType (org.apache.felix.scrplugin.description.PropertyType)1 PropertyUnbounded (org.apache.felix.scrplugin.description.PropertyUnbounded)1 MetatypeAttributeDefinition (org.apache.felix.scrplugin.helper.MetatypeAttributeDefinition)1 AttributesImpl (org.xml.sax.helpers.AttributesImpl)1