[maven-release-plugin]  copy for tag maven-scr-plugin-1.0.3

git-svn-id: https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.3@619019 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/NOTICE b/NOTICE
index 9750888..ac48c19 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,16 +1,35 @@
 Apache Felix SCR Maven Plugin
 Copyright 2007 The Apache Software Foundation
 
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
+
+I. Included Software
 
 This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+
+II. Used Software
+
+This product uses software developed at
 The OSGi Alliance (http://www.osgi.org/).
 Copyright 2006 The OSGi Alliance.
 Licensed under the Apache License 2.0.
 
-This product includes software developed at http://asm.objectweb.org
+This product uses software developed at http://asm.objectweb.org
 Copyright (c) 2000-2005 INRIA, France Telecom
+Licensed under the BSD License.
 
-This product includes software developed at
-The Codehaus (http://www.codehaus.org)
\ No newline at end of file
+This product uses software developed at
+The Codehaus (http://www.codehaus.org)
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+slf4j (http://www.sl4j.org)
+Licensed under the MIT License.
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- MIT License
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 8d50bb5..9fff7a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
     <groupId>org.apache.felix</groupId>
     <artifactId>maven-scr-plugin</artifactId>
 
-	<version>1.0.3-SNAPSHOT</version>
+	<version>1.0.3</version>
 	<packaging>maven-plugin</packaging>
 
 	<name>Maven SCR Plugin</name>
@@ -37,9 +37,9 @@
 	</description>
 
 	<scm>
-		<connection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/scrplugin</connection>
-		<developerConnection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/scrplugin</developerConnection>
-		<url>http://svn.apache.org/repos/asf/felix/scrplugin</url>
+		<connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.3</connection>
+		<developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.3</developerConnection>
+		<url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.3</url>
 	</scm>
 
 	<dependencies>
@@ -73,6 +73,7 @@
 			<artifactId>maven-plugin-api</artifactId>
 			<version>2.0.7</version>
 		</dependency>
+
 		<dependency>
 			<groupId>org.apache.maven</groupId>
 			<artifactId>maven-archiver</artifactId>
@@ -84,5 +85,17 @@
 			<artifactId>qdox</artifactId>
 			<version>1.6.3</version>
 		</dependency>
+
+    <!-- Logging support -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.4.3</version>
+        </dependency>
 	</dependencies>
 </project>
diff --git a/src/main/java/org/apache/felix/scrplugin/Constants.java b/src/main/java/org/apache/felix/scrplugin/Constants.java
index 50a3ec5..1777396 100644
--- a/src/main/java/org/apache/felix/scrplugin/Constants.java
+++ b/src/main/java/org/apache/felix/scrplugin/Constants.java
@@ -59,6 +59,12 @@
 
     public static final String PROPERTY_VALUE = "value";
 
+    public static final String PROPERTY_MULTIVALUE_PREFIX = "values";
+
+    public static final String PROPERTY_VALUE_REF = "valueRef";
+
+    public static final String PROPERTY_MULTIVALUE_REF_PREFIX = "refValues";
+
     public static final String PROPERTY_TYPE = "type";
 
     public static final String PROPERTY_CARDINALITY = "cardinality";
diff --git a/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java b/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
new file mode 100644
index 0000000..a986d01
--- /dev/null
+++ b/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
@@ -0,0 +1,311 @@
+/*
+ * 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.scrplugin;
+
+import java.util.*;
+
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Property;
+import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
+import org.apache.felix.scrplugin.om.metatype.OCD;
+import org.apache.felix.scrplugin.tags.JavaField;
+import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.codehaus.plexus.util.StringUtils;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Utility class for handling the properties.
+ */
+public class PropertyHandler {
+
+    /**
+     * This is a map using the property name as the key and
+     * {@link PropertyDescription} as values.
+     */
+    final private Map properties = new HashMap();
+
+    /** The component. */
+    final private Component component;
+
+    /** The ocd or null. */
+    final private OCD ocd;
+
+    public PropertyHandler(final Component c, OCD o) {
+        this.component = c;
+        this.ocd = o;
+    }
+
+    /**
+     * 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)
+    throws MojoExecutionException {
+        final Property prop = new Property(tag);
+        prop.setName(name);
+        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 values = new ArrayList();
+                final Map valueMap = tag.getNamedParameterMap();
+                for (Iterator vi = valueMap.entrySet().iterator(); vi.hasNext();) {
+                    final Map.Entry entry = (Map.Entry) vi.next();
+                    final String key = (String) 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, (String)entry.getValue());
+                        if ( stringValues != null ) {
+                            for(int i=0; i<stringValues.length; i++) {
+                                values.add(stringValues[i]);
+                            }
+                        }
+                    }
+                }
+                if ( values.size() > 0 ) {
+                    prop.setMultiValue((String[])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
+                    if ( tag.getNamedParameter(Constants.PROPERTY_NAME) != null && 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 = SCRDescriptorMojo.getBoolean(tag,
+            Constants.PROPERTY_PRIVATE, false)
+            || name.equals(org.osgi.framework.Constants.SERVICE_PID)
+            || name.equals(org.osgi.framework.Constants.SERVICE_DESCRIPTION)
+            || name.equals(org.osgi.framework.Constants.SERVICE_ID)
+            || name.equals(org.osgi.framework.Constants.SERVICE_RANKING)
+            || name.equals(org.osgi.framework.Constants.SERVICE_VENDOR)
+            || name.equals(ConfigurationAdmin.SERVICE_BUNDLELOCATION)
+            || name.equals(ConfigurationAdmin.SERVICE_FACTORYPID);
+
+        // 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 options = null;
+            for (int j=0; j < parameters.length; j++) {
+                if (Constants.PROPERTY_OPTIONS.equals(parameters[j])) {
+                    options = new LinkedHashMap();
+                } else if (options != null) {
+                    String optionLabel = parameters[j];
+                    String optionValue = (j < parameters.length-2) ? parameters[j+2] : null;
+                    if (optionValue != null) {
+                        options.put(optionLabel, optionValue);
+                    }
+                    j += 2;
+                }
+            }
+            ad.setOptions(options);
+        }
+
+        component.addProperty(prop);
+    }
+
+    /**
+     * Return the name of the property.
+     * @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) {
+        final String name = tag.getNamedParameter(Constants.PROPERTY_NAME);
+        if (!StringUtils.isEmpty(name)) {
+            return name;
+        }
+        String defaultName = null;
+        if ( field != null && "java.lang.String".equals(field.getType()) ) {
+            final String[] initValues = field.getInitializationExpression();
+            if ( initValues != null && initValues.length == 1 ) {
+                defaultName = initValues[0];
+            }
+        }
+
+        return defaultName;
+    }
+
+    protected void setPropertyValueRef(final JavaTag tag, Property property, String valueRef)
+    throws MojoExecutionException {
+        final String[] values = this.getPropertyValueRef(tag, property, valueRef);
+        if ( values != null && values.length == 1 ) {
+            property.setValue(values[0]);
+        } else if ( values != null && values.length > 1 ) {
+            property.setMultiValue(values);
+        }
+    }
+
+    protected String[] getPropertyValueRef(final JavaTag tag, Property prop, String valueRef)
+    throws MojoExecutionException {
+        int classSep = valueRef.lastIndexOf('.');
+        JavaField field = null;
+        if ( classSep == -1 ) {
+            // local variable
+            field = tag.getJavaClassDescription().getFieldByName(valueRef);
+        }
+        if ( field == null ) {
+            field = tag.getJavaClassDescription().getExternalFieldByName(valueRef);
+        }
+        if ( field == null ) {
+            throw new MojoExecutionException("Property references unknown field " + valueRef + " in class " + tag.getJavaClassDescription().getName());
+        }
+        // determine type (if not set explicitly)
+        if ( prop.getType() == null ) {
+            final String type = field.getType();
+            if ( "java.lang.String".equals(type) ) {
+                prop.setType("String");
+            } else if ("java.lang.Long".equals(type) || "long".equals(type) ) {
+                prop.setType("Long");
+            } else if ("java.lang.Double".equals(type) || "double".equals(type) ) {
+                prop.setType("Double");
+            } else if ("java.lang.Float".equals(type) || "float".equals(type) ) {
+                prop.setType("Float");
+            } else if ("java.lang.Integer".equals(type) || "int".equals(type) ) {
+                prop.setType("Integer");
+            } else if ("java.lang.Byte".equals(type) || "byte".equals(type) ) {
+                prop.setType("Byte");
+            } else if ("java.lang.Character".equals(type) || "char".equals(type) ) {
+                prop.setType("Char");
+            } else if ("java.lang.Boolean".equals(type) || "boolean".equals(type) ) {
+                prop.setType("Boolean");
+            } else if ("java.lang.Short".equals(type) || "short".equals(type) ) {
+                prop.setType("Short");
+            }
+
+        }
+        return field.getInitializationExpression();
+    }
+
+    /**
+     * Test if there is already a property with the same name.
+     * @param property The tag.
+     * @param field
+     * @param isInspectedClass
+     * @throws MojoExecutionException
+     */
+    public void testProperty(JavaTag   property,
+                             JavaField field,
+                             boolean   isInspectedClass)
+    throws MojoExecutionException {
+        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 MojoExecutionException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName());
+                }
+            } else {
+                properties.put(propName, new PropertyDescription(property, field));
+            }
+        } else {
+            throw new MojoExecutionException("Property has no name " + property.getSourceLocation());
+        }
+    }
+
+    public void handleField(JavaField javaField, boolean isInspectedClass)
+    throws MojoExecutionException {
+        final JavaTag tag = javaField.getTagByName(Constants.PROPERTY);
+        if (tag != null) {
+            this.testProperty(tag, javaField, isInspectedClass);
+        }
+    }
+
+    /**
+     * Process all found properties for the component.
+     * @throws MojoExecutionException
+     */
+    public void processProperties()
+    throws MojoExecutionException {
+        final Iterator propIter = properties.entrySet().iterator();
+        while ( propIter.hasNext() ) {
+            final Map.Entry entry = (Map.Entry)propIter.next();
+            final String propName = entry.getKey().toString();
+            final PropertyDescription desc = (PropertyDescription)entry.getValue();
+            this.processProperty(desc.propertyTag, propName, desc.field);
+        }
+    }
+
+    protected static final class PropertyDescription {
+        public final JavaTag propertyTag;
+        public final JavaField field;
+
+        public PropertyDescription(final JavaTag p, final JavaField f) {
+            this.propertyTag = p;
+            this.field = f;
+        }
+    }
+}
diff --git a/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java b/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
index 041e32d..94f0369 100644
--- a/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
+++ b/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
@@ -30,7 +30,6 @@
 import org.apache.maven.plugin.*;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.util.StringUtils;
