Moving scr plugin from sandbox to main trunk

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@567573 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/maven-scr-plugin/pom.xml b/maven-scr-plugin/pom.xml
new file mode 100644
index 0000000..0932791
--- /dev/null
+++ b/maven-scr-plugin/pom.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>felix</artifactId>
+        <groupId>org.apache.felix</groupId>
+        <version>1.0.0</version>
+    </parent>
+
+    <groupId>org.apache.felix</groupId>
+    <artifactId>maven-scr-plugin</artifactId>
+
+	<version>0.1.0-SNAPSHOT</version>
+	<packaging>maven-plugin</packaging>
+
+	<name>Maven Scr Plugin</name>
+	<description>
+		Maven plugin for generating OSGi service descriptors based on annotations.
+	</description>
+
+	<scm>
+		<connection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/maven-scr-plugin</connection>
+		<developerConnection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/maven-scr-plugin</developerConnection>
+		<url>http://svn.apache.org/repos/asf/felix/maven-scr-plugin</url>
+	</scm>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>osgi_R4_core</artifactId>
+			<version>1.0</version>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>osgi_R4_compendium</artifactId>
+			<version>1.0</version>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.commons</groupId>
+		    <artifactId>commons-io</artifactId>
+		    <version>1.3.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.maven</groupId>
+			<artifactId>maven-plugin-api</artifactId>
+			<version>2.0.7</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.maven</groupId>
+			<artifactId>maven-archiver</artifactId>
+			<version>2.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.thoughtworks.qdox</groupId>
+			<artifactId>qdox</artifactId>
+			<version>1.6.3</version>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/Constants.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/Constants.java
new file mode 100644
index 0000000..983dcd6
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/Constants.java
@@ -0,0 +1,94 @@
+/*
+ * 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.sandbox.scrplugin;
+
+import java.io.File;
+
+/**
+ * Constants
+ */
+public class Constants {
+
+    public static final String COMPONENT = "scr.component";
+
+    public static final String COMPONENT_NAME = "name";
+
+    public static final String COMPONENT_LABEL = "label";
+
+    public static final String COMPONENT_DESCRIPTION = "description";
+
+    public static final String COMPONENT_ENABLED = "enabled";
+
+    public static final String COMPONENT_FACTORY = "factory";
+
+    public static final String COMPONENT_IMMEDIATE = "immediate";
+
+    public static final String COMPONENT_INHERIT = "inherit";
+
+    public static final String COMPONENT_METATYPE = "metatype";
+
+    public static final String COMPONENT_ABSTRACT = "abstract";
+
+    public static final String PROPERTY = "scr.property";
+
+    public static final String PROPERTY_NAME = "name";
+
+    public static final String PROPERTY_LABEL = "label";
+
+    public static final String PROPERTY_DESCRIPTION = "description";
+
+    public static final String PROPERTY_VALUE = "value";
+
+    public static final String PROPERTY_TYPE = "type";
+
+    public static final String PROPERTY_CARDINALITY = "cardinality";
+
+    public static final String PROPERTY_PRIVATE = "private";
+
+    public static final String PROPERTY_OPTIONS = "options";
+
+    public static final String SERVICE = "scr.service";
+
+    public static final String SERVICE_INTERFACE = "interface";
+
+    public static final String SERVICE_FACTORY = "servicefactory";
+
+    public static final String REFERENCE = "scr.reference";
+
+    public static final String REFERENCE_NAME = "name";
+
+    public static final String REFERENCE_INTERFACE = "interface";
+
+    public static final String REFERENCE_CARDINALITY = "cardinality";
+
+    public static final String REFERENCE_POLICY = "policy";
+
+    public static final String REFERENCE_TARGET = "target";
+
+    public static final String REFERENCE_BIND = "bind";
+
+    public static final String REFERENCE_UNDBIND = "unbind";
+
+    public static final String ABSTRACT_DESCRIPTOR_FILENAME = "scrinfo.xml";
+
+    public static final String ABSTRACT_DESCRIPTOR_RELATIVE_PATH = "OSGI-INF" + File.separator + "scr-plugin" + File.separator + ABSTRACT_DESCRIPTOR_FILENAME;
+
+    public static final String ABSTRACT_DESCRIPTOR_ARCHIV_PATH = "OSGI-INF/scr-plugin/" + ABSTRACT_DESCRIPTOR_FILENAME;
+
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/SCRDescriptorMojo.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/SCRDescriptorMojo.java
new file mode 100644
index 0000000..2b8957b
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/SCRDescriptorMojo.java
@@ -0,0 +1,509 @@
+/*
+ * 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.sandbox.scrplugin;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.sandbox.scrplugin.om.Component;
+import org.apache.felix.sandbox.scrplugin.om.Components;
+import org.apache.felix.sandbox.scrplugin.om.Implementation;
+import org.apache.felix.sandbox.scrplugin.om.Interface;
+import org.apache.felix.sandbox.scrplugin.om.metatype.AttributeDefinition;
+import org.apache.felix.sandbox.scrplugin.om.metatype.Designate;
+import org.apache.felix.sandbox.scrplugin.om.metatype.MTObject;
+import org.apache.felix.sandbox.scrplugin.om.metatype.MetaData;
+import org.apache.felix.sandbox.scrplugin.om.metatype.OCD;
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescriptorManager;
+import org.apache.felix.sandbox.scrplugin.tags.JavaField;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+import org.apache.felix.sandbox.scrplugin.xml.ComponentDescriptorIO;
+import org.apache.felix.sandbox.scrplugin.xml.MetaTypeIO;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * The <code>SCRDescriptorMojo</code>
+ * generates a service descriptor file based on annotations found in the sources.
+ *
+ * @goal scr
+ * @phase generate-resources
+ * @description Build Service Descriptors from Java Source
+ * @requiresDependencyResolution compile
+ */
+public class SCRDescriptorMojo extends AbstractMojo {
+
+    /**
+     * @parameter expression="${project.build.directory}/scr-plugin-generated"
+     * @required
+     * @readonly
+     */
+    private File outputDirectory;
+
+    /**
+     * The Maven project.
+     *
+     * @parameter expression="${project}"
+     * @required
+     * @readonly
+     */
+    private MavenProject project;
+
+    /**
+     * Name of the generated descriptor.
+     *
+     * @parameter expression="${scr.descriptor.name}" default-value="serviceComponents.xml"
+     */
+    private String finalName;
+
+    /**
+     * Name of the generated meta type file.
+     *
+     * @parameter default-value="metatype.xml"
+     */
+    private String metaTypeName;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        this.getLog().debug("Starting SCRDescriptorMojo....");
+
+        boolean hasFailures = false;
+
+        JavaClassDescriptorManager jManager = new JavaClassDescriptorManager(this.getLog(),
+                                                                             this.project);
+        // iterate through all source classes and check for component tag
+        final JavaClassDescription[] javaSources = jManager.getSourceDescriptions();
+
+        final Components components = new Components();
+        final Components abstractComponents = new Components();
+        final MetaData metaData = new MetaData();
+        metaData.setLocalization("metatype");
+
+        for (int i = 0; i < javaSources.length; i++) {
+            this.getLog().debug("Testing source " + javaSources[i].getName());
+            final JavaTag tag = javaSources[i].getTagByName(Constants.COMPONENT);
+            if (tag != null) {
+                this.getLog().debug("Processing service class " + javaSources[i].getName());
+                final Component comp = this.createComponent(javaSources[i], metaData);
+                if (comp != null) {
+                    if ( comp.isAbstract() ) {
+                        this.getLog().debug("Adding abstract descriptor " + comp);
+                        abstractComponents.addComponent(comp);
+                    } else {
+                        this.getLog().debug("Adding descriptor " + comp);
+                        components.addComponent(comp);
+                    }
+                } else {
+                    hasFailures = true;
+                }
+            }
+        }
+
+        // after checking all classes, throw if there were any failures
+        if (hasFailures) {
+            throw new MojoFailureException("SCR Descriptor parsing had failures (see log)");
+        }
+
+        // if we have abstract descriptors, write them
+        final File adFile = new File(this.outputDirectory, Constants.ABSTRACT_DESCRIPTOR_RELATIVE_PATH);
+        if ( !abstractComponents.getComponents().isEmpty() ) {
+            this.getLog().info("Writing abstract service descriptor " + adFile + " with " + components.getComponents().size() + " entries.");
+            adFile.getParentFile().mkdirs();
+            ComponentDescriptorIO.write(abstractComponents, adFile);
+        } else {
+            this.getLog().debug("No abstract SCR Descriptors found in project.");
+            // remove file
+            if ( adFile.exists() ) {
+                this.getLog().debug("Removing obsolete abstract service descriptor " + adFile);
+                adFile.delete();
+            }
+        }
+
+        // terminate if there is nothing else to write
+        if (components.getComponents().isEmpty()) {
+            this.getLog().debug("No SCR Descriptors found in project.");
+            return;
+        }
+
+        // check file name
+        if (StringUtils.isEmpty(this.finalName)) {
+            this.getLog().error("Descriptor file name must not be empty.");
+            return;
+        }
+
+        // finally the descriptors have to be written ....
+        File descriptorFile = new File(new File(this.outputDirectory, "OSGI-INF"), this.finalName);
+        descriptorFile.getParentFile().mkdirs(); // ensure parent dir
+
+        this.getLog().info("Generating " + components.getComponents().size()
+                + " Service Component Descriptors to " + descriptorFile);
+
+        ComponentDescriptorIO.write(components, descriptorFile);
+
+        // check file name
+        if (StringUtils.isEmpty(this.metaTypeName)) {
+            this.getLog().error("Meta type file name must not be empty.");
+            return;
+        }
+
+        // create metatype information
+        File mtFile = new File(this.outputDirectory, "OSGI-INF" + File.separator + "metatype" + File.separator + this.metaTypeName);
+        mtFile.getParentFile().mkdirs();
+        if ( metaData.getDescriptors().size() > 0 ) {
+            MetaTypeIO.write(metaData, mtFile);
+        } else {
+            if ( mtFile.exists() ) {
+                mtFile.delete();
+            }
+        }
+
+        // now add the descriptor file to the maven resources
+        final String ourRsrcPath = this.outputDirectory.getAbsolutePath();
+        boolean found = false;
+        final Iterator rsrcIterator = this.project.getResources().iterator();
+        while ( !found && rsrcIterator.hasNext() ) {
+            final Resource rsrc = (Resource)rsrcIterator.next();
+            found = rsrc.getDirectory().equals(ourRsrcPath);
+        }
+        if ( !found ) {
+            final Resource resource = new Resource();
+            resource.setDirectory(this.outputDirectory.getAbsolutePath());
+            this.project.addResource(resource);
+        }
+        // and set include accordingly
+        this.project.getProperties().setProperty("Service-Component", "OSGI-INF/" + this.finalName);
+    }
+
+    /**
+     * Create a component for the java class description.
+     * @param description
+     * @return The generated component descriptor or null if any error occurs.
+     * @throws MojoExecutionException
+     */
+    protected Component createComponent(JavaClassDescription description, MetaData metaData)
+    throws MojoExecutionException {
+
+        final JavaTag componentTag = description.getTagByName(Constants.COMPONENT);
+        final Component component = new Component(componentTag);
+
+        // set implementation
+        component.setImplementation(new Implementation(description.getName()));
+
+        final OCD ocd = this.doComponent(componentTag, component, metaData);
+
+        boolean inherited = this.getBoolean(componentTag, Constants.COMPONENT_INHERIT, false);
+        boolean serviceFactory = this.doServices(description.getTagsByName(Constants.SERVICE, inherited), component, description);
+        component.setServiceFactory(serviceFactory);
+
+        // properties
+        final JavaTag[] properties = description.getTagsByName(Constants.PROPERTY, inherited);
+        if (properties != null && properties.length > 0) {
+            for (int i=0; i < properties.length; i++) {
+                this.doProperty(properties[i], null, component, ocd);
+            }
+        }
+
+        // references
+        final JavaTag[] references = description.getTagsByName(Constants.REFERENCE, inherited);
+        if (references != null || references.length > 0) {
+            for (int i=0; i < references.length; i++) {
+                this.doReference(references[i], null, component);
+            }
+        }
+
+        // fields
+        do {
+            JavaField[] fields = description.getFields();
+            for (int i=0; fields != null && i < fields.length; i++) {
+                JavaTag tag = fields[i].getTagByName(Constants.REFERENCE);
+                if (tag != null) {
+                    this.doReference(tag, fields[i].getName(), component);
+                }
+
+                tag = fields[i].getTagByName(Constants.PROPERTY);
+                if (tag != null) {
+                    this.doProperty(tag, fields[i].getInitializationExpression(), component, ocd);
+                }
+            }
+
+            description = description.getSuperClass();
+        } while (inherited && description != null);
+
+        final List issues = new ArrayList();
+        final List warnings = new ArrayList();
+        component.validate(issues, warnings);
+
+        // now log warnings and errors (warnings first)
+        Iterator i = warnings.iterator();
+        while ( i.hasNext() ) {
+            this.getLog().warn((String)i.next());
+        }
+        i = issues.iterator();
+        while ( i.hasNext() ) {
+            this.getLog().error((String)i.next());
+        }
+
+        // return nothing if validation fails
+        return issues.size() == 0 ? component : null;
+    }
+
+    /**
+     * Fill the component object with the information from the tag.
+     * @param tag
+     * @param component
+     */
+    protected OCD doComponent(JavaTag tag, Component component, MetaData metaData) {
+
+        // check if this is an abstract definition
+        final String abstractType = tag.getNamedParameter(Constants.COMPONENT_ABSTRACT);
+        component.setAbstract((abstractType == null ? false : "yes".equalsIgnoreCase(abstractType) || "true".equalsIgnoreCase(abstractType)));
+
+        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.setFactory(tag.getNamedParameter(Constants.COMPONENT_FACTORY));
+        component.setImmediate(Boolean.valueOf(this.getBoolean(tag, Constants.COMPONENT_IMMEDIATE, true)));
+
+        // 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 ( hasMetaType ) {
+            // ocd
+            final 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.setDescription(ocdDescription);
+            // designate
+            final Designate designate = new Designate();
+            metaData.addDesignate(designate);
+            designate.setPid(component.getName());
+            // designate.object
+            final MTObject mtobject = new MTObject();
+            designate.setObject(mtobject);
+            mtobject.setOcdref(component.getName());
+            return ocd;
+        }
+        return null;
+    }
+
+    /**
+     * Process the service annotations
+     * @param services
+     * @param component
+     * @param description
+     * @return
+     * @throws MojoExecutionException
+     */
+    protected boolean doServices(JavaTag[] services, Component component, JavaClassDescription description)
+    throws MojoExecutionException {
+        // no services, hence certainly no service factory
+        if (services == null || services.length == 0) {
+            return false;
+        }
+
+        org.apache.felix.sandbox.scrplugin.om.Service service = new org.apache.felix.sandbox.scrplugin.om.Service();
+        component.setService(service);
+        boolean serviceFactory = false;
+        for (int i=0; i < services.length; i++) {
+            String name = services[i].getNamedParameter(Constants.SERVICE_INTERFACE);
+            if (StringUtils.isEmpty(name)) {
+
+                while (description != null) {
+                    JavaClassDescription[] interfaces = description.getImplementedInterfaces();
+                    for (int j=0; interfaces != null && j < interfaces.length; j++) {
+                        final Interface interf = new Interface(services[i]);
+                        interf.setInterfacename(interfaces[j].getName());
+                        service.addInterface(interf);
+                    }
+
+                    // try super class
+                    description = description.getSuperClass();
+                }
+            } else {
+                final Interface interf = new Interface(services[i]);
+                interf.setInterfacename(name);
+                service.addInterface(interf);
+            }
+
+            serviceFactory |= this.getBoolean(services[i], Constants.SERVICE_FACTORY, false);
+        }
+
+        return serviceFactory;
+    }
+
+    /**
+     * @param property
+     * @param defaultName
+     * @param component
+     */
+    protected void doProperty(JavaTag property, String defaultName, Component component, OCD ocd) {
+        String name = property.getNamedParameter(Constants.PROPERTY_NAME);
+        if (StringUtils.isEmpty(name) && defaultName!= null) {
+            name = defaultName.trim();
+            if (name.startsWith("\"")) name = name.substring(1);
+            if (name.endsWith("\"")) name = name.substring(0, name.length()-1);
+        }
+
+        if (!StringUtils.isEmpty(name)) {
+            org.apache.felix.sandbox.scrplugin.om.Property prop = new org.apache.felix.sandbox.scrplugin.om.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()]));
+                }
+            }
+
+            final boolean isPrivate = this.getBoolean(property, Constants.PROPERTY_PRIVATE, false);
+            // 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);
+        }
+    }
+
+    /**
+     * @param reference
+     * @param defaultName
+     * @param component
+     */
+    protected void doReference(JavaTag reference, String defaultName, Component component) {
+        String name = reference.getNamedParameter(Constants.REFERENCE_NAME);
+        if (StringUtils.isEmpty(name)) {
+            name = defaultName;
+        }
+
+        // ensure interface
+        String type = reference.getNamedParameter(Constants.REFERENCE_INTERFACE);
+        if (StringUtils.isEmpty(type)) {
+            if ( reference.getField() != null ) {
+                type = reference.getField().getType();
+            }
+        }
+
+        if (!StringUtils.isEmpty(name)) {
+            org.apache.felix.sandbox.scrplugin.om.Reference ref = new org.apache.felix.sandbox.scrplugin.om.Reference(reference);
+            ref.setName(name);
+            ref.setInterfacename(type);
+            ref.setCardinality(reference.getNamedParameter(Constants.REFERENCE_CARDINALITY));
+            ref.setPolicy(reference.getNamedParameter(Constants.REFERENCE_POLICY));
+            ref.setTarget(reference.getNamedParameter(Constants.REFERENCE_TARGET));
+            String value;
+            value = reference.getNamedParameter(Constants.REFERENCE_BIND);
+            if ( value != null ) {
+                ref.setBind(value);
+            }
+            value = reference.getNamedParameter(Constants.REFERENCE_UNDBIND);
+            if ( value != null ) {
+                ref.setUnbind(value);
+            }
+            component.addReference(ref);
+        }
+    }
+
+    protected boolean getBoolean(JavaTag tag, String name, boolean defaultValue) {
+        String value = tag.getNamedParameter(name);
+        return (value == null) ? defaultValue : Boolean.valueOf(value).booleanValue();
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/AbstractObject.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/AbstractObject.java
new file mode 100644
index 0000000..5362f9d
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/AbstractObject.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+
+/**
+ * The <code>AbstractObject</code>
+ * is the base class for the all classes of the scr om.
+ */
+public abstract class AbstractObject {
+
+    protected final JavaTag tag;
+
+    protected AbstractObject(JavaTag tag) {
+        this.tag = tag;
+    }
+
+    protected String getMessage(String message) {
+        if ( this.tag == null ) {
+            return message;
+        } else {
+            return "@" + this.tag.getName() + ": " + message + " (" + this.tag.getSourceLocation() + ")";
+        }
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Component.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Component.java
new file mode 100644
index 0000000..25c651e
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Component.java
@@ -0,0 +1,291 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaMethod;
+import org.apache.felix.sandbox.scrplugin.tags.JavaParameter;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ * <code>Component</code>
+ * is a described component.
+ *
+ */
+public class Component extends AbstractObject {
+
+    /** The name of the component. */
+    protected String name;
+
+    /** Is this component enabled? */
+    protected Boolean enabled;
+
+    /** Is this component immediately started. */
+    protected Boolean immediate;
+
+    /** The factory. */
+    protected String factory;
+
+    /** The implementation. */
+    protected Implementation implementation;
+
+    /** All properties. */
+    protected List properties = new ArrayList();
+
+    /** The corresponding service. */
+    protected Service service;
+
+    /** The references. */
+    protected List references = new ArrayList();
+
+    /** Is this an abstract description? */
+    protected boolean isAbstract;
+
+    protected boolean serviceFactory;
+
+    /**
+     * Default constructor.
+     */
+    public Component() {
+        this(null);
+    }
+
+    /**
+     * Constructor from java source.
+     */
+    public Component(JavaTag t) {
+        super(t);
+    }
+
+    /**
+     * @return
+     */
+    public List getProperties() {
+        return this.properties;
+    }
+
+    public void setProperties(List properties) {
+        this.properties = properties;
+    }
+
+    public void addProperty(Property property) {
+        this.properties.add(property);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getFactory() {
+        return this.factory;
+    }
+
+    public void setFactory(String factory) {
+        this.factory = factory;
+    }
+
+    public Boolean isEnabled() {
+        return this.enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Boolean isImmediate() {
+        return this.immediate;
+    }
+
+    public void setImmediate(Boolean immediate) {
+        this.immediate = immediate;
+    }
+
+    public Implementation getImplementation() {
+        return this.implementation;
+    }
+
+    public void setImplementation(Implementation implementation) {
+        this.implementation = implementation;
+    }
+
+    public Service getService() {
+        return this.service;
+    }
+
+    public void setService(Service service) {
+        this.service = service;
+    }
+
+    public List getReferences() {
+        return this.references;
+    }
+
+    public void setReferences(List references) {
+        this.references = references;
+    }
+
+    public void addReference(Reference ref) {
+        this.references.add(ref);
+    }
+
+    public boolean isAbstract() {
+        return this.isAbstract;
+    }
+
+    public void setAbstract(boolean isAbstract) {
+        this.isAbstract = isAbstract;
+    }
+
+    public boolean isServiceFactory() {
+        return this.serviceFactory;
+    }
+
+    public void setServiceFactory(boolean serviceFactory) {
+        this.serviceFactory = serviceFactory;
+    }
+
+    /**
+     * Validate the component description.
+     * If errors occur a message is added to the issues list,
+     * warnings can be added to the warnings list.
+     */
+    public void validate(List issues, List warnings)
+    throws MojoExecutionException {
+        final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
+        if (javaClass == null) {
+            issues.add(this.getMessage("Tag not declared in a Java Class"));
+        } else {
+
+            // if the service is abstract, we do not validate everything
+            if ( !this.isAbstract ) {
+                // ensure non-abstract, public class
+                if (!javaClass.isPublic()) {
+                    issues.add(this.getMessage("Class must be pubic: " + javaClass.getName()));
+                }
+                if (javaClass.isAbstract() || javaClass.isInterface()) {
+                    issues.add(this.getMessage("Class must be concrete class (not abstract or interface) : " + javaClass.getName()));
+                }
+
+                // no errors so far, let's continue
+                if ( issues.size() == 0 ) {
+                    // check activate and deactivate methods
+                    this.checkActivationMethod(javaClass, "activate", warnings);
+                    this.checkActivationMethod(javaClass, "deactivate", warnings);
+
+                    // ensure public default constructor
+                    boolean constructorFound = true;
+                    JavaMethod[] methods = javaClass.getMethods();
+                    for (int i = 0; methods != null && i < methods.length; i++) {
+                        if (methods[i].isConstructor()) {
+                            // if public default, succeed
+                            if (methods[i].isPublic()
+                                && (methods[i].getParameters() == null || methods[i].getParameters().length == 0)) {
+                                constructorFound = true;
+                                break;
+                            }
+
+                            // non-public/non-default constructor found, must have explicit
+                            constructorFound = false;
+                        }
+                    }
+                    if (!constructorFound) {
+                        issues.add(this.getMessage("Class must have public default constructor: " + javaClass.getName()));
+                    }
+
+                    // verify properties
+                    for (Iterator pi = this.getProperties().iterator(); pi.hasNext();) {
+                        Property prop = (Property) pi.next();
+                        prop.validate(issues, warnings);
+                    }
+
+                    // verify service
+                    this.getService().validate(issues, warnings);
+
+                    // serviceFactory must not be true for immediate of component factory
+                    if (this.isServiceFactory() && this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
+                        issues.add(this.getMessage("Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName()));
+                    }
+
+                    // verify references
+                    for (Iterator ri = this.getReferences().iterator(); ri.hasNext();) {
+                        final Reference ref = (Reference) ri.next();
+                        ref.validate(issues, warnings);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Check methods.
+     * @param javaClass
+     * @param methodName
+     */
+    protected void checkActivationMethod(JavaClassDescription javaClass, String methodName, List warnings) {
+        JavaMethod[] methods = javaClass.getMethods();
+        JavaMethod activation = null;
+        for (int i=0; i < methods.length; i++) {
+            // ignore method not matching the name
+            if (!methodName.equals(methods[i].getName())) {
+                continue;
+            }
+
+            // if the method has the correct parameter type, check protected
+            JavaParameter[] params = methods[i].getParameters();
+            if (params == null || params.length != 1) {
+                continue;
+            }
+
+            // this might be considered, if it is an overload, drop out of check
+            if (activation != null) {
+                return;
+            }
+
+            // consider this method for further checks
+            activation = methods[i];
+        }
+
+        // no activation method found
+        if (activation == null) {
+            return;
+        }
+
+        // check protected
+        if (activation.isPublic()) {
+            warnings.add(this.getMessage("Activation method " + activation.getName() + " should be declared protected"));
+        } else if (!activation.isProtected()) {
+            warnings.add(this.getMessage("Activation method " + activation.getName() + " has wrong qualifier, public or protected required"));
+        }
+
+        // check paramter (we know there is exactly one)
+        JavaParameter param = activation.getParameters()[0];
+        if (!"org.osgi.service.component.ComponentContext".equals(param.getType())) {
+            warnings.add(this.getMessage("Activation method " + methodName + " has wrong argument type " + param.getType()));
+        }
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Components.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Components.java
new file mode 100644
index 0000000..9c4a59e
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Components.java
@@ -0,0 +1,54 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <code>Components</code>...
+ *
+ * Components is just a collection of {@link Component}s.
+ */
+public class Components {
+
+    /** The list of {@link Component}s. */
+    protected List components = new ArrayList();
+
+    /**
+     * Return the list of {@link Component}s.
+     */
+    public List getComponents() {
+        return this.components;
+    }
+
+    /**
+     * Set the list of {@link Component}s.
+     */
+    public void setComponents(List components) {
+        this.components = components;
+    }
+
+    /**
+     * Add a component to the list.
+     */
+    public void addComponent(Component component) {
+        this.components.add(component);
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Implementation.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Implementation.java
new file mode 100644
index 0000000..c809b41
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Implementation.java
@@ -0,0 +1,48 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+/**
+ * <code>Implementation</code>...
+ *
+ * contains the class name implementing the component.
+ */
+public class Implementation {
+
+    /** The class name. */
+    protected String classname;
+
+    public Implementation() {
+        // nothing to do
+    }
+
+    public Implementation(String name) {
+        this.classname = name;
+    }
+
+    public String getClassame() {
+        return this.classname;
+    }
+
+    public void setClassname(String name) {
+        this.classname = name;
+    }
+
+
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Interface.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Interface.java
new file mode 100644
index 0000000..bfd3726
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Interface.java
@@ -0,0 +1,75 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import java.util.List;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ * <code>Interface.java</code>...
+ *
+ */
+public class Interface extends AbstractObject {
+
+    protected String interfacename;
+
+    /**
+     * Default constructor.
+     */
+    public Interface() {
+        this(null);
+    }
+
+    /**
+     * Constructor from java source.
+     */
+    public Interface(JavaTag t) {
+        super(t);
+    }
+
+    public String getInterfacename() {
+        return this.interfacename;
+    }
+
+    public void setInterfacename(String name) {
+        this.interfacename = name;
+    }
+
+    /**
+     * Validate the interface.
+     * If errors occur a message is added to the issues list,
+     * warnings can be added to the warnings list.
+     */
+    public void validate(List issues, List warnings)
+    throws MojoExecutionException {
+        final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
+        if (javaClass == null) {
+            issues.add(this.getMessage("Must be declared in a Java class"));
+        } else {
+
+            if ( !javaClass.isA(this.getInterfacename()) ) {
+               // interface not implemented
+                issues.add(this.getMessage("Class must implement provided interface " + this.getInterfacename()));
+            }
+        }
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Property.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Property.java
new file mode 100644
index 0000000..7fad9cb
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Property.java
@@ -0,0 +1,92 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import java.util.List;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+
+/**
+ * <code>Property.java</code>...
+ *
+ */
+public class Property extends AbstractObject {
+
+    protected String name;
+    protected String value;
+    protected String type;
+    protected String[] multiValue;
+
+    /**
+     * Default constructor.
+     */
+    public Property() {
+        this(null);
+    }
+
+    /**
+     * Constructor from java source.
+     */
+    public Property(JavaTag t) {
+        super(t);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return this.value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+        this.multiValue = null;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String[] getMultiValue() {
+        return this.multiValue;
+    }
+
+    public void setMultiValue(String[] values) {
+        this.multiValue = values;
+        this.value = null;
+    }
+
+    /**
+     * Validate the property.
+     * If errors occur a message is added to the issues list,
+     * warnings can be added to the warnings list.
+     */
+    public void validate(List issues, List warnings) {
+        // might want to check name and type
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Reference.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Reference.java
new file mode 100644
index 0000000..d072f81
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Reference.java
@@ -0,0 +1,203 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import java.util.List;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaMethod;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * <code>Reference.java</code>...
+ *
+ */
+public class Reference extends AbstractObject {
+
+    protected String name;
+    protected String interfacename;
+    protected String target;
+    protected String cardinality;
+    protected String policy;
+    protected String bind;
+    protected String unbind;
+
+    /**
+     * Default constructor.
+     */
+    public Reference() {
+        this(null);
+    }
+
+    /**
+     * Constructor from java source.
+     */
+    public Reference(JavaTag t) {
+        super(t);
+        // set default values
+        this.setBind("bind");
+        this.setUnbind("unbind");
+    }
+
+    public String getName() {
+        return this.name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public String getInterfacename() {
+        return this.interfacename;
+    }
+    public void setInterfacename(String interfacename) {
+        this.interfacename = interfacename;
+    }
+    public String getTarget() {
+        return this.target;
+    }
+    public void setTarget(String target) {
+        this.target = target;
+    }
+    public String getCardinality() {
+        return this.cardinality;
+    }
+    public void setCardinality(String cardinality) {
+        this.cardinality = cardinality;
+    }
+    public String getPolicy() {
+        return this.policy;
+    }
+    public void setPolicy(String policy) {
+        this.policy = policy;
+    }
+    public String getBind() {
+        return this.bind;
+    }
+    public void setBind(String bind) {
+        this.bind = bind;
+    }
+    public String getUnbind() {
+        return this.unbind;
+    }
+    public void setUnbind(String unbind) {
+        this.unbind = unbind;
+    }
+
+    /**
+     * Validate the property.
+     * If errors occur a message is added to the issues list,
+     * warnings can be added to the warnings list.
+     */
+    public void validate(List issues, List warnings)
+    throws MojoExecutionException {
+        // validate name
+        if (StringUtils.isEmpty(this.name)) {
+            issues.add(this.getMessage("Reference has no name"));
+        }
+
+        // validate interface
+        if (StringUtils.isEmpty(this.interfacename)) {
+            issues.add(this.getMessage("Missing interface name"));
+        }
+
+        // validate cardinality
+        if (this.cardinality == null) {
+            this.cardinality = "1..1";
+        } else if (!"0..1".equals(this.cardinality) && !"1..1".equals(this.cardinality)
+            && !"0..n".equals(this.cardinality) && !"1..n".equals(this.cardinality)) {
+            issues.add(this.getMessage("Invalid Cardinality specification " + this.cardinality));
+        }
+
+        // validate policy
+        if (this.policy == null) {
+            this.policy = "static";
+        } else if (!"static".equals(this.policy) && !"dynamic".equals(this.policy)) {
+            issues.add(this.getMessage("Invalid Policy specification " + this.policy));
+        }
+
+        // validate bind and unbind methods
+        JavaClassDescription javaClass = this.tag.getJavaClassDescription();
+        if (javaClass != null) {
+            this.bind = this.validateMethod(javaClass, this.bind, issues, warnings);
+            this.unbind = this.validateMethod(javaClass, this.unbind, issues, warnings);
+        } else {
+            issues.add(this.getMessage("Cannot find Java class to which the reference belongs"));
+        }
+    }
+
+    protected String validateMethod(JavaClassDescription javaClass, String methodName, List issues, List warnings)
+    throws MojoExecutionException {
+
+        JavaMethod method = this.findMethod(javaClass, methodName);
+
+        if (method == null) {
+            issues.add(this.getMessage("Missing method " + methodName + " for reference " + this.getName()));
+            return null;
+        }
+
+        if (method.isPublic()) {
+            warnings.add(this.getMessage("Method " + method.getName() + " should be declared protected"));
+        } else if (!method.isProtected()) {
+            issues.add(this.getMessage("Method " + method.getName() + " has wrong qualifier, public or protected required"));
+            return null;
+        }
+
+        return method.getName();
+    }
+
+    protected JavaMethod findMethod(JavaClassDescription javaClass, String methodName)
+    throws MojoExecutionException {
+
+        String[] sig = new String[]{ this.getInterfacename() };
+        String[] sig2 = new String[]{ "org.osgi.framework.ServiceReference" };
+
+        // service interface or ServiceReference first
+        String realMethodName = methodName;
+        JavaMethod method = javaClass.getMethodBySignature(realMethodName, sig);
+        if (method == null) {
+            method = javaClass.getMethodBySignature(realMethodName, sig2);
+        }
+
+        // append reference name with service interface and ServiceReference
+        if (method == null) {
+            realMethodName = methodName + Character.toUpperCase(this.name.charAt(0))
+            + this.name.substring(1);
+
+            method = javaClass.getMethodBySignature(realMethodName, sig);
+        }
+        if (method == null) {
+            method = javaClass.getMethodBySignature(realMethodName, sig2);
+        }
+
+        // append type name with service interface and ServiceReference
+        if (method == null) {
+            int lastDot = this.getInterfacename().lastIndexOf('.');
+            realMethodName = methodName
+                + this.getInterfacename().substring(lastDot + 1);
+            method = javaClass.getMethodBySignature(realMethodName, sig);
+        }
+        if (method == null) {
+            method = javaClass.getMethodBySignature(realMethodName, sig2);
+        }
+
+        return method;
+    }
+
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Service.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Service.java
new file mode 100644
index 0000000..74e1679
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/Service.java
@@ -0,0 +1,78 @@
+/*
+ * 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.sandbox.scrplugin.om;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ * <code>Service</code>...
+ *
+ */
+public class Service {
+
+    protected String servicefactory;
+
+    protected List interfaces = new ArrayList();
+
+    /**
+     * Default constructor.
+     */
+    public Service() {
+        // nothing to do
+    }
+
+    public String getServicefactory() {
+        return this.servicefactory;
+    }
+
+    public void setServicefactory(String servicefactory) {
+        this.servicefactory = servicefactory;
+    }
+
+    public List getInterfaces() {
+        return this.interfaces;
+    }
+
+    public void setInterfaces(List interfaces) {
+        this.interfaces = interfaces;
+    }
+
+    public void addInterface(Interface interf) {
+        this.interfaces.add(interf);
+    }
+
+    /**
+     * Validate the service.
+     * If errors occur a message is added to the issues list,
+     * warnings can be added to the warnings list.
+     */
+    public void validate(List issues, List warnings)
+    throws MojoExecutionException {
+        final Iterator i = this.interfaces.iterator();
+        while ( i.hasNext() ) {
+            final Interface interf = (Interface)i.next();
+            interf.validate(issues, warnings);
+        }
+    }
+
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/AttributeDefinition.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/AttributeDefinition.java
new file mode 100644
index 0000000..5d29d40
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/AttributeDefinition.java
@@ -0,0 +1,109 @@
+/*
+ * 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.sandbox.scrplugin.om.metatype;
+
+import java.util.Map;
+
+public class AttributeDefinition {
+
+    protected String id;
+
+    protected String type;
+
+    protected String defaultValue;
+
+    protected String name;
+
+    protected String[] defaultMultiValue;
+
+    protected String description;
+
+    protected Integer cardinality;
+
+    protected Map options;
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Object getDefaultValue() {
+        return this.defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
+        this.defaultMultiValue = null;
+    }
+
+    public void setDefaultMultiValue(String[] values) {
+        this.defaultValue = null;
+        this.defaultMultiValue = values;
+        if (values != null && values.length > 0 && this.cardinality == null ) {
+            this.cardinality = new Integer(Integer.MAX_VALUE);
+        }
+    }
+
+    public String[] getDefaultMultiValue() {
+        return this.defaultMultiValue;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Integer getCardinality() {
+        return this.cardinality;
+    }
+
+    public void setCardinality(Integer cardinality) {
+        this.cardinality = cardinality;
+    }
+
+    public Map getOptions() {
+        return this.options;
+    }
+
+    public void setOptions(Map options) {
+        this.options = options;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/Designate.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/Designate.java
new file mode 100644
index 0000000..1e164b7
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/Designate.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sandbox.scrplugin.om.metatype;
+
+public class Designate {
+
+    protected String pid;
+
+    protected MTObject object;
+
+    public String getPid() {
+        return this.pid;
+    }
+
+    public void setPid(String pid) {
+        this.pid = pid;
+    }
+
+    public MTObject getObject() {
+        return this.object;
+    }
+
+    public void setObject(MTObject object) {
+        this.object = object;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/MTObject.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/MTObject.java
new file mode 100644
index 0000000..eaad5e1
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/MTObject.java
@@ -0,0 +1,32 @@
+/*
+ * 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.sandbox.scrplugin.om.metatype;
+
+public class MTObject {
+
+    protected String ocdref;
+
+    public String getOcdref() {
+        return this.ocdref;
+    }
+
+    public void setOcdref(String ocdref) {
+        this.ocdref = ocdref;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/MetaData.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/MetaData.java
new file mode 100644
index 0000000..47115c8
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/MetaData.java
@@ -0,0 +1,49 @@
+/*
+ * 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.sandbox.scrplugin.om.metatype;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class MetaData {
+
+    protected String localization;
+
+    protected List descriptors = new ArrayList();
+
+    public String getLocalization() {
+        return this.localization;
+    }
+
+    public void setLocalization(String localization) {
+        this.localization = localization;
+    }
+
+    public List getDescriptors() {
+        return this.descriptors;
+    }
+
+    public void addOCD(OCD ocd) {
+        this.descriptors.add(ocd);
+    }
+
+    public void addDesignate(Designate d) {
+        this.descriptors.add(d);
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/OCD.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/OCD.java
new file mode 100644
index 0000000..ee5e86f
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/om/metatype/OCD.java
@@ -0,0 +1,65 @@
+/*
+ * 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.sandbox.scrplugin.om.metatype;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class OCD {
+
+    protected String id;
+
+    protected String name;
+
+    protected String description;
+
+    protected List properties = new ArrayList();
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public List getProperties() {
+        return this.properties;
+    }
+
+    public void setProperties(List properties) {
+        this.properties = properties;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaClassDescription.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaClassDescription.java
new file mode 100644
index 0000000..6f942cf
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaClassDescription.java
@@ -0,0 +1,101 @@
+/*
+ * 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.sandbox.scrplugin.tags;
+
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ * <code>JavaClassDescription.java</code>...
+ * Description of a java class
+ *
+ */
+public interface JavaClassDescription {
+
+    /**
+     * Get the java class tag with the name.
+     * @param name
+     * @return the tag or null.
+     */
+    JavaTag getTagByName(String name);
+
+    /**
+     * Get all class tags with this name.
+     * @param name
+     * @param inherited If true, parent classes are searched as well.
+     * @return An array of tags or the empty array.
+     * @throws MojoExecutionException
+     */
+    JavaTag[] getTagsByName(String name, boolean inherited)
+    throws MojoExecutionException;
+
+    /**
+     * Get the description for the parent class.
+     * @return
+     * @throws MojoExecutionException
+     */
+    JavaClassDescription getSuperClass() throws MojoExecutionException;
+
+    /**
+     * Get the name of the described class.
+     * @return
+     */
+    String getName();
+
+    JavaField[] getFields();
+
+    JavaClassDescription[] getImplementedInterfaces() throws MojoExecutionException;
+
+    /**
+     * Search for a method with the given signature.
+     * @param name
+     * @param parameters
+     * @return
+     * @throws MojoExecutionException
+     */
+    JavaMethod getMethodBySignature(String name, String[] parameters)
+    throws MojoExecutionException;
+
+    /**
+     * Is this class public?
+     * @return
+     */
+    boolean isPublic();
+
+    /**
+     * Is this class abstract?
+     * @return
+     */
+    boolean isAbstract();
+
+    /**
+     * Is this class an interface?
+     * @return
+     */
+    boolean isInterface();
+
+    JavaMethod[] getMethods();
+
+    /**
+     * Is this class of the type?
+     * @param type
+     * @return
+     * @throws MojoExecutionException
+     */
+    boolean isA(String type) throws MojoExecutionException;
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaClassDescriptorManager.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaClassDescriptorManager.java
new file mode 100644
index 0000000..34c99fc
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaClassDescriptorManager.java
@@ -0,0 +1,307 @@
+/*
+ * 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.sandbox.scrplugin.tags;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+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 org.apache.felix.sandbox.scrplugin.Constants;
+import org.apache.felix.sandbox.scrplugin.om.Component;
+import org.apache.felix.sandbox.scrplugin.om.Components;
+import org.apache.felix.sandbox.scrplugin.tags.cl.ClassLoaderJavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.qdox.QDoxJavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.xml.ComponentDescriptorIO;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.ArtifactUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.IOUtil;
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.JavaSource;
+
+/**
+ * <code>JavaClassDescriptorManager.java</code>...
+ *
+ */
+public class JavaClassDescriptorManager {
+
+    protected static final String SERVICE_COMPONENT = "Service-Component";
+
+    /** The sources read by qdox. */
+    protected final JavaSource[] sources;
+
+    /** The maven log. */
+    protected final Log log;
+
+    /** The classloader used to compile the classes. */
+    protected final ClassLoader classloader;
+
+    /** A cache containing the java class descriptions hashed by classname. */
+    protected final Map javaClassDescriptions = new HashMap();
+
+    /** The component definitions from other bundles hashed by classname. */
+    protected final Map componentDescriptions = new HashMap();
+
+    /**
+     * Construct a new manager.
+     * @param log
+     * @param project
+     * @throws MojoFailureException
+     * @throws MojoExecutionException
+     */
+    public JavaClassDescriptorManager(final Log         log,
+                                      final MavenProject project)
+    throws MojoFailureException, MojoExecutionException {
+        this.log = log;
+        this.classloader = this.getCompileClassLoader(project);
+
+        // get all the class sources through qdox
+        this.log.debug("Setting up QDox");
+        JavaDocBuilder builder = new JavaDocBuilder();
+        builder.getClassLibrary().addClassLoader(this.classloader);
+        final Iterator i = project.getCompileSourceRoots().iterator();
+        while ( i.hasNext() ) {
+            final String tree = (String)i.next();
+            this.log.debug("Adding source tree " + tree);
+            builder.addSourceTree(new File(tree));
+        }
+        this.sources = builder.getSources();
+
+        // and now scan artifacts
+        final List components = new ArrayList();
+        final Map resolved = project.getArtifactMap();
+        final Set artifacts = project.getDependencyArtifacts();
+        final Iterator it = artifacts.iterator();
+        while ( it.hasNext() ) {
+            final Artifact declared = (Artifact) it.next();
+            this.log.debug("Checking artifact " + declared);
+            if (Artifact.SCOPE_COMPILE.equals(declared.getScope())
+                || Artifact.SCOPE_RUNTIME.equals(declared.getScope())) {
+                this.log.debug("Resolving artifact " + declared);
+                final Artifact artifact = (Artifact) resolved.get(ArtifactUtils.versionlessKey(declared));
+                if (artifact != null) {
+                    this.log.debug("Trying to get manifest from artifact " + artifact);
+                    try {
+                        final Manifest manifest = this.getManifest(artifact);
+                        if ( manifest != null ) {
+                            // read Service-Component entry
+                            if ( manifest.getMainAttributes().getValue(JavaClassDescriptorManager.SERVICE_COMPONENT) != null ) {
+                                final String serviceComponent = manifest.getMainAttributes().getValue(JavaClassDescriptorManager.SERVICE_COMPONENT);
+                                this.log.debug("Found Service-Component: " + serviceComponent + " in artifact " + artifact);
+                                final StringTokenizer st = new StringTokenizer(serviceComponent, ",");
+                                while ( st.hasMoreTokens() ) {
+                                    final String entry = st.nextToken().trim();
+                                    if ( entry.length() > 0 ) {
+                                        components.addAll(this.readServiceComponentDescriptor(artifact, entry).getComponents());
+                                    }
+                                }
+                            } else {
+                                this.log.debug("Artifact has no service component entry in manifest " + artifact);
+                            }
+                        } else {
+                            this.log.debug("Unable to get manifest from artifact " + artifact);
+                        }
+                    } catch (IOException ioe) {
+                        throw new MojoExecutionException("Unable to get manifest from artifact " + artifact, ioe);
+                    }
+                    this.log.debug("Trying to get scrinfo from artifact " + artifact);
+                    try {
+                        final File scrInfoFile = this.getFile(artifact, Constants.ABSTRACT_DESCRIPTOR_ARCHIV_PATH);
+                        if ( scrInfoFile != null ) {
+                            components.addAll(this.parseServiceComponentDescriptor(artifact, scrInfoFile).getComponents());
+                        } else {
+                            this.log.debug("Artifact has no scrinfo file (it's optional): " + artifact);
+                        }
+                    } catch (IOException ioe) {
+                        throw new MojoExecutionException("Unable to get scrinfo from artifact " + artifact, ioe);
+                    }
+                } else {
+                    this.log.debug("Unable to resolve artifact " + declared);
+                }
+            } else {
+                this.log.debug("Artifact " + declared + " has not scope compile or runtime, but " + declared.getScope());
+            }
+        }
+        // now create map with component descriptions
+        final Iterator cI = components.iterator();
+        while ( cI.hasNext() ) {
+            final Component component = (Component) cI.next();
+            this.componentDescriptions.put(component.getImplementation().getClassame(), component);
+        }
+    }
+
+    /**
+     * Return the log.
+     */
+    public Log getLog() {
+        return this.log;
+    }
+
+    /**
+     * Return the class laoder.
+     */
+    public ClassLoader getClassLoader() {
+        return this.classloader;
+    }
+
+    /**
+     * Read the service component description.
+     * @param artifact
+     * @param entry
+     * @throws IOException
+     * @throws MojoExecutionException
+     */
+    protected Components readServiceComponentDescriptor(Artifact artifact, String entry)
+    throws IOException, MojoExecutionException {
+        this.log.debug("Reading " + entry + " from " + artifact);
+        final File xml = this.getFile(artifact, entry);
+        if ( xml == null ) {
+            throw new MojoExecutionException("Artifact " + artifact + " does not contain declared service component descriptor " + entry);
+        }
+        return this.parseServiceComponentDescriptor(artifact, xml);
+    }
+
+    protected Components parseServiceComponentDescriptor(Artifact artifact, File file)
+    throws IOException, MojoExecutionException {
+        this.log.debug("Parsing " + file);
+        final Components list = ComponentDescriptorIO.read(file);
+        return list;
+    }
+
+    protected ClassLoader getCompileClassLoader(MavenProject project)
+    throws MojoFailureException {
+        List artifacts = project.getCompileArtifacts();
+        URL[] path = new URL[artifacts.size()];
+        int i = 0;
+        for (Iterator ai=artifacts.iterator(); ai.hasNext(); ) {
+            Artifact a = (Artifact) ai.next();
+            try {
+                path[i++] = a.getFile().toURI().toURL();
+            } catch (IOException ioe) {
+                throw new MojoFailureException("Unable to get compile class loader.");
+            }
+        }
+        return new URLClassLoader(path);
+    }
+
+    protected Manifest getManifest(Artifact artifact) throws IOException {
+        JarFile file = null;
+        try {
+            file = new JarFile(artifact.getFile());
+            return file.getManifest();
+        } finally {
+            if (file != null) {
+                try {
+                    file.close();
+                } catch (IOException ignore) {
+                }
+            }
+        }
+    }
+
+    protected File getFile(Artifact artifact, String path) throws IOException {
+        final int pos = path.lastIndexOf('.');
+        final String suffix = path.substring(pos + 1);
+        JarFile file = null;
+        File tmpFile = null;
+        try {
+            file = new JarFile(artifact.getFile());
+            final JarEntry entry = file.getJarEntry(path);
+            if ( entry != null ) {
+                tmpFile = File.createTempFile("scrjcdm" + artifact.getArtifactId(), suffix);
+                tmpFile.deleteOnExit();
+                final FileOutputStream fos = new FileOutputStream(tmpFile);
+                IOUtil.copy(file.getInputStream(entry), fos);
+                IOUtil.close(fos);
+                return tmpFile;
+            }
+            return null;
+        } finally {
+            if (file != null) {
+                try {
+                    file.close();
+                } catch (IOException ignore) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Return all source descriptions of this project.
+     * @return
+     */
+    public JavaClassDescription[] getSourceDescriptions() {
+        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);
+        }
+        return descs;
+    }
+
+    /**
+     * Get a java class description for the class.
+     * @param className
+     * @return
+     * @throws MojoExecutionException
+     */
+    public JavaClassDescription getJavaClassDescription(String className)
+    throws MojoExecutionException {
+        JavaClassDescription result = (JavaClassDescription) this.javaClassDescriptions.get(className);
+        if ( result == null ) {
+            this.log.debug("Searching description for: " + className);
+            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);
+                } else {
+                    index++;
+                }
+            }
+            if ( result == null ) {
+                try {
+                    this.log.debug("Generating classloader description for: " + className);
+                    result = new ClassLoaderJavaClassDescription(this.classloader.loadClass(className), (Component)this.componentDescriptions.get(className), this);
+                } catch (ClassNotFoundException e) {
+                    throw new MojoExecutionException("Unable to load class " + className);
+                }
+            }
+            if ( result != null ) {
+                this.javaClassDescriptions.put(className, result);
+            }
+        }
+        return result;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaField.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaField.java
new file mode 100644
index 0000000..4137f06
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaField.java
@@ -0,0 +1,34 @@
+/*
+ * 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.sandbox.scrplugin.tags;
+
+/**
+ * <code>JavaField.java</code>...
+ *
+ */
+public interface JavaField {
+
+    String getName();
+
+    String getType();
+
+    JavaTag getTagByName(String name);
+
+    String getInitializationExpression();
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaMethod.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaMethod.java
new file mode 100644
index 0000000..6b65177
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaMethod.java
@@ -0,0 +1,36 @@
+/*
+ * 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.sandbox.scrplugin.tags;
+
+/**
+ * <code>JavaMethod.java</code>...
+ *
+ */
+public interface JavaMethod {
+
+    boolean isPublic();
+
+    boolean isProtected();
+
+    String getName();
+
+    JavaParameter[] getParameters();
+
+    boolean isConstructor();
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaParameter.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaParameter.java
new file mode 100644
index 0000000..dbd14a7
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaParameter.java
@@ -0,0 +1,28 @@
+/*
+ * 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.sandbox.scrplugin.tags;
+
+/**
+ * <code>JavaParameter.java</code>...
+ *
+ */
+public interface JavaParameter {
+
+    String getType();
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaTag.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaTag.java
new file mode 100644
index 0000000..34bfa30
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/JavaTag.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sandbox.scrplugin.tags;
+
+import java.util.Map;
+
+/**
+ * <code>JavaTag.java</code>...
+ *
+ */
+public interface JavaTag {
+
+    String getName();
+
+    String[] getParameters();
+
+    String getNamedParameter(String arg0);
+
+    String getSourceLocation();
+
+    JavaClassDescription getJavaClassDescription();
+
+    JavaField getField();
+
+    Map getNamedParameterMap();
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
new file mode 100644
index 0000000..2ebab7b
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
@@ -0,0 +1,198 @@
+/*
+ * 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.sandbox.scrplugin.tags.cl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.sandbox.scrplugin.Constants;
+import org.apache.felix.sandbox.scrplugin.om.Component;
+import org.apache.felix.sandbox.scrplugin.om.Reference;
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescriptorManager;
+import org.apache.felix.sandbox.scrplugin.tags.JavaField;
+import org.apache.felix.sandbox.scrplugin.tags.JavaMethod;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ * <code>ClassLoaderJavaClassDescription.java</code>...
+ *
+ */
+public class ClassLoaderJavaClassDescription implements JavaClassDescription {
+
+    protected static final JavaTag[] EMPTY_TAGS = new JavaTag[0];
+
+    protected final Class clazz;
+
+    protected final JavaClassDescriptorManager manager;
+
+    protected final Component component;
+
+    public ClassLoaderJavaClassDescription(Class c, Component comp, JavaClassDescriptorManager m) {
+        this.clazz = c;
+        this.manager = m;
+        this.component = comp;
+    }
+
+    public JavaField[] getFields() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public JavaClassDescription[] getImplementedInterfaces() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getMethodBySignature(java.lang.String, java.lang.String[])
+     */
+    public JavaMethod getMethodBySignature(String name, String[] parameters) {
+        Class[] classParameters = null;
+        if ( parameters != null ) {
+            classParameters = new Class[parameters.length];
+            for(int i=0; i<parameters.length; i++) {
+                try {
+                    classParameters[i] = this.manager.getClassLoader().loadClass(parameters[i]);
+                } catch (ClassNotFoundException cnfe) {
+                    return null;
+                }
+            }
+        }
+        Method m = null;
+        try {
+            m = this.clazz.getDeclaredMethod(name, classParameters);
+        } catch (NoSuchMethodException e) {
+            // ignore this
+        }
+        if ( m != null ) {
+            return new ClassLoaderJavaMethod(m);
+        }
+        return null;
+    }
+
+    public JavaMethod[] getMethods() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getName()
+     */
+    public String getName() {
+        return this.clazz.getName();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getSuperClass()
+     */
+    public JavaClassDescription getSuperClass() throws MojoExecutionException {
+        if ( this.clazz.getSuperclass() != null ) {
+            return this.manager.getJavaClassDescription(this.clazz.getSuperclass().getName());
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getTagByName(java.lang.String)
+     */
+    public JavaTag getTagByName(String name) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getTagsByName(java.lang.String, boolean)
+     */
+    public JavaTag[] getTagsByName(String name, boolean inherited)
+    throws MojoExecutionException {
+        JavaTag[] javaTags = EMPTY_TAGS;
+        if ( this.component != null ) {
+            if ( Constants.SERVICE.equals(name) ) {
+
+            } else if ( Constants.PROPERTY.equals(name) ) {
+
+            } else if ( Constants.REFERENCE.equals(name) ) {
+                if ( this.component.getReferences().size() > 0 ) {
+                    javaTags = new JavaTag[this.component.getReferences().size()];
+                    for(int i=0; i<this.component.getReferences().size(); i++) {
+                        javaTags[i] = new ClassLoaderJavaTag(this, (Reference)this.component.getReferences().get(i));
+                    }
+                }
+            }
+        }
+        if ( inherited && this.getSuperClass() != null ) {
+            final JavaTag[] superTags = this.getSuperClass().getTagsByName(name, inherited);
+            if ( superTags.length > 0 ) {
+                final List list = new ArrayList(Arrays.asList(javaTags));
+                list.addAll(Arrays.asList(superTags));
+                javaTags = (JavaTag[]) list.toArray(new JavaTag[list.size()]);
+            }
+        }
+        return javaTags;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isA(java.lang.String)
+     */
+    public boolean isA(String type) {
+        if ( this.clazz.getName().equals(type) ) {
+            return true;
+        }
+        return this.testClass(this.clazz, type);
+    }
+
+    protected boolean testClass(Class c, String type) {
+        final Class[] interfaces = c.getInterfaces();
+        for(int i=0; i<interfaces.length; i++) {
+            if ( interfaces[i].getName().equals(type) ) {
+                return true;
+            }
+            if ( this.testClass(interfaces[i], type) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isAbstract()
+     */
+    public boolean isAbstract() {
+        return Modifier.isAbstract(this.clazz.getModifiers());
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isInterface()
+     */
+    public boolean isInterface() {
+        return Modifier.isInterface(this.clazz.getModifiers());
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isPublic()
+     */
+    public boolean isPublic() {
+        return Modifier.isPublic(this.clazz.getModifiers());
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaMethod.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaMethod.java
new file mode 100644
index 0000000..4280736
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaMethod.java
@@ -0,0 +1,77 @@
+/*
+ * 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.sandbox.scrplugin.tags.cl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaMethod;
+import org.apache.felix.sandbox.scrplugin.tags.JavaParameter;
+
+/**
+ * <code>ClassLoaderJavaMethod.java</code>...
+ *
+ */
+public class ClassLoaderJavaMethod implements JavaMethod {
+
+    protected final Method method;
+
+    protected boolean isConstructor = false;
+
+    public ClassLoaderJavaMethod(Method m) {
+        this.method = m;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#getName()
+     */
+    public String getName() {
+        return this.method.getName();
+    }
+
+    public JavaParameter[] getParameters() {
+        final JavaParameter[] params = new JavaParameter[this.method.getParameterTypes().length];
+        for(int i=0; i<this.method.getParameterTypes().length; i++) {
+            params[i] = new ClassLoaderJavaParameter(this.method.getParameterTypes()[i].getName());
+        }
+        return params;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#isConstructor()
+     */
+    public boolean isConstructor() {
+        return this.isConstructor;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#isProtected()
+     */
+    public boolean isProtected() {
+        return Modifier.isProtected(this.method.getModifiers());
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#isPublic()
+     */
+    public boolean isPublic() {
+        return Modifier.isPublic(this.method.getModifiers());
+    }
+
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaParameter.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaParameter.java
new file mode 100644
index 0000000..7b4fdfa
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaParameter.java
@@ -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.sandbox.scrplugin.tags.cl;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaParameter;
+
+/**
+ * <code>ClassLoaderJavaParameter.java</code>...
+ *
+ */
+public class ClassLoaderJavaParameter implements JavaParameter {
+
+    protected final String type;
+
+    public ClassLoaderJavaParameter(String t) {
+        this.type = t;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaParameter#getType()
+     */
+    public String getType() {
+        return this.type;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaTag.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaTag.java
new file mode 100644
index 0000000..4b1a798
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/cl/ClassLoaderJavaTag.java
@@ -0,0 +1,112 @@
+/*
+ * 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.sandbox.scrplugin.tags.cl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.sandbox.scrplugin.Constants;
+import org.apache.felix.sandbox.scrplugin.om.Reference;
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaField;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+
+/**
+ * <code>ClassLoaderJavaTag.java</code>...
+ *
+ */
+public class ClassLoaderJavaTag implements JavaTag {
+
+    protected final JavaClassDescription description;
+    protected final Reference reference;
+
+    public ClassLoaderJavaTag(JavaClassDescription desc, Reference reference) {
+        this.reference = reference;
+        this.description = desc;
+    }
+
+    public JavaField getField() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getJavaClassDescription()
+     */
+    public JavaClassDescription getJavaClassDescription() {
+        return this.description;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getName()
+     */
+    public String getName() {
+        if ( this.reference != null ) {
+            return Constants.REFERENCE;
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getNamedParameter(java.lang.String)
+     */
+    public String getNamedParameter(String name) {
+        final Map map = this.getNamedParameterMap();
+        if ( map != null ) {
+            return (String)map.get(name);
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getNamedParameterMap()
+     */
+    public Map getNamedParameterMap() {
+        if ( this.reference != null ) {
+            final Map map = new HashMap();
+            map.put(Constants.REFERENCE_BIND, this.reference.getBind());
+            map.put(Constants.REFERENCE_CARDINALITY, this.reference.getCardinality());
+            map.put(Constants.REFERENCE_INTERFACE, this.reference.getInterfacename());
+            map.put(Constants.REFERENCE_NAME, this.reference.getName());
+            map.put(Constants.REFERENCE_POLICY, this.reference.getPolicy());
+            map.put(Constants.REFERENCE_TARGET, this.reference.getTarget());
+            map.put(Constants.REFERENCE_UNDBIND, this.reference.getUnbind());
+            return map;
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getParameters()
+     */
+    public String[] getParameters() {
+        final Map map = this.getNamedParameterMap();
+        if ( map != null ) {
+            return (String[])map.keySet().toArray(new String[5]);
+        }
+        return new String[0];
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getSourceLocation()
+     */
+    public String getSourceLocation() {
+        return "Compiled class: " + this.description.getName();
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaClassDescription.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaClassDescription.java
new file mode 100644
index 0000000..7cfd8a4
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaClassDescription.java
@@ -0,0 +1,219 @@
+/*
+ * 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.sandbox.scrplugin.tags.qdox;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescriptorManager;
+import org.apache.felix.sandbox.scrplugin.tags.JavaField;
+import org.apache.felix.sandbox.scrplugin.tags.JavaMethod;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+import org.apache.maven.plugin.MojoExecutionException;
+
+import com.thoughtworks.qdox.model.DocletTag;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaSource;
+import com.thoughtworks.qdox.model.Type;
+
+/**
+ * <code>QDoxJavaClassDescription.java</code>...
+ *
+ */
+public class QDoxJavaClassDescription implements JavaClassDescription {
+
+    protected final JavaClass javaClass;
+
+    protected final JavaClassDescriptorManager manager;
+
+    public QDoxJavaClassDescription(JavaSource source, JavaClassDescriptorManager m) {
+        this.javaClass = source.getClasses()[0];
+        this.manager = m;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getSuperClass()
+     */
+    public JavaClassDescription getSuperClass() throws MojoExecutionException {
+        final JavaClass parent = this.javaClass.getSuperJavaClass();
+        if ( parent != null ) {
+            return this.manager.getJavaClassDescription(parent.getFullyQualifiedName());
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getTagForName(java.lang.String)
+     */
+    public JavaTag getTagByName(String name) {
+        final DocletTag tag = this.javaClass.getTagByName(name);
+        if ( tag == null ) {
+            return null;
+        }
+        return new QDoxJavaTag(tag, this);
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getName()
+     */
+    public String getName() {
+        return this.javaClass.getFullyQualifiedName();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getTagsByName(java.lang.String, boolean)
+     */
+    public JavaTag[] getTagsByName(String name, boolean inherited)
+    throws MojoExecutionException {
+        final DocletTag[] tags = this.javaClass.getTagsByName(name, false);
+        JavaTag[] javaTags;
+        if ( tags == null || tags.length == 0 ) {
+            javaTags = new JavaTag[0];
+        } else {
+            javaTags = new JavaTag[tags.length];
+            for(int i=0; i<tags.length;i++) {
+                javaTags[i] = new QDoxJavaTag(tags[i], this);
+            }
+        }
+        if ( inherited && this.getSuperClass() != null ) {
+            final JavaTag[] superTags = this.getSuperClass().getTagsByName(name, inherited);
+            if ( superTags.length > 0 ) {
+                final List list = new ArrayList(Arrays.asList(javaTags));
+                list.addAll(Arrays.asList(superTags));
+                javaTags = (JavaTag[]) list.toArray(new JavaTag[list.size()]);
+            }
+        }
+        return javaTags;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getFields()
+     */
+    public JavaField[] getFields() {
+        final com.thoughtworks.qdox.model.JavaField fields[] = this.javaClass.getFields();
+        if ( fields == null || fields.length == 0 ) {
+            return new JavaField[0];
+        }
+        final JavaField[] f = new JavaField[fields.length];
+        for(int i=0; i<fields.length; i++) {
+            f[i] = new QDoxJavaField(fields[i], this);
+        }
+        return f;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
+     */
+    public JavaClassDescription[] getImplementedInterfaces()
+    throws MojoExecutionException {
+        final JavaClass[] interfaces = this.javaClass.getImplementedInterfaces();
+        if ( interfaces == null || interfaces.length == 0 ) {
+            return new JavaClassDescription[0];
+        }
+        final JavaClassDescription[] descs = new JavaClassDescription[interfaces.length];
+        for(int i=0;i<interfaces.length; i++) {
+            descs[i] = this.manager.getJavaClassDescription(interfaces[i].getFullyQualifiedName());
+        }
+        return descs;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getMethodBySignature(java.lang.String, java.lang.String[])
+     */
+    public JavaMethod getMethodBySignature(String name, String[] parameters)
+    throws MojoExecutionException {
+        Type[] types = null;
+        if ( parameters == null || parameters.length == 0 ) {
+            types = new Type[0];
+        } else {
+            types = new Type[parameters.length];
+            for(int i=0;i<parameters.length;i++) {
+                types[i] = new Type(parameters[i]);
+            }
+        }
+        final com.thoughtworks.qdox.model.JavaMethod m = this.javaClass.getMethodBySignature(name, types);
+        if ( m == null ) {
+            if ( this.getSuperClass() != null ) {
+                return this.getSuperClass().getMethodBySignature(name, parameters);
+            }
+            return null;
+        }
+        return new QDoxJavaMethod(m);
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#getMethods()
+     */
+    public JavaMethod[] getMethods() {
+        final com.thoughtworks.qdox.model.JavaMethod[] methods = this.javaClass.getMethods();
+        if ( methods == null || methods.length == 0) {
+            return new JavaMethod[0];
+        }
+        final JavaMethod[] m = new JavaMethod[methods.length];
+        for(int i=0;i<methods.length;i++) {
+            m[i] = new QDoxJavaMethod(methods[i]);
+        }
+        return m;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isA(java.lang.String)
+     */
+    public boolean isA(String type) throws MojoExecutionException {
+        final Type qType = new Type(type);
+        if ( this.javaClass.isA(type) ) {
+            return true;
+        }
+        final Type[] interfaces = this.javaClass.getImplements();
+        if ( interfaces != null ) {
+            for(int i=0; i<interfaces.length; i++) {
+                if ( interfaces[i].isA(qType) ) {
+                    return true;
+                }
+            }
+        }
+        if ( this.getSuperClass() != null ) {
+            return this.getSuperClass().isA(type);
+        }
+        return false;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isAbstract()
+     */
+    public boolean isAbstract() {
+        return this.javaClass.isAbstract();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isInterface()
+     */
+    public boolean isInterface() {
+        return this.javaClass.isInterface();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription#isPublic()
+     */
+    public boolean isPublic() {
+        return this.javaClass.isPublic();
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaField.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaField.java
new file mode 100644
index 0000000..ad083b1
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaField.java
@@ -0,0 +1,73 @@
+/*
+ * 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.sandbox.scrplugin.tags.qdox;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaField;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+
+import com.thoughtworks.qdox.model.DocletTag;
+
+/**
+ * <code>QDoxJavaField.java</code>...
+ *
+ */
+public class QDoxJavaField implements JavaField {
+
+    protected final com.thoughtworks.qdox.model.JavaField field;
+
+    protected final JavaClassDescription description;
+
+    public QDoxJavaField(com.thoughtworks.qdox.model.JavaField f, JavaClassDescription d) {
+        this.field = f;
+        this.description = d;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaField#getInitializationExpression()
+     */
+    public String getInitializationExpression() {
+        return this.field.getInitializationExpression();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaField#getName()
+     */
+    public String getName() {
+        return this.field.getName();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaField#getTagByName(java.lang.String)
+     */
+    public JavaTag getTagByName(String name) {
+        final DocletTag tag = this.field.getTagByName(name);
+        if ( tag == null ) {
+            return null;
+        }
+        return new QDoxJavaTag(tag, this.description, this);
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaField#getType()
+     */
+    public String getType() {
+        return this.field.getType().getValue();
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaMethod.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaMethod.java
new file mode 100644
index 0000000..9485381
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaMethod.java
@@ -0,0 +1,78 @@
+/*
+ * 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.sandbox.scrplugin.tags.qdox;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaMethod;
+import org.apache.felix.sandbox.scrplugin.tags.JavaParameter;
+
+/**
+ * <code>QDoxJavaMethod.java</code>...
+ *
+ */
+public class QDoxJavaMethod implements JavaMethod {
+
+    protected final com.thoughtworks.qdox.model.JavaMethod method;
+
+    public QDoxJavaMethod(com.thoughtworks.qdox.model.JavaMethod m) {
+        this.method = m;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#getName()
+     */
+    public String getName() {
+        return this.method.getName();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#getParameters()
+     */
+    public JavaParameter[] getParameters() {
+        final com.thoughtworks.qdox.model.JavaParameter[] params = this.method.getParameters();
+        if ( params == null || params.length == 0) {
+            return new JavaParameter[0];
+        }
+        final JavaParameter[] p = new JavaParameter[params.length];
+        for(int i=0; i<params.length; i++) {
+            p[i] = new QDoxJavaParameter(params[i]);
+        }
+        return p;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#isConstructor()
+     */
+    public boolean isConstructor() {
+        return this.method.isConstructor();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#isProtected()
+     */
+    public boolean isProtected() {
+        return this.method.isProtected();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaMethod#isPublic()
+     */
+    public boolean isPublic() {
+        return this.method.isPublic();
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaParameter.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaParameter.java
new file mode 100644
index 0000000..e355dc7
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaParameter.java
@@ -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.sandbox.scrplugin.tags.qdox;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaParameter;
+
+/**
+ * <code>QDoxJavaParameter.java</code>...
+ *
+ */
+public class QDoxJavaParameter implements JavaParameter {
+
+    protected final com.thoughtworks.qdox.model.JavaParameter parameter;
+
+    public QDoxJavaParameter(com.thoughtworks.qdox.model.JavaParameter p) {
+        this.parameter = p;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaParameter#getType()
+     */
+    public String getType() {
+        return this.parameter.getType().getValue();
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaTag.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaTag.java
new file mode 100644
index 0000000..20f08bb
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/tags/qdox/QDoxJavaTag.java
@@ -0,0 +1,99 @@
+/*
+ * 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.sandbox.scrplugin.tags.qdox;
+
+import java.util.Map;
+
+import org.apache.felix.sandbox.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.sandbox.scrplugin.tags.JavaField;
+import org.apache.felix.sandbox.scrplugin.tags.JavaTag;
+
+import com.thoughtworks.qdox.model.DocletTag;
+
+/**
+ * <code>QDoxJavaTag.java</code>...
+ *
+ */
+public class QDoxJavaTag implements JavaTag {
+
+    protected final DocletTag docletTag;
+
+    protected final JavaClassDescription description;
+
+    protected final JavaField field;
+
+    public QDoxJavaTag(DocletTag t, JavaClassDescription desc) {
+        this(t, desc, null);
+    }
+
+    public QDoxJavaTag(DocletTag t, JavaClassDescription desc, JavaField field) {
+        this.docletTag = t;
+        this.description = desc;
+        this.field = field;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getName()
+     */
+    public String getName() {
+        return this.docletTag.getName();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getNamedParameter(java.lang.String)
+     */
+    public String getNamedParameter(String arg0) {
+        return this.docletTag.getNamedParameter(arg0);
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getParameters()
+     */
+    public String[] getParameters() {
+        return this.docletTag.getParameters();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getSourceLocation()
+     */
+    public String getSourceLocation() {
+        return this.docletTag.getContext().getSource().getURL() + ", line " + this.docletTag.getLineNumber();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getJavaClassDescription()
+     */
+    public JavaClassDescription getJavaClassDescription() {
+        return this.description;
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getNamedParameterMap()
+     */
+    public Map getNamedParameterMap() {
+        return this.docletTag.getNamedParameterMap();
+    }
+
+    /**
+     * @see org.apache.felix.sandbox.scrplugin.tags.JavaTag#getField()
+     */
+    public JavaField getField() {
+        return this.field;
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/xml/ComponentDescriptorIO.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/xml/ComponentDescriptorIO.java
new file mode 100644
index 0000000..113292d
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/xml/ComponentDescriptorIO.java
@@ -0,0 +1,474 @@
+/*
+ * 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.sandbox.scrplugin.xml;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.felix.sandbox.scrplugin.om.Component;
+import org.apache.felix.sandbox.scrplugin.om.Components;
+import org.apache.felix.sandbox.scrplugin.om.Implementation;
+import org.apache.felix.sandbox.scrplugin.om.Interface;
+import org.apache.felix.sandbox.scrplugin.om.Property;
+import org.apache.felix.sandbox.scrplugin.om.Reference;
+import org.apache.felix.sandbox.scrplugin.om.Service;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * <code>ComponentDescriptorIO</code>
+ *
+ * is a helper class to read and write component descriptor files.
+ *
+ */
+public class ComponentDescriptorIO {
+
+    public static final String NAMESPACE_URI = "http://www.osgi.org/xmlns/scr/v1.0.0";
+
+    private static final String PREFIX = "scr";
+
+    private static final String COMPONENTS = "components";
+
+    private static final String COMPONENT = "component";
+
+    private static final String COMPONENT_QNAME = PREFIX + ':' + COMPONENT;
+
+    private static final String IMPLEMENTATION = "implementation";
+
+    private static final String IMPLEMENTATION_QNAME = PREFIX + ':' + IMPLEMENTATION;
+
+    private static final String SERVICE = "service";
+
+    private static final String SERVICE_QNAME = PREFIX + ':' + SERVICE;
+
+    private static final String PROPERTY = "property";
+
+    private static final String PROPERTY_QNAME = PREFIX + ':' + PROPERTY;
+
+    private static final String REFERENCE = "reference";
+
+    private static final String REFERENCE_QNAME = PREFIX + ':' + REFERENCE;
+
+    private static final String INTERFACE = "provide";
+
+    private static final String INTERFACE_QNAME = PREFIX + ':' + INTERFACE;
+
+    private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+
+    public static Components read(File file)
+    throws MojoExecutionException {
+        try {
+            final Transformer transformer = FACTORY.newTransformer();
+            final XmlHandler xmlHandler = new XmlHandler();
+            transformer.transform(new StreamSource(new FileReader(file)),
+                    new SAXResult(xmlHandler));
+            return xmlHandler.components;
+        } catch (TransformerException e) {
+            throw new MojoExecutionException("Unable to read xml.", e);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Unable to read xml from " + file, e);
+        }
+    }
+
+    /**
+     * Write the component descriptors to the file.
+     * @param components
+     * @param file
+     * @throws MojoExecutionException
+     */
+    public static void write(Components components, File file)
+    throws MojoExecutionException {
+        try {
+            FileWriter writer = new FileWriter(file);
+            final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
+            final Transformer transformer = transformerHandler.getTransformer();
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformerHandler.setResult(new StreamResult(writer));
+
+            generateXML(components, transformerHandler);
+        } catch (TransformerException e) {
+            throw new MojoExecutionException("Unable to write xml to " + file, e);
+        } catch (SAXException e) {
+            throw new MojoExecutionException("Unable to generate xml for " + file, e);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Unable to write xml to " + file, e);
+        }
+    }
+
+    /**
+     * Generate the xml top level element and start streaming
+     * the components.
+     * @param components
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Components components, ContentHandler contentHandler)
+    throws SAXException {
+        contentHandler.startDocument();
+        contentHandler.startPrefixMapping(PREFIX, NAMESPACE_URI);
+
+        // wrapper element to generate well formed xml
+        contentHandler.startElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS, new AttributesImpl());
+
+        final Iterator i = components.getComponents().iterator();
+        while ( i.hasNext() ) {
+            final Component component = (Component)i.next();
+            generateXML(component, contentHandler);
+        }
+        // end wrapper element
+        contentHandler.endElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS);
+        contentHandler.endPrefixMapping(PREFIX);
+        contentHandler.endDocument();
+    }
+
+    /**
+     * Write the xml for a {@link Component}.
+     * @param component
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Component component, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "enabled", component.isEnabled());
+        addAttribute(ai, "immediate",component.isImmediate());
+        addAttribute(ai, "name", component.getName());
+        addAttribute(ai, "factory", component.getFactory());
+
+        contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME, ai);
+        generateXML(component.getImplementation(), contentHandler);
+        if ( component.getService() != null ) {
+            generateXML(component.getService(), contentHandler);
+        }
+        if ( component.getProperties() != null ) {
+            final Iterator i = component.getProperties().iterator();
+            while ( i.hasNext() ) {
+                final Property property = (Property)i.next();
+                generateXML(property, contentHandler);
+            }
+        }
+        if ( component.getReferences() != null ) {
+            final Iterator i = component.getReferences().iterator();
+            while ( i.hasNext() ) {
+                final Reference reference = (Reference)i.next();
+                generateXML(reference, contentHandler);
+            }
+        }
+        contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME);
+    }
+
+    /**
+     * Write the xml for a {@link Implementation}.
+     * @param implementation
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Implementation implementation, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "class", implementation.getClassame());
+        contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION, ComponentDescriptorIO.IMPLEMENTATION_QNAME, ai);
+        contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION, ComponentDescriptorIO.IMPLEMENTATION_QNAME);
+    }
+
+    /**
+     * Write the xml for a {@link Service}.
+     * @param service
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Service service, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "servicefactory", service.getServicefactory());
+        contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.SERVICE, ComponentDescriptorIO.SERVICE_QNAME, ai);
+        if ( service.getInterfaces() != null ) {
+            final Iterator i = service.getInterfaces().iterator();
+            while ( i.hasNext() ) {
+                final Interface interf = (Interface)i.next();
+                generateXML(interf, contentHandler);
+            }
+        }
+        contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.SERVICE, ComponentDescriptorIO.SERVICE_QNAME);
+    }
+
+    /**
+     * Write the xml for a {@link Interface}.
+     * @param interface
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Interface interf, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "interface", interf.getInterfacename());
+        contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME, ai);
+        contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME);
+    }
+
+    /**
+     * Write the xml for a {@link Property}.
+     * @param property
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Property property, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "name", property.getName());
+        addAttribute(ai, "type", property.getType());
+        addAttribute(ai, "value", property.getValue());
+        contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.PROPERTY, ComponentDescriptorIO.PROPERTY_QNAME, ai);
+        if ( property.getMultiValue() != null && property.getMultiValue().length > 0 ) {
+            for(int i=0; i<property.getMultiValue().length; i++) {
+                text(contentHandler, "    ");
+                text(contentHandler, property.getMultiValue()[i]);
+                text(contentHandler, "\n");
+            }
+        }
+        contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.PROPERTY, ComponentDescriptorIO.PROPERTY_QNAME);
+    }
+
+    /**
+     * Write the xml for a {@link Reference}.
+     * @param reference
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(Reference reference, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "name", reference.getName());
+        addAttribute(ai, "interface", reference.getInterfacename());
+        addAttribute(ai, "cardinality", reference.getCardinality());
+        addAttribute(ai, "policy", reference.getPolicy());
+        addAttribute(ai, "target", reference.getTarget());
+        addAttribute(ai, "bind", reference.getBind());
+        addAttribute(ai, "unbind", reference.getUnbind());
+        contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME, ai);
+        contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME);
+    }
+
+    /**
+     * Helper method to add an attribute.
+     * This implementation adds a new attribute with the given name
+     * and value. Before adding the value is checked for non-null.
+     * @param ai    The attributes impl receiving the additional attribute.
+     * @param name  The name of the attribute.
+     * @param value The value of the attribute.
+     */
+    protected static void addAttribute(AttributesImpl ai, String name, Object value) {
+        if ( value != null ) {
+            ai.addAttribute("", name, name, "CDATA", value.toString());
+        }
+    }
+
+    /**
+     * Helper method writing out a string.
+     * @param ch
+     * @param text
+     * @throws SAXException
+     */
+    protected static void text(ContentHandler ch, String text)
+    throws SAXException {
+        if ( text != null ) {
+            final char[] c = text.toCharArray();
+            ch.characters(c, 0, c.length);
+        }
+    }
+
+    /**
+     * A content handler for parsing the component descriptions.
+     *
+     */
+    protected static final class XmlHandler extends DefaultHandler {
+
+        /** The components container. */
+        protected final Components components = new Components();
+
+        /** A reference to the current component. */
+        protected Component currentComponent;
+
+        /** The current service. */
+        protected Service currentService;
+
+        /** Pending property. */
+        protected Property pendingProperty;
+
+        /** Flag for detecting the first element. */
+        protected boolean firstElement = true;
+
+        /** Override namespace. */
+        protected String overrideNamespace;
+
+        public void startElement(String uri, String localName, String name, Attributes attributes)
+        throws SAXException {
+            // according to the spec, the elements should have the namespace,
+            // except when the root element is the "component" element
+            // So we check this for the first element, we receive.
+            if ( this.firstElement ) {
+                this.firstElement = false;
+                if ( localName.equals(COMPONENT) && "".equals(uri) ) {
+                    this.overrideNamespace = NAMESPACE_URI;
+                }
+            }
+
+            if ( this.overrideNamespace != null && "".equals(uri) ) {
+                uri = this.overrideNamespace;
+            }
+
+            if ( NAMESPACE_URI.equals(uri) ) {
+
+                if (localName.equals(COMPONENT)) {
+
+                    this.currentComponent = new Component();
+                    this.currentComponent.setName(attributes.getValue("name"));
+
+                    // enabled attribute is optional
+                    if (attributes.getValue("enabled") != null) {
+                        this.currentComponent.setEnabled(Boolean.valueOf(attributes.getValue("enabled")));
+                    }
+
+                    // immediate attribute is optional
+                    if (attributes.getValue("immediate") != null) {
+                        this.currentComponent.setImmediate(Boolean.valueOf(attributes.getValue("immediate")));
+                    }
+
+                    this.currentComponent.setFactory(attributes.getValue("factory"));
+
+                } else if (localName.equals(IMPLEMENTATION)) {
+                    // Set the implementation class name (mandatory)
+                    final Implementation impl = new Implementation();
+                    this.currentComponent.setImplementation(impl);
+                    impl.setClassname(attributes.getValue("class"));
+
+                } else if (localName.equals(PROPERTY)) {
+                    final Property prop = new Property();
+
+                    prop.setName(attributes.getValue("name"));
+                    prop.setType(attributes.getValue("type"));
+
+                    if ( attributes.getValue("value") != null) {
+                        prop.setValue(attributes.getValue("value"));
+                        this.currentComponent.addProperty(prop);
+                    } else {
+                        // hold the property pending as we have a multi value
+                        this.pendingProperty = prop;
+                    }
+
+                } else if (localName.equals("properties")) {
+
+                    // TODO: implement the properties tag
+
+                } else if (localName.equals(SERVICE)) {
+
+                    this.currentService = new Service();
+
+                    this.currentService.setServicefactory(attributes.getValue("servicefactory"));
+
+                    this.currentComponent.setService(this.currentService);
+
+                } else if (localName.equals(INTERFACE)) {
+                    final Interface interf = new Interface();
+                    this.currentService.addInterface(interf);
+                    interf.setInterfacename(attributes.getValue("interface"));
+
+                } else if (localName.equals(REFERENCE)) {
+                    final Reference ref = new Reference();
+
+                    ref.setName(attributes.getValue("name"));
+                    ref.setInterfacename(attributes.getValue("interface"));
+                    ref.setCardinality(attributes.getValue("cardinality"));
+                    ref.setPolicy(attributes.getValue("policy"));
+                    ref.setTarget(attributes.getValue("target"));
+                    ref.setBind(attributes.getValue("bind"));
+                    ref.setUnbind(attributes.getValue("unbind"));
+
+                    this.currentComponent.addReference(ref);
+                }
+            }
+        }
+
+        /**
+         * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+         */
+        public void endElement(String uri, String localName, String name) throws SAXException {
+            if ( this.overrideNamespace != null && "".equals(uri) ) {
+                uri = this.overrideNamespace;
+            }
+
+            if ( NAMESPACE_URI.equals(uri) ) {
+                if (localName.equals("component") ) {
+                    this.components.addComponent(this.currentComponent);
+                    this.currentComponent = null;
+                } else if (localName.equals("property") && this.pendingProperty != null) {
+                    // now split the value
+                    final String text = this.pendingProperty.getValue();
+                    if ( text != null ) {
+                        final StringTokenizer st = new StringTokenizer(text);
+                        final String[] values = new String[st.countTokens()];
+                        int index = 0;
+                        while ( st.hasMoreTokens() ) {
+                            values[index] = st.nextToken();
+                            index++;
+                        }
+                        this.pendingProperty.setMultiValue(values);
+                    }
+                    this.currentComponent.addProperty(this.pendingProperty);
+                    this.pendingProperty = null;
+                }
+            }
+        }
+
+        /**
+         * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
+         */
+        public void characters(char[] ch, int start, int length) throws SAXException {
+            if ( this.pendingProperty != null ) {
+                final String text = new String(ch, start, length);
+                if ( this.pendingProperty.getValue() != null ) {
+                    this.pendingProperty.setValue(text);
+                } else {
+                    this.pendingProperty.setValue(this.pendingProperty.getValue() + text);
+                }
+            }
+        }
+    }
+}
diff --git a/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/xml/MetaTypeIO.java b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/xml/MetaTypeIO.java
new file mode 100644
index 0000000..02bb4e7
--- /dev/null
+++ b/maven-scr-plugin/src/main/java/org/apache/felix/sandbox/scrplugin/xml/MetaTypeIO.java
@@ -0,0 +1,214 @@
+/*
+ * 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.sandbox.scrplugin.xml;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.felix.sandbox.scrplugin.om.metatype.AttributeDefinition;
+import org.apache.felix.sandbox.scrplugin.om.metatype.Designate;
+import org.apache.felix.sandbox.scrplugin.om.metatype.MTObject;
+import org.apache.felix.sandbox.scrplugin.om.metatype.MetaData;
+import org.apache.felix.sandbox.scrplugin.om.metatype.OCD;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+
+/**
+ * <code>MetaType</code>
+ *
+ * is a helper class to read and write meta type service files.
+ *
+ */
+public class MetaTypeIO {
+
+    private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+
+    public static final String NAMESPACE_URI = "http://www.osgi.org/xmlns/metatype/v1.0.0";
+
+    public static final String PREFIX = "metatype";
+
+    protected static final String METADATA_ELEMENT = "MetaData";
+    protected static final String METADATA_ELEMENT_QNAME = PREFIX + ':' + METADATA_ELEMENT;
+
+    protected static final String OCD_ELEMENT = "OCD";
+    protected static final String OCD_ELEMENT_QNAME = PREFIX + ':' + OCD_ELEMENT;
+
+    protected static final String DESIGNATE_ELEMENT = "Designate";
+    protected static final String DESIGNATE_ELEMENT_QNAME = PREFIX + ':' + DESIGNATE_ELEMENT;
+
+    protected static final String OBJECT_ELEMENT = "Object";
+    protected static final String OBJECT_ELEMENT_QNAME = PREFIX + ':' + OBJECT_ELEMENT;
+
+    protected static final String AD_ELEMENT = "AD";
+    protected static final String AD_ELEMENT_QNAME = PREFIX + ':' + AD_ELEMENT;
+
+    public static void write(MetaData metaData, File file)
+    throws MojoExecutionException {
+        try {
+            FileWriter writer = new FileWriter(file);
+            final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
+            final Transformer transformer = transformerHandler.getTransformer();
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformerHandler.setResult(new StreamResult(writer));
+
+            generateXML(metaData, transformerHandler);
+        } catch (TransformerException e) {
+            throw new MojoExecutionException("Unable to write xml to " + file, e);
+        } catch (SAXException e) {
+            throw new MojoExecutionException("Unable to generate xml for " + file, e);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Unable to write xml to " + file, e);
+        }
+    }
+
+    /**
+     * Generate the xml top level element and start streaming
+     * the meta data.
+     * @param metaData
+     * @param contentHandler
+     * @throws SAXException
+     */
+    protected static void generateXML(MetaData metaData, ContentHandler contentHandler)
+    throws SAXException {
+        contentHandler.startDocument();
+        contentHandler.startPrefixMapping(PREFIX, NAMESPACE_URI);
+
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "localization", metaData.getLocalization());
+
+        contentHandler.startElement(NAMESPACE_URI, METADATA_ELEMENT, METADATA_ELEMENT_QNAME, ai);
+
+        final Iterator i = metaData.getDescriptors().iterator();
+        while ( i.hasNext() ) {
+            final Object obj = i.next();
+            if ( obj instanceof OCD ) {
+                generateXML((OCD)obj, contentHandler);
+            } else {
+                generateXML((Designate)obj, contentHandler);
+            }
+        }
+        // end wrapper element
+        contentHandler.endElement(NAMESPACE_URI, METADATA_ELEMENT, METADATA_ELEMENT_QNAME);
+        contentHandler.endPrefixMapping(PREFIX);
+        contentHandler.endDocument();
+    }
+
+    protected static void generateXML(OCD ocd, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "id", ocd.getId());
+        addAttribute(ai, "name", ocd.getName());
+        addAttribute(ai, "description", ocd.getDescription());
+        contentHandler.startElement(NAMESPACE_URI, OCD_ELEMENT, OCD_ELEMENT_QNAME, ai);
+
+        final Iterator i = ocd.getProperties().iterator();
+        while ( i.hasNext() ) {
+            final AttributeDefinition ad = (AttributeDefinition) i.next();
+            generateXML(ad, contentHandler);
+        }
+
+        contentHandler.endElement(NAMESPACE_URI, OCD_ELEMENT, OCD_ELEMENT_QNAME);
+    }
+
+    protected static void generateXML(AttributeDefinition ad, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "id", ad.getId());
+        addAttribute(ai, "type", ad.getType());
+        if ( ad.getDefaultMultiValue() != null ) {
+            final StringBuffer buf = new StringBuffer();
+            for(int i=0; i<ad.getDefaultMultiValue().length; i++) {
+                if ( i > 0 ) {
+                    buf.append(',');
+                }
+                buf.append(ad.getDefaultMultiValue()[i]);
+            }
+            addAttribute(ai, "default", buf);
+        } else {
+            addAttribute(ai, "default", ad.getDefaultValue());
+        }
+        addAttribute(ai, "name", ad.getName());
+        addAttribute(ai, "description", ad.getDescription());
+        addAttribute(ai, "cardinality", ad.getCardinality());
+        contentHandler.startElement(NAMESPACE_URI, AD_ELEMENT, AD_ELEMENT_QNAME, ai);
+
+        if (ad.getOptions() != null) {
+            for (Iterator oi=ad.getOptions().entrySet().iterator(); oi.hasNext(); ) {
+                final Map.Entry entry = (Map.Entry) oi.next();
+                ai.clear();
+                addAttribute(ai, "value", String.valueOf(entry.getKey()));
+                addAttribute(ai, "label", String.valueOf(entry.getValue()));
+                contentHandler.startElement(NAMESPACE_URI, "Option", PREFIX + ':' + "Option", ai);
+            }
+        }
+
+        contentHandler.endElement(NAMESPACE_URI, AD_ELEMENT, AD_ELEMENT_QNAME);
+    }
+
+    protected static void generateXML(Designate designate, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "pid", designate.getPid());
+        contentHandler.startElement(NAMESPACE_URI, DESIGNATE_ELEMENT, DESIGNATE_ELEMENT_QNAME, ai);
+
+        generateXML(designate.getObject(), contentHandler);
+
+        contentHandler.endElement(NAMESPACE_URI, DESIGNATE_ELEMENT, DESIGNATE_ELEMENT_QNAME);
+    }
+
+    protected static void generateXML(MTObject obj, ContentHandler contentHandler)
+    throws SAXException {
+        final AttributesImpl ai = new AttributesImpl();
+        addAttribute(ai, "ocdref", obj.getOcdref());
+        contentHandler.startElement(NAMESPACE_URI, OBJECT_ELEMENT, OBJECT_ELEMENT_QNAME, ai);
+        contentHandler.endElement(NAMESPACE_URI, OBJECT_ELEMENT, OBJECT_ELEMENT_QNAME);
+    }
+
+    /**
+     * Helper method to add an attribute.
+     * This implementation adds a new attribute with the given name
+     * and value. Before adding the value is checked for non-null.
+     * @param ai    The attributes impl receiving the additional attribute.
+     * @param name  The name of the attribute.
+     * @param value The value of the attribute.
+     */
+    protected static void addAttribute(AttributesImpl ai, String name, Object value) {
+        if ( value != null ) {
+            ai.addAttribute("", name, name, "CDATA", value.toString());
+        }
+    }
+
+}