FELIX-1684 Refactor plugin for non-Maven reuse. Everything maven specific
is in the o.a.f.scrplugin.mojo package. Everything else has no dependency
on Maven anymore.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@820997 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
index 9dff339..06dab72 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
@@ -21,9 +21,11 @@
import java.io.File;
/**
- * Constants
+ * The <code>Constants</code> interface provides use full constants for various
+ * values used for processing SCR annotations and JavaDoc tags into SCR
+ * descriptors.
*/
-public class Constants {
+public interface Constants {
/** Version 1.0 (R4.1) */
public static final int VERSION_1_0 = 0;
@@ -31,6 +33,11 @@
/** Version 1.1 (R4.2) */
public static final int VERSION_1_1 = 1;
+ /**
+ * The name of the Bundle manifest header providing the list of service
+ * component descriptor files.
+ */
+ public static final String SERVICE_COMPONENT = "Service-Component";
public static final String COMPONENT = "scr.component";
@@ -144,8 +151,8 @@
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;
+ public static final String ABSTRACT_DESCRIPTOR_RELATIVE_PATH = ABSTRACT_DESCRIPTOR_ARCHIV_PATH.replace( '/',
+ File.separatorChar );
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
new file mode 100644
index 0000000..b9e1794
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Components;
+import org.apache.felix.scrplugin.tags.ClassUtil;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.annotation.AnnotationJavaClassDescription;
+import org.apache.felix.scrplugin.tags.annotation.AnnotationTagProviderManager;
+import org.apache.felix.scrplugin.tags.cl.ClassLoaderJavaClassDescription;
+import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
+import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaSource;
+
+/**
+ * The <code>JavaClassDescriptorManager</code>
+ */
+public abstract class JavaClassDescriptorManager {
+
+ /** The maven log. */
+ protected final Log log;
+
+ /** The classloader used to compile the classes. */
+ private final ClassLoader classloader;
+
+ /** A cache containing the java class descriptions hashed by classname. */
+ private final Map<String, JavaClassDescription> javaClassDescriptions = new HashMap<String, JavaClassDescription>();
+
+ /**
+ * Supports mapping of built-in and custom java anntoations to {@link JavaTag} implementations.
+ */
+ private final AnnotationTagProviderManager annotationTagProviderManager;
+
+ /** Parse Javadocs? */
+ private final boolean parseJavadocs;
+
+ /** Process Annotations? */
+ private final boolean processAnnotations;
+
+ /**
+ * Construct a new manager.
+ * @param log
+ * @param project
+ * @param annotationTagProviders List of annotation tag providers
+ * @param excludeString The exclude information for sources
+ * @param parseJavadocs Should the javadocs be parsed?
+ * @param processAnnotations Should the annotations be processed?
+ * @throws SCRDescriptorFailureException
+ * @throws SCRDescriptorException
+ */
+ public JavaClassDescriptorManager(final Log log,
+ final ClassLoader classLoader,
+ final String[] annotationTagProviders,
+ final boolean parseJavadocs,
+ final boolean processAnnotations)
+ throws SCRDescriptorFailureException {
+ this.processAnnotations = processAnnotations;
+ this.parseJavadocs = parseJavadocs;
+ this.log = log;
+ this.annotationTagProviderManager = new AnnotationTagProviderManager(annotationTagProviders);
+ this.classloader = classLoader;
+ ClassUtil.classLoader = this.classloader;
+ }
+
+ /**
+ * Return the log.
+ */
+ public Log getLog() {
+ return this.log;
+ }
+
+ /**
+ * Return the class laoder.
+ */
+ public ClassLoader getClassLoader() {
+ return this.classloader;
+ }
+
+ /**
+ * @return Annotation tag provider manager
+ */
+ public AnnotationTagProviderManager getAnnotationTagProviderManager() {
+ return this.annotationTagProviderManager;
+ }
+
+ /**
+ * Returns <code>true</code> if this class descriptor manager is parsing
+ * JavaDoc tags.
+ */
+ public boolean isParseJavadocs()
+ {
+ return parseJavadocs;
+ }
+
+ /**
+ * Returns <code>true</code> if this class descriptor manager is parsing
+ * Java 5 annotations.
+ */
+ public boolean isProcessAnnotations()
+ {
+ return processAnnotations;
+ }
+
+ protected Components parseServiceComponentDescriptor(InputStream file)
+ throws SCRDescriptorException {
+ final Components list = ComponentDescriptorIO.read(file);
+ return list;
+ }
+
+ /**
+ * Get the absolute path to the target directory where the class files are
+ * compiled to.
+ */
+ public abstract String getOutputDirectory();
+
+
+ /**
+ * Return all source descriptions of this project.
+ * @return All contained java class descriptions.
+ */
+ public JavaClassDescription[] getSourceDescriptions() throws SCRDescriptorException {
+ final JavaClass[] javaClasses = getJavaClassesFromSources();
+ final JavaClassDescription[] descs = new JavaClassDescription[javaClasses.length];
+ for(int i=0; i<javaClasses.length; i++) {
+ descs[i] = this.getJavaClassDescription(javaClasses[i].getFullyQualifiedName());
+ }
+ return descs;
+ }
+
+ /**
+ * Get a java class description for the class.
+ * @param className
+ * @return The java class description.
+ * @throws SCRDescriptorException
+ */
+ public JavaClassDescription getJavaClassDescription(String className)
+ throws SCRDescriptorException {
+ JavaClassDescription result = this.javaClassDescriptions.get(className);
+ if ( result == null ) {
+ this.log.debug("Searching description for: " + className);
+ int index = 0;
+ final JavaClass[] javaClasses = getJavaClassesFromSources();
+ while ( result == null && index < javaClasses.length) {
+ final JavaClass javaClass = javaClasses[index];
+ if ( javaClass.getFullyQualifiedName().equals(className) ) {
+ try {
+ // check for java annotation descriptions - fallback to QDox if none found
+ Class<?> clazz = this.classloader.loadClass(className);
+ if (this.processAnnotations && getAnnotationTagProviderManager().hasScrPluginAnnotation(javaClass)) {
+ this.log.debug("Found java annotation description for: " + className);
+ result = new AnnotationJavaClassDescription(clazz, javaClasses[index], this);
+ } else if ( this.parseJavadocs ) {
+ this.log.debug("Found qdox description for: " + className);
+ result = new QDoxJavaClassDescription(clazz, javaClasses[index], this);
+ }
+ } catch (ClassNotFoundException e) {
+ throw new SCRDescriptorException("Unable to load class " + className);
+ }
+ } else {
+ index++;
+ }
+ }
+ if ( result == null ) {
+ try {
+ this.log.debug("Generating classloader description for: " + className);
+ result = new ClassLoaderJavaClassDescription(this.classloader.loadClass(className), this.getComponentDescriptors().get(className), this);
+ } catch (ClassNotFoundException e) {
+ throw new SCRDescriptorException("Unable to load class " + className);
+ }
+ }
+ this.javaClassDescriptions.put(className, result);
+ }
+ return result;
+ }
+
+
+ protected abstract JavaSource[] getSources() throws SCRDescriptorException;
+ protected abstract Map<String, Component> getComponentDescriptors() throws SCRDescriptorException;
+
+
+ /**
+ * Get a list of all {@link JavaClass} definitions four all source files (including nested/inner classes)
+ * @return List of {@link JavaClass} definitions
+ */
+ private JavaClass[] getJavaClassesFromSources() throws SCRDescriptorException {
+ final JavaSource[] sources = this.getSources();
+ final List<JavaClass> classes = new ArrayList<JavaClass>();
+ for(int i=0; i<sources.length; i++) {
+ for(int j=0; j<sources[i].getClasses().length; j++) {
+ final JavaClass clazz = sources[i].getClasses()[j];
+ classes.add(clazz);
+ for (int k=0; k<clazz.getNestedClasses().length; k++) {
+ final JavaClass nestedClass = clazz.getNestedClasses()[k];
+ classes.add(nestedClass);
+ }
+ }
+ }
+ return classes.toArray(new JavaClass[classes.size()]);
+ }
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java
new file mode 100644
index 0000000..3398928
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+
+/**
+ * This interface supplies the API for providing feedback to the user from
+ * SCR descriptor generation process using whatever means is implemented. There
+ * should be no big surprises here.
+ */
+public interface Log
+{
+ /**
+ * @return true if the <b>debug</b> error level is enabled
+ */
+ boolean isDebugEnabled();
+
+
+ /**
+ * Send a message to the user in the <b>debug</b> error level.
+ *
+ * @param content
+ */
+ void debug( String content );
+
+
+ /**
+ * Send a message (and accompanying exception) to the user in the <b>debug</b> error level.
+ * <br/>
+ * The error's stacktrace will be output when this error level is enabled.
+ *
+ * @param content
+ * @param error
+ */
+ void debug( String content, Throwable error );
+
+
+ /**
+ * Send an exception to the user in the <b>debug</b> error level.
+ * <br/>
+ * The stack trace for this exception will be output when this error level is enabled.
+ *
+ * @param error
+ */
+ void debug( Throwable error );
+
+
+ /**
+ * @return true if the <b>info</b> error level is enabled
+ */
+ boolean isInfoEnabled();
+
+
+ /**
+ * Send a message to the user in the <b>info</b> error level.
+ *
+ * @param content
+ */
+ void info( String content );
+
+
+ /**
+ * Send a message (and accompanying exception) to the user in the <b>info</b> error level.
+ * <br/>
+ * The error's stacktrace will be output when this error level is enabled.
+ *
+ * @param content
+ * @param error
+ */
+ void info( String content, Throwable error );
+
+
+ /**
+ * Send an exception to the user in the <b>info</b> error level.
+ * <br/>
+ * The stack trace for this exception will be output when this error level is enabled.
+ *
+ * @param error
+ */
+ void info( Throwable error );
+
+
+ /**
+ * @return true if the <b>warn</b> error level is enabled
+ */
+ boolean isWarnEnabled();
+
+
+ /**
+ * Send a message to the user in the <b>warn</b> error level.
+ *
+ * @param content
+ */
+ void warn( String content );
+
+
+ /**
+ * Send a message (and accompanying exception) to the user in the <b>warn</b> error level.
+ * <br/>
+ * The error's stacktrace will be output when this error level is enabled.
+ *
+ * @param content
+ * @param error
+ */
+ void warn( String content, Throwable error );
+
+
+ /**
+ * Send an exception to the user in the <b>warn</b> error level.
+ * <br/>
+ * The stack trace for this exception will be output when this error level is enabled.
+ *
+ * @param error
+ */
+ void warn( Throwable error );
+
+
+ /**
+ * @return true if the <b>error</b> error level is enabled
+ */
+ boolean isErrorEnabled();
+
+
+ /**
+ * Send a message to the user in the <b>error</b> error level.
+ *
+ * @param content
+ */
+ void error( String content );
+
+
+ /**
+ * Send a message (and accompanying exception) to the user in the <b>error</b> error level.
+ * <br/>
+ * The error's stacktrace will be output when this error level is enabled.
+ *
+ * @param content
+ * @param error
+ */
+ void error( String content, Throwable error );
+
+
+ /**
+ * Send an exception to the user in the <b>error</b> error level.
+ * <br/>
+ * The stack trace for this exception will be output when this error level is enabled.
+ *
+ * @param error
+ */
+ void error( Throwable error );
+}
\ No newline at end of file
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
new file mode 100644
index 0000000..13fa575
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+public class SCRDescriptorException extends Exception
+{
+
+ private static final long serialVersionUID = 1L;
+
+ public SCRDescriptorException(String message) {
+ super(message);
+ }
+
+ public SCRDescriptorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorFailureException.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorFailureException.java
new file mode 100644
index 0000000..4b2ce6a
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorFailureException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+
+public class SCRDescriptorFailureException extends Exception
+{
+
+ private static final long serialVersionUID = 1L;
+
+
+ public SCRDescriptorFailureException( String message )
+ {
+ super( message );
+ }
+
+
+ public SCRDescriptorFailureException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
new file mode 100644
index 0000000..35155ca
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
@@ -0,0 +1,862 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.helper.PropertyHandler;
+import org.apache.felix.scrplugin.helper.StringUtils;
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Components;
+import org.apache.felix.scrplugin.om.Implementation;
+import org.apache.felix.scrplugin.om.Interface;
+import org.apache.felix.scrplugin.om.Property;
+import org.apache.felix.scrplugin.om.Reference;
+import org.apache.felix.scrplugin.om.Service;
+import org.apache.felix.scrplugin.om.metatype.Designate;
+import org.apache.felix.scrplugin.om.metatype.MTObject;
+import org.apache.felix.scrplugin.om.metatype.MetaData;
+import org.apache.felix.scrplugin.om.metatype.OCD;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.JavaClassDescriptionInheritanceComparator;
+import org.apache.felix.scrplugin.tags.JavaField;
+import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.tags.ModifiableJavaClassDescription;
+import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
+import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;
+import org.apache.felix.scrplugin.xml.MetaTypeIO;
+import org.osgi.service.metatype.MetaTypeService;
+
+/**
+ * The <code>SCRDescriptorGenerator</code> class does the hard work of
+ * generating the SCR descriptors. This class is being instantiated and
+ * configured by clients and the {@link #execute()} method called to generate
+ * the descriptor files.
+ */
+public class SCRDescriptorGenerator
+{
+
+ private final Log logger;
+
+ private File outputDirectory = null;
+
+ private JavaClassDescriptorManager descriptorManager;
+
+ private String finalName = "serviceComponents.xml";
+
+ private String metaTypeName = "metatype.xml";
+
+ private boolean generateAccessors = true;
+
+ protected boolean strictMode = false;
+
+ private Map<String, String> properties = new HashMap<String, String>();
+
+ private String specVersion = null;
+
+
+ public SCRDescriptorGenerator( Log logger )
+ {
+ this.logger = logger;
+ }
+
+
+ //---------- property setup (write-only for now)
+
+ public void setOutputDirectory( File outputDirectory )
+ {
+ this.outputDirectory = outputDirectory;
+ }
+
+
+ /**
+ * Sets the class path used for resolving tags and annotations. The first
+ * entry in the class path is assumed to be the build target location.
+ */
+ public void setDescriptorManager( JavaClassDescriptorManager descriptorManager )
+ {
+ this.descriptorManager = descriptorManager;
+ }
+
+ public void setFinalName( String finalName )
+ {
+ this.finalName = finalName;
+ }
+
+
+ public void setMetaTypeName( String metaTypeName )
+ {
+ this.metaTypeName = metaTypeName;
+ }
+
+
+ public void setGenerateAccessors( boolean generateAccessors )
+ {
+ this.generateAccessors = generateAccessors;
+ }
+
+
+ public void setStrictMode( boolean strictMode )
+ {
+ this.strictMode = strictMode;
+ }
+
+
+ public void setProperties( Map<String, String> properties )
+ {
+ this.properties = new HashMap<String, String>( properties );
+ }
+
+
+ public void setSpecVersion( String specVersion )
+ {
+ this.specVersion = specVersion;
+ }
+
+ //---------- descriptor generation
+
+ public boolean execute() throws SCRDescriptorException, SCRDescriptorFailureException
+ {
+ this.logger.debug( "Starting SCRDescriptorMojo...." );
+ this.logger.debug( "..generating accessors: " + this.generateAccessors );
+ this.logger.debug( "..parsing javadocs: " + this.descriptorManager.isParseJavadocs() );
+ this.logger.debug( "..processing annotations: " + this.descriptorManager.isProcessAnnotations() );
+
+ // check speck version configuration
+ int specVersion = Constants.VERSION_1_0;
+ if ( this.specVersion != null )
+ {
+ if ( this.specVersion.equals( "1.1" ) )
+ {
+ specVersion = Constants.VERSION_1_1;
+ }
+ else if ( !this.specVersion.equals( "1.0" ) )
+ {
+ throw new SCRDescriptorException( "Unknown configuration for spec version: " + this.specVersion );
+ }
+ }
+ else
+ {
+ this.logger.debug( "..auto detecting spec version" );
+ }
+ final IssueLog iLog = new IssueLog( this.strictMode );
+
+ final MetaData metaData = new MetaData();
+ metaData.setLocalization( MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype" );
+
+ // iterate through all source classes and check for component tag
+ final JavaClassDescription[] javaSources = descriptorManager.getSourceDescriptions();
+ Arrays.sort( javaSources, new JavaClassDescriptionInheritanceComparator() );
+
+ final List<Component> scannedComponents = new ArrayList<Component>();
+ for ( int i = 0; i < javaSources.length; i++ )
+ {
+ this.logger.debug( "Testing source " + javaSources[i].getName() );
+ final JavaTag tag = javaSources[i].getTagByName( Constants.COMPONENT );
+ if ( tag != null )
+ {
+ this.logger.debug( "Processing service class " + javaSources[i].getName() );
+ // check if there is more than one component tag!
+ if ( javaSources[i].getTagsByName( Constants.COMPONENT, false ).length > 1 )
+ {
+ iLog.addError( "Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT
+ + " tag." + " Merge the tags to a single tag." );
+ }
+ else
+ {
+ final Component comp = this.createComponent( javaSources[i], tag, metaData, iLog );
+ if ( comp.getSpecVersion() > specVersion )
+ {
+ // if a spec version has been configured and a component requires a higher
+ // version, this is considered an error!
+ if ( this.specVersion != null )
+ {
+ String v = "1.0";
+ if ( comp.getSpecVersion() == Constants.VERSION_1_1 )
+ {
+ v = "1.1";
+ }
+ iLog.addError( "Component " + comp + " requires spec version " + v
+ + " but plugin is configured to use version " + this.specVersion );
+ }
+ specVersion = comp.getSpecVersion();
+ }
+ scannedComponents.add( comp );
+ }
+ }
+ }
+ this.logger.debug( "..generating descriptor for spec version: " + this.specVersion );
+
+ // now check for abstract components and fill components objects
+ final Components components = new Components();
+ final Components abstractComponents = new Components();
+ components.setSpecVersion( specVersion );
+ abstractComponents.setSpecVersion( specVersion );
+
+ for ( final Component comp : scannedComponents )
+ {
+ final int errorCount = iLog.getNumberOfErrors();
+ // before we can validate we should check the references for bind/unbind method
+ // in order to create them if possible
+
+ for ( final Reference ref : comp.getReferences() )
+ {
+ // if this is a field with a single cardinality,
+ // we look for the bind/unbind methods
+ // and create them if they are not availabe
+ if ( this.generateAccessors && !ref.isLookupStrategy() )
+ {
+ if ( ref.getJavaTag().getField() != null
+ && comp.getJavaClassDescription() instanceof ModifiableJavaClassDescription )
+ {
+ if ( ref.getCardinality().equals( "0..1" ) || ref.getCardinality().equals( "1..1" ) )
+ {
+ final String bindValue = ref.getBind();
+ final String unbindValue = ref.getUnbind();
+ final String name = ref.getName();
+ final String type = ref.getInterfacename();
+
+ boolean createBind = false;
+ boolean createUnbind = false;
+ // Only create method if no bind name has been specified
+ if ( bindValue == null && ref.findMethod( specVersion, "bind" ) == null )
+ {
+ // create bind method
+ createBind = true;
+ }
+ if ( unbindValue == null && ref.findMethod( specVersion, "unbind" ) == null )
+ {
+ // create unbind method
+ createUnbind = true;
+ }
+ if ( createBind || createUnbind )
+ {
+ ( ( ModifiableJavaClassDescription ) comp.getJavaClassDescription() ).addMethods( name,
+ type, createBind, createUnbind );
+ }
+ }
+ }
+ }
+ }
+ comp.validate( specVersion, iLog );
+ // ignore component if it has errors
+ if ( iLog.getNumberOfErrors() == errorCount )
+ {
+ if ( !comp.isDs() )
+ {
+ logger.debug( "Ignoring descriptor " + comp );
+ }
+ else if ( comp.isAbstract() )
+ {
+ this.logger.debug( "Adding abstract descriptor " + comp );
+ abstractComponents.addComponent( comp );
+ }
+ else
+ {
+ this.logger.debug( "Adding descriptor " + comp );
+ components.addComponent( comp );
+ abstractComponents.addComponent( comp );
+ }
+ }
+ }
+
+ // log issues
+ logMessages( iLog );
+
+ // after checking all classes, throw if there were any failures
+ if ( iLog.hasErrors() )
+ {
+ throw new SCRDescriptorFailureException( "SCR Descriptor parsing had failures (see log)" );
+ }
+
+ boolean addResources = false;
+ // write meta type info if there is a file name
+ if ( !StringUtils.isEmpty( this.metaTypeName ) )
+ {
+ File mtFile = new File( this.outputDirectory, "OSGI-INF" + File.separator + "metatype" + File.separator
+ + this.metaTypeName );
+ final int size = metaData.getOCDs().size() + metaData.getDesignates().size();
+ if ( size > 0 )
+ {
+ this.logger.info( "Generating " + size + " MetaType Descriptors to " + mtFile );
+ mtFile.getParentFile().mkdirs();
+ MetaTypeIO.write( metaData, mtFile );
+ addResources = true;
+ }
+ else
+ {
+ if ( mtFile.exists() )
+ {
+ mtFile.delete();
+ }
+ }
+
+ }
+ else
+ {
+ this.logger.info( "Meta type file name is not set: meta type info is not written." );
+ }
+
+ // if we have descriptors, write them in our scr private file (for component inheritance)
+ final File adFile = new File( this.outputDirectory, Constants.ABSTRACT_DESCRIPTOR_RELATIVE_PATH );
+ if ( !abstractComponents.getComponents().isEmpty() )
+ {
+ this.logger.info( "Writing abstract service descriptor " + adFile + " with "
+ + abstractComponents.getComponents().size() + " entries." );
+ adFile.getParentFile().mkdirs();
+ ComponentDescriptorIO.write( abstractComponents, adFile, true );
+ addResources = true;
+ }
+ else
+ {
+ this.logger.debug( "No abstract SCR Descriptors found in project." );
+ // remove file
+ if ( adFile.exists() )
+ {
+ this.logger.debug( "Removing obsolete abstract service descriptor " + adFile );
+ adFile.delete();
+ }
+ }
+
+ // check descriptor file
+ final File descriptorFile = StringUtils.isEmpty( this.finalName ) ? null : new File( new File(
+ this.outputDirectory, "OSGI-INF" ), this.finalName );
+
+ // terminate if there is nothing else to write
+ if ( components.getComponents().isEmpty() )
+ {
+ this.logger.debug( "No SCR Descriptors found in project." );
+ // remove file if it exists
+ if ( descriptorFile != null && descriptorFile.exists() )
+ {
+ this.logger.debug( "Removing obsolete service descriptor " + descriptorFile );
+ descriptorFile.delete();
+ }
+ }
+ else
+ {
+ if ( descriptorFile == null )
+ {
+ throw new SCRDescriptorFailureException( "Descriptor file name must not be empty." );
+ }
+
+ // finally the descriptors have to be written ....
+ descriptorFile.getParentFile().mkdirs(); // ensure parent dir
+
+ this.logger.info( "Generating " + components.getComponents().size() + " Service Component Descriptors to "
+ + descriptorFile );
+
+ ComponentDescriptorIO.write( components, descriptorFile, false );
+ addResources = true;
+ }
+
+ return addResources;
+ }
+
+
+ /**
+ * Create a component for the java class description.
+ * @param description
+ * @return The generated component descriptor or null if any error occurs.
+ * @throws SCRDescriptorException
+ */
+ protected Component createComponent( JavaClassDescription description, JavaTag componentTag, MetaData metaData,
+ final IssueLog iLog ) throws SCRDescriptorException
+ {
+ // create a new component
+ final Component component = new Component( componentTag );
+
+ // set implementation
+ component.setImplementation( new Implementation( description.getName() ) );
+
+ final OCD ocd = this.doComponent( componentTag, component, metaData, iLog );
+
+ boolean inherited = getBoolean( componentTag, Constants.COMPONENT_INHERIT, true );
+ this.doServices( description.getTagsByName( Constants.SERVICE, inherited ), component, description );
+
+ // collect references from class tags and fields
+ final Map<String, Object[]> references = new HashMap<String, Object[]>();
+ // Utility handler for propertie
+ final PropertyHandler propertyHandler = new PropertyHandler( component, ocd );
+
+ JavaClassDescription currentDescription = description;
+ do
+ {
+ // properties
+ final JavaTag[] props = currentDescription.getTagsByName( Constants.PROPERTY, false );
+ for ( int i = 0; i < props.length; i++ )
+ {
+ propertyHandler.testProperty( props[i], null, description == currentDescription );
+ }
+
+ // references
+ final JavaTag[] refs = currentDescription.getTagsByName( Constants.REFERENCE, false );
+ for ( int i = 0; i < refs.length; i++ )
+ {
+ this.testReference( references, refs[i], null, description == currentDescription );
+ }
+
+ // fields
+ final JavaField[] fields = currentDescription.getFields();
+ for ( int i = 0; i < fields.length; i++ )
+ {
+ JavaTag tag = fields[i].getTagByName( Constants.REFERENCE );
+ if ( tag != null )
+ {
+ this.testReference( references, tag, fields[i].getName(), description == currentDescription );
+ }
+
+ propertyHandler.handleField( fields[i], description == currentDescription );
+ }
+
+ currentDescription = currentDescription.getSuperClass();
+ }
+ while ( inherited && currentDescription != null );
+
+ // process properties
+ propertyHandler.processProperties( this.properties, iLog );
+
+ // process references
+ final Iterator<Map.Entry<String, Object[]>> refIter = references.entrySet().iterator();
+ while ( refIter.hasNext() )
+ {
+ final Map.Entry<String, Object[]> entry = refIter.next();
+ final String refName = entry.getKey();
+ final Object[] values = entry.getValue();
+ final JavaTag tag = ( JavaTag ) values[0];
+ this.doReference( tag, refName, component, values[1].toString() );
+ }
+
+ // pid handling
+ final boolean createPid = getBoolean( componentTag, Constants.COMPONENT_CREATE_PID, true );
+ if ( createPid )
+ {
+ // check for an existing pid first
+ boolean found = false;
+ final Iterator<Property> iter = component.getProperties().iterator();
+ while ( !found && iter.hasNext() )
+ {
+ final Property prop = iter.next();
+ found = org.osgi.framework.Constants.SERVICE_PID.equals( prop.getName() );
+ }
+ if ( !found )
+ {
+ final Property pid = new Property();
+ component.addProperty( pid );
+ pid.setName( org.osgi.framework.Constants.SERVICE_PID );
+ pid.setValue( component.getName() );
+ }
+ }
+ return component;
+ }
+
+
+ /**
+ * Fill the component object with the information from the tag.
+ * @param tag
+ * @param component
+ */
+ protected OCD doComponent( JavaTag tag, Component component, MetaData metaData, final IssueLog iLog )
+ {
+
+ // check if this is an abstract definition
+ final String abstractType = tag.getNamedParameter( Constants.COMPONENT_ABSTRACT );
+ if ( abstractType != null )
+ {
+ component.setAbstract( "yes".equalsIgnoreCase( abstractType ) || "true".equalsIgnoreCase( abstractType ) );
+ }
+ else
+ {
+ // default true for abstract classes, false otherwise
+ component.setAbstract( tag.getJavaClassDescription().isAbstract() );
+ }
+
+ // check if this is a definition to ignore
+ final String ds = tag.getNamedParameter( Constants.COMPONENT_DS );
+ component.setDs( ( ds == null ) ? true : ( "yes".equalsIgnoreCase( ds ) || "true".equalsIgnoreCase( ds ) ) );
+
+ String name = tag.getNamedParameter( Constants.COMPONENT_NAME );
+ component.setName( StringUtils.isEmpty( name ) ? component.getImplementation().getClassame() : name );
+
+ component.setEnabled( Boolean.valueOf( getBoolean( tag, Constants.COMPONENT_ENABLED, true ) ) );
+ component.setFactory( tag.getNamedParameter( Constants.COMPONENT_FACTORY ) );
+
+ // FELIX-593: immediate attribute does not default to true all the
+ // times hence we only set it if declared in the tag
+ if ( tag.getNamedParameter( Constants.COMPONENT_IMMEDIATE ) != null )
+ {
+ component.setImmediate( Boolean.valueOf( getBoolean( tag, Constants.COMPONENT_IMMEDIATE, true ) ) );
+ }
+
+ // check for V1.1 attributes: configuration policy
+ if ( tag.getNamedParameter( Constants.COMPONENT_CONFIG_POLICY ) != null )
+ {
+ component.setSpecVersion( Constants.VERSION_1_1 );
+ component.setConfigurationPolicy( tag.getNamedParameter( Constants.COMPONENT_CONFIG_POLICY ) );
+ }
+ // check for V1.1 attributes: activate, deactivate
+ if ( tag.getNamedParameter( Constants.COMPONENT_ACTIVATE ) != null )
+ {
+ component.setSpecVersion( Constants.VERSION_1_1 );
+ component.setActivate( tag.getNamedParameter( Constants.COMPONENT_ACTIVATE ) );
+ }
+ if ( tag.getNamedParameter( Constants.COMPONENT_DEACTIVATE ) != null )
+ {
+ component.setSpecVersion( Constants.VERSION_1_1 );
+ component.setDeactivate( tag.getNamedParameter( Constants.COMPONENT_DEACTIVATE ) );
+ }
+ if ( tag.getNamedParameter( Constants.COMPONENT_MODIFIED ) != null )
+ {
+ component.setSpecVersion( Constants.VERSION_1_1 );
+ component.setModified( tag.getNamedParameter( Constants.COMPONENT_MODIFIED ) );
+ }
+
+ // 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() );
+
+ // factory pid
+ final String setFactoryPidValue = tag.getNamedParameter( Constants.COMPONENT_SET_METATYPE_FACTORY_PID );
+ final boolean setFactoryPid = setFactoryPidValue != null
+ && ( "yes".equalsIgnoreCase( setFactoryPidValue ) || "true".equalsIgnoreCase( setFactoryPidValue ) );
+ if ( setFactoryPid )
+ {
+ if ( component.getFactory() == null )
+ {
+ designate.setFactoryPid( component.getName() );
+ }
+ else
+ {
+ iLog.addWarning( "Component factory " + component.getName()
+ + " should not set metatype factory pid." );
+ }
+ }
+ // 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
+ * @throws SCRDescriptorException
+ */
+ protected void doServices( JavaTag[] services, Component component, JavaClassDescription description )
+ throws SCRDescriptorException
+ {
+ // no services, hence certainly no service factory
+ if ( services == null || services.length == 0 )
+ {
+ return;
+ }
+
+ final Service service = new Service();
+ component.setService( service );
+ boolean serviceFactory = false;
+ for ( int i = 0; i < services.length; i++ )
+ {
+ final String name = services[i].getNamedParameter( Constants.SERVICE_INTERFACE );
+ if ( StringUtils.isEmpty( name ) )
+ {
+
+ this.addInterfaces( service, services[i], description );
+ }
+ else
+ {
+ String interfaceName = name;
+ // check if the value points to a class/interface
+ // and search through the imports
+ // but only for local services
+ if ( description instanceof QDoxJavaClassDescription )
+ {
+ final JavaClassDescription serviceClass = description.getReferencedClass( name );
+ if ( serviceClass == null )
+ {
+ throw new SCRDescriptorException( "Interface '" + name + "' in class " + description.getName()
+ + " does not point to a valid class/interface." );
+ }
+ interfaceName = serviceClass.getName();
+ }
+ final Interface interf = new Interface( services[i] );
+ interf.setInterfacename( interfaceName );
+ service.addInterface( interf );
+ }
+
+ serviceFactory |= getBoolean( services[i], Constants.SERVICE_FACTORY, false );
+ }
+
+ service.setServicefactory( serviceFactory );
+ }
+
+
+ /**
+ * Recursively add interfaces to the service.
+ */
+ protected void addInterfaces( final Service service, final JavaTag serviceTag,
+ final JavaClassDescription description ) throws SCRDescriptorException
+ {
+ if ( description != null )
+ {
+ JavaClassDescription[] interfaces = description.getImplementedInterfaces();
+ for ( int j = 0; j < interfaces.length; j++ )
+ {
+ final Interface interf = new Interface( serviceTag );
+ interf.setInterfacename( interfaces[j].getName() );
+ service.addInterface( interf );
+ // recursivly add interfaces implemented by this interface
+ this.addInterfaces( service, serviceTag, interfaces[j] );
+ }
+
+ // try super class
+ this.addInterfaces( service, serviceTag, description.getSuperClass() );
+ }
+ }
+
+
+ /**
+ * Test a newly found reference
+ * @param references
+ * @param reference
+ * @param defaultName
+ * @param isInspectedClass
+ * @throws SCRDescriptorException
+ */
+ protected void testReference( Map<String, Object[]> references, JavaTag reference, String defaultName,
+ boolean isInspectedClass ) throws SCRDescriptorException
+ {
+ final String refName = this.getReferenceName( reference, defaultName );
+
+ if ( refName != null )
+ {
+ if ( references.containsKey( refName ) )
+ {
+ // if the current class is the class we are currently inspecting, we
+ // have found a duplicate definition
+ if ( isInspectedClass )
+ {
+ throw new SCRDescriptorException( "Duplicate definition for reference " + refName + " in class "
+ + reference.getJavaClassDescription().getName() );
+ }
+ }
+ else
+ {
+ // ensure interface
+ String type = reference.getNamedParameter( Constants.REFERENCE_INTERFACE );
+ if ( StringUtils.isEmpty( type ) )
+ {
+ if ( reference.getField() != null )
+ {
+ type = reference.getField().getType();
+ }
+ else
+ {
+ throw new SCRDescriptorException( "Interface missing for reference " + refName + " in class "
+ + reference.getJavaClassDescription().getName() );
+ }
+ }
+ else if ( isInspectedClass )
+ {
+ // check if the value points to a class/interface
+ // and search through the imports
+ final JavaClassDescription serviceClass = reference.getJavaClassDescription().getReferencedClass(
+ type );
+ if ( serviceClass == null )
+ {
+ throw new SCRDescriptorException( "Interface '" + type + "' in class "
+ + reference.getJavaClassDescription().getName()
+ + " does not point to a valid class/interface." );
+ }
+ type = serviceClass.getName();
+ }
+ references.put( refName, new Object[]
+ { reference, type } );
+ }
+ }
+ }
+
+
+ protected String getReferenceName( JavaTag reference, String defaultName ) throws SCRDescriptorException
+ {
+ String name = reference.getNamedParameter( Constants.REFERENCE_NAME );
+ if ( !StringUtils.isEmpty( name ) )
+ {
+ return name;
+ }
+ name = reference.getNamedParameter( Constants.REFERENCE_NAME_REF );
+ if ( !StringUtils.isEmpty( name ) )
+ {
+ final JavaField refField = this.getReferencedField( reference, name );
+ final String[] values = refField.getInitializationExpression();
+ if ( values == null || values.length == 0 )
+ {
+ throw new SCRDescriptorException( "Referenced field for " + name
+ + " has no values for a reference name." );
+ }
+ if ( values.length > 1 )
+ {
+ throw new SCRDescriptorException( "Referenced field " + name
+ + " has more than one value for a reference name." );
+ }
+ name = values[0];
+ }
+
+ return defaultName;
+ }
+
+
+ protected JavaField getReferencedField( final JavaTag tag, String ref ) throws SCRDescriptorException
+ {
+ int classSep = ref.lastIndexOf( '.' );
+ JavaField field = null;
+ if ( classSep == -1 )
+ {
+ // local variable
+ field = tag.getJavaClassDescription().getFieldByName( ref );
+ }
+ if ( field == null )
+ {
+ field = tag.getJavaClassDescription().getExternalFieldByName( ref );
+ }
+ if ( field == null )
+ {
+ throw new SCRDescriptorException( "Reference references unknown field " + ref + " in class "
+ + tag.getJavaClassDescription().getName() );
+ }
+ return field;
+ }
+
+
+ /**
+ * @param reference
+ * @param defaultName
+ * @param component
+ */
+ protected void doReference( JavaTag reference, String name, Component component, String type )
+ throws SCRDescriptorException
+ {
+ final Reference ref = new Reference( reference, component.getJavaClassDescription() );
+ ref.setName( name );
+ ref.setInterfacename( type );
+ ref.setCardinality( reference.getNamedParameter( Constants.REFERENCE_CARDINALITY ) );
+ if ( ref.getCardinality() == null )
+ {
+ ref.setCardinality( "1..1" );
+ }
+ ref.setPolicy( reference.getNamedParameter( Constants.REFERENCE_POLICY ) );
+ if ( ref.getPolicy() == null )
+ {
+ ref.setPolicy( "static" );
+ }
+ ref.setTarget( reference.getNamedParameter( Constants.REFERENCE_TARGET ) );
+ final String bindValue = reference.getNamedParameter( Constants.REFERENCE_BIND );
+ if ( bindValue != null )
+ {
+ ref.setBind( bindValue );
+ }
+ final String unbindValue = reference.getNamedParameter( Constants.REFERENCE_UNDBIND );
+ if ( unbindValue != null )
+ {
+ ref.setUnbind( unbindValue );
+ }
+ final String isChecked = reference.getNamedParameter( Constants.REFERENCE_CHECKED );
+ if ( isChecked != null )
+ {
+ ref.setChecked( Boolean.valueOf( isChecked ).booleanValue() );
+ }
+ final String strategy = reference.getNamedParameter( Constants.REFERENCE_STRATEGY );
+ if ( strategy != null )
+ {
+ ref.setStrategy( strategy );
+ }
+
+ component.addReference( ref );
+ }
+
+
+ public static boolean getBoolean( JavaTag tag, String name, boolean defaultValue )
+ {
+ String value = tag.getNamedParameter( name );
+ return ( value == null ) ? defaultValue : Boolean.valueOf( value ).booleanValue();
+ }
+
+
+ private void logMessages( final IssueLog iLog )
+ {
+ final Log log = logger;
+
+ // now log warnings and errors (warnings first)
+ // in strict mode everything is an error!
+ final Iterator<String> warnings = iLog.getWarnings();
+ while ( warnings.hasNext() )
+ {
+ if ( strictMode )
+ {
+ log.error( warnings.next() );
+ }
+ else
+ {
+ log.warn( warnings.next() );
+ }
+ }
+
+ final Iterator<String> errors = iLog.getErrors();
+ while ( errors.hasNext() )
+ {
+ log.error( errors.next() );
+ }
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
deleted file mode 100644
index 2662880..0000000
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.scrplugin;
-
-import java.io.File;
-import java.util.*;
-
-import org.apache.felix.scrplugin.om.*;
-import org.apache.felix.scrplugin.om.metatype.*;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
-import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;
-import org.apache.felix.scrplugin.xml.MetaTypeIO;
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.*;
-import org.apache.maven.project.MavenProject;
-import org.codehaus.plexus.util.StringUtils;
-import org.osgi.service.metatype.MetaTypeService;
-
-/**
- * The <code>SCRDescriptorMojo</code>
- * generates a service descriptor file based on annotations found in the sources.
- *
- * @goal scr
- * @phase process-classes
- * @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;
-
- /**
- * This flag controls the generation of the bind/unbind methods.
- * @parameter default-value="true"
- */
- private boolean generateAccessors;
-
- /**
- * This flag controls whether the javadoc source code will be scanned for
- * tags.
- * @parameter default-value="true"
- */
- protected boolean parseJavadoc;
-
- /**
- * This flag controls whether the annotations in the sources will be
- * processed.
- * @parameter default-value="true"
- */
- protected boolean processAnnotations;
-
- /**
- * In strict mode the plugin even fails on warnings.
- * @parameter default-value="false"
- */
- protected boolean strictMode;
-
- /**
- * The comma separated list of tokens to exclude when processing sources.
- *
- * @parameter alias="excludes"
- */
- private String sourceExcludes;
-
- /**
- * Predefined properties.
- *
- * @parameter
- */
- private Map<String, String> properties = new HashMap<String, String>();
-
- /**
- * Allows to define additional implementations of the interface
- * {@link org.apache.felix.scrplugin.tags.annotation.AnnotationTagProvider}
- * that provide mappings from custom annotations to
- * {@link org.apache.felix.scrplugin.tags.JavaTag} implementations.
- * List of full qualified class file names.
- *
- * @parameter
- */
- private String[] annotationTagProviders = {};
-
- /**
- * The version of the DS spec this plugin generates a descriptor for.
- * By default the version is detected by the used tags.
- * @parameter
- */
- private String specVersion;
-
- /**
- * @see org.apache.maven.plugin.AbstractMojo#execute()
- */
- public void execute() throws MojoExecutionException, MojoFailureException {
- this.getLog().debug("Starting SCRDescriptorMojo....");
- this.getLog().debug("..generating accessors: " + this.generateAccessors);
- this.getLog().debug("..parsing javadocs: " + this.parseJavadoc);
- this.getLog().debug("..processing annotations: " + this.processAnnotations);
-
- // check speck version configuration
- int specVersion = Constants.VERSION_1_0;
- if ( this.specVersion != null ) {
- if ( this.specVersion.equals("1.1") ) {
- specVersion = Constants.VERSION_1_1;
- } else if ( !this.specVersion.equals("1.0") ) {
- throw new MojoExecutionException("Unknown configuration for spec version: " + this.specVersion);
- }
- } else {
- this.getLog().debug("..auto detecting spec version");
- }
- JavaClassDescriptorManager jManager = new JavaClassDescriptorManager(this.getLog(),
- this.project,
- this.annotationTagProviders,
- this.sourceExcludes,
- this.parseJavadoc,
- this.processAnnotations);
- final IssueLog iLog = new IssueLog(this.strictMode);
-
- final MetaData metaData = new MetaData();
- metaData.setLocalization(MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype");
-
- // iterate through all source classes and check for component tag
- final JavaClassDescription[] javaSources = jManager.getSourceDescriptions();
- Arrays.sort(javaSources, new JavaClassDescriptionInheritanceComparator());
-
- final List<Component> scannedComponents = new ArrayList<Component>();
- 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());
- // check if there is more than one component tag!
- if ( javaSources[i].getTagsByName(Constants.COMPONENT, false).length > 1 ) {
- iLog.addError("Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT + " tag." +
- " Merge the tags to a single tag.");
- } else {
- final Component comp = this.createComponent(javaSources[i], tag, metaData, iLog);
- if ( comp.getSpecVersion() > specVersion ) {
- // if a spec version has been configured and a component requires a higher
- // version, this is considered an error!
- if ( this.specVersion != null ) {
- String v = "1.0";
- if ( comp.getSpecVersion() == Constants.VERSION_1_1 ) {
- v = "1.1";
- }
- iLog.addError("Component " + comp + " requires spec version " + v + " but plugin is configured to use version " + this.specVersion);
- }
- specVersion = comp.getSpecVersion();
- }
- scannedComponents.add(comp);
- }
- }
- }
- this.getLog().debug("..generating descriptor for spec version: " + this.specVersion);
-
- // now check for abstract components and fill components objects
- final Components components = new Components();
- final Components abstractComponents = new Components();
- components.setSpecVersion(specVersion);
- abstractComponents.setSpecVersion(specVersion);
-
- for(final Component comp : scannedComponents ) {
- final int errorCount = iLog.getNumberOfErrors();
- // before we can validate we should check the references for bind/unbind method
- // in order to create them if possible
-
- for(final Reference ref : comp.getReferences() ) {
- // if this is a field with a single cardinality,
- // we look for the bind/unbind methods
- // and create them if they are not availabe
- if ( this.generateAccessors && !ref.isLookupStrategy() ) {
- if ( ref.getJavaTag().getField() != null && comp.getJavaClassDescription() instanceof ModifiableJavaClassDescription ) {
- if ( ref.getCardinality().equals("0..1") || ref.getCardinality().equals("1..1") ) {
- final String bindValue = ref.getBind();
- final String unbindValue = ref.getUnbind();
- final String name = ref.getName();
- final String type = ref.getInterfacename();
-
- boolean createBind = false;
- boolean createUnbind = false;
- // Only create method if no bind name has been specified
- if ( bindValue == null && ref.findMethod(specVersion, "bind") == null ) {
- // create bind method
- createBind = true;
- }
- if ( unbindValue == null && ref.findMethod(specVersion, "unbind") == null ) {
- // create unbind method
- createUnbind = true;
- }
- if ( createBind || createUnbind ) {
- ((ModifiableJavaClassDescription)comp.getJavaClassDescription()).addMethods(name, type, createBind, createUnbind);
- }
- }
- }
- }
- }
- comp.validate(specVersion, iLog);
- // ignore component if it has errors
- if ( iLog.getNumberOfErrors() == errorCount ) {
- if ( !comp.isDs() ) {
- getLog().debug("Ignoring descriptor " + comp);
- } else if ( comp.isAbstract() ) {
- this.getLog().debug("Adding abstract descriptor " + comp);
- abstractComponents.addComponent(comp);
- } else {
- this.getLog().debug("Adding descriptor " + comp);
- components.addComponent(comp);
- abstractComponents.addComponent(comp);
- }
- }
- }
-
- // log issues
- iLog.log(this.getLog());
-
- // after checking all classes, throw if there were any failures
- if ( iLog.hasErrors() ) {
- throw new MojoFailureException("SCR Descriptor parsing had failures (see log)");
- }
-
- boolean addResources = false;
- // write meta type info if there is a file name
- if (!StringUtils.isEmpty(this.metaTypeName)) {
- File mtFile = new File(this.outputDirectory, "OSGI-INF" + File.separator + "metatype" + File.separator + this.metaTypeName);
- final int size = metaData.getOCDs().size() + metaData.getDesignates().size();
- if (size > 0 ) {
- this.getLog().info("Generating "
- + size
- + " MetaType Descriptors to " + mtFile);
- mtFile.getParentFile().mkdirs();
- MetaTypeIO.write(metaData, mtFile);
- addResources = true;
- } else {
- if ( mtFile.exists() ) {
- mtFile.delete();
- }
- }
-
- } else {
- this.getLog().info("Meta type file name is not set: meta type info is not written.");
- }
-
- // if we have descriptors, write them in our scr private file (for component inheritance)
- final File adFile = new File(this.outputDirectory, Constants.ABSTRACT_DESCRIPTOR_RELATIVE_PATH);
- if ( !abstractComponents.getComponents().isEmpty() ) {
- this.getLog().info("Writing abstract service descriptor " + adFile + " with " + abstractComponents.getComponents().size() + " entries.");
- adFile.getParentFile().mkdirs();
- ComponentDescriptorIO.write(abstractComponents, adFile, true);
- addResources = true;
- } 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();
- }
- }
-
- // check descriptor file
- final File descriptorFile = StringUtils.isEmpty(this.finalName) ? null : new File(new File(this.outputDirectory, "OSGI-INF"), this.finalName);
-
- // terminate if there is nothing else to write
- if (components.getComponents().isEmpty()) {
- this.getLog().debug("No SCR Descriptors found in project.");
- // remove file if it exists
- if ( descriptorFile != null && descriptorFile.exists() ) {
- this.getLog().debug("Removing obsolete service descriptor " + descriptorFile);
- descriptorFile.delete();
- }
- } else {
-
- if (descriptorFile == null) {
- throw new MojoFailureException("Descriptor file name must not be empty.");
- }
-
- // finally the descriptors have to be written ....
- descriptorFile.getParentFile().mkdirs(); // ensure parent dir
-
- this.getLog().info("Generating " + components.getComponents().size()
- + " Service Component Descriptors to " + descriptorFile);
-
- ComponentDescriptorIO.write(components, descriptorFile, false);
- addResources = true;
-
- // and set include accordingly
- String svcComp = project.getProperties().getProperty("Service-Component");
- svcComp= (svcComp == null) ? "OSGI-INF/" + finalName : svcComp + ", " + "OSGI-INF/" + finalName;
- project.getProperties().setProperty("Service-Component", svcComp);
- }
-
- // now add the descriptor directory to the maven resources
- if (addResources) {
- final String ourRsrcPath = this.outputDirectory.getAbsolutePath();
- boolean found = false;
- @SuppressWarnings("unchecked")
- final Iterator<Resource> rsrcIterator = this.project.getResources().iterator();
- while ( !found && rsrcIterator.hasNext() ) {
- final Resource rsrc = rsrcIterator.next();
- found = rsrc.getDirectory().equals(ourRsrcPath);
- }
- if ( !found ) {
- final Resource resource = new Resource();
- resource.setDirectory(this.outputDirectory.getAbsolutePath());
- this.project.addResource(resource);
- }
- }
- }
-
- /**
- * 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,
- JavaTag componentTag,
- MetaData metaData,
- final IssueLog iLog)
- throws MojoExecutionException {
- // create a new component
- final Component component = new Component(componentTag);
-
- // set implementation
- component.setImplementation(new Implementation(description.getName()));
-
- final OCD ocd = this.doComponent(componentTag, component, metaData, iLog);
-
- boolean inherited = getBoolean(componentTag, Constants.COMPONENT_INHERIT, true);
- this.doServices(description.getTagsByName(Constants.SERVICE, inherited), component, description);
-
- // collect references from class tags and fields
- final Map<String, Object[]> references = new HashMap<String, Object[]>();
- // Utility handler for propertie
- final PropertyHandler propertyHandler = new PropertyHandler(component, ocd);
-
- JavaClassDescription currentDescription = description;
- do {
- // properties
- final JavaTag[] props = currentDescription.getTagsByName(Constants.PROPERTY, false);
- for (int i=0; i < props.length; i++) {
- propertyHandler.testProperty(props[i], null, description == currentDescription);
- }
-
- // references
- final JavaTag[] refs = currentDescription.getTagsByName(Constants.REFERENCE, false);
- for (int i=0; i < refs.length; i++) {
- this.testReference(references, refs[i], null, description == currentDescription);
- }
-
- // fields
- final JavaField[] fields = currentDescription.getFields();
- for (int i=0; i < fields.length; i++) {
- JavaTag tag = fields[i].getTagByName(Constants.REFERENCE);
- if (tag != null) {
- this.testReference(references, tag, fields[i].getName(), description == currentDescription);
- }
-
- propertyHandler.handleField(fields[i], description == currentDescription);
- }
-
- currentDescription = currentDescription.getSuperClass();
- } while (inherited && currentDescription != null);
-
- // process properties
- propertyHandler.processProperties(this.properties, iLog);
-
- // process references
- final Iterator<Map.Entry<String, Object[]>> refIter = references.entrySet().iterator();
- while ( refIter.hasNext() ) {
- final Map.Entry<String, Object[]> entry = refIter.next();
- final String refName = entry.getKey();
- final Object[] values = entry.getValue();
- final JavaTag tag = (JavaTag)values[0];
- this.doReference(tag, refName, component, values[1].toString());
- }
-
- // pid handling
- final boolean createPid = getBoolean(componentTag, Constants.COMPONENT_CREATE_PID, true);
- if ( createPid ) {
- // check for an existing pid first
- boolean found = false;
- final Iterator<Property> iter = component.getProperties().iterator();
- while ( !found && iter.hasNext() ) {
- final Property prop = iter.next();
- found = org.osgi.framework.Constants.SERVICE_PID.equals( prop.getName() );
- }
- if ( !found ) {
- final Property pid = new Property();
- component.addProperty(pid);
- pid.setName(org.osgi.framework.Constants.SERVICE_PID);
- pid.setValue(component.getName());
- }
- }
- return component;
- }
-
- /**
- * Fill the component object with the information from the tag.
- * @param tag
- * @param component
- */
- protected OCD doComponent(JavaTag tag, Component component, MetaData metaData,
- final IssueLog iLog) {
-
- // check if this is an abstract definition
- final String abstractType = tag.getNamedParameter(Constants.COMPONENT_ABSTRACT);
- if (abstractType != null) {
- component.setAbstract("yes".equalsIgnoreCase(abstractType) || "true".equalsIgnoreCase(abstractType));
- } else {
- // default true for abstract classes, false otherwise
- component.setAbstract(tag.getJavaClassDescription().isAbstract());
- }
-
- // check if this is a definition to ignore
- final String ds = tag.getNamedParameter(Constants.COMPONENT_DS);
- component.setDs((ds == null) ? true : ("yes".equalsIgnoreCase(ds) || "true".equalsIgnoreCase(ds)));
-
- String name = tag.getNamedParameter(Constants.COMPONENT_NAME);
- component.setName(StringUtils.isEmpty(name) ? component.getImplementation().getClassame() : name);
-
- component.setEnabled(Boolean.valueOf(getBoolean(tag, Constants.COMPONENT_ENABLED, true)));
- component.setFactory(tag.getNamedParameter(Constants.COMPONENT_FACTORY));
-
- // FELIX-593: immediate attribute does not default to true all the
- // times hence we only set it if declared in the tag
- if (tag.getNamedParameter(Constants.COMPONENT_IMMEDIATE) != null) {
- component.setImmediate(Boolean.valueOf(getBoolean(tag,
- Constants.COMPONENT_IMMEDIATE, true)));
- }
-
- // check for V1.1 attributes: configuration policy
- if ( tag.getNamedParameter(Constants.COMPONENT_CONFIG_POLICY) != null ) {
- component.setSpecVersion(Constants.VERSION_1_1);
- component.setConfigurationPolicy(tag.getNamedParameter(Constants.COMPONENT_CONFIG_POLICY));
- }
- // check for V1.1 attributes: activate, deactivate
- if ( tag.getNamedParameter(Constants.COMPONENT_ACTIVATE) != null ) {
- component.setSpecVersion(Constants.VERSION_1_1);
- component.setActivate(tag.getNamedParameter(Constants.COMPONENT_ACTIVATE));
- }
- if ( tag.getNamedParameter(Constants.COMPONENT_DEACTIVATE) != null ) {
- component.setSpecVersion(Constants.VERSION_1_1);
- component.setDeactivate(tag.getNamedParameter(Constants.COMPONENT_DEACTIVATE));
- }
- if ( tag.getNamedParameter(Constants.COMPONENT_MODIFIED) != null ) {
- component.setSpecVersion(Constants.VERSION_1_1);
- component.setModified(tag.getNamedParameter(Constants.COMPONENT_MODIFIED));
- }
-
- // 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());
-
- // factory pid
- final String setFactoryPidValue = tag.getNamedParameter(Constants.COMPONENT_SET_METATYPE_FACTORY_PID);
- final boolean setFactoryPid = setFactoryPidValue != null &&
- ("yes".equalsIgnoreCase(setFactoryPidValue) || "true".equalsIgnoreCase(setFactoryPidValue));
- if ( setFactoryPid ) {
- if ( component.getFactory() == null ) {
- designate.setFactoryPid( component.getName() );
- } else {
- iLog.addError("Component factory " + component.getName() + " should not set metatype factory pid.");
- }
- }
- // 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
- * @throws MojoExecutionException
- */
- protected void doServices(JavaTag[] services, Component component, JavaClassDescription description)
- throws MojoExecutionException {
- // no services, hence certainly no service factory
- if (services == null || services.length == 0) {
- return;
- }
-
- final Service service = new Service();
- component.setService(service);
- boolean serviceFactory = false;
- for (int i=0; i < services.length; i++) {
- final String name = services[i].getNamedParameter(Constants.SERVICE_INTERFACE);
- if (StringUtils.isEmpty(name)) {
-
- this.addInterfaces(service, services[i], description);
- } else {
- String interfaceName = name;
- // check if the value points to a class/interface
- // and search through the imports
- // but only for local services
- if ( description instanceof QDoxJavaClassDescription ) {
- final JavaClassDescription serviceClass = description.getReferencedClass(name);
- if ( serviceClass == null ) {
- throw new MojoExecutionException("Interface '"+ name + "' in class " + description.getName() + " does not point to a valid class/interface.");
- }
- interfaceName = serviceClass.getName();
- }
- final Interface interf = new Interface(services[i]);
- interf.setInterfacename(interfaceName);
- service.addInterface(interf);
- }
-
- serviceFactory |= getBoolean(services[i], Constants.SERVICE_FACTORY, false);
- }
-
- service.setServicefactory(serviceFactory);
- }
-
- /**
- * Recursively add interfaces to the service.
- */
- protected void addInterfaces(final Service service, final JavaTag serviceTag, final JavaClassDescription description)
- throws MojoExecutionException {
- if ( description != null ) {
- JavaClassDescription[] interfaces = description.getImplementedInterfaces();
- for (int j=0; j < interfaces.length; j++) {
- final Interface interf = new Interface(serviceTag);
- interf.setInterfacename(interfaces[j].getName());
- service.addInterface(interf);
- // recursivly add interfaces implemented by this interface
- this.addInterfaces(service, serviceTag, interfaces[j]);
- }
-
- // try super class
- this.addInterfaces(service, serviceTag, description.getSuperClass());
- }
- }
-
- /**
- * Test a newly found reference
- * @param references
- * @param reference
- * @param defaultName
- * @param isInspectedClass
- * @throws MojoExecutionException
- */
- protected void testReference(Map<String, Object[]> references, JavaTag reference, String defaultName, boolean isInspectedClass)
- throws MojoExecutionException {
- final String refName = this.getReferenceName(reference, defaultName);
-
- if ( refName != null ) {
- if ( references.containsKey(refName) ) {
- // if the current class is the class we are currently inspecting, we
- // have found a duplicate definition
- if ( isInspectedClass ) {
- throw new MojoExecutionException("Duplicate definition for reference " + refName + " in class " + reference.getJavaClassDescription().getName());
- }
- } else {
- // ensure interface
- String type = reference.getNamedParameter(Constants.REFERENCE_INTERFACE);
- if (StringUtils.isEmpty(type)) {
- if ( reference.getField() != null ) {
- type = reference.getField().getType();
- } else {
- throw new MojoExecutionException("Interface missing for reference " + refName + " in class " + reference.getJavaClassDescription().getName());
- }
- } else if ( isInspectedClass ) {
- // check if the value points to a class/interface
- // and search through the imports
- final JavaClassDescription serviceClass = reference.getJavaClassDescription().getReferencedClass(type);
- if ( serviceClass == null ) {
- throw new MojoExecutionException("Interface '"+ type + "' in class " + reference.getJavaClassDescription().getName() + " does not point to a valid class/interface.");
- }
- type = serviceClass.getName();
- }
- references.put(refName, new Object[] {reference, type});
- }
- }
- }
-
- protected String getReferenceName(JavaTag reference, String defaultName)
- throws MojoExecutionException {
- String name = reference.getNamedParameter(Constants.REFERENCE_NAME);
- if (!StringUtils.isEmpty(name)) {
- return name;
- }
- name = reference.getNamedParameter(Constants.REFERENCE_NAME_REF);
- if (!StringUtils.isEmpty(name)) {
- final JavaField refField = this.getReferencedField(reference, name);
- final String[] values = refField.getInitializationExpression();
- if ( values == null || values.length == 0 ) {
- throw new MojoExecutionException("Referenced field for " + name + " has no values for a reference name.");
- }
- if ( values.length > 1 ) {
- throw new MojoExecutionException("Referenced field " + name + " has more than one value for a reference name.");
- }
- name = values[0];
- }
-
- return defaultName;
- }
-
- protected JavaField getReferencedField(final JavaTag tag, String ref)
- throws MojoExecutionException {
- int classSep = ref.lastIndexOf('.');
- JavaField field = null;
- if ( classSep == -1 ) {
- // local variable
- field = tag.getJavaClassDescription().getFieldByName(ref);
- }
- if ( field == null ) {
- field = tag.getJavaClassDescription().getExternalFieldByName(ref);
- }
- if ( field == null ) {
- throw new MojoExecutionException("Reference references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName());
- }
- return field;
- }
-
- /**
- * @param reference
- * @param defaultName
- * @param component
- */
- protected void doReference(JavaTag reference, String name, Component component, String type)
- throws MojoExecutionException {
- final Reference ref = new Reference(reference, component.getJavaClassDescription());
- ref.setName(name);
- ref.setInterfacename(type);
- ref.setCardinality(reference.getNamedParameter(Constants.REFERENCE_CARDINALITY));
- if ( ref.getCardinality() == null ) {
- ref.setCardinality("1..1");
- }
- ref.setPolicy(reference.getNamedParameter(Constants.REFERENCE_POLICY));
- if ( ref.getPolicy() == null ) {
- ref.setPolicy("static");
- }
- ref.setTarget(reference.getNamedParameter(Constants.REFERENCE_TARGET));
- final String bindValue = reference.getNamedParameter(Constants.REFERENCE_BIND);
- if ( bindValue != null ) {
- ref.setBind(bindValue);
- }
- final String unbindValue = reference.getNamedParameter(Constants.REFERENCE_UNDBIND);
- if ( unbindValue != null ) {
- ref.setUnbind(unbindValue);
- }
- final String isChecked = reference.getNamedParameter(Constants.REFERENCE_CHECKED);
- if ( isChecked != null ) {
- ref.setChecked(Boolean.valueOf(isChecked).booleanValue());
- }
- final String strategy = reference.getNamedParameter(Constants.REFERENCE_STRATEGY);
- if ( strategy != null ) {
- ref.setStrategy(strategy);
- }
-
- component.addReference(ref);
- }
-
- public static boolean getBoolean(JavaTag tag, String name, boolean defaultValue) {
- String value = tag.getNamedParameter(name);
- return (value == null) ? defaultValue : Boolean.valueOf(value).booleanValue();
- }
-}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/IssueLog.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
similarity index 76%
rename from scrplugin/src/main/java/org/apache/felix/scrplugin/IssueLog.java
rename to scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
index 756821b..bc5e40a 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/IssueLog.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
@@ -16,13 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scrplugin;
+package org.apache.felix.scrplugin.helper;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
-import org.apache.maven.plugin.logging.Log;
-
/**
* Utility class for handling errors and warnings
*/
@@ -54,19 +53,11 @@
warnings.add(e);
}
- public void log(final Log log) {
- // now log warnings and errors (warnings first)
- // in strict mode everything is an error!
- for(String warn : warnings) {
- if ( strictMode ) {
- log.error(warn);
- } else {
- log.warn(warn);
- }
- }
- for(String err : errors) {
- log.error(err);
- }
+ public Iterator<String> getWarnings() {
+ return warnings.iterator();
+ }
+ public Iterator<String> getErrors() {
+ return errors.iterator();
}
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
similarity index 93%
rename from scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
rename to scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
index 1671831..6728389 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
@@ -16,18 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scrplugin;
+package org.apache.felix.scrplugin.helper;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.felix.scrplugin.Constants;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorGenerator;
import org.apache.felix.scrplugin.om.Component;
import org.apache.felix.scrplugin.om.Property;
import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
import org.apache.felix.scrplugin.om.metatype.OCD;
import org.apache.felix.scrplugin.tags.JavaField;
import org.apache.felix.scrplugin.tags.JavaTag;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.codehaus.plexus.util.StringUtils;
import org.osgi.service.cm.ConfigurationAdmin;
/**
@@ -62,7 +67,7 @@
String name,
JavaField javaField,
final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final Property prop = new Property(tag);
prop.setName(name);
prop.setType(tag.getNamedParameter(Constants.PROPERTY_TYPE));
@@ -109,7 +114,7 @@
// property is private if explicitly marked or a well known
// service property such as service.pid
- final boolean isPrivate = SCRDescriptorMojo.getBoolean(tag,
+ final boolean isPrivate = SCRDescriptorGenerator.getBoolean(tag,
Constants.PROPERTY_PRIVATE, false)
|| name.equals(org.osgi.framework.Constants.SERVICE_PID)
|| name.equals(org.osgi.framework.Constants.SERVICE_DESCRIPTION)
@@ -200,7 +205,7 @@
* @return The name of the property or the defaultName
*/
protected String getPropertyName(JavaTag tag, JavaField field)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
// check name property
String name = tag.getNamedParameter(Constants.PROPERTY_NAME);
@@ -211,10 +216,10 @@
final JavaField refField = this.getReferencedField(tag, name);
final String[] values = refField.getInitializationExpression();
if ( values == null || values.length == 0 ) {
- throw new MojoExecutionException("Referenced field for " + name + " has no values for a property name.");
+ throw new SCRDescriptorException("Referenced field for " + name + " has no values for a property name.");
}
if ( values.length > 1 ) {
- throw new MojoExecutionException("Referenced field " + name + " has more than one value for a property name.");
+ throw new SCRDescriptorException("Referenced field " + name + " has more than one value for a property name.");
}
name = values[0];
}
@@ -238,7 +243,7 @@
}
protected void setPropertyValueRef(final JavaTag tag, Property property, String valueRef)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final String[] values = this.getPropertyValueRef(tag, property, valueRef);
if ( values != null && values.length == 1 ) {
property.setValue(values[0]);
@@ -248,7 +253,7 @@
}
protected JavaField getReferencedField(final JavaTag tag, String ref)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
int classSep = ref.lastIndexOf('.');
JavaField field = null;
if ( classSep == -1 ) {
@@ -259,13 +264,13 @@
field = tag.getJavaClassDescription().getExternalFieldByName(ref);
}
if ( field == null ) {
- throw new MojoExecutionException("Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName());
+ throw new SCRDescriptorException("Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName());
}
return field;
}
protected String[] getPropertyValueRef(final JavaTag tag, Property prop, String valueRef)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final JavaField field = this.getReferencedField(tag, valueRef);
// determine type (if not set explicitly)
@@ -300,12 +305,12 @@
* @param property The tag.
* @param field
* @param isInspectedClass
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
public void testProperty(JavaTag property,
JavaField field,
boolean isInspectedClass)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final String propName = this.getPropertyName(property, field);
if ( propName != null ) {
@@ -313,18 +318,18 @@
// if the current class is the class we are currently inspecting, we
// have found a duplicate definition
if ( isInspectedClass ) {
- throw new MojoExecutionException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName());
+ throw new SCRDescriptorException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName());
}
} else {
properties.put(propName, new PropertyDescription(property, field));
}
} else {
- throw new MojoExecutionException("Property has no name " + property.getSourceLocation());
+ throw new SCRDescriptorException("Property has no name " + property.getSourceLocation());
}
}
public void handleField(JavaField javaField, boolean isInspectedClass)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final JavaTag tag = javaField.getTagByName(Constants.PROPERTY);
if (tag != null) {
this.testProperty(tag, javaField, isInspectedClass);
@@ -335,11 +340,11 @@
* Process all found properties for the component.
* @param globalProperties Global properties are set on all components.
* @param iLog The issue log.
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
public void processProperties(final Map<String, String> globalProperties,
final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final Iterator<Map.Entry<String, PropertyDescription>> propIter = properties.entrySet().iterator();
while ( propIter.hasNext() ) {
final Map.Entry<String, PropertyDescription> entry = propIter.next();
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/StringUtils.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/StringUtils.java
new file mode 100644
index 0000000..efee6d3
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/StringUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.helper;
+
+
+public class StringUtils
+{
+
+ public static String[] split( String value, String sep )
+ {
+ return value.split( sep );
+ }
+
+
+ public static boolean isEmpty( final String string )
+ {
+ return string == null || string.length() == 0;
+ }
+
+
+ public static String leftPad( final String base, final int width, final String pad )
+ {
+ StringBuilder builder = new StringBuilder( width );
+
+ int missing = width - base.length();
+ while ( missing > 0 )
+ {
+ builder.append( pad );
+ missing -= pad.length();
+ }
+
+ builder.append( base );
+
+ return builder.toString();
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
new file mode 100644
index 0000000..0978e80
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
@@ -0,0 +1,423 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.mojo;
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+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.scrplugin.Constants;
+import org.apache.felix.scrplugin.JavaClassDescriptorManager;
+import org.apache.felix.scrplugin.Log;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
+import org.apache.felix.scrplugin.helper.StringUtils;
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Components;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.ArtifactUtils;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.DirectoryScanner;
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.JavaSource;
+
+
+public class MavenJavaClassDescriptorManager extends JavaClassDescriptorManager
+{
+
+ private final MavenProject project;
+
+ private final String excludeString;
+
+ private JavaSource[] sources;
+
+ /** The component definitions from other bundles hashed by classname. */
+ private Map<String, Component> componentDescriptions;
+
+
+ public MavenJavaClassDescriptorManager( MavenProject project, Log log, ClassLoader classLoader,
+ String[] annotationTagProviders, String excludeString, boolean parseJavadocs, boolean processAnnotations )
+ throws SCRDescriptorFailureException
+ {
+ super( log, classLoader, annotationTagProviders, parseJavadocs, processAnnotations );
+
+ this.project = project;
+ this.excludeString = excludeString;
+ }
+
+
+ public String getOutputDirectory()
+ {
+ return this.project.getBuild().getOutputDirectory();
+ }
+
+
+ protected JavaSource[] getSources() throws SCRDescriptorException
+ {
+ if ( this.sources == null )
+ {
+
+ this.log.debug( "Setting up QDox" );
+
+ JavaDocBuilder builder = new JavaDocBuilder();
+ builder.getClassLibrary().addClassLoader( this.getClassLoader() );
+
+ @SuppressWarnings("unchecked")
+ final Iterator<String> i = project.getCompileSourceRoots().iterator();
+ // FELIX-509: check for excludes
+ if ( excludeString != null )
+ {
+ final String[] excludes = StringUtils.split( excludeString, "," );
+ final String[] includes = new String[]
+ { "**/*.java" };
+
+ while ( i.hasNext() )
+ {
+ final String tree = i.next();
+ this.log.debug( "Scanning source tree " + tree );
+ final File directory = new File( tree );
+ final DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir( directory );
+
+ if ( excludes != null && excludes.length > 0 )
+ {
+ scanner.setExcludes( excludes );
+ }
+ scanner.addDefaultExcludes();
+ scanner.setIncludes( includes );
+
+ scanner.scan();
+
+ final String[] files = scanner.getIncludedFiles();
+ if ( files != null )
+ {
+ for ( int m = 0; m < files.length; m++ )
+ {
+ this.log.debug( "Adding source file " + files[m] );
+ try
+ {
+ builder.addSource( new File( directory, files[m] ) );
+ }
+ catch ( FileNotFoundException e )
+ {
+ throw new SCRDescriptorException( "Unable to scan directory.", e );
+ }
+ catch ( IOException e )
+ {
+ throw new SCRDescriptorException( "Unable to scan directory.", e );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ while ( i.hasNext() )
+ {
+ final String tree = i.next();
+ this.log.debug( "Adding source tree " + tree );
+ final File directory = new File( tree );
+ builder.addSourceTree( directory );
+ }
+ }
+ this.sources = builder.getSources();
+ }
+
+ return this.sources;
+ }
+
+
+ protected Map<String, Component> getComponentDescriptors() throws SCRDescriptorException
+ {
+ if ( this.componentDescriptions == null )
+ {
+ this.componentDescriptions = new HashMap<String, Component>();
+
+ // and now scan artifacts
+ final List<Component> components = new ArrayList<Component>();
+ @SuppressWarnings("unchecked")
+ final Map<String, Artifact> resolved = project.getArtifactMap();
+ @SuppressWarnings("unchecked")
+ final Set<Artifact> artifacts = project.getDependencyArtifacts();
+ final Iterator<Artifact> it = artifacts.iterator();
+ while ( it.hasNext() )
+ {
+ final Artifact declared = it.next();
+ this.log.debug( "Checking artifact " + declared );
+ if ( this.isJavaArtifact( declared ) )
+ {
+ if ( Artifact.SCOPE_COMPILE.equals( declared.getScope() )
+ || Artifact.SCOPE_RUNTIME.equals( declared.getScope() )
+ || Artifact.SCOPE_PROVIDED.equals( declared.getScope() ) )
+ {
+ this.log.debug( "Resolving artifact " + declared );
+ final 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( Constants.SERVICE_COMPONENT ) != null )
+ {
+ final String serviceComponent = manifest.getMainAttributes().getValue(
+ Constants.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 )
+ {
+ final Components c = this.readServiceComponentDescriptor( artifact,
+ entry );
+ if ( c != null )
+ {
+ components.addAll( c.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 SCRDescriptorException( "Unable to get manifest from artifact " + artifact,
+ ioe );
+ }
+ this.log.debug( "Trying to get scrinfo from artifact " + artifact );
+ // now read the scr private file - components stored there overwrite components already
+ // read from the service component section.
+ InputStream scrInfoFile = null;
+ try
+ {
+ scrInfoFile = this.getFile( artifact, Constants.ABSTRACT_DESCRIPTOR_ARCHIV_PATH );
+ if ( scrInfoFile != null )
+ {
+ components.addAll( this.parseServiceComponentDescriptor( scrInfoFile )
+ .getComponents() );
+ }
+ else
+ {
+ this.log.debug( "Artifact has no scrinfo file (it's optional): " + artifact );
+ }
+ }
+ catch ( IOException ioe )
+ {
+ throw new SCRDescriptorException( "Unable to get scrinfo from artifact " + artifact,
+ ioe );
+ }
+ finally
+ {
+ if ( scrInfoFile != null )
+ {
+ try
+ {
+ scrInfoFile.close();
+ }
+ catch ( IOException ignore )
+ {
+ }
+ }
+ }
+ }
+ else
+ {
+ this.log.debug( "Unable to resolve artifact " + declared );
+ }
+ }
+ else
+ {
+ this.log.debug( "Artifact " + declared + " has not scope compile or runtime, but "
+ + declared.getScope() );
+ }
+ }
+ else
+ {
+ this.log.debug( "Artifact " + declared + " is not a java artifact, type is " + declared.getType() );
+ }
+ }
+ // now create map with component descriptions
+ for ( final Component component : components )
+ {
+ this.componentDescriptions.put( component.getImplementation().getClassame(), component );
+ }
+ }
+
+ return this.componentDescriptions;
+ }
+
+
+ /**
+ * Check if the artifact is a java artifact (jar or bundle)
+ */
+ private boolean isJavaArtifact( Artifact artifact )
+ {
+ if ( "jar".equals( artifact.getType() ) )
+ {
+ return true;
+ }
+ if ( "bundle".equals( artifact.getType() ) )
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Read the service component description.
+ * @param artifact
+ * @param entry
+ * @throws IOException
+ * @throws SCRDescriptorException
+ */
+ protected Components readServiceComponentDescriptor(Artifact artifact, String entry) {
+ this.log.debug("Reading " + entry + " from " + artifact);
+ InputStream xml = null;
+ try {
+ xml = this.getFile(artifact, entry);
+ if ( xml == null ) {
+ throw new SCRDescriptorException("Artifact " + artifact + " does not contain declared service component descriptor " + entry);
+ }
+ return this.parseServiceComponentDescriptor(xml);
+ } catch (IOException mee) {
+ this.log.warn("Unable to read SCR descriptor file from artifact " + artifact + " at " + entry);
+ this.log.debug("Exception occurred during reading: " + mee.getMessage(), mee);
+ } catch (SCRDescriptorException mee) {
+ this.log.warn("Unable to read SCR descriptor file from artifact " + artifact + " at " + entry);
+ this.log.debug("Exception occurred during reading: " + mee.getMessage(), mee);
+ }
+ finally
+ {
+ if ( xml != null )
+ {
+ try
+ {
+ xml.close();
+ }
+ catch ( IOException ignore )
+ {
+ }
+ }
+ }
+ return null;
+ }
+
+ 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 InputStream getFile(Artifact artifact, String path) throws IOException {
+ JarFile file = null;
+ try {
+ file = new JarFile(artifact.getFile());
+ final JarEntry entry = file.getJarEntry(path);
+ if ( entry != null ) {
+ final InputStream stream = new ArtifactFileInputStream( file, entry);
+ file = null; // prevent file from being closed now
+ return stream;
+ }
+ return null;
+ } finally {
+ if (file != null) {
+ try {
+ file.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+ }
+
+ private static class ArtifactFileInputStream extends FilterInputStream
+ {
+ final JarFile jarFile;
+
+
+ ArtifactFileInputStream( JarFile jarFile, JarEntry jarEntry ) throws IOException
+ {
+ super( jarFile.getInputStream( jarEntry ) );
+ this.jarFile = jarFile;
+ }
+
+
+ @Override
+ public void close() throws IOException
+ {
+ try
+ {
+ super.close();
+ }
+ catch ( IOException ioe )
+ {
+ }
+ jarFile.close();
+ }
+
+
+ @Override
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ close();
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java
new file mode 100644
index 0000000..e5312c1
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.mojo;
+
+
+import org.apache.felix.scrplugin.Log;
+
+
+/**
+ * The <code>MavenLog</code> class implements the {@link Log} interface using
+ * the Maven logger created on instantiation.
+ */
+public class MavenLog implements Log
+{
+
+ private final org.apache.maven.plugin.logging.Log mavenLog;
+
+
+ MavenLog( org.apache.maven.plugin.logging.Log mavenLog )
+ {
+ this.mavenLog = mavenLog;
+ }
+
+
+ public void debug( String content, Throwable error )
+ {
+ mavenLog.debug( content, error );
+ }
+
+
+ public void debug( String content )
+ {
+ mavenLog.debug( content );
+ }
+
+
+ public void debug( Throwable error )
+ {
+ mavenLog.debug( error );
+ }
+
+
+ public void error( String content, Throwable error )
+ {
+ mavenLog.error( content, error );
+ }
+
+
+ public void error( String content )
+ {
+ mavenLog.error( content );
+ }
+
+
+ public void error( Throwable error )
+ {
+ mavenLog.error( error );
+ }
+
+
+ public void info( String content, Throwable error )
+ {
+ mavenLog.info( content, error );
+ }
+
+
+ public void info( String content )
+ {
+ mavenLog.info( content );
+ }
+
+
+ public void info( Throwable error )
+ {
+ mavenLog.info( error );
+ }
+
+
+ public boolean isDebugEnabled()
+ {
+ return mavenLog.isDebugEnabled();
+ }
+
+
+ public boolean isErrorEnabled()
+ {
+ return mavenLog.isErrorEnabled();
+ }
+
+
+ public boolean isInfoEnabled()
+ {
+ return mavenLog.isInfoEnabled();
+ }
+
+
+ public boolean isWarnEnabled()
+ {
+ return mavenLog.isWarnEnabled();
+ }
+
+
+ public void warn( String content, Throwable error )
+ {
+ mavenLog.warn( content, error );
+ }
+
+
+ public void warn( String content )
+ {
+ mavenLog.warn( content );
+ }
+
+
+ public void warn( Throwable error )
+ {
+ mavenLog.warn( error );
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/SCRDescriptorMojo.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/SCRDescriptorMojo.java
new file mode 100644
index 0000000..40af222
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/SCRDescriptorMojo.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.mojo;
+
+import java.io.File;
+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 org.apache.felix.scrplugin.JavaClassDescriptorManager;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
+import org.apache.felix.scrplugin.SCRDescriptorGenerator;
+import org.apache.maven.artifact.Artifact;
+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 process-classes
+ * @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;
+
+ /**
+ * This flag controls the generation of the bind/unbind methods.
+ * @parameter default-value="true"
+ */
+ private boolean generateAccessors;
+
+ /**
+ * This flag controls whether the javadoc source code will be scanned for
+ * tags.
+ * @parameter default-value="true"
+ */
+ protected boolean parseJavadoc;
+
+ /**
+ * This flag controls whether the annotations in the sources will be
+ * processed.
+ * @parameter default-value="true"
+ */
+ protected boolean processAnnotations;
+
+ /**
+ * In strict mode the plugin even fails on warnings.
+ * @parameter default-value="false"
+ */
+ protected boolean strictMode;
+
+ /**
+ * The comma separated list of tokens to exclude when processing sources.
+ *
+ * @parameter alias="excludes"
+ */
+ private String sourceExcludes;
+
+ /**
+ * Predefined properties.
+ *
+ * @parameter
+ */
+ private Map<String, String> properties = new HashMap<String, String>();
+
+ /**
+ * Allows to define additional implementations of the interface
+ * {@link org.apache.felix.scrplugin.tags.annotation.AnnotationTagProvider}
+ * that provide mappings from custom annotations to
+ * {@link org.apache.felix.scrplugin.tags.JavaTag} implementations.
+ * List of full qualified class file names.
+ *
+ * @parameter
+ */
+ private String[] annotationTagProviders = {};
+
+ /**
+ * The version of the DS spec this plugin generates a descriptor for.
+ * By default the version is detected by the used tags.
+ * @parameter
+ */
+ private String specVersion;
+
+
+ public void execute() throws MojoExecutionException, MojoFailureException
+ {
+ try
+ {
+ final org.apache.felix.scrplugin.Log scrLog = new MavenLog( getLog() );
+
+ final ClassLoader classLoader = new URLClassLoader( getClassPath(), this.getClass().getClassLoader() );
+ final JavaClassDescriptorManager jManager = new MavenJavaClassDescriptorManager( project, scrLog,
+ classLoader, this.annotationTagProviders, this.sourceExcludes, this.parseJavadoc,
+ this.processAnnotations );
+
+ final SCRDescriptorGenerator generator = new SCRDescriptorGenerator( scrLog );
+
+ // setup from plugin configuration
+ generator.setOutputDirectory( outputDirectory );
+ generator.setDescriptorManager( jManager );
+ generator.setFinalName( finalName );
+ generator.setMetaTypeName( metaTypeName );
+ generator.setGenerateAccessors( generateAccessors );
+ generator.setStrictMode( strictMode );
+ generator.setProperties( properties );
+ generator.setSpecVersion( specVersion );
+
+ if ( generator.execute() )
+ {
+ setServiceComponentHeader();
+ addResources();
+ }
+ }
+ catch ( SCRDescriptorException sde )
+ {
+ throw new MojoExecutionException( sde.getMessage(), sde.getCause() );
+ }
+ catch ( SCRDescriptorFailureException sdfe )
+ {
+ throw ( MojoFailureException ) new MojoFailureException( sdfe.getMessage() ).initCause( sdfe );
+ }
+ }
+
+ private URL[] getClassPath() throws MojoFailureException{
+ @SuppressWarnings("unchecked")
+ List<Artifact> artifacts = this.project.getCompileArtifacts();
+ ArrayList<URL> path = new ArrayList<URL>();
+
+ try
+ {
+ path.add(new File( this.project.getBuild().getOutputDirectory() ).toURI().toURL());
+ }
+ catch ( IOException ioe )
+ {
+ throw new MojoFailureException( "Unable to add target directory to classloader.");
+ }
+
+ int i = 1;
+ for (Iterator<Artifact> ai=artifacts.iterator(); ai.hasNext(); ) {
+ Artifact a = ai.next();
+ try {
+ path.add(a.getFile().toURI().toURL());
+ } catch (IOException ioe) {
+ throw new MojoFailureException("Unable to get compile class loader.");
+ }
+ }
+
+ return path.toArray( new URL[path.size()] );
+ }
+
+
+ private void setServiceComponentHeader()
+ {
+ final File descriptorFile = StringUtils.isEmpty( this.finalName ) ? null : new File( new File(
+ this.outputDirectory, "OSGI-INF" ), this.finalName );
+ if ( descriptorFile.exists() )
+ {
+ String svcComp = project.getProperties().getProperty( "Service-Component" );
+ svcComp = ( svcComp == null ) ? "OSGI-INF/" + finalName : svcComp + ", " + "OSGI-INF/" + finalName;
+ project.getProperties().setProperty( "Service-Component", svcComp );
+ }
+ }
+
+
+ private void addResources()
+ {
+ // now add the descriptor directory to the maven resources
+ final String ourRsrcPath = this.outputDirectory.getAbsolutePath();
+ boolean found = false;
+ @SuppressWarnings("unchecked")
+ final Iterator<Resource> rsrcIterator = this.project.getResources().iterator();
+ while ( !found && rsrcIterator.hasNext() )
+ {
+ final Resource rsrc = rsrcIterator.next();
+ found = rsrc.getDirectory().equals( ourRsrcPath );
+ }
+ if ( !found )
+ {
+ final Resource resource = new Resource();
+ resource.setDirectory( this.outputDirectory.getAbsolutePath() );
+ this.project.addResource( resource );
+ }
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
index 7a3dab6..e69ff07 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
@@ -22,9 +22,11 @@
import java.util.List;
import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.IssueLog;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.JavaMethod;
+import org.apache.felix.scrplugin.tags.JavaTag;
/**
* <code>Component</code>
@@ -255,7 +257,7 @@
* warnings can be added to the warnings list.
*/
public void validate(final int specVersion, final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final int currentIssueCount = iLog.getNumberOfErrors();
// nothing to check if this is ignored
@@ -374,7 +376,7 @@
final String methodName,
final boolean isActivate,
final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
// first candidate is (de)activate(ComponentContext)
JavaMethod method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_COMPONENT_CONTEXT});
if ( method == null ) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
index d3997ba..281a483 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
@@ -18,10 +18,10 @@
*/
package org.apache.felix.scrplugin.om;
-import org.apache.felix.scrplugin.IssueLog;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.helper.IssueLog;
import org.apache.felix.scrplugin.tags.JavaClassDescription;
import org.apache.felix.scrplugin.tags.JavaTag;
-import org.apache.maven.plugin.MojoExecutionException;
/**
* <code>Interface.java</code>...
@@ -59,7 +59,7 @@
* warnings can be added to the warnings list.
*/
public void validate(final int specVersion, final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
if (javaClass == null) {
iLog.addError(this.getMessage("Must be declared in a Java class"));
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
index 7ba0703..a70ecf5 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
@@ -19,7 +19,7 @@
package org.apache.felix.scrplugin.om;
import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.IssueLog;
+import org.apache.felix.scrplugin.helper.IssueLog;
import org.apache.felix.scrplugin.tags.JavaTag;
/**
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
index 261a53f..901d883 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
@@ -19,10 +19,12 @@
package org.apache.felix.scrplugin.om;
import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.IssueLog;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.codehaus.plexus.util.StringUtils;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.helper.StringUtils;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.JavaMethod;
+import org.apache.felix.scrplugin.tags.JavaTag;
/**
* <code>Reference.java</code>...
@@ -149,7 +151,7 @@
public void validate(final int specVersion,
final boolean componentIsAbstract,
final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
// if this reference is already checked, return immediately
if ( this.checked ) {
return;
@@ -225,7 +227,7 @@
final String methodName,
final boolean componentIsAbstract,
final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final JavaMethod method = this.findMethod(specVersion, methodName);
if (method == null) {
if ( !componentIsAbstract ) {
@@ -251,7 +253,7 @@
public JavaMethod findMethod(final int specVersion,
final String methodName)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final String[] sig = new String[]{ TYPE_SERVICE_REFERENCE };
final String[] sig2 = new String[]{ this.getInterfacename() };
final String[] sig3 = new String[]{ this.getInterfacename(), TYPE_MAP};
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java
index 7d80258..49354ac 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java
@@ -18,10 +18,12 @@
*/
package org.apache.felix.scrplugin.om;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
-import org.apache.felix.scrplugin.IssueLog;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.helper.IssueLog;
/**
* <code>Service</code>...
@@ -92,7 +94,7 @@
* warnings can be added to the warnings list.
*/
public void validate(final int specVersion, final IssueLog iLog)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
for(final Interface interf : this.getInterfaces()) {
interf.validate(specVersion, iLog);
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
index af008e4..db299d1 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
@@ -18,7 +18,7 @@
*/
package org.apache.felix.scrplugin.tags;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
/**
* <code>JavaClassDescription.java</code>...
@@ -41,18 +41,18 @@
* @param name
* @param inherited If true, parent classes are searched as well.
* @return An array of tags or the empty array.
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
JavaTag[] getTagsByName(String name, boolean inherited)
- throws MojoExecutionException;
+ throws SCRDescriptorException;
/**
* Get the description for the parent class.
* @return The description or <code>null</code> if this class is the
* Object class.
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
- JavaClassDescription getSuperClass() throws MojoExecutionException;
+ JavaClassDescription getSuperClass() throws SCRDescriptorException;
/**
* Get the name of the described class.
@@ -70,29 +70,29 @@
* Get the field with the name.
* @param name The name of the field
* @return The field with the name or null.
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
- JavaField getFieldByName(String name) throws MojoExecutionException;
+ JavaField getFieldByName(String name) throws SCRDescriptorException;
- JavaField getExternalFieldByName(String name) throws MojoExecutionException;
+ JavaField getExternalFieldByName(String name) throws SCRDescriptorException;
/**
* Returns an array of the implemented interfaces of this class.
* @return An array containing the interfaces or an empty array
* if this class does not implement any interface.
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
- JavaClassDescription[] getImplementedInterfaces() throws MojoExecutionException;
+ JavaClassDescription[] getImplementedInterfaces() throws SCRDescriptorException;
/**
* Search for a method with the given signature.
* @param name
* @param parameters
* @return A descriptor for the method or <code>null</code>
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
JavaMethod getMethodBySignature(String name, String[] parameters)
- throws MojoExecutionException;
+ throws SCRDescriptorException;
/**
* Is this class public?
@@ -122,9 +122,9 @@
* Is this class of the type?
* @param type
* @return True if this class is of the type.
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
- boolean isA(String type) throws MojoExecutionException;
+ boolean isA(String type) throws SCRDescriptorException;
/**
* Search for the class.
@@ -132,8 +132,8 @@
* of the class are searched.
* @param referencedName
* @return The java class description or null
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
JavaClassDescription getReferencedClass(String referencedName)
- throws MojoExecutionException;
+ throws SCRDescriptorException;
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java
index 80a9cbe..e48cacd 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java
@@ -21,7 +21,7 @@
import java.util.Comparator;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
/**
@@ -88,7 +88,7 @@
return 1;
}
}
- catch ( MojoExecutionException mee )
+ catch ( SCRDescriptorException mee )
{
// what shall we do ??
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java
deleted file mode 100644
index 99c06eb..0000000
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptorManager.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.scrplugin.tags;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.*;
-import java.util.jar.*;
-
-import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.om.Component;
-import org.apache.felix.scrplugin.om.Components;
-import org.apache.felix.scrplugin.tags.annotation.AnnotationJavaClassDescription;
-import org.apache.felix.scrplugin.tags.annotation.AnnotationTagProviderManager;
-import org.apache.felix.scrplugin.tags.cl.ClassLoaderJavaClassDescription;
-import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
-import org.apache.felix.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.*;
-
-import com.thoughtworks.qdox.JavaDocBuilder;
-import com.thoughtworks.qdox.model.JavaClass;
-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<String, JavaClassDescription> javaClassDescriptions = new HashMap<String, JavaClassDescription>();
-
- /** The component definitions from other bundles hashed by classname. */
- protected final Map<String, Component> componentDescriptions = new HashMap<String, Component>();
-
- /** The maven project. */
- protected final MavenProject project;
-
- /**
- * Supports mapping of built-in and custom java anntoations to {@link JavaTag} implementations.
- */
- protected final AnnotationTagProviderManager annotationTagProviderManager;
-
- /** Parse Javadocs? */
- protected final boolean parseJavadocs;
-
- /** Process Annotations? */
- protected final boolean processAnnotations;
-
- /**
- * Construct a new manager.
- * @param log
- * @param project
- * @param annotationTagProviders List of annotation tag providers
- * @param excludeString The exclude information for sources
- * @param parseJavadocs Should the javadocs be parsed?
- * @param processAnnotations Should the annotations be processed?
- * @throws MojoFailureException
- * @throws MojoExecutionException
- */
- public JavaClassDescriptorManager(final Log log,
- final MavenProject project,
- final String[] annotationTagProviders,
- final String excludeString,
- final boolean parseJavadocs,
- final boolean processAnnotations)
- throws MojoFailureException, MojoExecutionException {
- this.processAnnotations = processAnnotations;
- this.parseJavadocs = parseJavadocs;
- this.log = log;
- this.project = project;
- this.annotationTagProviderManager = new AnnotationTagProviderManager(annotationTagProviders);
- this.classloader = this.getCompileClassLoader();
- ClassUtil.classLoader = this.classloader;
-
- // get all the class sources through qdox
- this.log.debug("Setting up QDox");
- JavaDocBuilder builder = new JavaDocBuilder();
- builder.getClassLibrary().addClassLoader(this.classloader);
- @SuppressWarnings("unchecked")
- final Iterator<String> i = project.getCompileSourceRoots().iterator();
- // FELIX-509: check for excludes
- if ( excludeString != null ) {
- final String[] excludes = StringUtils.split(excludeString, ",");
- final String[] includes = new String[] {"**/*.java"};
-
- while ( i.hasNext() ) {
- final String tree = i.next();
- this.log.debug("Scanning source tree " + tree);
- final File directory = new File(tree);
- final DirectoryScanner scanner = new DirectoryScanner();
- scanner.setBasedir( directory );
-
- if ( excludes != null && excludes.length > 0 ) {
- scanner.setExcludes( excludes );
- }
- scanner.addDefaultExcludes();
- scanner.setIncludes( includes );
-
- scanner.scan();
-
- final String[] files = scanner.getIncludedFiles();
- if ( files != null ) {
- for(int m=0; m<files.length; m++) {
- this.log.debug("Adding source file " + files[m]);
- try {
- builder.addSource(new File(directory, files[m]));
- } catch (FileNotFoundException e) {
- throw new MojoExecutionException("Unable to scan directory.", e);
- } catch (IOException e) {
- throw new MojoExecutionException("Unable to scan directory.", e);
- }
- }
- }
- }
- } else {
- while ( i.hasNext() ) {
- final String tree = i.next();
- this.log.debug("Adding source tree " + tree);
- final File directory = new File(tree);
- builder.addSourceTree(directory);
- }
- }
- this.sources = builder.getSources();
-
- // and now scan artifacts
- final List<Component> components = new ArrayList<Component>();
- @SuppressWarnings("unchecked")
- final Map<String, Artifact> resolved = project.getArtifactMap();
- @SuppressWarnings("unchecked")
- final Set<Artifact> artifacts = project.getDependencyArtifacts();
- final Iterator<Artifact> it = artifacts.iterator();
- while ( it.hasNext() ) {
- final Artifact declared = it.next();
- this.log.debug("Checking artifact " + declared);
- if ( this.isJavaArtifact(declared)) {
- if (Artifact.SCOPE_COMPILE.equals(declared.getScope())
- || Artifact.SCOPE_RUNTIME.equals(declared.getScope())
- || Artifact.SCOPE_PROVIDED.equals(declared.getScope())) {
- this.log.debug("Resolving artifact " + declared);
- final 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 ) {
- final Components c = this.readServiceComponentDescriptor(artifact, entry);
- if ( c != null ) {
- components.addAll(c.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);
- // now read the scr private file - components stored there overwrite components already
- // read from the service component section.
- 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());
- }
- } else {
- this.log.debug("Artifact " + declared + " is not a java artifact, type is " + declared.getType());
- }
- }
- // now create map with component descriptions
- for(final Component component : components) {
- this.componentDescriptions.put(component.getImplementation().getClassame(), component);
- }
- }
-
- /**
- * Check if the artifact is a java artifact (jar or bundle)
- */
- private boolean isJavaArtifact(Artifact artifact) {
- if ( "jar".equals(artifact.getType()) ) {
- return true;
- }
- if ( "bundle".equals(artifact.getType()) ) {
- return true;
- }
- return false;
- }
-
- /**
- * Return the log.
- */
- public Log getLog() {
- return this.log;
- }
-
- /**
- * Return the class laoder.
- */
- public ClassLoader getClassLoader() {
- return this.classloader;
- }
-
- /**
- * Return the project.
- */
- public MavenProject getProject() {
- return this.project;
- }
-
- /**
- * @return Annotation tag provider manager
- */
- public AnnotationTagProviderManager getAnnotationTagProviderManager() {
- return this.annotationTagProviderManager;
- }
-
- /**
- * Read the service component description.
- * @param artifact
- * @param entry
- * @throws IOException
- * @throws MojoExecutionException
- */
- protected Components readServiceComponentDescriptor(Artifact artifact, String entry) {
- this.log.debug("Reading " + entry + " from " + artifact);
- try {
- 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);
- } catch (IOException mee) {
- this.log.warn("Unable to read SCR descriptor file from artifact " + artifact + " at " + entry);
- this.log.debug("Exception occurred during reading: " + mee.getMessage(), mee);
- } catch (MojoExecutionException mee) {
- this.log.warn("Unable to read SCR descriptor file from artifact " + artifact + " at " + entry);
- this.log.debug("Exception occurred during reading: " + mee.getMessage(), mee);
- }
- return null;
- }
-
- protected Components parseServiceComponentDescriptor(Artifact artifact, File file)
- throws MojoExecutionException {
- this.log.debug("Parsing " + file);
- final Components list = ComponentDescriptorIO.read(file);
- return list;
- }
-
- /**
- * Get the url for the target directory
- */
- protected URL getOutputDirectory()
- throws MojoFailureException {
- final String targetDirectory = this.getProject().getBuild().getOutputDirectory();
- try {
- return new File(targetDirectory).toURI().toURL();
- } catch (IOException ioe) {
- throw new MojoFailureException("Unable to add target directory to classloader.");
- }
- }
-
- /**
- * Create a class loader containing all compile artifacts including
- * the target/class directory of the current project
- * @return The class loader
- * @throws MojoFailureException
- */
- protected ClassLoader getCompileClassLoader()
- throws MojoFailureException {
- @SuppressWarnings("unchecked")
- List<Artifact> artifacts = this.getProject().getCompileArtifacts();
- URL[] path = new URL[artifacts.size() + 1];
- int i = 0;
- for (Iterator<Artifact> ai=artifacts.iterator(); ai.hasNext(); ) {
- Artifact a = ai.next();
- try {
- path[i++] = a.getFile().toURI().toURL();
- } catch (IOException ioe) {
- throw new MojoFailureException("Unable to get compile class loader.");
- }
- }
- path[path.length - 1] = this.getOutputDirectory();
-
- return new URLClassLoader(path, this.getClass().getClassLoader());
- }
-
- 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 All contained java class descriptions.
- */
- public JavaClassDescription[] getSourceDescriptions() throws MojoExecutionException {
- final JavaClass[] javaClasses = getJavaClassesFromSources();
- final JavaClassDescription[] descs = new JavaClassDescription[javaClasses.length];
- for(int i=0; i<javaClasses.length; i++) {
- descs[i] = this.getJavaClassDescription(javaClasses[i].getFullyQualifiedName());
- }
- return descs;
- }
-
- /**
- * Get a java class description for the class.
- * @param className
- * @return The java class description.
- * @throws MojoExecutionException
- */
- public JavaClassDescription getJavaClassDescription(String className)
- throws MojoExecutionException {
- JavaClassDescription result = this.javaClassDescriptions.get(className);
- if ( result == null ) {
- this.log.debug("Searching description for: " + className);
- int index = 0;
- final JavaClass[] javaClasses = getJavaClassesFromSources();
- while ( result == null && index < javaClasses.length) {
- final JavaClass javaClass = javaClasses[index];
- if ( javaClass.getFullyQualifiedName().equals(className) ) {
- try {
- // check for java annotation descriptions - fallback to QDox if none found
- Class<?> clazz = this.classloader.loadClass(className);
- if (this.processAnnotations && getAnnotationTagProviderManager().hasScrPluginAnnotation(javaClass)) {
- this.log.debug("Found java annotation description for: " + className);
- result = new AnnotationJavaClassDescription(clazz, javaClasses[index], this);
- } else if ( this.parseJavadocs ) {
- this.log.debug("Found qdox description for: " + className);
- result = new QDoxJavaClassDescription(clazz, javaClasses[index], this);
- }
- } catch (ClassNotFoundException e) {
- throw new MojoExecutionException("Unable to load class " + className);
- }
- } else {
- index++;
- }
- }
- if ( result == null ) {
- try {
- this.log.debug("Generating classloader description for: " + className);
- result = new ClassLoaderJavaClassDescription(this.classloader.loadClass(className), this.componentDescriptions.get(className), this);
- } catch (ClassNotFoundException e) {
- throw new MojoExecutionException("Unable to load class " + className);
- }
- }
- this.javaClassDescriptions.put(className, result);
- }
- return result;
- }
-
- /**
- * Get a list of all {@link JavaClass} definitions four all source files (including nested/inner classes)
- * @return List of {@link JavaClass} definitions
- */
- private JavaClass[] getJavaClassesFromSources() {
- final List<JavaClass> classes = new ArrayList<JavaClass>();
- for(int i=0; i<this.sources.length; i++) {
- for(int j=0; j<this.sources[i].getClasses().length; j++) {
- final JavaClass clazz = this.sources[i].getClasses()[j];
- classes.add(clazz);
- for (int k=0; k<clazz.getNestedClasses().length; k++) {
- final JavaClass nestedClass = clazz.getNestedClasses()[k];
- classes.add(nestedClass);
- }
- }
- }
- return classes.toArray(new JavaClass[classes.size()]);
- }
-
-}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java
index 91a39fa..a3f5a79 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java
@@ -18,11 +18,11 @@
*/
package org.apache.felix.scrplugin.tags;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
public interface ModifiableJavaClassDescription {
void addMethods(String propertyName, String className, boolean createBind, boolean createUnbind)
- throws MojoExecutionException;
+ throws SCRDescriptorException;
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java
index 1cf785d..4881308 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java
@@ -18,11 +18,15 @@
*/
package org.apache.felix.scrplugin.tags.annotation;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
-import org.apache.felix.scrplugin.tags.*;
+import org.apache.felix.scrplugin.JavaClassDescriptorManager;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.tags.JavaField;
+import org.apache.felix.scrplugin.tags.JavaTag;
import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
-import org.apache.maven.plugin.MojoExecutionException;
import com.thoughtworks.qdox.model.JavaClass;
@@ -62,7 +66,7 @@
* @see JavaClassDescription#getTagsByName(String, boolean)
*/
@Override
- public JavaTag[] getTagsByName(String name, boolean inherited) throws MojoExecutionException {
+ public JavaTag[] getTagsByName(String name, boolean inherited) throws SCRDescriptorException {
List<JavaTag> tags = new ArrayList<JavaTag>();
for(com.thoughtworks.qdox.model.Annotation annotation : this.javaClass.getAnnotations()) {
@@ -104,7 +108,7 @@
* @see JavaClassDescription#getFieldByName(String)
*/
@Override
- public JavaField getFieldByName(String name) throws MojoExecutionException {
+ public JavaField getFieldByName(String name) throws SCRDescriptorException {
final com.thoughtworks.qdox.model.JavaField field = this.javaClass.getFieldByName(name);
if (field != null) {
return new AnnotationJavaField(field, this);
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
index d9068f0..9b7dbde 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
@@ -21,11 +21,11 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
import org.apache.felix.scrplugin.tags.JavaField;
import org.apache.felix.scrplugin.tags.JavaTag;
import org.apache.felix.scrplugin.tags.annotation.defaulttag.DefaultAnnotationTagProvider;
import org.apache.felix.scrplugin.tags.annotation.sling.SlingAnnotationTagProvider;
-import org.apache.maven.plugin.MojoFailureException;
import com.thoughtworks.qdox.model.Annotation;
import com.thoughtworks.qdox.model.JavaClass;
@@ -49,7 +49,7 @@
* {@link AnnotationTagProvider} interface.
* @throws MojoFailureException
*/
- public AnnotationTagProviderManager(String[] annotationTagProviderClasses) throws MojoFailureException {
+ public AnnotationTagProviderManager(String[] annotationTagProviderClasses) throws SCRDescriptorFailureException {
// always add provider supporting built-in SCR default properties
annotationTagProviders.add(new DefaultAnnotationTagProvider());
@@ -62,17 +62,17 @@
try {
annotationTagProviders.add((AnnotationTagProvider) clazz.newInstance());
} catch (ClassCastException e) {
- throw new MojoFailureException("Class '" + clazz.getName() + "' "
+ throw new SCRDescriptorFailureException("Class '" + clazz.getName() + "' "
+ "does not implement interface '" + AnnotationTagProvider.class.getName() + "'.");
} catch (InstantiationException e) {
- throw new MojoFailureException("Unable to instantiate class '" + clazz.getName() + "': "
+ throw new SCRDescriptorFailureException("Unable to instantiate class '" + clazz.getName() + "': "
+ e.getMessage());
} catch (IllegalAccessException e) {
- throw new MojoFailureException("Illegal access to class '" + clazz.getName() + "': "
+ throw new SCRDescriptorFailureException("Illegal access to class '" + clazz.getName() + "': "
+ e.getMessage());
}
} catch (ClassNotFoundException ex) {
- throw new MojoFailureException("Annotation provider class '" + annotationTagProviderClasses[i]
+ throw new SCRDescriptorFailureException("Annotation provider class '" + annotationTagProviderClasses[i]
+ "' not found.");
}
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/Util.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/Util.java
index 28f71c7..2a4b050 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/Util.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/Util.java
@@ -20,11 +20,16 @@
import java.util.List;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.tags.ClassUtil;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.JavaField;
import com.thoughtworks.qdox.model.Annotation;
-import com.thoughtworks.qdox.model.annotation.*;
+import com.thoughtworks.qdox.model.annotation.AnnotationConstant;
+import com.thoughtworks.qdox.model.annotation.AnnotationFieldRef;
+import com.thoughtworks.qdox.model.annotation.AnnotationValue;
+import com.thoughtworks.qdox.model.annotation.AnnotationValueList;
/**
* Helper class for getting values from annotations.
@@ -378,7 +383,7 @@
}
throw new IllegalArgumentException("Something is wrong.");
}
- catch (MojoExecutionException mee)
+ catch (SCRDescriptorException mee)
{
throw new IllegalArgumentException(mee);
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
index 58a9d87..62a2557 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
@@ -18,12 +18,14 @@
*/
package org.apache.felix.scrplugin.tags.annotation.sling;
-import java.util.*;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
import org.apache.felix.scrplugin.Constants;
+import org.apache.felix.scrplugin.helper.StringUtils;
import org.apache.felix.scrplugin.tags.JavaClassDescription;
import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
-import org.codehaus.plexus.util.StringUtils;
/**
* Description of a java tag for components.
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
index c7cba6f..cb98c98 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
@@ -18,13 +18,21 @@
*/
package org.apache.felix.scrplugin.tags.cl;
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Field;
+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.scrplugin.Constants;
+import org.apache.felix.scrplugin.JavaClassDescriptorManager;
+import org.apache.felix.scrplugin.SCRDescriptorException;
import org.apache.felix.scrplugin.om.Component;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.JavaField;
+import org.apache.felix.scrplugin.tags.JavaMethod;
+import org.apache.felix.scrplugin.tags.JavaTag;
/**
* <code>ClassLoaderJavaClassDescription.java</code>...
@@ -61,7 +69,7 @@
/**
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFieldByName(java.lang.String)
*/
- public JavaField getFieldByName(String name) throws MojoExecutionException {
+ public JavaField getFieldByName(String name) throws SCRDescriptorException {
Field field = null;
try {
field = this.clazz.getField(name);
@@ -83,22 +91,22 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
*/
public JavaField getExternalFieldByName(String name)
- throws MojoExecutionException {
- throw new MojoExecutionException("getExternalFieldByName not supported for this class.");
+ throws SCRDescriptorException {
+ throw new SCRDescriptorException("getExternalFieldByName not supported for this class.");
}
/**
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getReferencedClass(java.lang.String)
*/
public JavaClassDescription getReferencedClass(String referencedName)
- throws MojoExecutionException {
- throw new MojoExecutionException("getReferencedClass not supported for this class.");
+ throws SCRDescriptorException {
+ throw new SCRDescriptorException("getReferencedClass not supported for this class.");
}
/**
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
*/
- public JavaClassDescription[] getImplementedInterfaces() throws MojoExecutionException {
+ public JavaClassDescription[] getImplementedInterfaces() throws SCRDescriptorException {
Class<?>[] implemented = clazz.getInterfaces();
if (implemented.length == 0) {
return JavaClassDescription.EMPTY_RESULT;
@@ -115,7 +123,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getMethodBySignature(java.lang.String, java.lang.String[])
*/
public JavaMethod getMethodBySignature(String name, String[] parameters)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
Class<?>[] classParameters = null;
if ( parameters != null ) {
classParameters = new Class[parameters.length];
@@ -133,7 +141,7 @@
} catch (NoClassDefFoundError ncdfe) {
// if this occurs it usually means that a problem with the maven
// scopes exists.
- throw new MojoExecutionException("Class loading error. This error usually occurs if you have a " +
+ throw new SCRDescriptorException("Class loading error. This error usually occurs if you have a " +
"service inheriting from a class coming from another bundle and that class using a " +
"third library and all dependencies are specified with scope 'provided'.", ncdfe);
} catch (NoSuchMethodException e) {
@@ -166,7 +174,7 @@
/**
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getSuperClass()
*/
- public JavaClassDescription getSuperClass() throws MojoExecutionException {
+ public JavaClassDescription getSuperClass() throws SCRDescriptorException {
if ( this.clazz.getSuperclass() != null ) {
return this.manager.getJavaClassDescription(this.clazz.getSuperclass().getName());
}
@@ -186,7 +194,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagsByName(java.lang.String, boolean)
*/
public JavaTag[] getTagsByName(String name, boolean inherited)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
JavaTag[] javaTags = EMPTY_TAGS;
if ( this.component != null ) {
if ( Constants.SERVICE.equals(name) ) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
index 8a9c221..27023d5 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
@@ -18,18 +18,32 @@
*/
package org.apache.felix.scrplugin.tags.qdox;
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
-import org.apache.felix.scrplugin.tags.*;
+import org.apache.felix.scrplugin.JavaClassDescriptorManager;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
import org.apache.felix.scrplugin.tags.JavaField;
import org.apache.felix.scrplugin.tags.JavaMethod;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.objectweb.asm.*;
+import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.tags.ModifiableJavaClassDescription;
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
-import com.thoughtworks.qdox.model.*;
+import com.thoughtworks.qdox.model.DocletTag;
+import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaParameter;
+import com.thoughtworks.qdox.model.JavaSource;
import com.thoughtworks.qdox.model.Type;
/**
@@ -55,7 +69,7 @@
/**
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getSuperClass()
*/
- public JavaClassDescription getSuperClass() throws MojoExecutionException {
+ public JavaClassDescription getSuperClass() throws SCRDescriptorException {
final JavaClass parent = this.javaClass.getSuperJavaClass();
if ( parent != null ) {
return this.manager.getJavaClassDescription(parent.getFullyQualifiedName());
@@ -85,7 +99,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagsByName(java.lang.String, boolean)
*/
public JavaTag[] getTagsByName(String name, boolean inherited)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final DocletTag[] tags = this.javaClass.getTagsByName(name, false);
JavaTag[] javaTags;
if ( tags == null || tags.length == 0 ) {
@@ -126,7 +140,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFieldByName(java.lang.String)
*/
public JavaField getFieldByName(String name)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final com.thoughtworks.qdox.model.JavaField field = this.javaClass.getFieldByName(name);
if ( field != null ) {
return new QDoxJavaField(field, this);
@@ -141,7 +155,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
*/
public JavaField getExternalFieldByName(String name)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
int lastDot = name.lastIndexOf('.');
// if there is no dot, this should be a static import
if ( lastDot == -1 ) {
@@ -216,7 +230,7 @@
}
try {
return this.manager.getJavaClassDescription(className);
- } catch (MojoExecutionException mee) {
+ } catch (SCRDescriptorException mee) {
return null;
}
}
@@ -225,7 +239,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
*/
public JavaClassDescription[] getImplementedInterfaces()
- throws MojoExecutionException {
+ throws SCRDescriptorException {
final JavaClass[] interfaces = this.javaClass.getImplementedInterfaces();
if ( interfaces == null || interfaces.length == 0 ) {
return JavaClassDescription.EMPTY_RESULT;
@@ -241,7 +255,7 @@
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#getMethodBySignature(java.lang.String, java.lang.String[])
*/
public JavaMethod getMethodBySignature(String name, String[] parameters)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
Type[] types = null;
if ( parameters == null || parameters.length == 0 ) {
types = new Type[0];
@@ -279,7 +293,7 @@
/**
* @see org.apache.felix.scrplugin.tags.JavaClassDescription#isA(java.lang.String)
*/
- public boolean isA(String type) throws MojoExecutionException {
+ public boolean isA(String type) throws SCRDescriptorException {
final Type qType = new Type(type);
if ( this.javaClass.isA(type) ) {
return true;
@@ -326,9 +340,9 @@
final String className,
final boolean createBind,
final boolean createUnbind)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
// now do byte code manipulation
- final String targetDirectory = this.manager.getProject().getBuild().getOutputDirectory();
+ final String targetDirectory = this.manager.getOutputDirectory();
final String fileName = targetDirectory + File.separatorChar + this.getName().replace('.', File.separatorChar) + ".class";
final ClassNode cn = new ClassNode();
try {
@@ -375,7 +389,7 @@
fos.write(writer.toByteArray());
fos.close();
} catch (Exception e) {
- throw new MojoExecutionException("Unable to add methods to " + this.getName(), e);
+ throw new SCRDescriptorException("Unable to add methods to " + this.getName(), e);
}
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index d997848..482201e 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -20,14 +20,23 @@
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.util.StringTokenizer;
import javax.xml.transform.TransformerException;
import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.om.*;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.xml.sax.*;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Components;
+import org.apache.felix.scrplugin.om.Implementation;
+import org.apache.felix.scrplugin.om.Interface;
+import org.apache.felix.scrplugin.om.Property;
+import org.apache.felix.scrplugin.om.Reference;
+import org.apache.felix.scrplugin.om.Service;
+import org.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;
@@ -104,16 +113,14 @@
private static final String INTERFACE_QNAME = INTERFACE;
- public static Components read(File file)
- throws MojoExecutionException {
+ public static Components read(InputStream file)
+ throws SCRDescriptorException {
try {
final XmlHandler xmlHandler = new XmlHandler();
IOUtils.parse(file, xmlHandler);
return xmlHandler.components;
} catch (TransformerException e) {
- throw new MojoExecutionException("Unable to read xml from " + file, e);
- } catch (IOException e) {
- throw new MojoExecutionException("Unable to read xml from " + file, e);
+ throw new SCRDescriptorException("Unable to read xml from " + file, e);
}
}
@@ -121,18 +128,18 @@
* Write the component descriptors to the file.
* @param components
* @param file
- * @throws MojoExecutionException
+ * @throws SCRDescriptorException
*/
public static void write(Components components, File file, boolean isScrPrivateFile)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
try {
generateXML(components, IOUtils.getSerializer(file), isScrPrivateFile);
} catch (TransformerException e) {
- throw new MojoExecutionException("Unable to write xml to " + file, e);
+ throw new SCRDescriptorException("Unable to write xml to " + file, e);
} catch (SAXException e) {
- throw new MojoExecutionException("Unable to generate xml for " + file, e);
+ throw new SCRDescriptorException("Unable to generate xml for " + file, e);
} catch (IOException e) {
- throw new MojoExecutionException("Unable to write xml to " + file, e);
+ throw new SCRDescriptorException("Unable to write xml to " + file, e);
}
}
@@ -428,25 +435,36 @@
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"));
+ // read the property, unless it is the service.pid
+ // property which must not be inherited
+ final String propName = attributes.getValue( "name" );
+ if ( !org.osgi.framework.Constants.SERVICE_PID.equals( propName ) )
+ {
+ final Property prop = new Property();
- 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;
- }
- // check for abstract properties
- prop.setLabel(attributes.getValue("label"));
- prop.setDescription(attributes.getValue("description"));
- prop.setCardinality(attributes.getValue("cardinality"));
- final String pValue = attributes.getValue("private");
- if ( pValue != null ) {
- prop.setPrivate(Boolean.valueOf(pValue).booleanValue());
+ prop.setName( propName );
+ 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;
+ }
+ // check for abstract properties
+ prop.setLabel( attributes.getValue( "label" ) );
+ prop.setDescription( attributes.getValue( "description" ) );
+ prop.setCardinality( attributes.getValue( "cardinality" ) );
+ final String pValue = attributes.getValue( "private" );
+ if ( pValue != null )
+ {
+ prop.setPrivate( Boolean.valueOf( pValue ).booleanValue() );
+ }
}
} else if (localName.equals("properties")) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
index 46b819a..8671088 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
@@ -49,11 +49,10 @@
* @throws IOException
* @throws TransformerException
*/
- public static final void parse(File file, ContentHandler handler)
- throws IOException, TransformerException {
+ public static final void parse(InputStream file, ContentHandler handler)
+ throws TransformerException {
final Transformer transformer = FACTORY.newTransformer();
- transformer.transform(new StreamSource(new FileReader(file)),
- new SAXResult(handler));
+ transformer.transform( new StreamSource( file ), new SAXResult( handler ) );
}
public static ContentHandler getSerializer(File file)
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
index 7bb4f36..15eeaff 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
@@ -25,8 +25,12 @@
import javax.xml.transform.TransformerException;
-import org.apache.felix.scrplugin.om.metatype.*;
-import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
+import org.apache.felix.scrplugin.om.metatype.Designate;
+import org.apache.felix.scrplugin.om.metatype.MTObject;
+import org.apache.felix.scrplugin.om.metatype.MetaData;
+import org.apache.felix.scrplugin.om.metatype.OCD;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -65,15 +69,15 @@
protected static final String OPTION_ELEMENT_QNAME = OPTION_ELEMENT;
public static void write(MetaData metaData, File file)
- throws MojoExecutionException {
+ throws SCRDescriptorException {
try {
generateXML(metaData, IOUtils.getSerializer(file));
} catch (TransformerException e) {
- throw new MojoExecutionException("Unable to write xml to " + file, e);
+ throw new SCRDescriptorException("Unable to write xml to " + file, e);
} catch (SAXException e) {
- throw new MojoExecutionException("Unable to generate xml for " + file, e);
+ throw new SCRDescriptorException("Unable to generate xml for " + file, e);
} catch (IOException e) {
- throw new MojoExecutionException("Unable to write xml to " + file, e);
+ throw new SCRDescriptorException("Unable to write xml to " + file, e);
}
}