-import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * The <code>SCRDescriptorMojo</code>
@@ -219,19 +218,20 @@
 
         final OCD ocd = this.doComponent(componentTag, component, metaData);
 
-        boolean inherited = this.getBoolean(componentTag, Constants.COMPONENT_INHERIT, true);
+        boolean inherited = getBoolean(componentTag, Constants.COMPONENT_INHERIT, true);
         this.doServices(description.getTagsByName(Constants.SERVICE, inherited), component, description);
 
-        // collect properties and references from class tags and fields
-        final Map properties = new HashMap();
+        // collect references from class tags and fields
         final Map references = new HashMap();
+        // Utility handler for propertie
+        final PropertyHandler propertyHandler = new PropertyHandler(component, ocd);
 
         JavaClassDescription currentDescription = description;
         do {
             // properties
             final JavaTag[] props = currentDescription.getTagsByName(Constants.PROPERTY, false);
             for (int i=0; i < props.length; i++) {
-                this.testProperty(properties, props[i], null, description == currentDescription);
+                propertyHandler.testProperty(props[i], null, description == currentDescription);
             }
 
             // references
@@ -248,32 +248,14 @@
                     this.testReference(references, tag, fields[i].getName(), description == currentDescription);
                 }
 
-                tag = fields[i].getTagByName(Constants.PROPERTY);
-                if (tag != null) {
-                    String defaultName = null;
-                    if ( "java.lang.String".equals(fields[i].getType()) ) {
-                        defaultName = fields[i].getInitializationExpression().trim();
-                        int pos = defaultName.indexOf("\"");
-                        if ( pos != -1 ) {
-                            defaultName = defaultName.substring(pos + 1);
-                            defaultName = defaultName.substring(0, defaultName.lastIndexOf("\""));
-                        }
-                    }
-                    this.testProperty(properties, tag, defaultName, description == currentDescription);
-                }
+                propertyHandler.handleField(fields[i], description == currentDescription);
             }
 
             currentDescription = currentDescription.getSuperClass();
         } while (inherited && currentDescription != null);
 
         // process properties
