You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2012/06/13 14:03:37 UTC

svn commit: r1349773 [2/5] - in /felix/trunk/scrplugin/generator: ./ src/main/java/org/apache/felix/scrplugin/ src/main/java/org/apache/felix/scrplugin/description/ src/main/java/org/apache/felix/scrplugin/helper/ src/main/java/org/apache/felix/scrplug...

Modified: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
URL: http://svn.apache.org/viewvc/felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java?rev=1349773&r1=1349772&r2=1349773&view=diff
==============================================================================
--- felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java (original)
+++ felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java Wed Jun 13 12:03:35 2012
@@ -18,994 +18,685 @@
  */
 package org.apache.felix.scrplugin;
 
-
 import java.io.File;
-import java.util.*;
-
-import org.apache.felix.scrplugin.helper.*;
-import org.apache.felix.scrplugin.om.*;
-import org.apache.felix.scrplugin.om.metatype.*;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.felix.scrplugin.tags.annotation.AnnotationJavaClassDescription;
-import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.description.ComponentDescription;
+import org.apache.felix.scrplugin.description.PropertyDescription;
+import org.apache.felix.scrplugin.description.PropertyType;
+import org.apache.felix.scrplugin.description.PropertyUnbounded;
+import org.apache.felix.scrplugin.description.ReferenceCardinality;
+import org.apache.felix.scrplugin.description.ReferenceDescription;
+import org.apache.felix.scrplugin.description.ServiceDescription;
+import org.apache.felix.scrplugin.description.SpecVersion;
+import org.apache.felix.scrplugin.helper.AnnotationProcessorManager;
+import org.apache.felix.scrplugin.helper.ClassModifier;
+import org.apache.felix.scrplugin.helper.ClassScanner;
+import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.helper.StringUtils;
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Components;
+import org.apache.felix.scrplugin.om.Context;
+import org.apache.felix.scrplugin.om.Implementation;
+import org.apache.felix.scrplugin.om.Interface;
+import org.apache.felix.scrplugin.om.Property;
+import org.apache.felix.scrplugin.om.Reference;
+import org.apache.felix.scrplugin.om.Service;
+import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
+import org.apache.felix.scrplugin.om.metatype.Designate;
+import org.apache.felix.scrplugin.om.metatype.MTObject;
+import org.apache.felix.scrplugin.om.metatype.MetaData;
+import org.apache.felix.scrplugin.om.metatype.OCD;
 import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;
 import org.apache.felix.scrplugin.xml.MetaTypeIO;
+import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.metatype.MetaTypeService;
 
-
 /**
  * The <code>SCRDescriptorGenerator</code> class does the hard work of
  * generating the SCR descriptors. This class is being instantiated and
  * configured by clients and the {@link #execute()} method called to generate
  * the descriptor files.
  * <p>
- * When using this class carefully consider calling <i>all</i> setter methods
- * to properly configure the generator. All setter method document, which
- * default value is assumed for the respective property if the setter is
- * not called.
+ * When using this class carefully consider calling <i>all</i> setter methods to properly configure the generator. All setter
+ * method document, which default value is assumed for the respective property if the setter is not called.
  * <p>
  * Instances of this class are not thread save and should not be reused.
  */
