protected JavaField getReferencedField(final JavaTag tag, String ref) throws SCRDescriptorException { int classSep = ref.lastIndexOf('.'); JavaField field = null; if (classSep == -1) { // local variable field = tag.getJavaClassDescription().getFieldByName(ref); } if (field == null) { field = tag.getJavaClassDescription().getExternalFieldByName(ref); } if (field == null) { throw new SCRDescriptorException( "Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName(), tag); } return field; }
/** * Return the name of the property. The name of the property is derived by: * * <ol> * <li>looking at the attribute {@link Constants.PROPERTY_NAME} * <li>looking at the attribute {@link Constants.PROPERTY_NAME_REF} * <li>if the property is specified at a filed and the field is of type string the init value is * used. * </ol> * * @param property The property tag. * @param field The corresponding field if the property is a tag of a field. * @return The name of the property or the defaultName */ protected String getPropertyName(JavaTag tag, JavaField field) throws SCRDescriptorException { // check name property String name = tag.getNamedParameter(Constants.PROPERTY_NAME); if (StringUtils.isEmpty(name)) { // check name ref propery name = tag.getNamedParameter(Constants.PROPERTY_NAME_REF); if (!StringUtils.isEmpty(name)) { final JavaField refField = this.getReferencedField(tag, name); final String[] values = refField.getInitializationExpression(); if (values == null || values.length == 0) { throw new SCRDescriptorException( "Referenced field for " + name + " has no values for a property name.", tag); } if (values.length > 1) { throw new SCRDescriptorException( "Referenced field " + name + " has more than one value for a property name.", tag); } name = values[0]; } if (StringUtils.isEmpty(name)) { // check field name = null; if (field != null && "java.lang.String".equals(field.getType())) { final String[] initValues = field.getInitializationExpression(); if (initValues != null && initValues.length == 1) { name = initValues[0]; } } } } // final empty check if (StringUtils.isEmpty(name)) { name = null; } return name; }
/** * Test if there is already a property with the same name. * * @param property The tag. * @param field * @param isInspectedClass * @throws SCRDescriptorException */ public void testProperty(JavaTag property, JavaField field, boolean isInspectedClass) throws SCRDescriptorException { final String propName = this.getPropertyName(property, field); if (propName != null) { if (properties.containsKey(propName)) { // if the current class is the class we are currently inspecting, we // have found a duplicate definition if (isInspectedClass) { throw new SCRDescriptorException( "Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName(), property); } } else { properties.put(propName, new PropertyDescription(property, field)); } } else { throw new SCRDescriptorException("Property has no name", property); } }
/** * Process a property. * * @param tag The property tag. * @param name The name of the property. * @param javaField The corresponding java field or null. */ protected void processProperty(JavaTag tag, String name, JavaField javaField, final IssueLog iLog) throws SCRDescriptorException { final Property prop = new Property(tag); prop.setName(name); // special handling for service.ranking - FELIX-2333 if (name.equals(org.osgi.framework.Constants.SERVICE_RANKING)) { prop.setType(Constants.PROPERTY_TYPE_INTEGER); } if (tag.getNamedParameter(Constants.PROPERTY_TYPE) != null) { prop.setType(tag.getNamedParameter(Constants.PROPERTY_TYPE)); } // let's first check for a value attribute final String value = tag.getNamedParameter(Constants.PROPERTY_VALUE); if (value != null) { prop.setValue(value); } else { // now we check for a value ref attribute final String valueRef = tag.getNamedParameter(Constants.PROPERTY_VALUE_REF); if (valueRef != null) { this.setPropertyValueRef(tag, prop, valueRef); } else { // check for multivalue - these can either be values or value refs final List<String> values = new ArrayList<String>(); final Map<String, String> valueMap = tag.getNamedParameterMap(); for (Iterator<Map.Entry<String, String>> vi = valueMap.entrySet().iterator(); vi.hasNext(); ) { final Map.Entry<String, String> entry = vi.next(); final String key = entry.getKey(); if (key.startsWith(Constants.PROPERTY_MULTIVALUE_PREFIX)) { values.add(entry.getValue()); } else if (key.startsWith(Constants.PROPERTY_MULTIVALUE_REF_PREFIX)) { final String[] stringValues = this.getPropertyValueRef(tag, prop, entry.getValue()); if (stringValues != null) { for (int i = 0; i < stringValues.length; i++) { values.add(stringValues[i]); } } } } if (values.size() > 0) { prop.setMultiValue(values.toArray(new String[values.size()])); } else { // we have no value, valueRef or values so let's try to // get the value of the field if a name attribute is specified final boolean isNamedParameter = tag.getNamedParameter(Constants.PROPERTY_NAME) != null || tag.getNamedParameter(Constants.PROPERTY_NAME_REF) != null; if (isNamedParameter && javaField != null) { this.setPropertyValueRef(tag, prop, javaField.getName()); } } } } // property is private if explicitly marked or a well known // service property such as service.pid final boolean isPrivate = isPrivate(name, tag); // if this is an abstract component we store the extra info in the property if (component.isAbstract()) { prop.setPrivate(isPrivate); prop.setLabel(tag.getNamedParameter(Constants.PROPERTY_LABEL)); prop.setDescription(tag.getNamedParameter(Constants.PROPERTY_DESCRIPTION)); prop.setCardinality(tag.getNamedParameter(Constants.PROPERTY_CARDINALITY)); } // if this is a public property and the component is generating metatype info // store the information! if (!isPrivate && ocd != null) { final AttributeDefinition ad = new AttributeDefinition(); ocd.getProperties().add(ad); ad.setId(prop.getName()); ad.setType(prop.getType()); String adName = tag.getNamedParameter(Constants.PROPERTY_LABEL); if (adName == null) { adName = "%" + prop.getName() + ".name"; } ad.setName(adName); String adDesc = tag.getNamedParameter(Constants.PROPERTY_DESCRIPTION); if (adDesc == null) { adDesc = "%" + prop.getName() + ".description"; } ad.setDescription(adDesc); // set optional multivalues, cardinality might be overwritten by setValues !! final String cValue = tag.getNamedParameter(Constants.PROPERTY_CARDINALITY); if (cValue != null) { if ("-".equals(cValue)) { // unlimited vector ad.setCardinality(new Integer(Integer.MIN_VALUE)); } else if ("+".equals(cValue)) { // unlimited array ad.setCardinality(new Integer(Integer.MAX_VALUE)); } else { try { ad.setCardinality(Integer.valueOf(cValue)); } catch (NumberFormatException nfe) { // default to scalar in case of conversion problem } } } ad.setDefaultValue(prop.getValue()); ad.setDefaultMultiValue(prop.getMultiValue()); // check options String[] parameters = tag.getParameters(); Map<String, String> options = null; for (int j = 0; j < parameters.length; j++) { if (Constants.PROPERTY_OPTIONS.equals(parameters[j])) { options = new LinkedHashMap<String, String>(); } else if (options != null) { final String option = parameters[j]; final int pos = option.indexOf('='); if (pos != -1) { // handle options from javadoc comments String optionLabel = option.substring(0, pos); String optionValue = option.substring(pos + 1); if (optionValue != null && optionValue.length() > 0) { options.put(optionLabel, optionValue); } } else { // handle options from java annotations String optionLabel = parameters[j]; String optionValue = (j < parameters.length - 2) ? parameters[j + 2] : null; if (optionValue != null && "=".equals(parameters[j + 1])) { options.put(optionLabel, optionValue); } j += 2; } } } ad.setOptions(options); } component.addProperty(prop); }