-        final Iterator propIter = properties.entrySet().iterator();
-        while ( propIter.hasNext() ) {
-            final Map.Entry entry = (Map.Entry)propIter.next();
-            final String propName = entry.getKey().toString();
-            final JavaTag tag = (JavaTag)entry.getValue();
-            this.doProperty(tag, propName, component, ocd);
-        }
+        propertyHandler.processProperties();
 
         // process references
         final Iterator refIter = references.entrySet().iterator();
@@ -285,7 +267,7 @@
         }
 
         // pid handling
-        final boolean createPid = this.getBoolean(componentTag, Constants.COMPONENT_CREATE_PID, true);
+        final boolean createPid = getBoolean(componentTag, Constants.COMPONENT_CREATE_PID, true);
         if ( createPid ) {
             // check for an existing pid first
             boolean found = false;
@@ -343,9 +325,9 @@
         String name = tag.getNamedParameter(Constants.COMPONENT_NAME);
         component.setName(StringUtils.isEmpty(name) ? component.getImplementation().getClassame() : name);
 
-        component.setEnabled(Boolean.valueOf(this.getBoolean(tag, Constants.COMPONENT_ENABLED, true)));
+        component.setEnabled(Boolean.valueOf(getBoolean(tag, Constants.COMPONENT_ENABLED, true)));
         component.setFactory(tag.getNamedParameter(Constants.COMPONENT_FACTORY));
-        component.setImmediate(Boolean.valueOf(this.getBoolean(tag, Constants.COMPONENT_IMMEDIATE, true)));
+        component.setImmediate(Boolean.valueOf(getBoolean(tag, Constants.COMPONENT_IMMEDIATE, true)));
 
         // whether metatype information is to generated for the component
         final String metaType = tag.getNamedParameter(Constants.COMPONENT_METATYPE);
@@ -407,7 +389,7 @@
                 service.addInterface(interf);
             }
 