-public class SCRDescriptorGenerator
-{
+public class SCRDescriptorGenerator {
 
     private final Log logger;
 
-    private File outputDirectory = null;
-
-    private JavaClassDescriptorManager descriptorManager;
+    private File outputDirectory;
 
     private String finalName = "serviceComponents.xml";
 
     private String metaTypeName = "metatype.xml";
 
-    private boolean generateAccessors = true;
-
-    protected boolean strictMode = false;
+    /** The project. */
+    private Project project;
 
-    private Map<String, String> properties = new HashMap<String, String>();
+    /** The options. */
+    private Options options = new Options();
 
-    private String specVersion = null;
+    /** The annotation scanner. */
+    private ClassScanner scanner;
 
+    /** The issue log. */
+    private IssueLog iLog;
 
     /**
-     * Create an instance of this generator using the given {@link Log}
-     * instance of logging.
+     * Create an instance of this generator using the given {@link Log} instance
+     * of logging.
      */
-    public SCRDescriptorGenerator( Log logger )
-    {
+    public SCRDescriptorGenerator(final Log logger) {
         this.logger = logger;
     }
 
-
     /**
-     * Sets the directory where the descriptor files will be created.
-     * <p>
-     * This field has no default value and this setter <b>must</b> called prior
-     * to calling {@link #execute()}.
+     * Set the project. This is required.
      */
-    public void setOutputDirectory( File outputDirectory )
-    {
-        this.outputDirectory = outputDirectory;
+    public void setProject(final Project p) {
+        this.project = p;
     }
 
+    /**
+     * Set the options.
+     */
+    public void setOptions(final Options p) {
+        this.options = p;
+    }
 
     /**
-     * Sets the {@link JavaClassDescriptorManager} instance used to access
-     * existing descriptors and to parse JavaDoc tags as well as interpret
-     * the SCR annotations.
+     * Sets the directory where the descriptor files will be created.
      * <p>
-     * This field has no default value and this setter <b>must</b> called prior
-     * to calling {@link #execute()}.
+     * This field has no default value and this setter <b>must</b> called prior to calling {@link #execute()}.
      */
-    public void setDescriptorManager( JavaClassDescriptorManager descriptorManager )
-    {
-        this.descriptorManager = descriptorManager;
+    public void setOutputDirectory(final File outputDirectory) {
+        this.outputDirectory = outputDirectory;
     }
 
-
     /**
      * Sets the name of the SCR declaration descriptor file. This file will be
-     * created in the <i>OSGI-INF</i> directory below the
-     * {@link #setOutputDirectory(File) output directory}.
+     * created in the <i>OSGI-INF</i> directory below the {@link #setOutputDirectory(File) output directory}.
      * <p>
-     * This file will be overwritten if already existing. If no descriptors
-     * are created the file is actually removed.
+     * This file will be overwritten if already existing. If no descriptors are created the file is actually removed.
      * <p>
      * The default value of this property is <code>serviceComponents.xml</code>.
      */
-    public void setFinalName( String finalName )
-    {
+    public void setFinalName(final String finalName) {
         this.finalName = finalName;
     }
 
-
     /**
      * Sets the name of the file taking the Metatype Service descriptors. This
-     * file will be created in the <i>OSGI-INF/metatype</i> directory below the
-     * {@link #setOutputDirectory(File) output directory}.
+     * file will be created in the <i>OSGI-INF/metatype</i> directory below the {@link #setOutputDirectory(File) output directory}
+     * .
      * <p>
-     * This file will be overwritten if already existing. If no descriptors
-     * are created the file is actually removed.
+     * This file will be overwritten if already existing. If no descriptors are created the file is actually removed.
      * <p>
      * The default value of this property is <code>metatype.xml</code>.
      */
-    public void setMetaTypeName( String metaTypeName )
-    {
+    public void setMetaTypeName(final String metaTypeName) {
         this.metaTypeName = metaTypeName;
     }
 
-
-    /**
-     * Defines whether bind and unbind methods are automatically created by
-     * the SCR descriptor generator.
-     * <p>
-     * The generator uses the ASM library to create the method byte codes
-     * directly inside the class files. If bind and unbind methods are not
-     * to be created, the generator fails if such methods are missing.
-     * <p>
-     * The default value of this property is <code>true</code>.
-     */
-    public void setGenerateAccessors( boolean generateAccessors )
-    {
-        this.generateAccessors = generateAccessors;
-    }
-
-
-    /**
-     * Defines whether warnings should be considered as errors and thus cause
-     * the generation process to fail.
-     * <p>
-     * The default value of this property is <code>false</code>.
-     */
-    public void setStrictMode( boolean strictMode )
-    {
-        this.strictMode = strictMode;
-    }
-
-
-    /**
-     * Sets global properties to be set for each descriptor. If a descriptor
-     * provides properties of the same name, the descriptor properties are preferred
-     * over the properties provided here.
-     * <p>
-     * The are no default global properties.
-     */
-    public void setProperties( Map<String, String> properties )
-    {
-        this.properties = new HashMap<String, String>( properties );
-    }
-
-
-    /**
-     * Sets the Declarative Services specification version number to be forced
-     * on the declarations.
-     * <p>
-     * Supported values for this property are <code>null</code> to autodetect
-     * the specification version, <code>1.0</code> to force 1.0 descriptors and
-     * <code>1.1</code> to force 1.1 descriptors. If 1.0 descriptors are forced
-     * the generation fails if a descriptor requires 1.1 functionality.
-     * <p>
-     * The default is to generate the descriptor version according to the
-     * capabilities used by the descriptors. If no 1.1 capabilities, such as
-     * <code>configuration-policy</code>, are used, version 1.0 is used,
-     * otherwise a 1.1 descriptor is generated.
-     */
-    public void setSpecVersion( String specVersion )
-    {
-        this.specVersion = specVersion;
-    }
-
-
     /**
      * Actually generates the Declarative Services and Metatype descriptors
-     * scanning the java sources provided by the
-     * {@link #setDescriptorManager(JavaClassDescriptorManager) descriptor manager}.
+     * scanning the java sources provided by the {@link #setProject(Project)}
      *
-     * @return <code>true</code> if descriptors have been generated.
+     * @return A list of generated file names, relative to the output directory
      *
      * @throws SCRDescriptorException
      * @throws SCRDescriptorFailureException
      */
-    public boolean execute() throws SCRDescriptorException, SCRDescriptorFailureException
-    {
-        this.logger.debug( "Starting SCRDescriptorMojo...." );
-        this.logger.debug( "..generating accessors: " + this.generateAccessors );
-        this.logger.debug( "..parsing javadocs: " + this.descriptorManager.isParseJavadocs() );
-        this.logger.debug( "..processing annotations: " + this.descriptorManager.isProcessAnnotations() );
+    public Result execute() throws SCRDescriptorException, SCRDescriptorFailureException {
+        if (this.project == null) {
+            throw new SCRDescriptorFailureException("Project has not been set!");
+        }
+        if (this.options == null) {
+            // use default options
+            this.options = new Options();
+        }
+
+        this.logger.debug("Starting SCRDescriptorMojo....");
+        this.logger.debug("..generating accessors: " + this.options.isGenerateAccessors());
 
         // check speck version configuration
-        int specVersion = toSpecVersionCode( this.specVersion, null );
-        if ( this.specVersion == null )
-        {
-            this.logger.debug( "..auto detecting spec version" );
-        }
-        else
-        {
-            this.logger.debug( "..using spec version " + this.specVersion + " (" + specVersion + ")" );
+        SpecVersion specVersion = options.getSpecVersion();
+        if (specVersion == null) {
+            this.logger.debug("..auto detecting spec version");
+        } else {
+            this.logger.debug("..using spec version " + specVersion.getName());
         }
 
-        final IssueLog iLog = new IssueLog( this.strictMode );
+        // create a log
+        this.iLog = new IssueLog(this.options.isStrictMode());
+
+        // create the annotation processor manager
+        final AnnotationProcessor aProcessor = new AnnotationProcessorManager(options.getAnnotationProcessors(),
+                        this.project.getClassLoader());
+
+        // create the class scanner - and start scanning
+        this.scanner = new ClassScanner(logger, iLog, project, aProcessor);
+        final List<ClassDescription> scannedDescriptions = scanner.scanSources();
 
+        // setup metadata
         final MetaData metaData = new MetaData();
-        metaData.setLocalization( MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype" );
+        metaData.setLocalization(MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype");
 
-        // iterate through all source classes and check for component tag
-        final JavaClassDescription[] javaSources = descriptorManager.getSourceDescriptions();
-        Arrays.sort( javaSources, new JavaClassDescriptionInheritanceComparator() );
-
-        final List<Component> scannedComponents = new ArrayList<Component>();
-        for ( int i = 0; i < javaSources.length; i++ )
-        {
-            this.logger.debug( "Testing source " + javaSources[i].getName() );
-            final JavaTag tag = javaSources[i].getTagByName( Constants.COMPONENT );
-            if ( tag != null )
-            {
-                // FELIX-2853 : Deprecate javadoc tags.
-                // This is not the most clever way of doing this, but it is the least intrusive...
-                if ( javaSources[i] instanceof QDoxJavaClassDescription
-                     && !(javaSources[i] instanceof AnnotationJavaClassDescription)) {
-                    iLog.addDeprecationWarning("Class " + javaSources[i].getName() + " is using deprecated javadoc tags ",
-                            tag.getSourceLocation(), tag.getLineNumber());
-                }
-                this.logger.debug( "Processing service class " + javaSources[i].getName() );
-                // check if there is more than one component tag!
-                if ( javaSources[i].getTagsByName( Constants.COMPONENT, false ).length > 1 )
-                {
-                    iLog.addError( "Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT
-                        + " tag." + " Merge the tags to a single tag.", tag.getSourceLocation(), tag.getLineNumber() );
-                }
-                else
-                {
-                    try
-                    {
-                        final Component comp = this.createComponent( javaSources[i], tag, metaData, iLog );
-                        if ( comp.getSpecVersion() > specVersion )
-                        {
+        final List<Component> processedComponents = new ArrayList<Component>();
+        for (final ClassDescription desc : scannedDescriptions) {
+            this.logger.debug("Processing component class " + desc.getSource());
+
+            // check if there is more than one component definition
+            if (desc.getDescriptions(ComponentDescription.class).size() > 1) {
+                iLog.addError("Class has more than one component definition." +
+                             " Check the annotations and merge the definitions to a single definition.",
+                                desc.getSource());
+            } else {
+                try {
+                    final Component comp = this.createComponent(desc, metaData, iLog);
+                    if (comp.getSpecVersion() != null) {
+                        if ( specVersion == null ) {
+                            specVersion = comp.getSpecVersion();
+                            logger.debug("Setting used spec version to " + specVersion);
+                        } else if (comp.getSpecVersion().ordinal() > specVersion.ordinal() && this.options.getSpecVersion() != null) {
                             // if a spec version has been configured and a component requires a higher
                             // version, this is considered an error!
-                            if ( this.specVersion != null )
-                            {
-                                String v = Constants.COMPONENT_DS_SPEC_VERSION_10;
-                                if ( comp.getSpecVersion() == Constants.VERSION_1_1 )
-                                {
-                                    v = Constants.COMPONENT_DS_SPEC_VERSION_11;
-                                }
-                                iLog.addError( "Component " + comp + " requires spec version " + v
-                                    + " but plugin is configured to use version " + this.specVersion, tag
-                                    .getSourceLocation(), tag.getLineNumber() );
-                            }
-                            specVersion = comp.getSpecVersion();
+                            iLog.addError("Component " + comp + " requires spec version " + comp.getSpecVersion().name()
+                                            + " but plugin is configured to use version " + this.options.getSpecVersion(),
+                                            desc.getSource());
                         }
-                        scannedComponents.add( comp );
-                    }
-                    catch ( SCRDescriptorException sde )
-                    {
-                        iLog.addError( sde.getMessage(), sde.getSourceLocation(), sde.getLineNumber() );
                     }
+                    processedComponents.add(comp);
+                } catch (final SCRDescriptorException sde) {
+                    iLog.addError(sde.getMessage(), sde.getSourceLocation());
                 }
             }
         }
-        this.logger.debug( "..generating descriptor for spec version: " + this.specVersion );
+        // if spec version is still not set, we're using lowest available
+        if ( specVersion == null ) {
+            specVersion = SpecVersion.VERSION_1_0;
+            logger.debug("Using default spec version " + specVersion);
+        }
+        this.logger.debug("Generating descriptor for spec version: " + specVersion);
 
         // now check for abstract components and fill components objects
         final Components components = new Components();
-        final Components abstractComponents = new Components();
-        components.setSpecVersion( specVersion );
-        abstractComponents.setSpecVersion( specVersion );
+        components.setSpecVersion(specVersion);
 
-        for ( final Component comp : scannedComponents )
-        {
+        for (final Component comp : processedComponents) {
             final int errorCount = iLog.getNumberOfErrors();
-            // before we can validate we should check the references for bind/unbind method
-            // in order to create them if possible
 
-            for ( final Reference ref : comp.getReferences() )
-            {
-                // if this is a field with a single cardinality,
-                // we look for the bind/unbind methods
-                // and create them if they are not availabe
-                if ( this.generateAccessors && !ref.isLookupStrategy() )
-                {
-                    if ( ref.getJavaTag().getField() != null
-                        && comp.getJavaClassDescription() instanceof ModifiableJavaClassDescription )
-                    {
-                        if ( ref.getCardinality().equals( "0..1" ) || ref.getCardinality().equals( "1..1" ) )
-                        {
-                            final String bindValue = ref.getBind();
-                            final String unbindValue = ref.getUnbind();
-                            final String name = ref.getName();
-                            final String type = ref.getInterfacename();
-
-                            boolean createBind = false;
-                            boolean createUnbind = false;
-                            // Only create method if no bind name has been specified
-                            if ( bindValue == null && ref.findMethod( specVersion, "bind" ) == null )
-                            {
-                                // create bind method
-                                createBind = true;
-                            }
-                            if ( unbindValue == null && ref.findMethod( specVersion, "unbind" ) == null )
-                            {
-                                // create unbind method
-                                createUnbind = true;
-                            }
-                            if ( createBind || createUnbind )
-                            {
-                                ( ( ModifiableJavaClassDescription ) comp.getJavaClassDescription() ).addMethods( name,
-                                    type, createBind, createUnbind );
-                            }
+            final Context ctx = new Context();
+            ctx.setClassDescription(comp.getClassDescription());
+            ctx.setIssueLog(iLog);
+            ctx.setProject(project);
+            ctx.setSpecVersion(specVersion);
+            ctx.setOptions(options);
+
+            if ( this.options.isGenerateAccessors() ) {
+                // before we can validate we should check the references for bind/unbind method
+                // in order to create them if possible
+
+                for (final Reference ref : comp.getReferences()) {
+                    // if this is a field with a single cardinality,
+                    // we look for the bind/unbind methods
+                    // and create them if they are not availabe
+                    if (!ref.isLookupStrategy() && ref.getField() != null
+                        && (ref.getCardinality() == ReferenceCardinality.OPTIONAL_UNARY || ref.getCardinality() == ReferenceCardinality.MANDATORY_UNARY)) {
+
+                        final String bindValue = ref.getBind();
+                        final String unbindValue = ref.getUnbind();
+                        final String name = ref.getName();
+                        final String type = ref.getInterfacename();
+
+                        boolean createBind = false;
+                        boolean createUnbind = false;
+
+                        // Only create method if no bind name has been specified
+                        if (bindValue == null && ref.findMethod(ctx, "bind") == null) {
+                            // create bind method
+                            createBind = true;
+                        }
+                        if (unbindValue == null && ref.findMethod(ctx, "unbind") == null) {
+                            // create unbind method
+                            createUnbind = true;
+                        }
+                        if (createBind || createUnbind) {
+                            ClassModifier.addMethods(comp.getClassDescription().getDescribedClass().getName(),
+                                            name,
+                                            ref.getField().getName(),
+                                            type,
+                                            createBind,
+                                            createUnbind,
+                                            this.project.getClassesDirectory());
                         }
                     }
                 }
             }
-            comp.validate( specVersion, iLog );
+            comp.validate(ctx);
+
             // ignore component if it has errors
-            if ( iLog.getNumberOfErrors() == errorCount )
-            {
-                if ( !comp.isDs() )
-                {
-                    logger.debug( "Ignoring descriptor " + comp );
-                }
-                else if ( comp.isAbstract() )
-                {
-                    this.logger.debug( "Adding abstract descriptor " + comp );
-                    abstractComponents.addComponent( comp );
-                }
-                else
-                {
-                    this.logger.debug( "Adding descriptor " + comp );
-                    components.addComponent( comp );
-                    abstractComponents.addComponent( comp );
+            if (iLog.getNumberOfErrors() == errorCount) {
+                if (!comp.isDs()) {
+                    logger.debug("Ignoring descriptor for DS : " + comp);
+                } else if (!comp.isAbstract()) {
+                    this.logger.debug("Adding descriptor for DS : " + comp);
+                    components.addComponent(comp);
                 }
             }
         }
 
         // log issues
-        iLog.logMessages( logger );
+        iLog.logMessages(logger);
 
         // after checking all classes, throw if there were any failures
-        if ( iLog.hasErrors() )
-        {
-            throw new SCRDescriptorFailureException( "SCR Descriptor parsing had failures (see log)" );
+        if (iLog.hasErrors()) {
+            throw new SCRDescriptorFailureException("SCR Descriptor parsing had failures (see log)");
         }
 
-        boolean addResources = false;
+        final Result result = new Result();
         // write meta type info if there is a file name
-        if ( !StringUtils.isEmpty( this.metaTypeName ) )
-        {
-            File mtFile = new File( this.outputDirectory, "OSGI-INF" + File.separator + "metatype" + File.separator
-                + this.metaTypeName );
+        if (!StringUtils.isEmpty(this.metaTypeName)) {
+            final String path = "OSGI-INF" + File.separator + "metatype" + File.separator + this.metaTypeName;
+            final File mtFile = new File(this.outputDirectory, path);
             final int size = metaData.getOCDs().size() + metaData.getDesignates().size();
-            if ( size > 0 )
-            {
-                this.logger.info( "Generating " + size + " MetaType Descriptors to " + mtFile );
+            if (size > 0) {
+                this.logger.info("Generating " + size + " MetaType Descriptors to " + mtFile);
                 mtFile.getParentFile().mkdirs();
-                MetaTypeIO.write( metaData, mtFile );
-                addResources = true;
-            }
-            else
-            {
-                if ( mtFile.exists() )
-                {
+                MetaTypeIO.write(metaData, mtFile);
+                result.setMetatypeFiles(Collections.singletonList(path.replace(File.separatorChar, '/')));
+            } else {
+                if (mtFile.exists()) {
                     mtFile.delete();
                 }
             }
 
-        }
-        else
-        {
-            this.logger.info( "Meta type file name is not set: meta type info is not written." );
-        }
-
-        // if we have descriptors, write them in our scr private file (for component inheritance)
-        final File adFile = new File( this.outputDirectory, Constants.ABSTRACT_DESCRIPTOR_RELATIVE_PATH );
-        if ( !abstractComponents.getComponents().isEmpty() )
-        {
-            this.logger.info( "Writing abstract service descriptor " + adFile + " with "
-                + abstractComponents.getComponents().size() + " entries." );
-            adFile.getParentFile().mkdirs();
-            ComponentDescriptorIO.write( abstractComponents, adFile, true );
-            addResources = true;
-        }
-        else
-        {
-            this.logger.debug( "No abstract SCR Descriptors found in project." );
-            // remove file
-            if ( adFile.exists() )
-            {
-                this.logger.debug( "Removing obsolete abstract service descriptor " + adFile );
-                adFile.delete();
-            }
+        } else {
+            this.logger.info("Meta type file name is not set: meta type info is not written.");
         }
 
         // check descriptor file
-        final File descriptorFile = StringUtils.isEmpty( this.finalName ) ? null : new File( new File(
-            this.outputDirectory, "OSGI-INF" ), this.finalName );
+        final String descriptorPath = "OSGI-INF" + File.separator + this.finalName;
+        final File descriptorFile = StringUtils.isEmpty(this.finalName) ? null : new File(this.outputDirectory, descriptorPath);
 
         // terminate if there is nothing else to write
-        if ( components.getComponents().isEmpty() )
-        {
-            this.logger.debug( "No SCR Descriptors found in project." );
+        if (components.getComponents().isEmpty()) {
+            this.logger.debug("No Service Component Descriptors found in project.");
             // remove file if it exists
-            if ( descriptorFile != null && descriptorFile.exists() )
-            {
-                this.logger.debug( "Removing obsolete service descriptor " + descriptorFile );
+            if (descriptorFile != null && descriptorFile.exists()) {
+                this.logger.debug("Removing obsolete service descriptor " + descriptorFile);
                 descriptorFile.delete();
             }
-        }
-        else
-        {
-            if ( descriptorFile == null )
-            {
-                throw new SCRDescriptorFailureException( "Descriptor file name must not be empty." );
+        } else {
+            if (descriptorFile == null) {
+                throw new SCRDescriptorFailureException("Descriptor file name must not be empty.");
             }
 
             // finally the descriptors have to be written ....
             descriptorFile.getParentFile().mkdirs(); // ensure parent dir
 
-            this.logger.info( "Generating " + components.getComponents().size() + " Service Component Descriptors to "
-                + descriptorFile );
+            this.logger.info("Writing " + components.getComponents().size() + " Service Component Descriptors to "
+                            + descriptorFile);
 
-            ComponentDescriptorIO.write( components, descriptorFile, false );
-            addResources = true;
+            ComponentDescriptorIO.write(components, descriptorFile);
+            result.setScrFiles(Collections.singletonList(descriptorPath.replace(File.separatorChar, '/')));
         }
 
-        return addResources;
+        return result;
     }
 
-
     /**
-     * Create a component for the java class description.
-     * @param description
-     * @return The generated component descriptor or null if any error occurs.
-     * @throws SCRDescriptorException
+     * Create the SCR objects based on the descriptions
      */
-    protected Component createComponent( JavaClassDescription description, JavaTag componentTag, MetaData metaData,
-        final IssueLog iLog ) throws SCRDescriptorException
-    {
-        // create a new component
-        final Component component = new Component( componentTag );
-
-        // set implementation
-        component.setImplementation( new Implementation( description.getName() ) );
-
-        final boolean inherited = getBoolean( componentTag, Constants.COMPONENT_INHERIT, true );
-        final OCD ocd = this.doComponent( componentTag, component, metaData,inherited,  iLog );
-
-        this.doServices( description.getTagsByName( Constants.SERVICE, inherited ), component, description );
-
-        // collect references from class tags and fields
-        final Map<String, Object[]> references = new LinkedHashMap<String, Object[]>();
-        // 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++ )
-            {
-                propertyHandler.testProperty( props[i], null, description == currentDescription );
-            }
-
-            // references
-            final JavaTag[] refs = currentDescription.getTagsByName( Constants.REFERENCE, false );
-            for ( int i = 0; i < refs.length; i++ )
-            {
-                this.testReference( references, refs[i], null, description == currentDescription );
-            }
-
-            // fields
-            final JavaField[] fields = currentDescription.getFields();
-            for ( int i = 0; i < fields.length; i++ )
-            {
-                JavaTag tag = fields[i].getTagByName( Constants.REFERENCE );
-                if ( tag != null )
-                {
-                    this.testReference( references, tag, fields[i].getName(), description == currentDescription );
-                }
-
-                propertyHandler.handleField( fields[i], description == currentDescription );
-            }
-
-            currentDescription = currentDescription.getSuperClass();
-        }
-        while ( inherited && currentDescription != null );
-
-        // process properties
-        propertyHandler.processProperties( this.properties, iLog );
-
-        // process references
-        final Iterator<Map.Entry<String, Object[]>> refIter = references.entrySet().iterator();
-        while ( refIter.hasNext() )
-        {
-            final Map.Entry<String, Object[]> entry = refIter.next();
-            final String refName = entry.getKey();
-            final Object[] values = entry.getValue();
-            final JavaTag tag = ( JavaTag ) values[0];
-            this.doReference( tag, refName, component, values[1].toString(), ((Boolean)values[2]).booleanValue() );
-        }
-
-        // pid handling
-        final boolean createPid = getBoolean( componentTag, Constants.COMPONENT_CREATE_PID, true );
-        if ( createPid )
-        {
-            // check for an existing pid first
-            boolean found = false;
-            final Iterator<Property> iter = component.getProperties().iterator();
-            while ( !found && iter.hasNext() )
-            {
-                final Property prop = iter.next();
-                found = org.osgi.framework.Constants.SERVICE_PID.equals( prop.getName() );
-            }
-            if ( !found )
-            {
-                final Property pid = new Property();
-                component.addProperty( pid );
-                pid.setName( org.osgi.framework.Constants.SERVICE_PID );
-                pid.setValue( component.getName() );
-            }
-        }
-        return component;
-    }
-
-
-    /**
-     * Fill the component object with the information from the tag.
-     * @param tag
-     * @param component
-     */
-    protected OCD doComponent( final JavaTag tag,
-            final Component component,
-            final MetaData metaData,
-            final boolean inherit,
-            final IssueLog iLog )
-        throws SCRDescriptorException
-    {
-
-        // check if this is an abstract definition
-        final String abstractType = tag.getNamedParameter( Constants.COMPONENT_ABSTRACT );
-        if ( abstractType != null )
-        {
-            component.setAbstract( "yes".equalsIgnoreCase( abstractType ) || "true".equalsIgnoreCase( abstractType ) );
-        }
-        else
-        {
-            // default true for abstract classes, false otherwise
-            component.setAbstract( tag.getJavaClassDescription().isAbstract() );
-        }
-
-        // check if this is a definition to ignore
-        final String ds = tag.getNamedParameter( Constants.COMPONENT_DS );
-        component.setDs( ( ds == null ) ? true : ( "yes".equalsIgnoreCase( ds ) || "true".equalsIgnoreCase( ds ) ) );
-
-        String name = tag.getNamedParameter( Constants.COMPONENT_NAME );
-        component.setName( StringUtils.isEmpty( name ) ? component.getImplementation().getClassame() : name );
-
-        component.setEnabled( Boolean.valueOf( getBoolean( tag, Constants.COMPONENT_ENABLED, true ) ) );
-        component.setFactory( tag.getNamedParameter( Constants.COMPONENT_FACTORY ) );
-
-        // FELIX-1703: support explicit SCR version declaration
-        final String dsSpecVersion = tag.getNamedParameter( Constants.COMPONENT_DS_SPEC_VERSION );
-        if ( dsSpecVersion != null )
-        {
-            component.setSpecVersion( toSpecVersionCode( dsSpecVersion, tag ) );
-        }
-
-        // FELIX-593: immediate attribute does not default to true all the
-        // times hence we only set it if declared in the tag
-        if ( tag.getNamedParameter( Constants.COMPONENT_IMMEDIATE ) != null )
-        {
-            component.setImmediate( Boolean.valueOf( getBoolean( tag, Constants.COMPONENT_IMMEDIATE, true ) ) );
-        }
-
-        // check for V1.1 attributes: configuration policy
-        if ( tag.getNamedParameter( Constants.COMPONENT_CONFIG_POLICY ) != null )
-        {
-            component.setSpecVersion( Constants.VERSION_1_1 );
-            component.setConfigurationPolicy( tag.getNamedParameter( Constants.COMPONENT_CONFIG_POLICY ) );
-        }
-        // check for V1.1 attributes: activate, deactivate, modified
-        component.setActivate(this.checkLifecycleMethod(component, Constants.COMPONENT_ACTIVATE, tag, inherit));
-        component.setDeactivate(this.checkLifecycleMethod(component, Constants.COMPONENT_DEACTIVATE, tag, inherit));
-        component.setModified(this.checkLifecycleMethod(component, Constants.COMPONENT_MODIFIED, tag, inherit));
-
-        // whether metatype information is to generated for the component
-        final String metaType = tag.getNamedParameter( Constants.COMPONENT_METATYPE );
-        final boolean hasMetaType = metaType == null || "yes".equalsIgnoreCase( metaType )
-            || "true".equalsIgnoreCase( metaType );
-        if ( !component.isAbstract() && hasMetaType )
-        {
-            // ocd
-            final OCD ocd = new OCD();
+    private Component createComponent(final ClassDescription desc,
+                    final MetaData metaData,
+                    final IssueLog iLog)
+    throws SCRDescriptorException, SCRDescriptorFailureException {
+        final ComponentDescription componentDesc = desc.getDescription(ComponentDescription.class);
+        final Component comp = new Component(desc, componentDesc.getAnnotation(), desc.getSource());
+
+        comp.setName(componentDesc.getName());
+        comp.setConfigurationPolicy(componentDesc.getConfigurationPolicy());
+        comp.setAbstract(componentDesc.isAbstract());
+        comp.setDs(componentDesc.isCreateDs());
+        comp.setFactory(componentDesc.getFactory());
+        comp.setSpecVersion(componentDesc.getSpecVersion());
+
+        // Create metatype (if required)
+        final OCD ocd;
+        if ( !componentDesc.isAbstract() && componentDesc.isCreateMetatype() ) {
+            // OCD
+            ocd = new OCD();
             metaData.addOCD( ocd );
-            ocd.setId( component.getName() );
-            String ocdName = tag.getNamedParameter( Constants.COMPONENT_LABEL );
-            if ( ocdName == null )
-            {
-                ocdName = "%" + component.getName() + ".name";
-            }
-            ocd.setName( ocdName );
-            String ocdDescription = tag.getNamedParameter( Constants.COMPONENT_DESCRIPTION );
-            if ( ocdDescription == null )
-            {
-                ocdDescription = "%" + component.getName() + ".description";
+            ocd.setId( componentDesc.getName() );
+            if ( componentDesc.getLabel() != null ) {
+                ocd.setName( componentDesc.getLabel() );
+            } else {
+                ocd.setName( "%" + componentDesc.getName() + ".name");
+            }
+            if ( componentDesc.getDescription() != null ) {
+                ocd.setDescription( componentDesc.getDescription() );
+            } else {
+                ocd.setDescription( "%" + componentDesc.getName() + ".description");
             }
-            ocd.setDescription( ocdDescription );
-            // designate
+
+            // Designate
             final Designate designate = new Designate();
             metaData.addDesignate( designate );
-            designate.setPid( component.getName() );
+            designate.setPid( componentDesc.getName() );
 
-            // factory pid
-            final String setFactoryPidValue = tag.getNamedParameter( Constants.COMPONENT_SET_METATYPE_FACTORY_PID );
-            final boolean setFactoryPid = setFactoryPidValue != null
-                && ( "yes".equalsIgnoreCase( setFactoryPidValue ) || "true".equalsIgnoreCase( setFactoryPidValue ) );
-            if ( setFactoryPid )
-            {
-                if ( component.getFactory() == null )
-                {
-                    designate.setFactoryPid( component.getName() );
-                }
-                else
-                {
-                    iLog.addWarning( "Component factory " + component.getName()
-                        + " should not set metatype factory pid.", tag.getSourceLocation(), tag.getLineNumber() );
+            // Factory pid
+            if ( componentDesc.isSetMetatypeFactoryPid() ) {
+                if ( componentDesc.getFactory() == null ) {
+                    designate.setFactoryPid( componentDesc.getName() );
+                } else {
+                    iLog.addWarning( "Component factory " + componentDesc.getName()
+                        + " should not set metatype factory pid.", desc.getSource() );
                 }
             }
-            // designate.object
+            // MTObject
             final MTObject mtobject = new MTObject();
             designate.setObject( mtobject );
-            mtobject.setOcdref( component.getName() );
-            return ocd;
+            mtobject.setOcdref( componentDesc.getName() );
+        } else {
+            ocd = null;
         }
-        return null;
-    }
 
-    private String checkLifecycleMethod(final Component component,
-            final String methodTagName,
-            final JavaTag tag,
-            final boolean inherit)
-    throws SCRDescriptorException
-    {
-        String method = null;
-        if ( tag.getNamedParameter( methodTagName ) != null )
-        {
-            method = tag.getNamedParameter( methodTagName );
-        }
-        else if ( inherit )
-        {
-            // check if a super class has the activate method specified
-            JavaClassDescription desc = tag.getJavaClassDescription().getSuperClass();
-            while ( desc != null && method == null )
-            {
-                final JavaTag componentTag = desc.getTagByName( Constants.COMPONENT );
-                if ( componentTag != null && componentTag.getNamedParameter( methodTagName ) != null )
-                {
-                    method = componentTag.getNamedParameter( methodTagName );
+        // Create implementation object
+        final Implementation impl = new Implementation(desc.getDescribedClass().getName());
+        comp.setImplementation(impl);
+
+        final Map<String, Reference> allReferences = new HashMap<String, Reference>();
+        final Map<String, Property> allProperties = new HashMap<String, Property>();
+
+        ClassDescription current = desc;
+        boolean inherit;
+        do {
+            final ComponentDescription cd = current.getDescription(ComponentDescription.class);
+            inherit = (cd == null ? true : cd.isInherit());
+
+            if ( cd != null ) {
+                // handle enabled and immediate
+                if ( comp.isEnabled() == null ) {
+                    comp.setEnabled(cd.getEnabled());
+                }
+                if ( comp.isImmediate() == null ) {
+                    comp.setImmediate(cd.getImmediate());
                 }
-                desc = desc.getSuperClass();
-            }
-        }
-        if ( method != null )
-        {
-            component.setSpecVersion( Constants.VERSION_1_1 );
-        }
-        return method;
-    }
 
-    /**
-     * Process the service annotations
-     * @param services
-     * @param component
-     * @param description
-     * @throws SCRDescriptorException
-     */
-    protected void doServices( JavaTag[] services, Component component, JavaClassDescription description )
-        throws SCRDescriptorException
-    {
-        // no services, hence certainly no service factory
-        if ( services == null || services.length == 0 )
-        {
-            return;
-        }
-
-        final Service service = new Service();
-        component.setService( service );
-        boolean serviceFactory = false;
-        for ( int i = 0; i < services.length; i++ )
-        {
-            final String name = services[i].getNamedParameter( Constants.SERVICE_INTERFACE );
-            if ( StringUtils.isEmpty( name ) )
-            {
-
-                this.addInterfaces( service, services[i], description );
-            }
-            else
-            {
-                String interfaceName = name;
-                // check if the value points to a class/interface
-                // and search through the imports
-                // but only for local services
-                if ( description instanceof QDoxJavaClassDescription )
-                {
-                    final JavaClassDescription serviceClass = description.getReferencedClass( name );
-                    if ( serviceClass == null )
-                    {
-                        throw new SCRDescriptorException( "Interface '" + name + "' in class " + description.getName()
-                            + " does not point to a valid class/interface.", services[i] );
-                    }
-                    interfaceName = serviceClass.getName();
+                // lifecycle methods
+                if ( comp.getActivate() == null && cd.getActivate() != null ) {
+                    comp.setActivate(cd.getActivate().getName());
+                }
+                if ( comp.getDeactivate() == null && cd.getDeactivate() != null ) {
+                    comp.setDeactivate(cd.getDeactivate().getName());
+                }
+                if ( comp.getModified() == null && cd.getModified() != null ) {
+                    comp.setModified(cd.getModified().getName());
+                }
+                if ( comp.getActivate() != null || comp.getDeactivate() != null || comp.getModified() != null ) {
+                    // spec version must be at least 1.1
+                    comp.setSpecVersion(SpecVersion.VERSION_1_1);
                 }
-                final Interface interf = new Interface( services[i] );
-                interf.setInterfacename( interfaceName );
-                service.addInterface( interf );
             }
 
-            serviceFactory |= getBoolean( services[i], Constants.SERVICE_FACTORY, false );
-        }
-
-        service.setServicefactory( serviceFactory );
-    }
-
+            // services, properties, references
+            this.processServices(current, comp);
+            this.processProperties(current, comp, ocd, allProperties);
+            this.processReferences(current, comp, allReferences);
 
-    /**
-     * Recursively add interfaces to the service.
-     */
-    protected void addInterfaces( final Service service, final JavaTag serviceTag,
-        final JavaClassDescription description ) throws SCRDescriptorException
-    {
-        if ( description != null )
-        {
-            JavaClassDescription[] interfaces = description.getImplementedInterfaces();
-            for ( int j = 0; j < interfaces.length; j++ )
-            {
-                final Interface interf = new Interface( serviceTag );
-                interf.setInterfacename( interfaces[j].getName() );
-                service.addInterface( interf );
-                // recursivly add interfaces implemented by this interface
-                this.addInterfaces( service, serviceTag, interfaces[j] );
+            // go up in the class hierarchy
+            if ( !inherit || current.getDescribedClass().getSuperclass() == null ) {
+                current = null;
+            } else {
+                current = this.scanner.getDescription(current.getDescribedClass().getSuperclass());
             }
+        } while ( inherit && current != null);
 
-            // try super class
-            this.addInterfaces( service, serviceTag, description.getSuperClass() );
+        // PID handling
+        if ( componentDesc.isCreatePid() && !allProperties.containsKey(org.osgi.framework.Constants.SERVICE_PID)) {
+            final Property pid = new Property(null, "scr-generator");
+            pid.setName( org.osgi.framework.Constants.SERVICE_PID );
+            pid.setValue( comp.getName() );
+
+            allProperties.put(org.osgi.framework.Constants.SERVICE_PID, pid);
+            comp.addProperty( pid );
         }
-    }
+        this.processGlobalProperties(desc, comp, allProperties);
 
+        return comp;
+    }
 
     /**
-     * Test a newly found reference
-     * @param references
-     * @param reference
-     * @param defaultName
-     * @param isInspectedClass
-     * @throws SCRDescriptorException
+     * Process service directives
      */
-    protected void testReference( Map<String, Object[]> references, JavaTag reference, String defaultName,
-        boolean isInspectedClass ) throws SCRDescriptorException
-    {
-        String refName = this.getReferenceName( reference, defaultName );
-
-        boolean setName = refName != null;
-        if ( refName == null)
-        {
-            refName = this.getReferencedInterface(reference, isInspectedClass, null);
-        }
+    private void processServices(final ClassDescription current, final Component component)
+    throws SCRDescriptorException, SCRDescriptorFailureException {
 
-        if ( refName != null )
-        {
-            if ( references.containsKey( refName ) )
-            {
-                // 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 reference " + refName + " in class "
-                        + reference.getJavaClassDescription().getName(), reference );
-                }
+        final ServiceDescription serviceDesc = current.getDescription(ServiceDescription.class);
+        if ( serviceDesc != null ) {
+            Service service = component.getService();
+            if ( service == null ) {
+                service = new Service();
+                service.setServiceFactory(false);
+                component.setService(service);
             }
-            else
-            {
-                // ensure interface
-                final String type = this.getReferencedInterface(reference, isInspectedClass, refName);
-                references.put( refName, new Object[]
-                    { reference, type, (setName ? Boolean.TRUE : Boolean.FALSE) } );
+            if ( serviceDesc.isServiceFactory() ) {
+                service.setServiceFactory(true);
+            }
+            for(final String className : serviceDesc.getInterfaces()) {
+                final Interface interf = new Interface(serviceDesc.getAnnotation(), current.getSource());
+                interf.setInterfaceName(className);
+                service.addInterface(interf);
             }
-        }
-        else
-        {
-            throw new SCRDescriptorException( "No name detectable for reference in class "
-                    + reference.getJavaClassDescription().getName(), reference );
         }
     }
 
-    protected String getReferencedInterface(final JavaTag reference,
-                                            final boolean isInspectedClass,
-                                            final String refName) throws SCRDescriptorException
-    {
-        String type = reference.getNamedParameter( Constants.REFERENCE_INTERFACE );
-        if ( StringUtils.isEmpty( type ) )
-        {
-            if ( reference.getField() != null )
-            {
-                type = reference.getField().getType();
-            }
-            else
-            {
-                throw new SCRDescriptorException( "Interface missing for reference " + (refName == null ? "" : refName) + " in class "
-                    + reference.getJavaClassDescription().getName(), reference );
+    /**
+     * Process property directives
+     */
+    private void processProperties(
+                    final ClassDescription current,
+                    final Component component,
+                    final OCD ocd,
+                    final Map<String, Property> allProperties)
+    throws SCRDescriptorException, SCRDescriptorFailureException {
+        for(final PropertyDescription pd : current.getDescriptions(PropertyDescription.class)) {
+            final Property prop = new Property(pd.getAnnotation(), current.getSource());
+            prop.setName(pd.getName());
+            prop.setType(pd.getType());
+            if ( pd.getValue() != null ) {
+                prop.setValue(pd.getValue());
+            } else {
+                prop.setMultiValue(pd.getMultiValue());
             }
-        }
-        else if ( isInspectedClass )
-        {
-            // check if the value points to a class/interface
-            // and search through the imports
-            final JavaClassDescription serviceClass = reference.getJavaClassDescription().getReferencedClass(
-                type );
-            if ( serviceClass == null )
-            {
-                throw new SCRDescriptorException( "Interface '" + type + "' in class "
-                    + reference.getJavaClassDescription().getName()
-                    + " does not point to a valid class/interface.", reference );
+
+            // metatype - is this property private?
+            final boolean isPrivate;
+            if ( pd.isPrivate() != null ) {
+                isPrivate = pd.isPrivate();
+            } else {
+                final String name = prop.getName();
+                if (org.osgi.framework.Constants.SERVICE_RANKING.equals(name)
+                    || org.osgi.framework.Constants.SERVICE_PID.equals(name)
+                    || org.osgi.framework.Constants.SERVICE_DESCRIPTION.equals(name)
+                    || org.osgi.framework.Constants.SERVICE_ID.equals(name)
+                    || org.osgi.framework.Constants.SERVICE_VENDOR.equals(name)
+                    || ConfigurationAdmin.SERVICE_BUNDLELOCATION.equals(name)
+                    || ConfigurationAdmin.SERVICE_FACTORYPID.equals(name) ) {
+                    isPrivate = true;
+                } else {
+                    isPrivate = false;
+                }
             }
-            type = serviceClass.getName();
-        }
-        return type;
-    }
+            if ( !isPrivate && ocd != null ) {
+                final AttributeDefinition ad = new AttributeDefinition();
+                ocd.getProperties().add(ad);
+                ad.setId(prop.getName());
+                ad.setType(prop.getType().name());
+
+                if (pd.getLabel() != null ) {
+                    ad.setName(pd.getLabel());
+                } else {
+                    ad.setName("%" + prop.getName() + ".name");
+                }
+                if (pd.getDescription() != null ) {
+                    ad.setDescription(pd.getDescription());
+                } else {
+                    ad.setDescription("%" + prop.getName() + ".description");
+                }
+
+                if ( pd.getUnbounded() == PropertyUnbounded.DEFAULT ) {
+                    ad.setCardinality(pd.getCardinality());
+                } else if ( pd.getUnbounded() == PropertyUnbounded.ARRAY ) {
+                    // unlimited array
+                    ad.setCardinality(new Integer(Integer.MAX_VALUE));
+                } else {
+                    // unlimited vector
+                    ad.setCardinality(new Integer(Integer.MIN_VALUE));
+                }
+
+                ad.setDefaultValue(prop.getValue());
+                ad.setDefaultMultiValue(prop.getMultiValue());
+
+                // check options
+                final String[] parameters = pd.getOptions();
+                if ( parameters != null && parameters.length > 0 ) {
+                    final Map<String, String> options = new LinkedHashMap<String, String>();
+                    for (int j=0; j < parameters.length; j=j+2) {
+                        final String optionLabel = parameters[j];
+                        final String optionValue = (j < parameters.length-1) ? parameters[j+1] : null;
+                        if (optionValue != null) {
+                            options.put(optionLabel, optionValue);
+                        }
+                    }
+                    ad.setOptions(options);
+                }
 
-    protected String getReferenceName( final JavaTag reference,
-            final String defaultName) throws SCRDescriptorException
-    {
-        String name = reference.getNamedParameter( Constants.REFERENCE_NAME );
-        if ( !StringUtils.isEmpty( name ) )
-        {
-            return name;
-        }
-        name = reference.getNamedParameter( Constants.REFERENCE_NAME_REF );
-        if ( !StringUtils.isEmpty( name ) )
-        {
-            final JavaField refField = this.getReferencedField( reference, name );
-            final String[] values = refField.getInitializationExpression();
-            if ( values == null || values.length == 0 )
-            {
-                throw new SCRDescriptorException( "Referenced field for " + name
-                    + " has no values for a reference name.", reference );
             }
-            if ( values.length > 1 )
-            {
-                throw new SCRDescriptorException( "Referenced field " + name
-                    + " has more than one value for a reference name.", reference );
+            if ( this.testProperty(current, allProperties, prop, current == component.getClassDescription())) {
+                component.addProperty(prop);
             }
-            return values[0];
         }
-
-        return defaultName;
     }
 
+    /**
+     * Add global properties (if not already defined in the component)
+     */
+    private void processGlobalProperties(final ClassDescription desc,
+                    final Component component,
+                    final Map<String, Property> 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) ) {
 
-    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( "Reference references unknown field " + ref + " in class "
-                + tag.getJavaClassDescription().getName(), tag );
+                    final Property p = new Property(null, "scr-generator");
+                    p.setName(propName);
+                    p.setValue(value);
+                    p.setType(PropertyType.String);
+
+                    component.addProperty(p);
+                    allProperties.put(propName, p);
+                }
+            }
         }
-        return field;
     }
 
-
     /**
-     * Process a reference
-     * @param reference
-     * @param defaultName
-     * @param component
+     * Test a newly found property
      */
-    protected void doReference( JavaTag reference, String name, Component component, String type,
-            final boolean setName)
-        throws SCRDescriptorException
-    {
-        final Reference ref = new Reference( reference, component.getJavaClassDescription() );
-        if ( setName )
-        {
-            ref.setName( name );
-        }
-        ref.setInterfacename( type );
-        ref.setCardinality( reference.getNamedParameter( Constants.REFERENCE_CARDINALITY ) );
-        if ( ref.getCardinality() == null )
-        {
-            ref.setCardinality( "1..1" );
-        }
-        ref.setPolicy( reference.getNamedParameter( Constants.REFERENCE_POLICY ) );
-        if ( ref.getPolicy() == null )
-        {
-            ref.setPolicy( "static" );
-        }
-        ref.setTarget( reference.getNamedParameter( Constants.REFERENCE_TARGET ) );
-        final String bindValue = reference.getNamedParameter( Constants.REFERENCE_BIND );
-        if ( bindValue != null )
-        {
-            ref.setBind( bindValue );
-        }
-        final String unbindValue = reference.getNamedParameter( Constants.REFERENCE_UNDBIND );
-        if ( unbindValue != null )
-        {
-            ref.setUnbind( unbindValue );
-        }
-        final String updatedValue = reference.getNamedParameter( Constants.REFERENCE_UPDATED );
-        if ( updatedValue != null )
-        {
-            ref.setUpdated( updatedValue );
-        }
-        final String isChecked = reference.getNamedParameter( Constants.REFERENCE_CHECKED );
-        if ( isChecked != null )
-        {
-            ref.setChecked( Boolean.valueOf( isChecked ).booleanValue() );
-        }
-        final String strategy = reference.getNamedParameter( Constants.REFERENCE_STRATEGY );
-        if ( strategy != null )
-        {
-            ref.setStrategy( strategy );
-        }
+    private boolean testProperty(final ClassDescription current,
+                    final Map<String, Property> allProperties,
+                    final Property newProperty,
+                    boolean isInspectedClass ) {
+        final String propName = newProperty.getName();
 
-        component.addReference( ref );
+        if ( !StringUtils.isEmpty(propName) ) {
+            if ( allProperties.containsKey(propName) ) {
+                // if the current class is the class we are currently inspecting, we
+                // have found a duplicate definition
+                if ( isInspectedClass ) {
+                    iLog.addError("Duplicate definition for property " + propName + " in class "
+                                    + current.getDescribedClass().getName(), current.getSource() );
+                }
+            } else {
+                allProperties.put(propName, newProperty);
+                return true;
+            }
+        }
+        return false;
     }
 
+    /**
+     * Process reference directives
+     */
+    private void processReferences(final ClassDescription current,
+                    final Component component,
+                    final Map<String, Reference> allReferences)
+    throws SCRDescriptorException, SCRDescriptorFailureException {
+        for(final ReferenceDescription rd : current.getDescriptions(ReferenceDescription.class)) {
+            final Reference ref = new Reference(rd.getAnnotation(), current.getSource());
+            ref.setName(rd.getName());
+            ref.setInterfacename(rd.getInterfaceName());
+            ref.setCardinality(rd.getCardinality());
+            ref.setPolicy(rd.getPolicy());
+            ref.setStrategy(rd.getStrategy());
+            ref.setTarget(rd.getTarget());
+            ref.setField(rd.getField());
+            if ( rd.getBind() != null ) {
+                ref.setBind(rd.getBind().getName());
+            }
+            if ( rd.getUnbind() != null ) {
+                ref.setUnbind(rd.getUnbind().getName());
+            }
+            if ( rd.getUpdated() != null ) {
+                ref.setUpdated(rd.getUpdated().getName());
+            }
 
-    public static boolean getBoolean( JavaTag tag, String name, boolean defaultValue )
-    {
-        String value = tag.getNamedParameter( name );
-        return ( value == null ) ? defaultValue : Boolean.valueOf( value ).booleanValue();
+            if ( this.testReference(current, allReferences, ref, component.getClassDescription() == current) ) {
+                component.addReference(ref);
+            }
+        }
     }
 
-
-
     /**
-     * Converts the specification version string to a specification version
-     * code. Currently the following conversions are supported:
-     * <table>
-     * <tr><td><code>null</code></td><td>0</td></tr>
-     * <tr><td>1.0</td><td>0</td></tr>
-     * <tr><td>1.1</td><td>1</td></tr>
-     * <tr><td>1.1-felix</td><td>2</td></tr>
-     * </table>
-     *
-     * @param specVersion The specification version to convert. This may be
-     *      <code>null</code> to assume the default version.
-     *
-     * @return The specification version code.
-     *
-     * @throws SCRDescriptorException if the <code>specVersion</code> parameter
-     *      is not a supported value.
+     * Test a newly found reference
      */
-    private int toSpecVersionCode( String specVersion, JavaTag tag ) throws SCRDescriptorException
-    {
-        if ( specVersion == null || specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_10 ) )
-        {
-            return Constants.VERSION_1_0;
-        }
-        else if ( specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_11 ) )
-        {
-            return Constants.VERSION_1_1;
-        }
-        else if ( specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_11_FELIX ) )
-        {
-            return Constants.VERSION_1_1_FELIX;
+    private boolean testReference(final ClassDescription current,
+                    final Map<String, Reference> allReferences,
+                    final Reference newReference,
+                    boolean isInspectedClass ) {
+        String refName = newReference.getName();
+        if ( refName == null) {
+            refName = newReference.getInterfacename();
         }
 
-        // unknown specVersion string
-        throw new SCRDescriptorException( "Unsupported or unknown DS spec version: " + specVersion, tag );
+        if ( refName != null ) {
+            if ( allReferences.containsKey( refName ) ) {
+                // if the current class is the class we are currently inspecting, we
+                // have found a duplicate definition
+                if ( isInspectedClass ) {
+                    iLog.addError("Duplicate definition for reference " + refName + " in class "
+                        + current.getDescribedClass().getName(), current.getSource() );
+                }
+            } else {
+                allReferences.put(refName, newReference);
+                return true;
+            }
+        }
+        return false;
     }
 }

Added: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java?rev=1349773&view=auto
==============================================================================
--- felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java (added)
+++ felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java Wed Jun 13 12:03:35 2012
@@ -0,0 +1,52 @@
+/*
+ * 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.description;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+
+/**
+ * <code>AbstractDescription</code> is the base class for all descriptions.
+ *
+ * @see ComponentDescription
+ * @see ServiceDescription
+ * @see ReferenceDescription
+ * @see PropertyDescription
+ */
+public abstract class AbstractDescription {
+
+    /** The corresponding annotation from the class file. */
+    protected final ScannedAnnotation annotation;
+
+    /**
+     * Create a new abstract description
+     * @param annotation The corresponding annotation.
+     */
+    public AbstractDescription(final ScannedAnnotation annotation) {
+        this.annotation = annotation;
+    }
+
+    /**
+     * Get the annotation.
+     * @return The annotation or <code>null</code>
+     */
+    public ScannedAnnotation getAnnotation() {
+        return this.annotation;
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java?rev=1349773&view=auto
==============================================================================
--- felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java (added)
+++ felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java Wed Jun 13 12:03:35 2012
@@ -0,0 +1,113 @@
+/*
+ * 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.description;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A <code>ClassDescription</code> is describing the found annotations
+ * of a class.
+ * Its basically used as a wrapper to hold all the various annotations
+ * found in a class. This description only contains the annotations
+ * found in the current class, but not in any superclass.
+ * The annotations are available as descriptions.
+ * @see ComponentDescription
+ * @see ServiceDescription
+ * @see ReferenceDescription
+ * @see PropertyDescription
+ */
+public class ClassDescription {
+
+    /** All descriptions. */
+    final List<AbstractDescription> descriptions = new ArrayList<AbstractDescription>();
+
+    /** The corresponding class. */
+    private final Class<?> describedClass;
+
+    /** The source (file) of the class or any other location information. */
+    private final String source;
+
+    /**
+     * Create a new class description
+     */
+    public ClassDescription(final Class<?> describedClass, final String source) {
+        this.describedClass = describedClass;
+        this.source = source;
+    }
+
+    /**
+     * Get the associated class.
+     * @return The associated class.
+     */
+    public Class<?> getDescribedClass() {
+        return this.describedClass;
+    }
+
+    /**
+     * Get the location information like the source file etc.
+     * @return The location information.
+     */
+    public String getSource() {
+        return this.source;
+    }
+
+    /**
+     * Add a new description
+     */
+    public void add(final AbstractDescription desc) {
+        this.descriptions.add(desc);
+    }
+
+    /**
+     * Get all descriptions of that type.
+     * @param descType The description class.
+     * @return A list of found descriptions or the empty array.
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends AbstractDescription> List<T> getDescriptions(final Class<T> descType) {
+        final List<T> result = new ArrayList<T>();
+        for(final AbstractDescription desc : descriptions) {
+            if ( descType.isAssignableFrom(desc.getClass()) ) {
+                result.add((T) desc);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Get the first description of that type
+     * @param descType The description class
+     * @return THe first description or <code>null</code>
+     */
+    public <T extends AbstractDescription> T getDescription(final Class<T> descType) {
+        final List<T> result = this.getDescriptions(descType);
+        if ( result.size() > 0 ) {
+            return result.get(0);
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return "ClassDescription [descriptions=" + descriptions
+                        + ", describedClass=" + describedClass + ", source=" + source
+                        + "]";
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
URL: http://svn.apache.org/viewvc/felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java?rev=1349773&view=auto
==============================================================================
--- felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java (added)
+++ felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java Wed Jun 13 12:03:35 2012
@@ -0,0 +1,41 @@
+/*
+ * 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.description;
+
+/**
+ * Options for {@link ComponentDescription#getConfigurationPolicy()}.
+ */
+public enum ComponentConfigurationPolicy {
+
+    /**
+     * If a configuration is available it will be used, if not the component
+     * will be activated anyway (this is the default).
+     */
+    OPTIONAL,
+
+    /**
+     * The configuration admin is not consulted for a configuration for this component.
+     */
+    IGNORE,
+
+    /**
+     * In order to activate this component a configuration is required.
+     */
+    REQUIRE;
+}

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java?rev=1349773&view=auto
==============================================================================
--- felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java (added)
+++ felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java Wed Jun 13 12:03:35 2012
@@ -0,0 +1,260 @@
+/*
+ * 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.description;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+/**
+ * <code>ComponentDescription</code> is a described component.
+ *
+ * In general all fields should be set by an annocation scanner,
+ * no default values should be assumed for these fields:
+ * <ul>
+ * <li>name</li>
+ * <li>configurationPolicy</li>
+ * </ul>
+ *
+ * These values have the following default values:
+ * <ul>
+ * <li>label : null - will be handled by the scr generator</li>
+ * <li>description : null - will be handled by the scr generator</li>
+ * <li>isAbstract : false</li>
+ * <li>isInherit : true</li>
+ * <li>createDs : true</li>
+ * <li>createPid : true</li>
+ * <li>createMetatype : false</li>
+ * <li>enabled : null</li>
+ * <li>immediate : null</li>
+ * <li>factory : null</li>
+ * <li>isSetMetatypeFactoryPid : false</li>
+ * <li>activate : null</li>
+ * <li>deactivate : null</li>
+ * <li>modified : null</li>
+ * <li>specVersion : null</li>
+ * </ul>
+ *
+ */
+public class ComponentDescription extends AbstractDescription {
+
+    /** The name of the component. */
+    private String name;
+
+    /** The label of the component. */
+    private String label;
+
+    /** The description of the component. */
+    private String description;
+
+    /** Configuration policy. (V1.1) */
+    private ComponentConfigurationPolicy configurationPolicy;
+
+    /** Is this an abstract description? */
+    private boolean isAbstract = false;
+
+    /** Does this inherit? */
+    private boolean isInherit = true;
+
+    /** Create ds info */
+    private boolean createDs = true;
+
+    /** Create pid */
+    private boolean createPid = true;
+
+    /** Create metatype info. */
+    private boolean createMetatype = false;
+
+    /** Is this component enabled? */
+    private Boolean enabled;
+
+    /** Is this component immediately started. */
+    private Boolean immediate;
+
+    /** The factory. */
+    private String factory;
+
+    /** The set metatype factory pid flag. */
+    private boolean isSetMetatypeFactoryPid = false;
+
+    /** Activation method. (V1.1) */
+    private MethodDescription activate;
+
+    /** Deactivation method. (V1.1) */
+    private MethodDescription deactivate;
+
+    /** Modified method. (V1.1) */
+    private MethodDescription modified;
+
+    /** The spec version. */
+    private SpecVersion specVersion;
+
+    public ComponentDescription(final ScannedAnnotation annotation) {
+        super(annotation);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Boolean getImmediate() {
+        return immediate;
+    }
+
+    public void setImmediate(Boolean immediate) {
+        this.immediate = immediate;
+    }
+
+    public String getFactory() {
+        return factory;
+    }
+
+    public void setFactory(String factory) {
+        this.factory = factory;
+    }
+
+    public boolean isSetMetatypeFactoryPid() {
+        return isSetMetatypeFactoryPid;
+    }
+
+    public void setSetMetatypeFactoryPid(boolean isSetMetatypeFactoryPid) {
+        this.isSetMetatypeFactoryPid = isSetMetatypeFactoryPid;
+    }
+
+    public boolean isAbstract() {
+        return isAbstract;
+    }
+
+    public void setAbstract(boolean isAbstract) {
+        this.isAbstract = isAbstract;
+    }
+
+    public boolean isInherit() {
+        return isInherit;
+    }
+
+    public void setInherit(boolean isInherit) {
+        this.isInherit = isInherit;
+    }
+
+    public boolean isCreateDs() {
+        return createDs;
+    }
+
+    public void setCreateDs(boolean createDs) {
+        this.createDs = createDs;
+    }
+
+    public boolean isCreatePid() {
+        return createPid;
+    }
+
+    public void setCreatePid(boolean createPid) {
+        this.createPid = createPid;
+    }
+
+    public boolean isCreateMetatype() {
+        return createMetatype;
+    }
+
+    public void setCreateMetatype(boolean createMetatype) {
+        this.createMetatype = createMetatype;
+    }
+
+    public ComponentConfigurationPolicy getConfigurationPolicy() {
+        return configurationPolicy;
+    }
+
+    public void setConfigurationPolicy(ComponentConfigurationPolicy configurationPolicy) {
+        this.configurationPolicy = configurationPolicy;
+    }
+
+    public MethodDescription getActivate() {
+        return activate;
+    }
+
+    public void setActivate(MethodDescription activate) {
+        this.activate = activate;
+    }
+
+    public MethodDescription getDeactivate() {
+        return deactivate;
+    }
+
+    public void setDeactivate(MethodDescription deactivate) {
+        this.deactivate = deactivate;
+    }
+
+    public MethodDescription getModified() {
+        return modified;
+    }
+
+    public void setModified(MethodDescription modified) {
+        this.modified = modified;
+    }
+
+    public SpecVersion getSpecVersion() {
+        return specVersion;
+    }
+
+    public void setSpecVersion(SpecVersion specVersion) {
+        this.specVersion = specVersion;
+    }
+
+    @Override
+    public String toString() {
+        return "ComponentDescription [name=" + name + ", label=" + label
+                + ", description=" + description + ", enabled=" + enabled
+                + ", immediate=" + immediate + ", factory=" + factory
+                + ", isSetMetatypeFactoryPid=" + isSetMetatypeFactoryPid
+                + ", isAbstract=" + isAbstract + ", isInherit=" + isInherit
+                + ", createDs=" + createDs + ", createPid=" + createPid
+                + ", createMetatype=" + createMetatype
+                + ", configurationPolicy=" + configurationPolicy
+                + ", activate=" + activate + ", deactivate=" + deactivate
+                + ", modified=" + modified + ", specVersion=" + specVersion
+                + ", annotation=" + annotation + "]";
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java?rev=1349773&view=auto
==============================================================================
--- felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java (added)
+++ felix/trunk/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java Wed Jun 13 12:03:35 2012
@@ -0,0 +1,55 @@
+/*
+ * 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.description;
+
+import java.lang.reflect.Method;
+
+/**
+ * A method description describes a reference to a method,
+ * this can either just be the name or a real method object.
+ */
+public class MethodDescription {
+
+    private final String name;
+
+    private final Method method;
+
+    public MethodDescription(final String name) {
+        this.name = name;
+        this.method = null;
+    }
+
+    public MethodDescription(final Method method) {
+        this.name = method.getName();
+        this.method = method;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public Method getMethod() {
+        return this.method;
+    }
+
+    @Override
+    public String toString() {
+        return "MethodDescription [name=" + name + ", method=" + method + "]";
+    }
+}