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());
+ }
+ }
+
+}