-            serviceFactory |= this.getBoolean(services[i], Constants.SERVICE_FACTORY, false);
+            serviceFactory |= getBoolean(services[i], Constants.SERVICE_FACTORY, false);
         }
 
         service.setServicefactory(serviceFactory);
@@ -433,134 +415,6 @@
         }
     }
 
-    /**
-     * @param property
-     * @param defaultName
-     * @param component
-     */
-    protected void doProperty(JavaTag property, String name, Component component, OCD ocd) {
-        final Property prop = new Property(property);
-        prop.setName(name);
-        prop.setType(property.getNamedParameter(Constants.PROPERTY_TYPE));
-        final String value = property.getNamedParameter(Constants.PROPERTY_VALUE);
-        if ( value != null ) {
-            prop.setValue(value);
-        } else {
-            // check for multivalue
-            final List values = new ArrayList();
-            final Map valueMap = property.getNamedParameterMap();
-            for (Iterator vi = valueMap.entrySet().iterator(); vi.hasNext();) {
-                final Map.Entry entry = (Map.Entry) vi.next();
-                final String key = (String) entry.getKey();
-                if (key.startsWith("values")) {
-                    values.add(entry.getValue());
-                }
-            }
-            if ( values.size() > 0 ) {
-                prop.setMultiValue((String[])values.toArray(new String[values.size()]));
-            }
-        }
-
-        // property is private if explicitly marked or a well known
-        // service property such as service.pid
-        final boolean isPrivate = getBoolean(property,
-            Constants.PROPERTY_PRIVATE, false)
-            || name.equals(org.osgi.framework.Constants.SERVICE_PID)
-            || name.equals(org.osgi.framework.Constants.SERVICE_DESCRIPTION)
-            || name.equals(org.osgi.framework.Constants.SERVICE_ID)
-            || name.equals(org.osgi.framework.Constants.SERVICE_RANKING)
-            || name.equals(org.osgi.framework.Constants.SERVICE_VENDOR)
-            || name.equals(ConfigurationAdmin.SERVICE_BUNDLELOCATION)
-            || name.equals(ConfigurationAdmin.SERVICE_FACTORYPID);
-
-        // 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 = property.getNamedParameter(Constants.PROPERTY_LABEL);
-            if ( adName == null ) {
-                adName = "%" + prop.getName() + ".name";
-            }
-            ad.setName(adName);
-            String adDesc = property.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 = property.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 = property.getParameters();
-            Map options = null;
-            for (int j=0; j < parameters.length; j++) {
-                if (Constants.PROPERTY_OPTIONS.equals(parameters[j])) {
-                    options = new LinkedHashMap();
-                } else if (options != null) {
-                    String optionLabel = parameters[j];
-                    String optionValue = (j < parameters.length-2) ? parameters[j+2] : null;
-                    if (optionValue != null) {
-                        options.put(optionLabel, optionValue);
-                    }
-                    j += 2;
-                }
-            }
-            ad.setOptions(options);
-        }
-
-        component.addProperty(prop);
-    }
-
-    protected String getPropertyName(JavaTag property, String defaultName) {
-        String name = property.getNamedParameter(Constants.PROPERTY_NAME);
-        if (StringUtils.isEmpty(name) && defaultName != null) {
-            name = defaultName;
-        }
-
-        if (!StringUtils.isEmpty(name)) {
-            return name;
-        }
-        return null;
-    }
-
-    protected void testProperty(Map properties, JavaTag property, String defaultName, boolean isInspectedClass)
-    throws MojoExecutionException {
-        final String propName = this.getPropertyName(property, defaultName);
-
-        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 MojoExecutionException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName());
-                }
-            } else {
-                properties.put(propName, property);
-            }
-        }
-    }
-
     protected void testReference(Map references, JavaTag reference, String defaultName, boolean isInspectedClass)
     throws MojoExecutionException {
         final String refName = this.getReferenceName(reference, defaultName);
@@ -651,7 +505,7 @@
         component.addReference(ref);
     }
 
-    protected boolean getBoolean(JavaTag tag, String name, boolean defaultValue) {
+    public static boolean getBoolean(JavaTag tag, String name, boolean defaultValue) {
         String value = tag.getNamedParameter(name);
         return (value == null) ? defaultValue : Boolean.valueOf(value).booleanValue();
     }
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/ClassUtil.java b/src/main/java/org/apache/felix/scrplugin/tags/ClassUtil.java
new file mode 100644
index 0000000..496c00f
--- /dev/null
+++ b/src/main/java/org/apache/felix/scrplugin/tags/ClassUtil.java
@@ -0,0 +1,58 @@
+/*
+ * 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.scrplugin.tags;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+/**
+ * Utility class.
+ */
+public class ClassUtil {
+
+    /**
+     * Try to get the initial value of a static field
+     * @param clazz     The class.
+     * @param fieldName The name of the field.
+     * @return The initial value or null.
+     */
+    public static String[] getInitializationExpression(Class clazz, String fieldName) {
+        try {
+            final Field field = clazz.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            final Object value = field.get(null);
+            if ( value != null ) {
+                if ( value.getClass().isArray() ) {
+                    final String[] values = new String[Array.getLength(value)];
+                    for(int i=0; i<values.length; i++) {
+                        values[i] = Array.get(value, i).toString();
+                    }
+                    return values;
+                }
+                return new String[] {value.toString()};
+            }
+            return null;
+        } catch (NoClassDefFoundError e) {
+            // ignore and just return null
+        } catch (Exception e) {
+            // ignore and just return null
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java b/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
index cbab33a..724a395 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
@@ -60,9 +60,23 @@
      */
     String getName();
 
+    /**
+     * Get the fields of this class
+     * @return All fields or an empty array
+     */
     JavaField[] getFields();
 
     /**
+     * Get the field with the name.
+     * @param name The name of the field
+     * @return The field with the name or null.
+     * @throws MojoExecutionException
+     */
+    JavaField getFieldByName(String name) throws MojoExecutionException;
+
+    JavaField getExternalFieldByName(String name) throws MojoExecutionException;
+
+    /**
      * Returns an array of the implemented interfaces of this class.
      * @return An array containing the interfaces or an empty array
      *         if this class does not implement any interface.
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java b/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java
index 20f1cdc..c268edc 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java
@@ -18,21 +18,11 @@
  */
 package org.apache.felix.scrplugin.tags;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import java.io.*;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
+import java.util.*;
+import java.util.jar.*;
 
 import org.apache.felix.scrplugin.Constants;
 import org.apache.felix.scrplugin.om.Component;
@@ -214,7 +204,7 @@
     protected ClassLoader getCompileClassLoader(MavenProject project)
     throws MojoFailureException {
         List artifacts = project.getCompileArtifacts();
-        URL[] path = new URL[artifacts.size()];
+        URL[] path = new URL[artifacts.size() + 1];
         int i = 0;
         for (Iterator ai=artifacts.iterator(); ai.hasNext(); ) {
             Artifact a = (Artifact) ai.next();
@@ -224,7 +214,13 @@
                 throw new MojoFailureException("Unable to get compile class loader.");
             }
         }
-        return new URLClassLoader(path);
+        final String targetDirectory = this.getProject().getBuild().getOutputDirectory();
+        try {
+            path[path.length - 1] = new File(targetDirectory).toURI().toURL();
+        } catch (IOException ioe) {
+            throw new MojoFailureException("Unable to add target directory to classloader.");
+        }
+        return new URLClassLoader(path, this.getClass().getClassLoader());
     }
 
     protected Manifest getManifest(Artifact artifact) throws IOException {
@@ -273,10 +269,15 @@
      * Return all source descriptions of this project.
      * @return All contained java class descriptions.
      */
-    public JavaClassDescription[] getSourceDescriptions() {
+    public JavaClassDescription[] getSourceDescriptions() throws MojoExecutionException {
         final JavaClassDescription[] descs = new JavaClassDescription[this.sources.length];
         for(int i=0; i<this.sources.length; i++) {
-            descs[i] = new QDoxJavaClassDescription(this.sources[i], this);
+            final String className = this.sources[i].getClasses()[0].getFullyQualifiedName();
+            try {
+                descs[i] = new QDoxJavaClassDescription(this.classloader.loadClass(className), this.sources[i], this);
+            } catch (ClassNotFoundException e) {
+                throw new MojoExecutionException("Unable to load class " + className);
+            }
         }
         return descs;
     }
@@ -295,8 +296,12 @@
             int index = 0;
             while ( result == null && index < this.sources.length) {
                 if ( this.sources[index].getClasses()[0].getFullyQualifiedName().equals(className) ) {
-                    this.log.debug("Found qdox description for: " + className);
-                    result = new QDoxJavaClassDescription(this.sources[index], this);
+                    try {
+                        this.log.debug("Found qdox description for: " + className);
+                        result = new QDoxJavaClassDescription(this.classloader.loadClass(className), this.sources[index], this);
+                    } catch (ClassNotFoundException e) {
+                        throw new MojoExecutionException("Unable to load class " + className);
+                    }
                 } else {
                     index++;
                 }
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java b/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java
index 2fc9769..cbadb04 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java
@@ -24,11 +24,25 @@
  */
 public interface JavaField {
 
+    /** The name of the field. */
     String getName();
 
+    /** The type of the field. */
     String getType();
 
+    /**
+     * Return the given tag.
+     * @param name The tag name.
+     * @return The tag or null.
+     */
     JavaTag getTagByName(String name);
 
-    String getInitializationExpression();
+    /**
+     * Return the initial value if this is a static constant.
+     * If this field is not an array, an array of length 1 is
+     * returned with the value. If this field is an array,
+     * the array of values is returned.
+     * @return The initial value of the field.
+     */
+    String[] getInitializationExpression();
 }
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java b/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
index 4e8bf14..432be47 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
@@ -60,6 +60,35 @@
     }
 
     /**
+     * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFieldByName(java.lang.String)
+     */
+    public JavaField getFieldByName(String name) throws MojoExecutionException {
+        Field field = null;
+        try {
+            field = this.clazz.getField(name);
+        } catch (SecurityException e) {
+            // ignore
+        } catch (NoSuchFieldException e) {
+            // ignore
+        }
+        if ( field != null ) {
+            return new ClassLoaderJavaField(field, this);
+        }
+        if ( this.getSuperClass() != null ) {
+            this.getSuperClass().getFieldByName(name);
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
+     */
+    public JavaField getExternalFieldByName(String name)
+    throws MojoExecutionException {
+        throw new MojoExecutionException("getExternalFieldByName not support for this class.");
+    }
+
+    /**
      * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
      */
     public JavaClassDescription[] getImplementedInterfaces() throws MojoExecutionException {
@@ -213,7 +242,7 @@
     public boolean isPublic() {
         return Modifier.isPublic(this.clazz.getModifiers());
     }
-    
+
     public String toString() {
         return getName();
     }
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java b/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java
index 2b2f8be..37ab90b 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java
@@ -20,9 +20,7 @@
 
 import java.lang.reflect.Field;
 
-import org.apache.felix.scrplugin.tags.JavaClassDescription;
-import org.apache.felix.scrplugin.tags.JavaField;
-import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.tags.*;
 
 /**
  * <code>ClassLoaderJavaField.java</code>...
@@ -42,9 +40,8 @@
     /**
      * @see org.apache.felix.scrplugin.tags.JavaField#getInitializationExpression()
      */
-    public String getInitializationExpression() {
-        // TODO
-        return null;
+    public String[] getInitializationExpression() {
+        return ClassUtil.getInitializationExpression(this.field.getDeclaringClass(), this.field.getName());
     }
 
     /**
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java b/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
index 9a51a96..db58728 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
@@ -45,10 +45,14 @@
 
     protected final JavaSource source;
 
-    public QDoxJavaClassDescription(JavaSource source, JavaClassDescriptorManager m) {
+    /** The compiled class. */
+    protected final Class clazz;
+
+    public QDoxJavaClassDescription(Class clazz, JavaSource source, JavaClassDescriptorManager m) {
         this.javaClass = source.getClasses()[0];
         this.manager = m;
         this.source = source;
+        this.clazz = clazz;
     }
 
     /**
@@ -122,6 +126,83 @@
     }
 
     /**
+     * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFieldByName(java.lang.String)
+     */
+    public JavaField getFieldByName(String name)
+    throws MojoExecutionException {
+        final com.thoughtworks.qdox.model.JavaField field = this.javaClass.getFieldByName(name);
+        if ( field != null ) {
+            return new QDoxJavaField(field, this);
+        }
+        if ( this.getSuperClass() != null ) {
+            return this.getSuperClass().getFieldByName(name);
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
+     */
+    public JavaField getExternalFieldByName(String name)
+    throws MojoExecutionException {
+        int lastDot = name.lastIndexOf('.');
+        // if there is no dot, this should be a static import
+        if ( lastDot == -1 ) {
+            final String importDef = this.searchImport('.' + name);
+            if ( importDef != null ) {
+                int sep = importDef.lastIndexOf('.');
+                final String className = importDef.substring(0, sep);
+                final String constantName = importDef.substring(sep+1);
+                final JavaClassDescription jcd = this.manager.getJavaClassDescription(className);
+                if ( jcd != null ) {
+                    return jcd.getFieldByName(constantName);
+                }
+            }
+        } else {
+            // check for fully qualified
+            int firstDot = name.indexOf('.');
+            if ( firstDot == lastDot ) {
+                // we only have one dot, so either the class is imported or in the same package
+                final String className = name.substring(0, lastDot);
+                final String constantName = name.substring(lastDot+1);
+                final String importDef = this.searchImport('.' + className);
+                if ( importDef != null ) {
+                    final JavaClassDescription jcd = this.manager.getJavaClassDescription(importDef);
+                    if ( jcd != null ) {
+                        return jcd.getFieldByName(constantName);
+                    }
+                }
+                final JavaClassDescription jcd = this.manager.getJavaClassDescription(this.javaClass.getSource().getPackage() + '.' + className);
+                if ( jcd != null ) {
+                    return jcd.getFieldByName(constantName);
+                }
+
+            } else {
+                // we have more than one dot, so this is a fully qualified class
+                final String className = name.substring(0, lastDot);
+                final String constantName = name.substring(lastDot+1);
+                final JavaClassDescription jcd = this.manager.getJavaClassDescription(className);
+                if ( jcd != null ) {
+                    return jcd.getFieldByName(constantName);
+                }
+            }
+        }
+        return null;
+    }
+
+    protected String searchImport(String name) {
+        final String[] imports = this.javaClass.getSource().getImports();
+        if ( imports != null ) {
+            for(int i=0; i<imports.length; i++ ) {
+                if ( imports[i].endsWith(name) ) {
+                    return imports[i];
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
      * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
      */
     public JavaClassDescription[] getImplementedInterfaces()
@@ -308,8 +389,15 @@
         meth.setModifiers(new String[] {"protected"});
         this.javaClass.addMethod(meth);
     }
-    
+
+    /**
+     * @see java.lang.Object#toString()
+     */
     public String toString() {
         return getName();
     }
+
+    public Class getCompiledClass() {
+        return this.clazz;
+    }
 }
diff --git a/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java b/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java
index e4d0564..5719e73 100644
--- a/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java
+++ b/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java
@@ -18,9 +18,7 @@
  */
 package org.apache.felix.scrplugin.tags.qdox;
 
-import org.apache.felix.scrplugin.tags.JavaClassDescription;
-import org.apache.felix.scrplugin.tags.JavaField;
-import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.tags.*;
 
 import com.thoughtworks.qdox.model.DocletTag;
 
@@ -32,9 +30,9 @@
 
     protected final com.thoughtworks.qdox.model.JavaField field;
 
-    protected final JavaClassDescription description;
+    protected final QDoxJavaClassDescription description;
 
-    public QDoxJavaField(com.thoughtworks.qdox.model.JavaField f, JavaClassDescription d) {
+    public QDoxJavaField(com.thoughtworks.qdox.model.JavaField f, QDoxJavaClassDescription d) {
         this.field = f;
         this.description = d;
     }
@@ -42,8 +40,26 @@
     /**
      * @see org.apache.felix.scrplugin.tags.JavaField#getInitializationExpression()
      */
-    public String getInitializationExpression() {
-        return this.field.getInitializationExpression();
+    public String[] getInitializationExpression() {
+        String[] values = ClassUtil.getInitializationExpression(this.description.getCompiledClass(), this.getName());
+        if ( values == null ) {
+            // try qdox
+            String value = this.field.getInitializationExpression();
+            if ( value != null ) {
+                int pos = value.indexOf("\"");
+                if ( pos != -1 ) {
+                    try {
+                        value = value.substring(pos + 1);
+                        value = value.substring(0, value.lastIndexOf("\""));
+                    } catch (ArrayIndexOutOfBoundsException aioobe) {
+                        // ignore this as this is a qdox problem
+                        value = this.field.getInitializationExpression();
+                    }
+                }
+                values = new String[] {value};
+            }
+        }
+        return values;
     }
 
     /**