FELIX-3550 : Reimplement the SCR Generator
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1349773 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/generator/DEPENDENCIES b/scrplugin/generator/DEPENDENCIES
index 23a9770..cdfe014 100644
--- a/scrplugin/generator/DEPENDENCIES
+++ b/scrplugin/generator/DEPENDENCIES
@@ -1,5 +1,5 @@
Apache Felix Descriptor Generator Implementation
-Copyright 2010-2011 The Apache Software Foundation
+Copyright 2010-2012 The Apache Software Foundation
This software was developed at the Apache Software Foundation
(http://www.apache.org) and may have dependencies on other
@@ -19,10 +19,6 @@
Copyright (c) 2000-2005 INRIA, France Telecom
Licensed under the BSD License.
-This product uses software developed at
-The Codehaus (http://www.codehaus.org)
-Licensed under the Apache License 2.0.
-
III. License Summary
- Apache License 2.0
diff --git a/scrplugin/generator/NOTICE b/scrplugin/generator/NOTICE
index 9d3e412..4441938 100644
--- a/scrplugin/generator/NOTICE
+++ b/scrplugin/generator/NOTICE
@@ -1,5 +1,5 @@
Apache Felix Descriptor Generator Implementation
-Copyright 2010-2011 The Apache Software Foundation
+Copyright 2010-2012 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/scrplugin/generator/pom.xml b/scrplugin/generator/pom.xml
index 45ffdd7..67794f3 100644
--- a/scrplugin/generator/pom.xml
+++ b/scrplugin/generator/pom.xml
@@ -29,7 +29,7 @@
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.generator</artifactId>
- <version>1.1.5-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Descriptor Generator Implementation</name>
@@ -45,14 +45,6 @@
</scm>
<dependencies>
- <!-- JavaDoc Tags -->
- <dependency>
- <groupId>com.thoughtworks.qdox</groupId>
- <artifactId>qdox</artifactId>
- <version>1.12</version>
- <scope>compile</scope>
- </dependency>
-
<!-- bind/unbind method generation -->
<dependency>
<groupId>asm</groupId>
@@ -60,19 +52,15 @@
<version>3.1</version>
<scope>compile</scope>
</dependency>
-
- <!-- OSGi APIs (some constant references used only) -->
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <version>4.0.0</version>
- <scope>provided</scope>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
- <version>4.0.0</version>
- <scope>provided</scope>
+ <version>4.2.0</version>
</dependency>
</dependencies>
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/AnnotationProcessor.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/AnnotationProcessor.java
new file mode 100644
index 0000000..376df37
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/AnnotationProcessor.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.scanner.ScannedClass;
+
+/**
+ * This service provides a plugin for annotation processing. Custom tags
+ * can be processed.
+ * On a scanned class all available annotation processors are called in
+ * order of their {@link #getRanking()} value (lowest value first).
+ */
+public interface AnnotationProcessor {
+
+ /**
+ * Processes annotations from the provided list and adds objects
+ * to the object model based on the read annotations.
+ * If this service processes an annotation, it should remove this
+ * annotation from the provided list to avoid duplicate processing
+ * by other processors.
+ * @param scannedClass The scanned class.
+ * @param describedClass The descriptions.
+ */
+ void process(final ScannedClass scannedClass,
+ final ClassDescription describedClass)
+ throws SCRDescriptorException, SCRDescriptorFailureException;
+
+ /**
+ * The ranking of this processor.
+ */
+ int getRanking();
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Constants.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Constants.java
deleted file mode 100644
index 5a362e2..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Constants.java
+++ /dev/null
@@ -1,175 +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;
-
-/**
- * The <code>Constants</code> interface provides use full constants for various
- * values used for processing SCR annotations and JavaDoc tags into SCR
- * descriptors.
- */
-public interface Constants {
-
- /** Version 1.0 (R4.1) */
- public static final int VERSION_1_0 = 0;
-
- /** Version 1.1 (R4.2) */
- public static final int VERSION_1_1 = 1;
-
- /** Version 1.1-felix (R4.2 + FELIX-1893) */
- public static final int VERSION_1_1_FELIX = 2;
-
- /**
- * 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";
-
- public static final String COMPONENT_NAME = "name";
-
- public static final String COMPONENT_LABEL = "label";
-
- public static final String COMPONENT_DESCRIPTION = "description";
-
- public static final String COMPONENT_ENABLED = "enabled";
-
- public static final String COMPONENT_FACTORY = "factory";
-
- public static final String COMPONENT_IMMEDIATE = "immediate";
-
- public static final String COMPONENT_INHERIT = "inherit";
-
- public static final String COMPONENT_METATYPE = "metatype";
-
- public static final String COMPONENT_ABSTRACT = "abstract";
-
- public static final String COMPONENT_DS = "ds";
-
- // Force the descriptor version (since 1.4.1)
- public static final String COMPONENT_DS_SPEC_VERSION = "specVersion";
-
- // Specification version identifier for SCR 1.0 (R 4.1)
- public static final String COMPONENT_DS_SPEC_VERSION_10 = "1.0";
-
- // Specification version identifier for SCR 1.1 (R 4.2)
- public static final String COMPONENT_DS_SPEC_VERSION_11 = "1.1";
-
- // Specification version identifier for SCR 1.1-felix (R 4.2+FELIX-1893)
- public static final String COMPONENT_DS_SPEC_VERSION_11_FELIX = "1.1-felix";
-
- public static final String COMPONENT_CREATE_PID = "create-pid";
-
- public static final String COMPONENT_SET_METATYPE_FACTORY_PID = "configurationFactory";
-
- // The component configuration policy (V1.1)
- public static final String COMPONENT_CONFIG_POLICY = "policy";
- public static final String COMPONENT_CONFIG_POLICY_OPTIONAL = "optional";
- public static final String COMPONENT_CONFIG_POLICY_REQUIRE = "require";
- public static final String COMPONENT_CONFIG_POLICY_IGNORE = "ignore";
-
- // The component activate method name (V1.1)
- public static final String COMPONENT_ACTIVATE = "activate";
-
- // The component activate method name (V1.1)
- public static final String COMPONENT_DEACTIVATE = "deactivate";
-
- // The component modified method name (V1.1)
- public static final String COMPONENT_MODIFIED = "modified";
-
- public static final String PROPERTY = "scr.property";
-
- public static final String PROPERTY_NAME = "name";
-
- public static final String PROPERTY_NAME_REF = "nameRef";
-
- public static final String PROPERTY_LABEL = "label";
-
- public static final String PROPERTY_DESCRIPTION = "description";
-
- public static final String PROPERTY_VALUE = "value";
-
- public static final String PROPERTY_MULTIVALUE_PREFIX = "values";
-
- public static final String PROPERTY_VALUE_REF = "valueRef";
-
- /** Property for multi value fields using references. */
- public static final String PROPERTY_MULTIVALUE_REF_PREFIX = "valueRefs";
-
- // property type
- public static final String PROPERTY_TYPE = "type";
- public static final String PROPERTY_TYPE_STRING = "String";
- public static final String PROPERTY_TYPE_LONG = "Long";
- public static final String PROPERTY_TYPE_DOUBLE = "Double";
- public static final String PROPERTY_TYPE_FLOAT = "Float";
- public static final String PROPERTY_TYPE_INTEGER = "Integer";
- public static final String PROPERTY_TYPE_BYTE = "Byte";
- public static final String PROPERTY_TYPE_CHAR = "Char";
- public static final String PROPERTY_TYPE_CHAR_1_1 = "Character";
- public static final String PROPERTY_TYPE_BOOLEAN = "Boolean";
- public static final String PROPERTY_TYPE_SHORT = "Short";
-
- public static final String PROPERTY_CARDINALITY = "cardinality";
-
- public static final String PROPERTY_PRIVATE = "private";
-
- public static final String PROPERTY_OPTIONS = "options";
-
- public static final String SERVICE = "scr.service";
-
- public static final String SERVICE_INTERFACE = "interface";
-
- public static final String SERVICE_FACTORY = "servicefactory";
-
- public static final String REFERENCE = "scr.reference";
-
- public static final String REFERENCE_NAME = "name";
-
- public static final String REFERENCE_NAME_REF = "nameRef";
-
- public static final String REFERENCE_INTERFACE = "interface";
-
- public static final String REFERENCE_CARDINALITY = "cardinality";
-
- public static final String REFERENCE_POLICY = "policy";
-
- public static final String REFERENCE_TARGET = "target";
-
- public static final String REFERENCE_BIND = "bind";
-
- public static final String REFERENCE_UNDBIND = "unbind";
-
- public static final String REFERENCE_UPDATED = "updated";
-
- public static final String REFERENCE_CHECKED = "checked";
-
- /** Lookup strategy for references @since 1.0.9 */
- public static final String REFERENCE_STRATEGY = "strategy";
- public static final String REFERENCE_STRATEGY_LOOKUP = "lookup";
- public static final String REFERENCE_STRATEGY_EVENT = "event";
-
- public static final String ABSTRACT_DESCRIPTOR_FILENAME = "scrinfo.xml";
-
- 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/generator/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
deleted file mode 100644
index 4fd2f48..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
+++ /dev/null
@@ -1,666 +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.*;
-import java.util.*;
-import java.util.jar.*;
-
-import org.apache.felix.scrplugin.om.Component;
-import org.apache.felix.scrplugin.om.Components;
-import org.apache.felix.scrplugin.tags.JavaClassDescription;
-import org.apache.felix.scrplugin.tags.JavaTag;
-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.JavaDocBuilder;
-import com.thoughtworks.qdox.model.JavaClass;
-import com.thoughtworks.qdox.model.JavaSource;
-
-
-/**
- * The <code>JavaClassDescriptorManager</code> must be implemented to provide
- * access to the java sources to be scanned for descriptor annotations and
- * JavaDoc tags, the descriptors of components from the class path and the
- * location of the generated class files to be able to add the bind and unbind
- * methods.
- */
-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;
-
- /** The Java sources gathered by {@link #getSourceDescriptions()} */
- private JavaSource[] sources;
-
- /** The component definitions from other bundles hashed by classname. */
- private Map<String, Component> componentDescriptions;
-
-
- /**
- * Construct a new manager.
- *
- * @throws SCRDescriptorFailureException
- */
- 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, classLoader );
- this.classloader = classLoader;
- }
-
-
- /**
- * Returns the QDox JavaSource instances representing the source files for
- * which the Declarative Services and Metatype descriptors have to be
- * generated.
- *
- * @throws SCRDescriptorException May be thrown if an error occurrs
- * gathering the java sources.
- */
- protected JavaSource[] getSources() throws SCRDescriptorException
- {
- if ( this.sources == null )
- {
- this.log.debug( "Setting up QDox" );
-
- JavaDocBuilder builder = new JavaDocBuilder();
- builder.getClassLibrary().addClassLoader( this.getClassLoader() );
-
- final Iterator<File> i = getSourceFiles();
- while ( i.hasNext() )
- {
- File file = i.next();
- this.log.debug( "Adding source file " + file );
- try
- {
- builder.addSource( file );
- }
- catch ( IOException e )
- {
- // also FileNotFoundException
- throw new SCRDescriptorException( "Unable to add source file", file.toString(), 0, e );
- }
- }
- this.sources = builder.getSources();
- }
-
- return this.sources;
- }
-
-
- /**
- * Returns an iterator of paths to directories providing Java source files
- * to be parsed.
- * <p>
- * This method is called by the default {@link #getSources()} implementation
- * to return the root directories for the Java files to be parsed. This
- * default implementation returns an empty iterator. Implementations of this
- * class not overwriting the {@link #getSources()} method should overwrite
- * this method by providing the concrete source locations.
- *
- * @return An iterator of Java source locations.
- */
- protected Iterator<File> getSourceFiles()
- {
- return Collections.<File> emptyList().iterator();
- }
-
-
- /**
- * Returns a map of component descriptors which may be extended by the java
- * sources returned by the {@link #getSources()} method.
- * <p>
- * This method calls the {@link #getDependencies()} method and checks for
- * any Service-Component descriptors in the returned files.
- * <p>
- * This method may be overwritten by extensions of this class.
- *
- * @throws SCRDescriptorException May be thrown if an error occurrs
- * gethering the component descriptors.
- */
- protected Map<String, Component> getComponentDescriptors() throws SCRDescriptorException
- {
- if ( this.componentDescriptions == null )
- {
- final List<Component> components = new ArrayList<Component>();
- final List<File> dependencies = getDependencies();
- for ( File artifact : dependencies )
- {
- 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.toString(), 0,
- 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.toString(), 0,
- ioe );
- }
- finally
- {
- if ( scrInfoFile != null )
- {
- try
- {
- scrInfoFile.close();
- }
- catch ( IOException ignore )
- {
- }
- }
- }
-
- }
- // now create map with component descriptions
- this.componentDescriptions = new HashMap<String, Component>();
- for ( final Component component : components )
- {
- this.componentDescriptions.put( component.getImplementation().getClassame(), component );
- }
- }
-
- return this.componentDescriptions;
- }
-
-
- /**
- * Returns a list of files denoting dependencies of the module for which
- * descriptors are to be generated. The returned dependencies are expected
- * to be bundles which may (or may not) contain Service Component
- * descriptors (or internal descriptors in the case of abstract components
- * not listed in the "official" descriptors).
- * <p>
- * This method is called by the {@link #getComponentDescriptors()} method in
- * this class to get the list of bundles from where base component
- * descriptors are to be extracted.
- * <p>
- * Extensions of this class not overwriting the
- * {@link #getComponentDescriptors()} method should overwrite this method if
- * they wish to provide such base component descriptors.
- *
- * @return
- */
- protected List<File> getDependencies()
- {
- return Collections.<File> emptyList();
- }
-
-
- /**
- * Returns the absolute filesystem path to the directory where the classes
- * compiled from the java source files (see {@link #getSources()}) have been
- * placed.
- * <p>
- * This method is called to find the class files to which bind and unbind
- * methods are to be added.
- */
- public abstract String getOutputDirectory();
-
-
- /**
- * 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;
- }
-
-
- /**
- * Parses the descriptors read from the given input stream. This method may
- * be called by the {@link #getComponentDescriptors()} method to parse the
- * descriptors gathered in an implementation dependent way.
- *
- * @throws SCRDescriptorException If an error occurrs reading the
- * descriptors from the stream.
- */
- protected Components parseServiceComponentDescriptor( InputStream file ) throws SCRDescriptorException
- {
- return ComponentDescriptorIO.read( file );
- }
-
-
- /**
- * 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;
- }
-
- private boolean doingHasScrPluginAnnotationCheck = false;
-
- private boolean hasScrPluginAnnotation(final Class<?> clazz, final JavaClass javaClass)
- {
- boolean result;
- doingHasScrPluginAnnotationCheck = true;
-
- result = getAnnotationTagProviderManager().hasScrPluginAnnotation( javaClass,
- new AnnotationJavaClassDescription( clazz, javaClass, this ));
- doingHasScrPluginAnnotationCheck = false;
- return result;
- }
-
- /**
- * 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 && !doingHasScrPluginAnnotationCheck
- && hasScrPluginAnnotation(clazz, javaClass) )
- {
- this.log.debug( "Generating java annotation description for: " + className );
- result = new AnnotationJavaClassDescription( clazz, javaClass, this );
- }
- else if ( this.parseJavadocs )
- {
- this.log.debug( "Generating qdox description for: " + className );
- result = new QDoxJavaClassDescription( clazz, javaClass, this );
- }
- else
- {
- index++;
- }
- }
- catch ( ClassNotFoundException e )
- {
- throw new SCRDescriptorException( "Unable to load class", className, 0 );
- }
- }
- 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, 0 );
- }
- }
- if ( !doingHasScrPluginAnnotationCheck ) {
- 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() throws SCRDescriptorException
- {
- final JavaSource[] sources = this.getSources();
- final List<JavaClass> classes = new ArrayList<JavaClass>();
- for ( int i = 0; i < sources.length; i++ )
- {
- if ( sources[i].getClasses() == null || sources[i].getClasses().length == 0 )
- {
- continue;
- }
- 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()] );
- }
-
-
- /**
- * Read the service component description.
- *
- * @param artifact
- * @param entry
- * @throws IOException
- * @throws SCRDescriptorException
- */
- private Components readServiceComponentDescriptor( final File artifactFile, String entry )
- {
- this.log.debug( "Reading " + entry + " from " + artifactFile );
- InputStream xml = null;
- try
- {
- xml = this.getFile( artifactFile, entry );
- if ( xml == null )
- {
- throw new SCRDescriptorException( "Entry " + entry + " not contained in JAR File ", artifactFile.toString(),
- 0 );
- }
- return this.parseServiceComponentDescriptor( xml );
- }
- catch ( IOException mee )
- {
- this.log.warn( "Unable to read SCR descriptor file from JAR File " + artifactFile + " 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 JAR File " + artifactFile + " at " + entry );
- this.log.debug( "Exception occurred during reading: " + mee.getMessage(), mee );
- }
- finally
- {
- if ( xml != null )
- {
- try
- {
- xml.close();
- }
- catch ( IOException ignore )
- {
- }
- }
- }
- return null;
- }
-
-
- private Manifest getManifest( File artifact ) throws IOException
- {
- if ( artifact.isDirectory() )
- {
- // this is maybe a classes directory, try to read manifest file directly
- final File dir = new File(artifact, "META-INF");
- if ( !dir.exists() || !dir.isDirectory() )
- {
- return null;
- }
- final File mf = new File(dir, "MANIFEST.MF");
- if ( !mf.exists() || !mf.isFile() )
- {
- return null;
- }
- final InputStream is = new FileInputStream(mf);
- try
- {
- return new Manifest(is);
- }
- finally
- {
- try
- {
- is.close();
- }
- catch (final IOException ignore) { }
- }
- }
- JarFile file = null;
- try
- {
- file = new JarFile( artifact );
- return file.getManifest();
- }
- finally
- {
- if ( file != null )
- {
- try
- {
- file.close();
- }
- catch ( IOException ignore )
- {
- }
- }
- }
- }
-
-
- private InputStream getFile( final File artifactFile, final String path ) throws IOException
- {
- if ( artifactFile.isDirectory() )
- {
- final String filePath = path.replace('/', File.separatorChar).replace('\\', File.separatorChar);
- final File file = new File(artifactFile, filePath);
- if ( file.exists() && file.isFile() )
- {
- return new FileInputStream(file);
- }
- return null;
- }
- JarFile file = null;
- try
- {
- file = new JarFile( artifactFile );
- 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/generator/src/main/java/org/apache/felix/scrplugin/Log.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Log.java
index 46d44ff..ec679cb 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Log.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Log.java
@@ -24,8 +24,8 @@
* SCR descriptor generation process using whatever means is implemented. There
* should be no big surprises here.
*/
-public interface Log
-{
+public interface Log {
+
/**
* @return true if the <b>debug</b> error level is enabled
*/
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java
new file mode 100644
index 0000000..bc5e041
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.felix.scrplugin.description.SpecVersion;
+
+
+public class Options {
+
+ private boolean generateAccessors = true;
+
+ private boolean strictMode = false;
+
+ private Map<String, String> properties = Collections.emptyMap();
+
+ private SpecVersion specVersion;
+
+ private String[] annotationProcessors;
+
+ public String[] getAnnotationProcessors() {
+ return annotationProcessors;
+ }
+
+ public void setAnnotationProcessors(String[] annotationProcessors) {
+ this.annotationProcessors = annotationProcessors;
+ }
+
+ public boolean isGenerateAccessors() {
+ return generateAccessors;
+ }
+
+ /**
+ * Defines whether bind and unbind methods are automatically created by
+ * the SCR descriptor generator.
+ * <p>
+ * The generator uses the ASM library to create the method byte codes
+ * directly inside the class files. If bind and unbind methods are not
+ * to be created, the generator fails if such methods are missing.
+ * <p>
+ * The default value of this property is <code>true</code>.
+ */
+ public void setGenerateAccessors(boolean generateAccessors) {
+ this.generateAccessors = generateAccessors;
+ }
+
+ public boolean isStrictMode() {
+ return strictMode;
+ }
+
+ /**
+ * Defines whether warnings should be considered as errors and thus cause
+ * the generation process to fail.
+ * <p>
+ * The default value of this property is <code>false</code>.
+ */
+ public void setStrictMode(boolean strictMode) {
+ this.strictMode = strictMode;
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets global properties to be set for each descriptor. If a descriptor
+ * provides properties of the same name, the descriptor properties are preferred
+ * over the properties provided here.
+ * <p>
+ * The are no default global properties.
+ */
+ public void setProperties(Map<String, String> properties) {
+ this.properties = properties;
+ }
+
+ public SpecVersion getSpecVersion() {
+ return specVersion;
+ }
+
+ /**
+ * Sets the Declarative Services specification version number to be forced
+ * on the declarations.
+ * <p>
+ * Supported values for this property are <code>null</code> to autodetect
+ * the specification version, or one of the enum values from
+ * {@link SpecVersion}.
+ * <p>
+ * The default is to generate the descriptor version according to the
+ * capabilities used by the descriptors. If no 1.1 capabilities, such as
+ * <code>configuration-policy</code>, are used, version 1.0 is used,
+ * otherwise a 1.1 descriptor is generated.
+ */
+ public void setSpecVersion(SpecVersion specVersion) {
+ this.specVersion = specVersion;
+ }
+
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Project.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Project.java
new file mode 100644
index 0000000..91e4658
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Project.java
@@ -0,0 +1,67 @@
+/*
+ * 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.Collection;
+
+import org.apache.felix.scrplugin.scanner.Source;
+
+public class Project {
+
+ private Collection<Source> sources;
+
+ private Collection<File> dependencies;
+
+ private ClassLoader classLoader;
+
+ private String classesDirectory;
+
+ public Collection<Source> getSources() {
+ return sources;
+ }
+
+ public void setSources(Collection<Source> sources) {
+ this.sources = sources;
+ }
+
+ public Collection<File> getDependencies() {
+ return dependencies;
+ }
+
+ public void setDependencies(Collection<File> dependencies) {
+ this.dependencies = dependencies;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public String getClassesDirectory() {
+ return this.classesDirectory;
+ }
+
+ public void setClassesDirectory(final String dir) {
+ this.classesDirectory = dir;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Result.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Result.java
new file mode 100644
index 0000000..5ebe459
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Result.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin;
+
+import java.util.List;
+
+
+/**
+ * The result of the generation.
+ */
+public class Result {
+
+ /** The list of metatype files. */
+ private List<String> metatypeFiles;
+
+ /** The list of scr files. */
+ private List<String> scrFiles;
+
+ /**
+ * Set the list of metatype files
+ */
+ public void setMetatypeFiles(List<String> metatypeFiles) {
+ this.metatypeFiles = metatypeFiles;
+ }
+
+ /**
+ * Set the list of scr files
+ */
+ public void setScrFiles(List<String> scrFiles) {
+ this.scrFiles = scrFiles;
+ }
+
+ /**
+ * Return a list of generated metatype files
+ * @return A list of relative paths or <code>null</code>
+ */
+ public List<String> getMetatypeFiles() {
+ return metatypeFiles;
+ }
+
+ /**
+ * Return a list of generated scr files
+ * @return A list of relative paths or <code>null</code>
+ */
+ public List<String> getScrFiles() {
+ return scrFiles;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
index 0721681..fec894b 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
@@ -19,11 +19,7 @@
package org.apache.felix.scrplugin;
-import org.apache.felix.scrplugin.tags.JavaTag;
-
-
-public class SCRDescriptorException extends Exception
-{
+public class SCRDescriptorException extends Exception {
private static final long serialVersionUID = 1L;
@@ -32,12 +28,6 @@
private final int m_lineNumber;
- public SCRDescriptorException( final String message, final JavaTag tag )
- {
- this( message, tag.getSourceLocation(), tag.getLineNumber() );
- }
-
-
public SCRDescriptorException( final String message, final String sourceLocation, final int lineNumber )
{
super( message );
@@ -46,9 +36,9 @@
}
- public SCRDescriptorException( final String message, final JavaTag tag, final Throwable cause )
+ public SCRDescriptorException( final String message, final Throwable cause )
{
- this( message, tag.getSourceLocation(), tag.getLineNumber(), cause );
+ this( message, null, -1, cause );
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
index c4db2a5..83d5d45 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
@@ -18,994 +18,685 @@
*/
package org.apache.felix.scrplugin;
-
import java.io.File;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
-import org.apache.felix.scrplugin.helper.*;
-import org.apache.felix.scrplugin.om.*;
-import org.apache.felix.scrplugin.om.metatype.*;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.felix.scrplugin.tags.annotation.AnnotationJavaClassDescription;
-import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.description.ComponentDescription;
+import org.apache.felix.scrplugin.description.PropertyDescription;
+import org.apache.felix.scrplugin.description.PropertyType;
+import org.apache.felix.scrplugin.description.PropertyUnbounded;
+import org.apache.felix.scrplugin.description.ReferenceCardinality;
+import org.apache.felix.scrplugin.description.ReferenceDescription;
+import org.apache.felix.scrplugin.description.ServiceDescription;
+import org.apache.felix.scrplugin.description.SpecVersion;
+import org.apache.felix.scrplugin.helper.AnnotationProcessorManager;
+import org.apache.felix.scrplugin.helper.ClassModifier;
+import org.apache.felix.scrplugin.helper.ClassScanner;
+import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.helper.StringUtils;
+import org.apache.felix.scrplugin.om.Component;
+import org.apache.felix.scrplugin.om.Components;
+import org.apache.felix.scrplugin.om.Context;
+import org.apache.felix.scrplugin.om.Implementation;
+import org.apache.felix.scrplugin.om.Interface;
+import org.apache.felix.scrplugin.om.Property;
+import org.apache.felix.scrplugin.om.Reference;
+import org.apache.felix.scrplugin.om.Service;
+import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
+import org.apache.felix.scrplugin.om.metatype.Designate;
+import org.apache.felix.scrplugin.om.metatype.MTObject;
+import org.apache.felix.scrplugin.om.metatype.MetaData;
+import org.apache.felix.scrplugin.om.metatype.OCD;
import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;
import org.apache.felix.scrplugin.xml.MetaTypeIO;
+import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.metatype.MetaTypeService;
-
/**
* The <code>SCRDescriptorGenerator</code> class does the hard work of
* generating the SCR descriptors. This class is being instantiated and
* configured by clients and the {@link #execute()} method called to generate
* the descriptor files.
* <p>
- * When using this class carefully consider calling <i>all</i> setter methods
- * to properly configure the generator. All setter method document, which
- * default value is assumed for the respective property if the setter is
- * not called.
+ * When using this class carefully consider calling <i>all</i> setter methods to properly configure the generator. All setter
+ * method document, which default value is assumed for the respective property if the setter is not called.
* <p>
* Instances of this class are not thread save and should not be reused.
*/
-public class SCRDescriptorGenerator
-{
+public class SCRDescriptorGenerator {
private final Log logger;
- private File outputDirectory = null;
-
- private JavaClassDescriptorManager descriptorManager;
+ private File outputDirectory;
private String finalName = "serviceComponents.xml";
private String metaTypeName = "metatype.xml";
- private boolean generateAccessors = true;
+ /** The project. */
+ private Project project;
- protected boolean strictMode = false;
+ /** The options. */
+ private Options options = new Options();
- private Map<String, String> properties = new HashMap<String, String>();
+ /** The annotation scanner. */
+ private ClassScanner scanner;
- private String specVersion = null;
-
+ /** The issue log. */
+ private IssueLog iLog;
/**
- * Create an instance of this generator using the given {@link Log}
- * instance of logging.
+ * Create an instance of this generator using the given {@link Log} instance
+ * of logging.
*/
- public SCRDescriptorGenerator( Log logger )
- {
+ public SCRDescriptorGenerator(final Log logger) {
this.logger = logger;
}
+ /**
+ * Set the project. This is required.
+ */
+ public void setProject(final Project p) {
+ this.project = p;
+ }
+
+ /**
+ * Set the options.
+ */
+ public void setOptions(final Options p) {
+ this.options = p;
+ }
/**
* Sets the directory where the descriptor files will be created.
* <p>
- * This field has no default value and this setter <b>must</b> called prior
- * to calling {@link #execute()}.
+ * This field has no default value and this setter <b>must</b> called prior to calling {@link #execute()}.
*/
- public void setOutputDirectory( File outputDirectory )
- {
+ public void setOutputDirectory(final File outputDirectory) {
this.outputDirectory = outputDirectory;
}
-
- /**
- * Sets the {@link JavaClassDescriptorManager} instance used to access
- * existing descriptors and to parse JavaDoc tags as well as interpret
- * the SCR annotations.
- * <p>
- * This field has no default value and this setter <b>must</b> called prior
- * to calling {@link #execute()}.
- */
- public void setDescriptorManager( JavaClassDescriptorManager descriptorManager )
- {
- this.descriptorManager = descriptorManager;
- }
-
-
/**
* Sets the name of the SCR declaration descriptor file. This file will be
- * created in the <i>OSGI-INF</i> directory below the
- * {@link #setOutputDirectory(File) output directory}.
+ * created in the <i>OSGI-INF</i> directory below the {@link #setOutputDirectory(File) output directory}.
* <p>
- * This file will be overwritten if already existing. If no descriptors
- * are created the file is actually removed.
+ * This file will be overwritten if already existing. If no descriptors are created the file is actually removed.
* <p>
* The default value of this property is <code>serviceComponents.xml</code>.
*/
- public void setFinalName( String finalName )
- {
+ public void setFinalName(final String finalName) {
this.finalName = finalName;
}
-
/**
* Sets the name of the file taking the Metatype Service descriptors. This
- * file will be created in the <i>OSGI-INF/metatype</i> directory below the
- * {@link #setOutputDirectory(File) output directory}.
+ * file will be created in the <i>OSGI-INF/metatype</i> directory below the {@link #setOutputDirectory(File) output directory}
+ * .
* <p>
- * This file will be overwritten if already existing. If no descriptors
- * are created the file is actually removed.
+ * This file will be overwritten if already existing. If no descriptors are created the file is actually removed.
* <p>
* The default value of this property is <code>metatype.xml</code>.
*/
- public void setMetaTypeName( String metaTypeName )
- {
+ public void setMetaTypeName(final String metaTypeName) {
this.metaTypeName = metaTypeName;
}
-
- /**
- * Defines whether bind and unbind methods are automatically created by
- * the SCR descriptor generator.
- * <p>
- * The generator uses the ASM library to create the method byte codes
- * directly inside the class files. If bind and unbind methods are not
- * to be created, the generator fails if such methods are missing.
- * <p>
- * The default value of this property is <code>true</code>.
- */
- public void setGenerateAccessors( boolean generateAccessors )
- {
- this.generateAccessors = generateAccessors;
- }
-
-
- /**
- * Defines whether warnings should be considered as errors and thus cause
- * the generation process to fail.
- * <p>
- * The default value of this property is <code>false</code>.
- */
- public void setStrictMode( boolean strictMode )
- {
- this.strictMode = strictMode;
- }
-
-
- /**
- * Sets global properties to be set for each descriptor. If a descriptor
- * provides properties of the same name, the descriptor properties are preferred
- * over the properties provided here.
- * <p>
- * The are no default global properties.
- */
- public void setProperties( Map<String, String> properties )
- {
- this.properties = new HashMap<String, String>( properties );
- }
-
-
- /**
- * Sets the Declarative Services specification version number to be forced
- * on the declarations.
- * <p>
- * Supported values for this property are <code>null</code> to autodetect
- * the specification version, <code>1.0</code> to force 1.0 descriptors and
- * <code>1.1</code> to force 1.1 descriptors. If 1.0 descriptors are forced
- * the generation fails if a descriptor requires 1.1 functionality.
- * <p>
- * The default is to generate the descriptor version according to the
- * capabilities used by the descriptors. If no 1.1 capabilities, such as
- * <code>configuration-policy</code>, are used, version 1.0 is used,
- * otherwise a 1.1 descriptor is generated.
- */
- public void setSpecVersion( String specVersion )
- {
- this.specVersion = specVersion;
- }
-
-
/**
* Actually generates the Declarative Services and Metatype descriptors
- * scanning the java sources provided by the
- * {@link #setDescriptorManager(JavaClassDescriptorManager) descriptor manager}.
+ * scanning the java sources provided by the {@link #setProject(Project)}
*
- * @return <code>true</code> if descriptors have been generated.
+ * @return A list of generated file names, relative to the output directory
*
* @throws SCRDescriptorException
* @throws SCRDescriptorFailureException
*/
- public boolean execute() throws SCRDescriptorException, SCRDescriptorFailureException
- {
- this.logger.debug( "Starting SCRDescriptorMojo...." );
- this.logger.debug( "..generating accessors: " + this.generateAccessors );
- this.logger.debug( "..parsing javadocs: " + this.descriptorManager.isParseJavadocs() );
- this.logger.debug( "..processing annotations: " + this.descriptorManager.isProcessAnnotations() );
+ public Result execute() throws SCRDescriptorException, SCRDescriptorFailureException {
+ if (this.project == null) {
+ throw new SCRDescriptorFailureException("Project has not been set!");
+ }
+ if (this.options == null) {
+ // use default options
+ this.options = new Options();
+ }
+
+ this.logger.debug("Starting SCRDescriptorMojo....");
+ this.logger.debug("..generating accessors: " + this.options.isGenerateAccessors());
// check speck version configuration
- int specVersion = toSpecVersionCode( this.specVersion, null );
- if ( this.specVersion == null )
- {
- this.logger.debug( "..auto detecting spec version" );
- }
- else
- {
- this.logger.debug( "..using spec version " + this.specVersion + " (" + specVersion + ")" );
+ SpecVersion specVersion = options.getSpecVersion();
+ if (specVersion == null) {
+ this.logger.debug("..auto detecting spec version");
+ } else {
+ this.logger.debug("..using spec version " + specVersion.getName());
}
- final IssueLog iLog = new IssueLog( this.strictMode );
+ // create a log
+ this.iLog = new IssueLog(this.options.isStrictMode());
+ // create the annotation processor manager
+ final AnnotationProcessor aProcessor = new AnnotationProcessorManager(options.getAnnotationProcessors(),
+ this.project.getClassLoader());
+
+ // create the class scanner - and start scanning
+ this.scanner = new ClassScanner(logger, iLog, project, aProcessor);
+ final List<ClassDescription> scannedDescriptions = scanner.scanSources();
+
+ // setup metadata
final MetaData metaData = new MetaData();
- metaData.setLocalization( MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype" );
+ metaData.setLocalization(MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype");
- // iterate through all source classes and check for component tag
- final JavaClassDescription[] javaSources = descriptorManager.getSourceDescriptions();
- Arrays.sort( javaSources, new JavaClassDescriptionInheritanceComparator() );
+ final List<Component> processedComponents = new ArrayList<Component>();
+ for (final ClassDescription desc : scannedDescriptions) {
+ this.logger.debug("Processing component class " + desc.getSource());
- final List<Component> scannedComponents = new ArrayList<Component>();
- for ( int i = 0; i < javaSources.length; i++ )
- {
- this.logger.debug( "Testing source " + javaSources[i].getName() );
- final JavaTag tag = javaSources[i].getTagByName( Constants.COMPONENT );
- if ( tag != null )
- {
- // FELIX-2853 : Deprecate javadoc tags.
- // This is not the most clever way of doing this, but it is the least intrusive...
- if ( javaSources[i] instanceof QDoxJavaClassDescription
- && !(javaSources[i] instanceof AnnotationJavaClassDescription)) {
- iLog.addDeprecationWarning("Class " + javaSources[i].getName() + " is using deprecated javadoc tags ",
- tag.getSourceLocation(), tag.getLineNumber());
- }
- this.logger.debug( "Processing service class " + javaSources[i].getName() );
- // check if there is more than one component tag!
- if ( javaSources[i].getTagsByName( Constants.COMPONENT, false ).length > 1 )
- {
- iLog.addError( "Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT
- + " tag." + " Merge the tags to a single tag.", tag.getSourceLocation(), tag.getLineNumber() );
- }
- else
- {
- try
- {
- final Component comp = this.createComponent( javaSources[i], tag, metaData, iLog );
- if ( comp.getSpecVersion() > specVersion )
- {
+ // check if there is more than one component definition
+ if (desc.getDescriptions(ComponentDescription.class).size() > 1) {
+ iLog.addError("Class has more than one component definition." +
+ " Check the annotations and merge the definitions to a single definition.",
+ desc.getSource());
+ } else {
+ try {
+ final Component comp = this.createComponent(desc, metaData, iLog);
+ if (comp.getSpecVersion() != null) {
+ if ( specVersion == null ) {
+ specVersion = comp.getSpecVersion();
+ logger.debug("Setting used spec version to " + specVersion);
+ } else if (comp.getSpecVersion().ordinal() > specVersion.ordinal() && this.options.getSpecVersion() != null) {
// if a spec version has been configured and a component requires a higher
// version, this is considered an error!
- if ( this.specVersion != null )
- {
- String v = Constants.COMPONENT_DS_SPEC_VERSION_10;
- if ( comp.getSpecVersion() == Constants.VERSION_1_1 )
- {
- v = Constants.COMPONENT_DS_SPEC_VERSION_11;
- }
- iLog.addError( "Component " + comp + " requires spec version " + v
- + " but plugin is configured to use version " + this.specVersion, tag
- .getSourceLocation(), tag.getLineNumber() );
- }
- specVersion = comp.getSpecVersion();
+ iLog.addError("Component " + comp + " requires spec version " + comp.getSpecVersion().name()
+ + " but plugin is configured to use version " + this.options.getSpecVersion(),
+ desc.getSource());
}
- scannedComponents.add( comp );
}
- catch ( SCRDescriptorException sde )
- {
- iLog.addError( sde.getMessage(), sde.getSourceLocation(), sde.getLineNumber() );
- }
+ processedComponents.add(comp);
+ } catch (final SCRDescriptorException sde) {
+ iLog.addError(sde.getMessage(), sde.getSourceLocation());
}
}
}
- this.logger.debug( "..generating descriptor for spec version: " + this.specVersion );
+ // if spec version is still not set, we're using lowest available
+ if ( specVersion == null ) {
+ specVersion = SpecVersion.VERSION_1_0;
+ logger.debug("Using default spec version " + specVersion);
+ }
+ this.logger.debug("Generating descriptor for spec version: " + specVersion);
// now check for abstract components and fill components objects
final Components components = new Components();
- final Components abstractComponents = new Components();
- components.setSpecVersion( specVersion );
- abstractComponents.setSpecVersion( specVersion );
+ components.setSpecVersion(specVersion);
- for ( final Component comp : scannedComponents )
- {
+ for (final Component comp : processedComponents) {
final int errorCount = iLog.getNumberOfErrors();
- // before we can validate we should check the references for bind/unbind method
- // in order to create them if possible
- for ( final Reference ref : comp.getReferences() )
- {
- // if this is a field with a single cardinality,
- // we look for the bind/unbind methods
- // and create them if they are not availabe
- if ( this.generateAccessors && !ref.isLookupStrategy() )
- {
- if ( ref.getJavaTag().getField() != null
- && comp.getJavaClassDescription() instanceof ModifiableJavaClassDescription )
- {
- if ( ref.getCardinality().equals( "0..1" ) || ref.getCardinality().equals( "1..1" ) )
- {
- final String bindValue = ref.getBind();
- final String unbindValue = ref.getUnbind();
- final String name = ref.getName();
- final String type = ref.getInterfacename();
+ final Context ctx = new Context();
+ ctx.setClassDescription(comp.getClassDescription());
+ ctx.setIssueLog(iLog);
+ ctx.setProject(project);
+ ctx.setSpecVersion(specVersion);
+ ctx.setOptions(options);
- 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 );
- }
+ if ( this.options.isGenerateAccessors() ) {
+ // before we can validate we should check the references for bind/unbind method
+ // in order to create them if possible
+
+ for (final Reference ref : comp.getReferences()) {
+ // if this is a field with a single cardinality,
+ // we look for the bind/unbind methods
+ // and create them if they are not availabe
+ if (!ref.isLookupStrategy() && ref.getField() != null
+ && (ref.getCardinality() == ReferenceCardinality.OPTIONAL_UNARY || ref.getCardinality() == ReferenceCardinality.MANDATORY_UNARY)) {
+
+ final String bindValue = ref.getBind();
+ final String unbindValue = ref.getUnbind();
+ final String name = ref.getName();
+ final String type = ref.getInterfacename();
+
+ boolean createBind = false;
+ boolean createUnbind = false;
+
+ // Only create method if no bind name has been specified
+ if (bindValue == null && ref.findMethod(ctx, "bind") == null) {
+ // create bind method
+ createBind = true;
+ }
+ if (unbindValue == null && ref.findMethod(ctx, "unbind") == null) {
+ // create unbind method
+ createUnbind = true;
+ }
+ if (createBind || createUnbind) {
+ ClassModifier.addMethods(comp.getClassDescription().getDescribedClass().getName(),
+ name,
+ ref.getField().getName(),
+ type,
+ createBind,
+ createUnbind,
+ this.project.getClassesDirectory());
}
}
}
}
- comp.validate( specVersion, iLog );
+ comp.validate(ctx);
+
// ignore component if it has errors
- if ( iLog.getNumberOfErrors() == errorCount )
- {
- if ( !comp.isDs() )
- {
- logger.debug( "Ignoring descriptor " + comp );
- }
- else if ( comp.isAbstract() )
- {
- this.logger.debug( "Adding abstract descriptor " + comp );
- abstractComponents.addComponent( comp );
- }
- else
- {
- this.logger.debug( "Adding descriptor " + comp );
- components.addComponent( comp );
- abstractComponents.addComponent( comp );
+ if (iLog.getNumberOfErrors() == errorCount) {
+ if (!comp.isDs()) {
+ logger.debug("Ignoring descriptor for DS : " + comp);
+ } else if (!comp.isAbstract()) {
+ this.logger.debug("Adding descriptor for DS : " + comp);
+ components.addComponent(comp);
}
}
}
// log issues
- iLog.logMessages( logger );
+ iLog.logMessages(logger);
// after checking all classes, throw if there were any failures
- if ( iLog.hasErrors() )
- {
- throw new SCRDescriptorFailureException( "SCR Descriptor parsing had failures (see log)" );
+ if (iLog.hasErrors()) {
+ throw new SCRDescriptorFailureException("SCR Descriptor parsing had failures (see log)");
}
- boolean addResources = false;
+ final Result result = new Result();
// write meta type info if there is a file name
- if ( !StringUtils.isEmpty( this.metaTypeName ) )
- {
- File mtFile = new File( this.outputDirectory, "OSGI-INF" + File.separator + "metatype" + File.separator
- + this.metaTypeName );
+ if (!StringUtils.isEmpty(this.metaTypeName)) {
+ final String path = "OSGI-INF" + File.separator + "metatype" + File.separator + this.metaTypeName;
+ final File mtFile = new File(this.outputDirectory, path);
final int size = metaData.getOCDs().size() + metaData.getDesignates().size();
- if ( size > 0 )
- {
- this.logger.info( "Generating " + size + " MetaType Descriptors to " + mtFile );
+ if (size > 0) {
+ this.logger.info("Generating " + size + " MetaType Descriptors to " + mtFile);
mtFile.getParentFile().mkdirs();
- MetaTypeIO.write( metaData, mtFile );
- addResources = true;
- }
- else
- {
- if ( mtFile.exists() )
- {
+ MetaTypeIO.write(metaData, mtFile);
+ result.setMetatypeFiles(Collections.singletonList(path.replace(File.separatorChar, '/')));
+ } else {
+ if (mtFile.exists()) {
mtFile.delete();
}
}
- }
- else
- {
- this.logger.info( "Meta type file name is not set: meta type info is not written." );
- }
-
- // if we have descriptors, write them in our scr private file (for component inheritance)
- final File adFile = new File( this.outputDirectory, Constants.ABSTRACT_DESCRIPTOR_RELATIVE_PATH );
- if ( !abstractComponents.getComponents().isEmpty() )
- {
- this.logger.info( "Writing abstract service descriptor " + adFile + " with "
- + abstractComponents.getComponents().size() + " entries." );
- adFile.getParentFile().mkdirs();
- ComponentDescriptorIO.write( abstractComponents, adFile, true );
- addResources = true;
- }
- else
- {
- this.logger.debug( "No abstract SCR Descriptors found in project." );
- // remove file
- if ( adFile.exists() )
- {
- this.logger.debug( "Removing obsolete abstract service descriptor " + adFile );
- adFile.delete();
- }
+ } else {
+ this.logger.info("Meta type file name is not set: meta type info is not written.");
}
// check descriptor file
- final File descriptorFile = StringUtils.isEmpty( this.finalName ) ? null : new File( new File(
- this.outputDirectory, "OSGI-INF" ), this.finalName );
+ final String descriptorPath = "OSGI-INF" + File.separator + this.finalName;
+ final File descriptorFile = StringUtils.isEmpty(this.finalName) ? null : new File(this.outputDirectory, descriptorPath);
// terminate if there is nothing else to write
- if ( components.getComponents().isEmpty() )
- {
- this.logger.debug( "No SCR Descriptors found in project." );
+ if (components.getComponents().isEmpty()) {
+ this.logger.debug("No Service Component Descriptors found in project.");
// remove file if it exists
- if ( descriptorFile != null && descriptorFile.exists() )
- {
- this.logger.debug( "Removing obsolete service descriptor " + descriptorFile );
+ if (descriptorFile != null && descriptorFile.exists()) {
+ this.logger.debug("Removing obsolete service descriptor " + descriptorFile);
descriptorFile.delete();
}
- }
- else
- {
- if ( descriptorFile == null )
- {
- throw new SCRDescriptorFailureException( "Descriptor file name must not be empty." );
+ } else {
+ if (descriptorFile == null) {
+ throw new SCRDescriptorFailureException("Descriptor file name must not be empty.");
}
// finally the descriptors have to be written ....
descriptorFile.getParentFile().mkdirs(); // ensure parent dir
- this.logger.info( "Generating " + components.getComponents().size() + " Service Component Descriptors to "
- + descriptorFile );
+ this.logger.info("Writing " + components.getComponents().size() + " Service Component Descriptors to "
+ + descriptorFile);
- ComponentDescriptorIO.write( components, descriptorFile, false );
- addResources = true;
+ ComponentDescriptorIO.write(components, descriptorFile);
+ result.setScrFiles(Collections.singletonList(descriptorPath.replace(File.separatorChar, '/')));
}
- return addResources;
+ return result;
}
-
/**
- * Create a component for the java class description.
- * @param description
- * @return The generated component descriptor or null if any error occurs.
- * @throws SCRDescriptorException
+ * Create the SCR objects based on the descriptions
*/
- protected Component createComponent( JavaClassDescription description, JavaTag componentTag, MetaData metaData,
- final IssueLog iLog ) throws SCRDescriptorException
- {
- // create a new component
- final Component component = new Component( componentTag );
+ private Component createComponent(final ClassDescription desc,
+ final MetaData metaData,
+ final IssueLog iLog)
+ throws SCRDescriptorException, SCRDescriptorFailureException {
+ final ComponentDescription componentDesc = desc.getDescription(ComponentDescription.class);
+ final Component comp = new Component(desc, componentDesc.getAnnotation(), desc.getSource());
- // set implementation
- component.setImplementation( new Implementation( description.getName() ) );
+ comp.setName(componentDesc.getName());
+ comp.setConfigurationPolicy(componentDesc.getConfigurationPolicy());
+ comp.setAbstract(componentDesc.isAbstract());
+ comp.setDs(componentDesc.isCreateDs());
+ comp.setFactory(componentDesc.getFactory());
+ comp.setSpecVersion(componentDesc.getSpecVersion());
- final boolean inherited = getBoolean( componentTag, Constants.COMPONENT_INHERIT, true );
- final OCD ocd = this.doComponent( componentTag, component, metaData,inherited, iLog );
-
- this.doServices( description.getTagsByName( Constants.SERVICE, inherited ), component, description );
-
- // collect references from class tags and fields
- final Map<String, Object[]> references = new LinkedHashMap<String, Object[]>();
- // Utility handler for propertie
- final PropertyHandler propertyHandler = new PropertyHandler( component, ocd );
-
- JavaClassDescription currentDescription = description;
- do
- {
- // properties
- final JavaTag[] props = currentDescription.getTagsByName( Constants.PROPERTY, false );
- for ( int i = 0; i < props.length; i++ )
- {
- propertyHandler.testProperty( props[i], null, description == currentDescription );
- }
-
- // references
- final JavaTag[] refs = currentDescription.getTagsByName( Constants.REFERENCE, false );
- for ( int i = 0; i < refs.length; i++ )
- {
- this.testReference( references, refs[i], null, description == currentDescription );
- }
-
- // fields
- final JavaField[] fields = currentDescription.getFields();
- for ( int i = 0; i < fields.length; i++ )
- {
- JavaTag tag = fields[i].getTagByName( Constants.REFERENCE );
- if ( tag != null )
- {
- this.testReference( references, tag, fields[i].getName(), description == currentDescription );
- }
-
- propertyHandler.handleField( fields[i], description == currentDescription );
- }
-
- currentDescription = currentDescription.getSuperClass();
- }
- while ( inherited && currentDescription != null );
-
- // process properties
- propertyHandler.processProperties( this.properties, iLog );
-
- // process references
- final Iterator<Map.Entry<String, Object[]>> refIter = references.entrySet().iterator();
- while ( refIter.hasNext() )
- {
- final Map.Entry<String, Object[]> entry = refIter.next();
- final String refName = entry.getKey();
- final Object[] values = entry.getValue();
- final JavaTag tag = ( JavaTag ) values[0];
- this.doReference( tag, refName, component, values[1].toString(), ((Boolean)values[2]).booleanValue() );
- }
-
- // pid handling
- final boolean createPid = getBoolean( componentTag, Constants.COMPONENT_CREATE_PID, true );
- if ( createPid )
- {
- // check for an existing pid first
- boolean found = false;
- final Iterator<Property> iter = component.getProperties().iterator();
- while ( !found && iter.hasNext() )
- {
- final Property prop = iter.next();
- found = org.osgi.framework.Constants.SERVICE_PID.equals( prop.getName() );
- }
- if ( !found )
- {
- final Property pid = new Property();
- component.addProperty( pid );
- pid.setName( org.osgi.framework.Constants.SERVICE_PID );
- pid.setValue( component.getName() );
- }
- }
- return component;
- }
-
-
- /**
- * Fill the component object with the information from the tag.
- * @param tag
- * @param component
- */
- protected OCD doComponent( final JavaTag tag,
- final Component component,
- final MetaData metaData,
- final boolean inherit,
- final IssueLog iLog )
- throws SCRDescriptorException
- {
-
- // check if this is an abstract definition
- final String abstractType = tag.getNamedParameter( Constants.COMPONENT_ABSTRACT );
- if ( abstractType != null )
- {
- component.setAbstract( "yes".equalsIgnoreCase( abstractType ) || "true".equalsIgnoreCase( abstractType ) );
- }
- else
- {
- // default true for abstract classes, false otherwise
- component.setAbstract( tag.getJavaClassDescription().isAbstract() );
- }
-
- // check if this is a definition to ignore
- final String ds = tag.getNamedParameter( Constants.COMPONENT_DS );
- component.setDs( ( ds == null ) ? true : ( "yes".equalsIgnoreCase( ds ) || "true".equalsIgnoreCase( ds ) ) );
-
- String name = tag.getNamedParameter( Constants.COMPONENT_NAME );
- component.setName( StringUtils.isEmpty( name ) ? component.getImplementation().getClassame() : name );
-
- component.setEnabled( Boolean.valueOf( getBoolean( tag, Constants.COMPONENT_ENABLED, true ) ) );
- component.setFactory( tag.getNamedParameter( Constants.COMPONENT_FACTORY ) );
-
- // FELIX-1703: support explicit SCR version declaration
- final String dsSpecVersion = tag.getNamedParameter( Constants.COMPONENT_DS_SPEC_VERSION );
- if ( dsSpecVersion != null )
- {
- component.setSpecVersion( toSpecVersionCode( dsSpecVersion, tag ) );
- }
-
- // FELIX-593: immediate attribute does not default to true all the
- // times hence we only set it if declared in the tag
- if ( tag.getNamedParameter( Constants.COMPONENT_IMMEDIATE ) != null )
- {
- component.setImmediate( Boolean.valueOf( getBoolean( tag, Constants.COMPONENT_IMMEDIATE, true ) ) );
- }
-
- // check for V1.1 attributes: configuration policy
- if ( tag.getNamedParameter( Constants.COMPONENT_CONFIG_POLICY ) != null )
- {
- component.setSpecVersion( Constants.VERSION_1_1 );
- component.setConfigurationPolicy( tag.getNamedParameter( Constants.COMPONENT_CONFIG_POLICY ) );
- }
- // check for V1.1 attributes: activate, deactivate, modified
- component.setActivate(this.checkLifecycleMethod(component, Constants.COMPONENT_ACTIVATE, tag, inherit));
- component.setDeactivate(this.checkLifecycleMethod(component, Constants.COMPONENT_DEACTIVATE, tag, inherit));
- component.setModified(this.checkLifecycleMethod(component, Constants.COMPONENT_MODIFIED, tag, inherit));
-
- // whether metatype information is to generated for the component
- final String metaType = tag.getNamedParameter( Constants.COMPONENT_METATYPE );
- final boolean hasMetaType = metaType == null || "yes".equalsIgnoreCase( metaType )
- || "true".equalsIgnoreCase( metaType );
- if ( !component.isAbstract() && hasMetaType )
- {
- // ocd
- final OCD ocd = new OCD();
+ // Create metatype (if required)
+ final OCD ocd;
+ if ( !componentDesc.isAbstract() && componentDesc.isCreateMetatype() ) {
+ // OCD
+ ocd = new OCD();
metaData.addOCD( ocd );
- ocd.setId( component.getName() );
- String ocdName = tag.getNamedParameter( Constants.COMPONENT_LABEL );
- if ( ocdName == null )
- {
- ocdName = "%" + component.getName() + ".name";
+ ocd.setId( componentDesc.getName() );
+ if ( componentDesc.getLabel() != null ) {
+ ocd.setName( componentDesc.getLabel() );
+ } else {
+ ocd.setName( "%" + componentDesc.getName() + ".name");
}
- ocd.setName( ocdName );
- String ocdDescription = tag.getNamedParameter( Constants.COMPONENT_DESCRIPTION );
- if ( ocdDescription == null )
- {
- ocdDescription = "%" + component.getName() + ".description";
+ if ( componentDesc.getDescription() != null ) {
+ ocd.setDescription( componentDesc.getDescription() );
+ } else {
+ ocd.setDescription( "%" + componentDesc.getName() + ".description");
}
- ocd.setDescription( ocdDescription );
- // designate
+
+ // Designate
final Designate designate = new Designate();
metaData.addDesignate( designate );
- designate.setPid( component.getName() );
+ designate.setPid( componentDesc.getName() );
- // factory pid
- final String setFactoryPidValue = tag.getNamedParameter( Constants.COMPONENT_SET_METATYPE_FACTORY_PID );
- final boolean setFactoryPid = setFactoryPidValue != null
- && ( "yes".equalsIgnoreCase( setFactoryPidValue ) || "true".equalsIgnoreCase( setFactoryPidValue ) );
- if ( setFactoryPid )
- {
- if ( component.getFactory() == null )
- {
- designate.setFactoryPid( component.getName() );
- }
- else
- {
- iLog.addWarning( "Component factory " + component.getName()
- + " should not set metatype factory pid.", tag.getSourceLocation(), tag.getLineNumber() );
+ // Factory pid
+ if ( componentDesc.isSetMetatypeFactoryPid() ) {
+ if ( componentDesc.getFactory() == null ) {
+ designate.setFactoryPid( componentDesc.getName() );
+ } else {
+ iLog.addWarning( "Component factory " + componentDesc.getName()
+ + " should not set metatype factory pid.", desc.getSource() );
}
}
- // designate.object
+ // MTObject
final MTObject mtobject = new MTObject();
designate.setObject( mtobject );
- mtobject.setOcdref( component.getName() );
- return ocd;
+ mtobject.setOcdref( componentDesc.getName() );
+ } else {
+ ocd = null;
}
- return null;
- }
- private String checkLifecycleMethod(final Component component,
- final String methodTagName,
- final JavaTag tag,
- final boolean inherit)
- throws SCRDescriptorException
- {
- String method = null;
- if ( tag.getNamedParameter( methodTagName ) != null )
- {
- method = tag.getNamedParameter( methodTagName );
- }
- else if ( inherit )
- {
- // check if a super class has the activate method specified
- JavaClassDescription desc = tag.getJavaClassDescription().getSuperClass();
- while ( desc != null && method == null )
- {
- final JavaTag componentTag = desc.getTagByName( Constants.COMPONENT );
- if ( componentTag != null && componentTag.getNamedParameter( methodTagName ) != null )
- {
- method = componentTag.getNamedParameter( methodTagName );
+ // Create implementation object
+ final Implementation impl = new Implementation(desc.getDescribedClass().getName());
+ comp.setImplementation(impl);
+
+ final Map<String, Reference> allReferences = new HashMap<String, Reference>();
+ final Map<String, Property> allProperties = new HashMap<String, Property>();
+
+ ClassDescription current = desc;
+ boolean inherit;
+ do {
+ final ComponentDescription cd = current.getDescription(ComponentDescription.class);
+ inherit = (cd == null ? true : cd.isInherit());
+
+ if ( cd != null ) {
+ // handle enabled and immediate
+ if ( comp.isEnabled() == null ) {
+ comp.setEnabled(cd.getEnabled());
}
- desc = desc.getSuperClass();
+ if ( comp.isImmediate() == null ) {
+ comp.setImmediate(cd.getImmediate());
+ }
+
+ // lifecycle methods
+ if ( comp.getActivate() == null && cd.getActivate() != null ) {
+ comp.setActivate(cd.getActivate().getName());
+ }
+ if ( comp.getDeactivate() == null && cd.getDeactivate() != null ) {
+ comp.setDeactivate(cd.getDeactivate().getName());
+ }
+ if ( comp.getModified() == null && cd.getModified() != null ) {
+ comp.setModified(cd.getModified().getName());
+ }
+ if ( comp.getActivate() != null || comp.getDeactivate() != null || comp.getModified() != null ) {
+ // spec version must be at least 1.1
+ comp.setSpecVersion(SpecVersion.VERSION_1_1);
+ }
}
+
+ // services, properties, references
+ this.processServices(current, comp);
+ this.processProperties(current, comp, ocd, allProperties);
+ this.processReferences(current, comp, allReferences);
+
+ // go up in the class hierarchy
+ if ( !inherit || current.getDescribedClass().getSuperclass() == null ) {
+ current = null;
+ } else {
+ current = this.scanner.getDescription(current.getDescribedClass().getSuperclass());
+ }
+ } while ( inherit && current != null);
+
+ // PID handling
+ if ( componentDesc.isCreatePid() && !allProperties.containsKey(org.osgi.framework.Constants.SERVICE_PID)) {
+ final Property pid = new Property(null, "scr-generator");
+ pid.setName( org.osgi.framework.Constants.SERVICE_PID );
+ pid.setValue( comp.getName() );
+
+ allProperties.put(org.osgi.framework.Constants.SERVICE_PID, pid);
+ comp.addProperty( pid );
}
- if ( method != null )
- {
- component.setSpecVersion( Constants.VERSION_1_1 );
- }
- return method;
+ this.processGlobalProperties(desc, comp, allProperties);
+
+ return comp;
}
/**
- * Process the service annotations
- * @param services
- * @param component
- * @param description
- * @throws SCRDescriptorException
+ * Process service directives
*/
- 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;
- }
+ private void processServices(final ClassDescription current, final Component component)
+ throws SCRDescriptorException, SCRDescriptorFailureException {
- 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 );
+ final ServiceDescription serviceDesc = current.getDescription(ServiceDescription.class);
+ if ( serviceDesc != null ) {
+ Service service = component.getService();
+ if ( service == null ) {
+ service = new Service();
+ service.setServiceFactory(false);
+ component.setService(service);
}
- else
- {
- String interfaceName = name;
- // check if the value points to a class/interface
- // and search through the imports
- // but only for local services
- if ( description instanceof QDoxJavaClassDescription )
- {
- final JavaClassDescription serviceClass = description.getReferencedClass( name );
- if ( serviceClass == null )
- {
- throw new SCRDescriptorException( "Interface '" + name + "' in class " + description.getName()
- + " does not point to a valid class/interface.", services[i] );
+ if ( serviceDesc.isServiceFactory() ) {
+ service.setServiceFactory(true);
+ }
+ for(final String className : serviceDesc.getInterfaces()) {
+ final Interface interf = new Interface(serviceDesc.getAnnotation(), current.getSource());
+ interf.setInterfaceName(className);
+ service.addInterface(interf);
+ }
+ }
+ }
+
+ /**
+ * Process property directives
+ */
+ private void processProperties(
+ final ClassDescription current,
+ final Component component,
+ final OCD ocd,
+ final Map<String, Property> allProperties)
+ throws SCRDescriptorException, SCRDescriptorFailureException {
+ for(final PropertyDescription pd : current.getDescriptions(PropertyDescription.class)) {
+ final Property prop = new Property(pd.getAnnotation(), current.getSource());
+ prop.setName(pd.getName());
+ prop.setType(pd.getType());
+ if ( pd.getValue() != null ) {
+ prop.setValue(pd.getValue());
+ } else {
+ prop.setMultiValue(pd.getMultiValue());
+ }
+
+ // metatype - is this property private?
+ final boolean isPrivate;
+ if ( pd.isPrivate() != null ) {
+ isPrivate = pd.isPrivate();
+ } else {
+ final String name = prop.getName();
+ if (org.osgi.framework.Constants.SERVICE_RANKING.equals(name)
+ || org.osgi.framework.Constants.SERVICE_PID.equals(name)
+ || org.osgi.framework.Constants.SERVICE_DESCRIPTION.equals(name)
+ || org.osgi.framework.Constants.SERVICE_ID.equals(name)
+ || org.osgi.framework.Constants.SERVICE_VENDOR.equals(name)
+ || ConfigurationAdmin.SERVICE_BUNDLELOCATION.equals(name)
+ || ConfigurationAdmin.SERVICE_FACTORYPID.equals(name) ) {
+ isPrivate = true;
+ } else {
+ isPrivate = false;
+ }
+ }
+ if ( !isPrivate && ocd != null ) {
+ final AttributeDefinition ad = new AttributeDefinition();
+ ocd.getProperties().add(ad);
+ ad.setId(prop.getName());
+ ad.setType(prop.getType().name());
+
+ if (pd.getLabel() != null ) {
+ ad.setName(pd.getLabel());
+ } else {
+ ad.setName("%" + prop.getName() + ".name");
+ }
+ if (pd.getDescription() != null ) {
+ ad.setDescription(pd.getDescription());
+ } else {
+ ad.setDescription("%" + prop.getName() + ".description");
+ }
+
+ if ( pd.getUnbounded() == PropertyUnbounded.DEFAULT ) {
+ ad.setCardinality(pd.getCardinality());
+ } else if ( pd.getUnbounded() == PropertyUnbounded.ARRAY ) {
+ // unlimited array
+ ad.setCardinality(new Integer(Integer.MAX_VALUE));
+ } else {
+ // unlimited vector
+ ad.setCardinality(new Integer(Integer.MIN_VALUE));
+ }
+
+ ad.setDefaultValue(prop.getValue());
+ ad.setDefaultMultiValue(prop.getMultiValue());
+
+ // check options
+ final String[] parameters = pd.getOptions();
+ if ( parameters != null && parameters.length > 0 ) {
+ final Map<String, String> options = new LinkedHashMap<String, String>();
+ for (int j=0; j < parameters.length; j=j+2) {
+ final String optionLabel = parameters[j];
+ final String optionValue = (j < parameters.length-1) ? parameters[j+1] : null;
+ if (optionValue != null) {
+ options.put(optionLabel, optionValue);
+ }
}
- interfaceName = serviceClass.getName();
+ ad.setOptions(options);
}
- final Interface interf = new Interface( services[i] );
- interf.setInterfacename( interfaceName );
- service.addInterface( interf );
+
}
-
- serviceFactory |= getBoolean( services[i], Constants.SERVICE_FACTORY, false );
+ if ( this.testProperty(current, allProperties, prop, current == component.getClassDescription())) {
+ component.addProperty(prop);
+ }
}
-
- service.setServicefactory( serviceFactory );
}
-
/**
- * Recursively add interfaces to the service.
+ * Add global properties (if not already defined in the component)
*/
- 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] );
- }
+ private void processGlobalProperties(final ClassDescription desc,
+ final Component component,
+ final Map<String, Property> allProperties) {
+ // apply pre configured global properties
+ if ( this.options.getProperties() != null ) {
+ for(final Map.Entry<String, String> entry : this.options.getProperties().entrySet()) {
+ final String propName = entry.getKey();
+ final String value = entry.getValue();
+ // check if the service already provides this property
+ if ( value != null && !allProperties.containsKey(propName) ) {
- // try super class
- this.addInterfaces( service, serviceTag, description.getSuperClass() );
+ final Property p = new Property(null, "scr-generator");
+ p.setName(propName);
+ p.setValue(value);
+ p.setType(PropertyType.String);
+
+ component.addProperty(p);
+ allProperties.put(propName, p);
+ }
+ }
}
}
+ /**
+ * Test a newly found property
+ */
+ private boolean testProperty(final ClassDescription current,
+ final Map<String, Property> allProperties,
+ final Property newProperty,
+ boolean isInspectedClass ) {
+ final String propName = newProperty.getName();
+
+ if ( !StringUtils.isEmpty(propName) ) {
+ if ( allProperties.containsKey(propName) ) {
+ // if the current class is the class we are currently inspecting, we
+ // have found a duplicate definition
+ if ( isInspectedClass ) {
+ iLog.addError("Duplicate definition for property " + propName + " in class "
+ + current.getDescribedClass().getName(), current.getSource() );
+ }
+ } else {
+ allProperties.put(propName, newProperty);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Process reference directives
+ */
+ private void processReferences(final ClassDescription current,
+ final Component component,
+ final Map<String, Reference> allReferences)
+ throws SCRDescriptorException, SCRDescriptorFailureException {
+ for(final ReferenceDescription rd : current.getDescriptions(ReferenceDescription.class)) {
+ final Reference ref = new Reference(rd.getAnnotation(), current.getSource());
+ ref.setName(rd.getName());
+ ref.setInterfacename(rd.getInterfaceName());
+ ref.setCardinality(rd.getCardinality());
+ ref.setPolicy(rd.getPolicy());
+ ref.setStrategy(rd.getStrategy());
+ ref.setTarget(rd.getTarget());
+ ref.setField(rd.getField());
+ if ( rd.getBind() != null ) {
+ ref.setBind(rd.getBind().getName());
+ }
+ if ( rd.getUnbind() != null ) {
+ ref.setUnbind(rd.getUnbind().getName());
+ }
+ if ( rd.getUpdated() != null ) {
+ ref.setUpdated(rd.getUpdated().getName());
+ }
+
+ if ( this.testReference(current, allReferences, ref, component.getClassDescription() == current) ) {
+ component.addReference(ref);
+ }
+ }
+ }
/**
* 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
- {
- String refName = this.getReferenceName( reference, defaultName );
-
- boolean setName = refName != null;
- if ( refName == null)
- {
- refName = this.getReferencedInterface(reference, isInspectedClass, null);
+ private boolean testReference(final ClassDescription current,
+ final Map<String, Reference> allReferences,
+ final Reference newReference,
+ boolean isInspectedClass ) {
+ String refName = newReference.getName();
+ if ( refName == null) {
+ refName = newReference.getInterfacename();
}
- if ( refName != null )
- {
- if ( references.containsKey( refName ) )
- {
+ if ( refName != null ) {
+ if ( allReferences.containsKey( refName ) ) {
// if the current class is the class we are currently inspecting, we
// have found a duplicate definition
- if ( isInspectedClass )
- {
- throw new SCRDescriptorException( "Duplicate definition for reference " + refName + " in class "
- + reference.getJavaClassDescription().getName(), reference );
+ if ( isInspectedClass ) {
+ iLog.addError("Duplicate definition for reference " + refName + " in class "
+ + current.getDescribedClass().getName(), current.getSource() );
}
- }
- else
- {
- // ensure interface
- final String type = this.getReferencedInterface(reference, isInspectedClass, refName);
- references.put( refName, new Object[]
- { reference, type, (setName ? Boolean.TRUE : Boolean.FALSE) } );
+ } else {
+ allReferences.put(refName, newReference);
+ return true;
}
}
- else
- {
- throw new SCRDescriptorException( "No name detectable for reference in class "
- + reference.getJavaClassDescription().getName(), reference );
- }
- }
-
- protected String getReferencedInterface(final JavaTag reference,
- final boolean isInspectedClass,
- final String refName) throws SCRDescriptorException
- {
- String type = reference.getNamedParameter( Constants.REFERENCE_INTERFACE );
- if ( StringUtils.isEmpty( type ) )
- {
- if ( reference.getField() != null )
- {
- type = reference.getField().getType();
- }
- else
- {
- throw new SCRDescriptorException( "Interface missing for reference " + (refName == null ? "" : refName) + " in class "
- + reference.getJavaClassDescription().getName(), reference );
- }
- }
- else if ( isInspectedClass )
- {
- // check if the value points to a class/interface
- // and search through the imports
- final JavaClassDescription serviceClass = reference.getJavaClassDescription().getReferencedClass(
- type );
- if ( serviceClass == null )
- {
- throw new SCRDescriptorException( "Interface '" + type + "' in class "
- + reference.getJavaClassDescription().getName()
- + " does not point to a valid class/interface.", reference );
- }
- type = serviceClass.getName();
- }
- return type;
- }
-
- protected String getReferenceName( final JavaTag reference,
- final String defaultName) throws SCRDescriptorException
- {
- String name = reference.getNamedParameter( Constants.REFERENCE_NAME );
- if ( !StringUtils.isEmpty( name ) )
- {
- return name;
- }
- name = reference.getNamedParameter( Constants.REFERENCE_NAME_REF );
- if ( !StringUtils.isEmpty( name ) )
- {
- final JavaField refField = this.getReferencedField( reference, name );
- final String[] values = refField.getInitializationExpression();
- if ( values == null || values.length == 0 )
- {
- throw new SCRDescriptorException( "Referenced field for " + name
- + " has no values for a reference name.", reference );
- }
- if ( values.length > 1 )
- {
- throw new SCRDescriptorException( "Referenced field " + name
- + " has more than one value for a reference name.", reference );
- }
- return 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(), tag );
- }
- return field;
- }
-
-
- /**
- * Process a reference
- * @param reference
- * @param defaultName
- * @param component
- */
- protected void doReference( JavaTag reference, String name, Component component, String type,
- final boolean setName)
- throws SCRDescriptorException
- {
- final Reference ref = new Reference( reference, component.getJavaClassDescription() );
- if ( setName )
- {
- ref.setName( name );
- }
- ref.setInterfacename( type );
- ref.setCardinality( reference.getNamedParameter( Constants.REFERENCE_CARDINALITY ) );
- if ( ref.getCardinality() == null )
- {
- ref.setCardinality( "1..1" );
- }
- ref.setPolicy( reference.getNamedParameter( Constants.REFERENCE_POLICY ) );
- if ( ref.getPolicy() == null )
- {
- ref.setPolicy( "static" );
- }
- ref.setTarget( reference.getNamedParameter( Constants.REFERENCE_TARGET ) );
- final String bindValue = reference.getNamedParameter( Constants.REFERENCE_BIND );
- if ( bindValue != null )
- {
- ref.setBind( bindValue );
- }
- final String unbindValue = reference.getNamedParameter( Constants.REFERENCE_UNDBIND );
- if ( unbindValue != null )
- {
- ref.setUnbind( unbindValue );
- }
- final String updatedValue = reference.getNamedParameter( Constants.REFERENCE_UPDATED );
- if ( updatedValue != null )
- {
- ref.setUpdated( updatedValue );
- }
- final String isChecked = reference.getNamedParameter( Constants.REFERENCE_CHECKED );
- if ( isChecked != null )
- {
- ref.setChecked( Boolean.valueOf( isChecked ).booleanValue() );
- }
- final String strategy = reference.getNamedParameter( Constants.REFERENCE_STRATEGY );
- if ( strategy != null )
- {
- ref.setStrategy( strategy );
- }
-
- 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();
- }
-
-
-
- /**
- * Converts the specification version string to a specification version
- * code. Currently the following conversions are supported:
- * <table>
- * <tr><td><code>null</code></td><td>0</td></tr>
- * <tr><td>1.0</td><td>0</td></tr>
- * <tr><td>1.1</td><td>1</td></tr>
- * <tr><td>1.1-felix</td><td>2</td></tr>
- * </table>
- *
- * @param specVersion The specification version to convert. This may be
- * <code>null</code> to assume the default version.
- *
- * @return The specification version code.
- *
- * @throws SCRDescriptorException if the <code>specVersion</code> parameter
- * is not a supported value.
- */
- private int toSpecVersionCode( String specVersion, JavaTag tag ) throws SCRDescriptorException
- {
- if ( specVersion == null || specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_10 ) )
- {
- return Constants.VERSION_1_0;
- }
- else if ( specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_11 ) )
- {
- return Constants.VERSION_1_1;
- }
- else if ( specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_11_FELIX ) )
- {
- return Constants.VERSION_1_1_FELIX;
- }
-
- // unknown specVersion string
- throw new SCRDescriptorException( "Unsupported or unknown DS spec version: " + specVersion, tag );
+ return false;
}
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.java
new file mode 100644
index 0000000..7854d20
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/AbstractDescription.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.description;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+
+/**
+ * <code>AbstractDescription</code> is the base class for all descriptions.
+ *
+ * @see ComponentDescription
+ * @see ServiceDescription
+ * @see ReferenceDescription
+ * @see PropertyDescription
+ */
+public abstract class AbstractDescription {
+
+ /** The corresponding annotation from the class file. */
+ protected final ScannedAnnotation annotation;
+
+ /**
+ * Create a new abstract description
+ * @param annotation The corresponding annotation.
+ */
+ public AbstractDescription(final ScannedAnnotation annotation) {
+ this.annotation = annotation;
+ }
+
+ /**
+ * Get the annotation.
+ * @return The annotation or <code>null</code>
+ */
+ public ScannedAnnotation getAnnotation() {
+ return this.annotation;
+ }
+}
\ No newline at end of file
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java
new file mode 100644
index 0000000..2d1f70f
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ClassDescription.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A <code>ClassDescription</code> is describing the found annotations
+ * of a class.
+ * Its basically used as a wrapper to hold all the various annotations
+ * found in a class. This description only contains the annotations
+ * found in the current class, but not in any superclass.
+ * The annotations are available as descriptions.
+ * @see ComponentDescription
+ * @see ServiceDescription
+ * @see ReferenceDescription
+ * @see PropertyDescription
+ */
+public class ClassDescription {
+
+ /** All descriptions. */
+ final List<AbstractDescription> descriptions = new ArrayList<AbstractDescription>();
+
+ /** The corresponding class. */
+ private final Class<?> describedClass;
+
+ /** The source (file) of the class or any other location information. */
+ private final String source;
+
+ /**
+ * Create a new class description
+ */
+ public ClassDescription(final Class<?> describedClass, final String source) {
+ this.describedClass = describedClass;
+ this.source = source;
+ }
+
+ /**
+ * Get the associated class.
+ * @return The associated class.
+ */
+ public Class<?> getDescribedClass() {
+ return this.describedClass;
+ }
+
+ /**
+ * Get the location information like the source file etc.
+ * @return The location information.
+ */
+ public String getSource() {
+ return this.source;
+ }
+
+ /**
+ * Add a new description
+ */
+ public void add(final AbstractDescription desc) {
+ this.descriptions.add(desc);
+ }
+
+ /**
+ * Get all descriptions of that type.
+ * @param descType The description class.
+ * @return A list of found descriptions or the empty array.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractDescription> List<T> getDescriptions(final Class<T> descType) {
+ final List<T> result = new ArrayList<T>();
+ for(final AbstractDescription desc : descriptions) {
+ if ( descType.isAssignableFrom(desc.getClass()) ) {
+ result.add((T) desc);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get the first description of that type
+ * @param descType The description class
+ * @return THe first description or <code>null</code>
+ */
+ public <T extends AbstractDescription> T getDescription(final Class<T> descType) {
+ final List<T> result = this.getDescriptions(descType);
+ if ( result.size() > 0 ) {
+ return result.get(0);
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "ClassDescription [descriptions=" + descriptions
+ + ", describedClass=" + describedClass + ", source=" + source
+ + "]";
+ }
+}
\ No newline at end of file
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaParameter.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
similarity index 61%
rename from scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaParameter.java
rename to scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
index daa2427..271d1f4 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaParameter.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentConfigurationPolicy.java
@@ -16,26 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scrplugin.tags.cl;
-
-import org.apache.felix.scrplugin.tags.JavaParameter;
+package org.apache.felix.scrplugin.description;
/**
- * <code>ClassLoaderJavaParameter.java</code>...
- *
+ * Options for {@link ComponentDescription#getConfigurationPolicy()}.
*/
-public class ClassLoaderJavaParameter implements JavaParameter {
-
- protected final String type;
-
- public ClassLoaderJavaParameter(String t) {
- this.type = t;
- }
+public enum ComponentConfigurationPolicy {
/**
- * @see org.apache.felix.scrplugin.tags.JavaParameter#getType()
+ * If a configuration is available it will be used, if not the component
+ * will be activated anyway (this is the default).
*/
- public String getType() {
- return this.type;
- }
+ OPTIONAL,
+
+ /**
+ * The configuration admin is not consulted for a configuration for this component.
+ */
+ IGNORE,
+
+ /**
+ * In order to activate this component a configuration is required.
+ */
+ REQUIRE;
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java
new file mode 100644
index 0000000..b7a67a8
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ComponentDescription.java
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+/**
+ * <code>ComponentDescription</code> is a described component.
+ *
+ * In general all fields should be set by an annocation scanner,
+ * no default values should be assumed for these fields:
+ * <ul>
+ * <li>name</li>
+ * <li>configurationPolicy</li>
+ * </ul>
+ *
+ * These values have the following default values:
+ * <ul>
+ * <li>label : null - will be handled by the scr generator</li>
+ * <li>description : null - will be handled by the scr generator</li>
+ * <li>isAbstract : false</li>
+ * <li>isInherit : true</li>
+ * <li>createDs : true</li>
+ * <li>createPid : true</li>
+ * <li>createMetatype : false</li>
+ * <li>enabled : null</li>
+ * <li>immediate : null</li>
+ * <li>factory : null</li>
+ * <li>isSetMetatypeFactoryPid : false</li>
+ * <li>activate : null</li>
+ * <li>deactivate : null</li>
+ * <li>modified : null</li>
+ * <li>specVersion : null</li>
+ * </ul>
+ *
+ */
+public class ComponentDescription extends AbstractDescription {
+
+ /** The name of the component. */
+ private String name;
+
+ /** The label of the component. */
+ private String label;
+
+ /** The description of the component. */
+ private String description;
+
+ /** Configuration policy. (V1.1) */
+ private ComponentConfigurationPolicy configurationPolicy;
+
+ /** Is this an abstract description? */
+ private boolean isAbstract = false;
+
+ /** Does this inherit? */
+ private boolean isInherit = true;
+
+ /** Create ds info */
+ private boolean createDs = true;
+
+ /** Create pid */
+ private boolean createPid = true;
+
+ /** Create metatype info. */
+ private boolean createMetatype = false;
+
+ /** Is this component enabled? */
+ private Boolean enabled;
+
+ /** Is this component immediately started. */
+ private Boolean immediate;
+
+ /** The factory. */
+ private String factory;
+
+ /** The set metatype factory pid flag. */
+ private boolean isSetMetatypeFactoryPid = false;
+
+ /** Activation method. (V1.1) */
+ private MethodDescription activate;
+
+ /** Deactivation method. (V1.1) */
+ private MethodDescription deactivate;
+
+ /** Modified method. (V1.1) */
+ private MethodDescription modified;
+
+ /** The spec version. */
+ private SpecVersion specVersion;
+
+ public ComponentDescription(final ScannedAnnotation annotation) {
+ super(annotation);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public Boolean getImmediate() {
+ return immediate;
+ }
+
+ public void setImmediate(Boolean immediate) {
+ this.immediate = immediate;
+ }
+
+ public String getFactory() {
+ return factory;
+ }
+
+ public void setFactory(String factory) {
+ this.factory = factory;
+ }
+
+ public boolean isSetMetatypeFactoryPid() {
+ return isSetMetatypeFactoryPid;
+ }
+
+ public void setSetMetatypeFactoryPid(boolean isSetMetatypeFactoryPid) {
+ this.isSetMetatypeFactoryPid = isSetMetatypeFactoryPid;
+ }
+
+ public boolean isAbstract() {
+ return isAbstract;
+ }
+
+ public void setAbstract(boolean isAbstract) {
+ this.isAbstract = isAbstract;
+ }
+
+ public boolean isInherit() {
+ return isInherit;
+ }
+
+ public void setInherit(boolean isInherit) {
+ this.isInherit = isInherit;
+ }
+
+ public boolean isCreateDs() {
+ return createDs;
+ }
+
+ public void setCreateDs(boolean createDs) {
+ this.createDs = createDs;
+ }
+
+ public boolean isCreatePid() {
+ return createPid;
+ }
+
+ public void setCreatePid(boolean createPid) {
+ this.createPid = createPid;
+ }
+
+ public boolean isCreateMetatype() {
+ return createMetatype;
+ }
+
+ public void setCreateMetatype(boolean createMetatype) {
+ this.createMetatype = createMetatype;
+ }
+
+ public ComponentConfigurationPolicy getConfigurationPolicy() {
+ return configurationPolicy;
+ }
+
+ public void setConfigurationPolicy(ComponentConfigurationPolicy configurationPolicy) {
+ this.configurationPolicy = configurationPolicy;
+ }
+
+ public MethodDescription getActivate() {
+ return activate;
+ }
+
+ public void setActivate(MethodDescription activate) {
+ this.activate = activate;
+ }
+
+ public MethodDescription getDeactivate() {
+ return deactivate;
+ }
+
+ public void setDeactivate(MethodDescription deactivate) {
+ this.deactivate = deactivate;
+ }
+
+ public MethodDescription getModified() {
+ return modified;
+ }
+
+ public void setModified(MethodDescription modified) {
+ this.modified = modified;
+ }
+
+ public SpecVersion getSpecVersion() {
+ return specVersion;
+ }
+
+ public void setSpecVersion(SpecVersion specVersion) {
+ this.specVersion = specVersion;
+ }
+
+ @Override
+ public String toString() {
+ return "ComponentDescription [name=" + name + ", label=" + label
+ + ", description=" + description + ", enabled=" + enabled
+ + ", immediate=" + immediate + ", factory=" + factory
+ + ", isSetMetatypeFactoryPid=" + isSetMetatypeFactoryPid
+ + ", isAbstract=" + isAbstract + ", isInherit=" + isInherit
+ + ", createDs=" + createDs + ", createPid=" + createPid
+ + ", createMetatype=" + createMetatype
+ + ", configurationPolicy=" + configurationPolicy
+ + ", activate=" + activate + ", deactivate=" + deactivate
+ + ", modified=" + modified + ", specVersion=" + specVersion
+ + ", annotation=" + annotation + "]";
+ }
+}
\ No newline at end of file
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java
new file mode 100644
index 0000000..fbffba8
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/MethodDescription.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+import java.lang.reflect.Method;
+
+/**
+ * A method description describes a reference to a method,
+ * this can either just be the name or a real method object.
+ */
+public class MethodDescription {
+
+ private final String name;
+
+ private final Method method;
+
+ public MethodDescription(final String name) {
+ this.name = name;
+ this.method = null;
+ }
+
+ public MethodDescription(final Method method) {
+ this.name = method.getName();
+ this.method = method;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public Method getMethod() {
+ return this.method;
+ }
+
+ @Override
+ public String toString() {
+ return "MethodDescription [name=" + name + ", method=" + method + "]";
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyDescription.java
new file mode 100644
index 0000000..9b6ecee
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyDescription.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+import java.util.Arrays;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+
+/**
+ * A <code>PropertyDescription</code> describes a property
+ * of a component.
+ *
+ * In general all fields should be set by an annocation scanner,
+ * no default values should be assumed for these fields:
+ * <ul>
+ * <li>name</li>
+ * <li>value</li>
+ * <li>multiValue</li>
+ * <li>type</li>
+ * <li>unbounded</li>
+ * <li>cardinality</li>
+ * </ul>
+ *
+ * These values have the following default values:
+ * <ul>
+ * <li>label : null - will be handled by the scr generator</li>
+ * <li>description : null - will be handled by the scr generator</li>
+ * <li>isPrivate : null - will be be handled by the scr generator</li>
+ * <li>options : null</li>
+ * </ul>
+ *
+ */
+public class PropertyDescription extends AbstractDescription {
+
+ private String name;
+ private String value;
+ private PropertyType type;
+ private String[] multiValue;
+ private PropertyUnbounded unbounded;
+ private int cardinality;
+
+ private Boolean isPrivate;
+ private String label;
+ private String description;
+ private String[] options;
+
+ public PropertyDescription(final ScannedAnnotation annotation) {
+ super(annotation);
+ }
+
+ public PropertyUnbounded getUnbounded() {
+ return unbounded;
+ }
+
+ public void setUnbounded(PropertyUnbounded unbounded) {
+ this.unbounded = unbounded;
+ }
+
+ public String[] getOptions() {
+ return options;
+ }
+
+ public void setOptions(String[] values) {
+ this.options = values;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ this.multiValue = null;
+ }
+
+ public PropertyType getType() {
+ return this.type;
+ }
+
+ public void setType(PropertyType type) {
+ this.type = type;
+ }
+
+ public String[] getMultiValue() {
+ return this.multiValue;
+ }
+
+ public void setMultiValue(String[] values) {
+ this.multiValue = values;
+ this.value = null;
+ }
+ public Boolean isPrivate() {
+ return isPrivate;
+ }
+
+ public void setPrivate(Boolean isPrivate) {
+ this.isPrivate = isPrivate;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public int getCardinality() {
+ return cardinality;
+ }
+
+ public void setCardinality(int cardinality) {
+ this.cardinality = cardinality;
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyDescription [name=" + name + ", value=" + value
+ + ", type=" + type + ", multiValue="
+ + Arrays.toString(multiValue) + ", isPrivate=" + isPrivate
+ + ", label=" + label + ", description=" + description
+ + ", cardinality=" + cardinality + ", unbounded=" + unbounded
+ + ", options=" + Arrays.toString(options) + ", annotation=" + annotation + "]";
+ }
+
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyType.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyType.java
new file mode 100644
index 0000000..5aca421
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyType.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+public enum PropertyType {
+
+ String,
+ Long,
+ Double,
+ Float,
+ Integer,
+ Byte,
+ Char,
+ Character,
+ Boolean,
+ Short;
+
+ public static PropertyType from(final Class<?> javaClass) {
+ if ( javaClass.getName().equals(Long.class.getName())) {
+ return PropertyType.Long;
+ }
+ if ( javaClass.getName().equals(Double.class.getName())) {
+ return PropertyType.Double;
+ }
+ if ( javaClass.getName().equals(Float.class.getName())) {
+ return PropertyType.Float;
+ }
+ if ( javaClass.getName().equals(Integer.class.getName())) {
+ return PropertyType.Integer;
+ }
+ if ( javaClass.getName().equals(Byte.class.getName())) {
+ return PropertyType.Byte;
+ }
+ if ( javaClass.getName().equals(Character.class.getName())) {
+ return PropertyType.Character;
+ }
+ if ( javaClass.getName().equals(Boolean.class.getName())) {
+ return PropertyType.Boolean;
+ }
+ if ( javaClass.getName().equals(Short.class.getName())) {
+ return PropertyType.Short;
+ }
+ // default
+ return PropertyType.String;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyUnbounded.java
similarity index 71%
copy from scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java
copy to scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyUnbounded.java
index a00ab18..f73ae8c 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/PropertyUnbounded.java
@@ -16,8 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * Extracting SCR tags from source file declared as Java 1.5 annotations.
- */
-package org.apache.felix.scrplugin.tags.annotation;
+package org.apache.felix.scrplugin.description;
+/**
+ * Options for {@link PropertyDescription#getUnbounded()}
+ */
+public enum PropertyUnbounded {
+
+ /** Property is not unbounded. This is the default. */
+ DEFAULT,
+
+ /** Property is an unbounded array. */
+ ARRAY,
+
+ /** Property is an unbounded vector. */
+ VECTOR
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceCardinality.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceCardinality.java
new file mode 100644
index 0000000..0f102ed
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceCardinality.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+/**
+ * Options for {@link ReferenceDescription#getCardinality()}
+ */
+public enum ReferenceCardinality {
+
+ /**
+ * Optional, unary reference: No service required to be available for the
+ * refernce to be satisfied. Only a single service is available through this
+ * reference.
+ */
+ OPTIONAL_UNARY("0..1"),
+
+ /**
+ * Mandatory, unary reference: At least one service must be available for
+ * the reference to be satisfied. Only a single service is available through
+ * this reference.
+ */
+ MANDATORY_UNARY("1..1"),
+
+ /**
+ * Optional, multiple reference: No service required to be available for the
+ * refernce to be satisfied. All matching services are available through
+ * this reference.
+ */
+ OPTIONAL_MULTIPLE("0..n"),
+
+ /**
+ * Mandatory, multiple reference: At least one service must be available for
+ * the reference to be satisified. All matching services are available
+ * through this reference.
+ */
+ MANDATORY_MULTIPLE("1..n");
+
+ private final String cardinalityString;
+
+ private ReferenceCardinality(final String cardinalityString) {
+ this.cardinalityString = cardinalityString;
+ }
+
+ /**
+ * @return String representation of cardinality
+ */
+ public String getCardinalityString() {
+ return this.cardinalityString;
+ }
+
+ public static ReferenceCardinality fromValue(final String value) {
+ for(final ReferenceCardinality rd : ReferenceCardinality.values() ) {
+ if ( rd.getCardinalityString().equals(value) ) {
+ return rd;
+ }
+ }
+ return null;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceDescription.java
new file mode 100644
index 0000000..b11e7de
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceDescription.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+import java.lang.reflect.Field;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+/**
+ * A <code>ReferenceDescription</code> describes a reference
+ * from a component to another service.
+ *
+ * In general all fields should be set by an annocation scanner,
+ * no default values should be assumed for these fields:
+ * <ul>
+ * <li>name</li>
+ * <li>interfaceName</li>
+ * <li>target</li>
+ * <li>cardinality</li>
+ * <li>policy</li>
+ * <li>strategy</li>
+ * <li>field</li>
+ * </ul>
+ *
+ * These values have the following default values:
+ * <ul>
+ * <li>bind : null</li>
+ * <li>unbind : null</li>
+ * <li>updated : null</li>
+ * </ul>
+ */
+public class ReferenceDescription extends AbstractDescription {
+
+ private String name;
+ private String interfaceName;
+ private String target;
+ private ReferenceCardinality cardinality;
+ private ReferencePolicy policy;
+ private ReferenceStrategy strategy;
+
+ private Field field;
+
+ private MethodDescription bind;
+ private MethodDescription unbind;
+ private MethodDescription updated;
+
+ public ReferenceDescription(final ScannedAnnotation annotation) {
+ super(annotation);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getInterfaceName() {
+ return interfaceName;
+ }
+
+ public void setInterfaceName(String interfacename) {
+ this.interfaceName = interfacename;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ public ReferenceCardinality getCardinality() {
+ return cardinality;
+ }
+
+ public void setCardinality(ReferenceCardinality cardinality) {
+ this.cardinality = cardinality;
+ }
+
+ public ReferencePolicy getPolicy() {
+ return policy;
+ }
+
+ public void setPolicy(ReferencePolicy policy) {
+ this.policy = policy;
+ }
+
+ public MethodDescription getBind() {
+ return bind;
+ }
+
+ public void setBind(MethodDescription bind) {
+ this.bind = bind;
+ }
+
+ public MethodDescription getUnbind() {
+ return unbind;
+ }
+
+ public void setUnbind(MethodDescription unbind) {
+ this.unbind = unbind;
+ }
+
+ public MethodDescription getUpdated() {
+ return updated;
+ }
+
+ public void setUpdated(MethodDescription updated) {
+ this.updated = updated;
+ }
+
+ public ReferenceStrategy getStrategy() {
+ return strategy;
+ }
+
+ public void setStrategy(ReferenceStrategy strategy) {
+ this.strategy = strategy;
+ }
+
+ @Override
+ public String toString() {
+ return "ReferenceDescription [name=" + name + ", interfaceName="
+ + interfaceName + ", target=" + target + ", cardinality="
+ + cardinality + ", policy=" + policy + ", bind=" + bind
+ + ", unbind=" + unbind + ", updated=" + updated + ", strategy="
+ + strategy + ", field=" + field + ", annotation=" + annotation
+ + "]";
+ }
+
+ public Field getField() {
+ return field;
+ }
+
+ public void setField(Field field) {
+ this.field = field;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaMethod.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferencePolicy.java
similarity index 68%
copy from scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaMethod.java
copy to scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferencePolicy.java
index cf36076..a4429a4 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaMethod.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferencePolicy.java
@@ -16,23 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scrplugin.tags;
+package org.apache.felix.scrplugin.description;
/**
- * <code>JavaMethod.java</code>...
- *
+ * Options for {@link ReferenceDescription#getPolicy()}
*/
-public interface JavaMethod {
+public enum ReferencePolicy {
- JavaMethod[] EMPTY_RESULT = new JavaMethod[0];
+ /**
+ * The component will be deactivated and re-activated if the service comes
+ * and/or goes away.
+ */
+ STATIC,
- boolean isPublic();
-
- boolean isProtected();
-
- String getName();
-
- JavaParameter[] getParameters();
-
- boolean isConstructor();
+ /**
+ * The service will be made available to the component as it comes and goes.
+ */
+ DYNAMIC;
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceStrategy.java
similarity index 82%
rename from scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java
rename to scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceStrategy.java
index a00ab18..5a158e8 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ReferenceStrategy.java
@@ -16,8 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * Extracting SCR tags from source file declared as Java 1.5 annotations.
- */
-package org.apache.felix.scrplugin.tags.annotation;
+package org.apache.felix.scrplugin.description;
+/**
+ * Options for {@link ReferenceDescription#getStrategy()}
+ */
+public enum ReferenceStrategy {
+
+ EVENT,
+
+ LOOKUP;
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ServiceDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ServiceDescription.java
new file mode 100644
index 0000000..7ee3647
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/ServiceDescription.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+
+/**
+ * If a component is a service, the {@link ClassDescription} should
+ * contain a <code>ServiceDescription</code>.
+ *
+ * The service description defines whether this is a service factory
+ * and which interfaces this service implements.
+ */
+public class ServiceDescription extends AbstractDescription {
+
+ /** Flag for service factory. */
+ private boolean isServiceFactory = false;
+
+ /** The list of implemented interfaces. */
+ protected final Set<String> interfaces = new HashSet<String>();
+
+ public ServiceDescription(final ScannedAnnotation annotation) {
+ super(annotation);
+ }
+
+ public boolean isServiceFactory() {
+ return this.isServiceFactory;
+ }
+
+ public void setServiceFactory(boolean flag) {
+ this.isServiceFactory = flag;
+ }
+
+ public Set<String> getInterfaces() {
+ return this.interfaces;
+ }
+
+ /**
+ * Add an interface to the list of interfaces.
+ * @param interf The interface.
+ */
+ public void addInterface(final String interf) {
+ this.interfaces.add(interf);
+ }
+
+ @Override
+ public String toString() {
+ return "ServiceDescription [isServiceFactory=" + isServiceFactory
+ + ", interfaces=" + interfaces + ", annotation=" + annotation
+ + "]";
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/SpecVersion.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/SpecVersion.java
new file mode 100644
index 0000000..1f0d11a
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/description/SpecVersion.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.felix.scrplugin.description;
+
+
+public enum SpecVersion {
+
+ VERSION_1_0("1.0"), // R4.1
+ VERSION_1_1("1.1"), // R4.2
+ VERSION_1_1_FELIX("1.1_FELIX"); // R4.2 + FELIX-1893
+
+ /**
+ * internal human readable name
+ */
+ private final String name;
+
+ /**
+ * Create a type
+ *
+ * @param name name
+ */
+ private SpecVersion(final String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the human readable type name of this type.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Creates a version for the given name. if the name cannot be mapped
+ * to a enum type or if it's <code>null</code>, <code>null</code> is
+ * returned.
+ *
+ * @param n the name
+ * @return the type or <code>null</code>
+ */
+ public static SpecVersion fromName(final String n) {
+ if (n == null) {
+ return null;
+ }
+ try {
+ return SpecVersion.valueOf(n.toUpperCase());
+ } catch (final IllegalArgumentException e) {
+ // ignore
+ }
+ for(final SpecVersion sv : SpecVersion.values() ) {
+ if ( sv.getName().equals(n)) {
+ return sv;
+ }
+ }
+ return null;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/AnnotationProcessorManager.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/AnnotationProcessorManager.java
new file mode 100644
index 0000000..913d290
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/AnnotationProcessorManager.java
@@ -0,0 +1,150 @@
+/*
+ * 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;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.imageio.spi.ServiceRegistry;
+
+import org.apache.felix.scrplugin.AnnotationProcessor;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.scanner.ScannedClass;
+
+
+/**
+ * Supports mapping of built-in and custom java annotations to
+ * descriptions.
+ */
+public class AnnotationProcessorManager implements AnnotationProcessor {
+
+ /**
+ * Allows to define additional implementations of the interface
+ * {@linkAnnotationProcessor}
+ * that provide mappings from custom annotations to descriptions.
+ */
+ private final Map<String, AnnotationProcessor> processors = new HashMap<String, AnnotationProcessor>();
+
+ /**
+ * Ordered list of processors
+ */
+ private final List<AnnotationProcessor> cachedProcessors = new ArrayList<AnnotationProcessor>();
+
+ /**
+ * @param annotationProcessorClasses List of classes that implements
+ * {@link AnnotationProcessor} interface.
+ * @throws SCRDescriptorFailureException
+ */
+ public AnnotationProcessorManager(
+ final String[] annotationProcessorClasses,
+ final ClassLoader classLoader )
+ throws SCRDescriptorFailureException {
+ // search for providers
+ final Iterator<AnnotationProcessor> serviceIter = ServiceRegistry.lookupProviders(AnnotationProcessor.class, classLoader);
+ while ( serviceIter.hasNext() ) {
+ final AnnotationProcessor provider = serviceIter.next();
+ this.addProvider(provider);
+ }
+
+ // add custom processors defined in the tool (maven, ant...)
+ for ( int i = 0; i < annotationProcessorClasses.length; i++ ) {
+ loadProcessor( classLoader, annotationProcessorClasses[i], false );
+ }
+
+ // always add processors supporting built-in SCR default properties (for compatibility with older
+ // annotation versions)
+ loadProcessor( classLoader,
+ "org.apache.felix.scrplugin.SCRAnnotationProcessor", true );
+ loadProcessor( classLoader,
+ "org.apache.felix.scrplugin.SlingAnnotationProcessor", true );
+
+ // create ordered list
+ for(final AnnotationProcessor pro : this.processors.values() ) {
+ this.cachedProcessors.add(pro);
+ }
+ Collections.sort(this.cachedProcessors, new Comparator<AnnotationProcessor>() {
+
+ public int compare(AnnotationProcessor o1, AnnotationProcessor o2) {
+ return Integer.valueOf(o1.getRanking()).compareTo(Integer.valueOf(o2.getRanking()));
+ }
+ });
+ }
+
+ /**
+ * @see org.apache.felix.scrplugin.AnnotationProcessor#process(org.apache.felix.scrplugin.scanner.ScannedClass, org.apache.felix.scrplugin.description.ClassDescription)
+ */
+ public void process(final ScannedClass scannedClass,
+ final ClassDescription describedClass)
+ throws SCRDescriptorException, SCRDescriptorFailureException {
+ for(final AnnotationProcessor ap : this.cachedProcessors) {
+ ap.process(scannedClass, describedClass);
+ }
+ }
+
+ /**
+ * @see org.apache.felix.scrplugin.AnnotationProcessor#getRanking()
+ */
+ public int getRanking() {
+ return 0;
+ }
+
+ /**
+ * Add a processor (if not already available)
+ */
+ private void addProvider(final AnnotationProcessor processor) {
+ // check if this processor is already loaded
+ final String key = processor.getClass().getName();
+ if ( !this.processors.containsKey(key) ) {
+ this.processors.put(key, processor);
+ }
+ }
+
+ private void loadProcessor( final ClassLoader classLoader, final String className, final boolean silent )
+ throws SCRDescriptorFailureException {
+ String failureMessage = null;
+ try {
+ Class<?> clazz = classLoader.loadClass( className );
+ try {
+ addProvider( ( AnnotationProcessor ) clazz.newInstance() );
+ } catch ( final ClassCastException e ) {
+ failureMessage = "Class '" + clazz.getName() + "' " + "does not implement interface '"
+ + AnnotationProcessor.class.getName() + "'.";
+ } catch ( final InstantiationException e ) {
+ failureMessage = "Unable to instantiate class '" + clazz.getName() + "': " + e.getMessage();
+ } catch ( final IllegalAccessException e ) {
+ failureMessage = "Illegal access to class '" + clazz.getName() + "': " + e.getMessage();
+ }
+ } catch ( final ClassNotFoundException e ) {
+ failureMessage = "Annotation provider class '" + className + "' not found.";
+ }
+
+ // throw an optional exception if not required to remaing silent
+ if ( failureMessage != null && !silent ) {
+ throw new SCRDescriptorFailureException( failureMessage );
+ }
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ClassModifier.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ClassModifier.java
new file mode 100644
index 0000000..aedb87c
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ClassModifier.java
@@ -0,0 +1,98 @@
+package org.apache.felix.scrplugin.helper;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.felix.scrplugin.SCRDescriptorException;
+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;
+
+public class ClassModifier {
+
+ public static void addMethods(final String className,
+ final String referenceName,
+ final String fieldName,
+ final String typeName,
+ final boolean createBind,
+ final boolean createUnbind,
+ final String outputDirectory)
+ throws SCRDescriptorException {
+ // now do byte code manipulation
+ final String fileName = outputDirectory + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
+ final ClassNode cn = new ClassNode();
+ try {
+ final ClassReader reader = new ClassReader(new FileInputStream(fileName));
+ reader.accept(cn, 0);
+
+ final ClassWriter writer = new ClassWriter(0);
+
+ // remove existing implementation von previous builds
+ final ClassAdapter adapter = new ClassAdapter(writer) {
+
+ protected final String bindMethodName = "bind" + referenceName.substring(0, 1).toUpperCase() + referenceName.substring(1);
+ protected final String unbindMethodName = "unbind" + referenceName.substring(0, 1).toUpperCase() + referenceName.substring(1);
+ protected final String description = "(L" + typeName.replace('.', '/') + ";)V";
+
+ /**
+ * @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
+ */
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions) {
+ if ( createBind && name.equals(bindMethodName) && description.equals(desc) ) {
+ return null;
+ }
+ if ( createUnbind && name.equals(unbindMethodName) && description.equals(desc) ) {
+ return null;
+ }
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ };
+
+ cn.accept(adapter);
+ if ( createBind ) {
+ createMethod(writer, className, referenceName, fieldName, typeName, true);
+ }
+ if ( createUnbind ) {
+ createMethod(writer, className, referenceName, fieldName, typeName, false);
+ }
+
+ final FileOutputStream fos = new FileOutputStream(fileName);
+ fos.write(writer.toByteArray());
+ fos.close();
+ } catch (final Exception e) {
+ throw new SCRDescriptorException("Unable to add methods to " + className, typeName, 0, e);
+ }
+ }
+
+ private static void createMethod(final ClassWriter cw, final String className, final String referenceName, final String fieldName, final String typeName, boolean bind) {
+ final org.objectweb.asm.Type type = org.objectweb.asm.Type.getType("L" + typeName.replace('.', '/') + ";");
+ final String methodName = (bind ? "" : "un") + "bind" + referenceName.substring(0, 1).toUpperCase() + referenceName.substring(1);
+ MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, methodName, "(" + type.toString() + ")V", null, null);
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ if ( bind ) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), 1);
+ mv.visitFieldInsn(Opcodes.PUTFIELD, className.replace('.', '/'), fieldName, type.toString());
+ } else {
+ mv.visitFieldInsn(Opcodes.GETFIELD, className.replace('.', '/'), fieldName, type.toString());
+ mv.visitVarInsn(Opcodes.ALOAD, 1);
+ final Label jmpLabel = new Label();
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, jmpLabel);
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ mv.visitFieldInsn(Opcodes.PUTFIELD, className.replace('.', '/'), fieldName, type.toString());
+ mv.visitLabel(jmpLabel);
+ }
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(2, 2);
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ClassScanner.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ClassScanner.java
new file mode 100644
index 0000000..fb62805
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ClassScanner.java
@@ -0,0 +1,597 @@
+/*
+ * 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;
+
+import static org.objectweb.asm.ClassReader.SKIP_CODE;
+import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
+import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.apache.felix.scrplugin.AnnotationProcessor;
+import org.apache.felix.scrplugin.Log;
+import org.apache.felix.scrplugin.Project;
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.description.ComponentDescription;
+import org.apache.felix.scrplugin.scanner.ClassAnnotation;
+import org.apache.felix.scrplugin.scanner.FieldAnnotation;
+import org.apache.felix.scrplugin.scanner.MethodAnnotation;
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
+import org.apache.felix.scrplugin.scanner.ScannedClass;
+import org.apache.felix.scrplugin.scanner.Source;
+import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * The class scanner scans class files for annotations and invokes
+ * the {@link AnnotationProcessor} on each scanned class file.
+ */
+public class ClassScanner {
+
+ /**
+ * The name of the Bundle manifest header providing the list of service
+ * component descriptor files.
+ */
+ private static final String SERVICE_COMPONENT = "Service-Component";
+
+ /**
+ * The name of the file containing the scanned information from older
+ * SCR generator versions.
+ */
+ private static final String ABSTRACT_DESCRIPTOR_ARCHIV_PATH = "OSGI-INF/scr-plugin/scrinfo.xml";
+
+ /** Source for all generated descriptions. */
+ private static final String GENERATED = "<generated>";
+
+ /** Component descriptions loaded from dependencies*/
+ private Map<String, ClassDescription> loadedDependencies;
+
+ /** All used component descriptions. */
+ private final Map<String, ClassDescription> allDescriptions;
+
+ /** The log. */
+ private final Log log;
+
+ /** The issue log. */
+ private final IssueLog iLog;
+
+ /** The project. */
+ private final Project project;
+
+ /** The annotation processor. */
+ private final AnnotationProcessor aProcessor;
+
+ /**
+ * Create a new scanner.
+ */
+ public ClassScanner(final Log log,
+ final IssueLog iLog,
+ final Project project,
+ final AnnotationProcessor aProcessor) {
+ // create map for all descriptions and dummy entry for Object
+ this.allDescriptions = new HashMap<String, ClassDescription>();
+ allDescriptions.put(Object.class.getName(), new ClassDescription(Object.class, GENERATED));
+ this.log = log;
+ this.iLog = iLog;
+ this.project = project;
+ this.aProcessor = aProcessor;
+ }
+
+ /**
+ * Scan all source class files for annotations and process them.
+ */
+ public List<ClassDescription> scanSources()
+ throws SCRDescriptorException, SCRDescriptorFailureException {
+ final List<ClassDescription> result = new ArrayList<ClassDescription>();
+
+ for (final Source src : project.getSources()) {
+ log.debug("Scanning class " + src.getClassName());
+
+ try {
+ // load the class
+ final Class<?> annotatedClass = project.getClassLoader().loadClass(src.getClassName());
+
+ final ClassDescription desc = this.processClass(annotatedClass, src.getFile().toString());
+ if (desc != null) {
+ result.add(desc);
+ this.allDescriptions.put(annotatedClass.getName(), desc);
+ } else {
+ this.allDescriptions.put(annotatedClass.getName(), new ClassDescription(annotatedClass, GENERATED));
+ }
+ } catch (final ClassNotFoundException cnfe) {
+ throw new SCRDescriptorFailureException("Unable to load compiled class: " + src.getClassName(), cnfe);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Scan a single class.
+ */
+ private ClassDescription processClass(final Class<?> annotatedClass, final String location)
+ throws SCRDescriptorFailureException, SCRDescriptorException {
+ try {
+ // get the class file for ASM
+ final String pathToClassFile = annotatedClass.getName().replace('.', '/') + ".class";
+ final InputStream input = project.getClassLoader().getResourceAsStream(pathToClassFile);
+ final ClassReader classReader;
+ try {
+ classReader = new ClassReader(input);
+ } finally {
+ input.close();
+ }
+ final ClassNode classNode = new ClassNode();
+ classReader.accept(classNode, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
+
+ // create descriptions
+ final List<ScannedAnnotation> descriptions = extractAnnotation(classNode, annotatedClass);
+ if (descriptions.size() > 0) {
+ // process descriptions
+ final ClassDescription desc = new ClassDescription(annotatedClass, location);
+ aProcessor.process(new ScannedClass(descriptions, annotatedClass), desc);
+
+ if (desc.getDescriptions(ComponentDescription.class).size() > 0) {
+ log.debug("Found component description " + desc + " in " + annotatedClass.getName());
+ return desc;
+ }
+ }
+ } catch (final IOException ioe) {
+ throw new SCRDescriptorFailureException("Unable to scan class files: " + annotatedClass.getName(), ioe);
+ }
+ return null;
+ }
+
+ /**
+ * Extract annotations
+ */
+ private final List<ScannedAnnotation> extractAnnotation(final ClassNode classNode, final Class<?> annotatedClass)
+ throws SCRDescriptorException {
+ final List<ScannedAnnotation> descriptions = new ArrayList<ScannedAnnotation>();
+ // first parse class annotations
+ @SuppressWarnings("unchecked")
+ final List<AnnotationNode> annotations = classNode.invisibleAnnotations;
+ if (annotations != null) {
+ for (final AnnotationNode annotation : annotations) {
+ this.parseAnnotation(descriptions, annotation, annotatedClass);
+ }
+
+ // second parse method annotations
+ @SuppressWarnings("unchecked")
+ final List<MethodNode> methods = classNode.methods;
+ if (methods != null) {
+ for (final MethodNode method : methods) {
+ @SuppressWarnings("unchecked")
+ final List<AnnotationNode> annos = method.invisibleAnnotations;
+ if (annos != null) {
+ final String name = method.name;
+ String signature = method.signature;
+ if (signature != null) {
+ // remove generics
+ int pos;
+ while ((pos = signature.indexOf('<')) > 0) {
+ final int lastPos = signature.indexOf('>');
+ signature = signature.substring(0, pos) + signature.substring(lastPos + 1);
+ }
+ // remove everthing after the brackets and replace slash with dot
+ pos = signature.lastIndexOf(')');
+ signature = signature.substring(0, pos + 1);
+ signature = signature.replace('/', '.');
+ }
+ final Method[] allMethods = annotatedClass.getDeclaredMethods();
+ Method found = null;
+ for (final Method m : allMethods) {
+ if (m.getName().equals(name)) {
+ if (m.getParameterTypes().length == 0 && signature == null) {
+ found = m;
+ }
+ if (m.getParameterTypes().length > 0 && signature != null) {
+ final StringBuilder sb = new StringBuilder("(");
+ for (final Class<?> c : m.getParameterTypes()) {
+ sb.append("L");
+ sb.append(c.getName());
+ sb.append(";");
+ }
+ sb.append(")");
+ if (sb.toString().equals(signature)) {
+ found = m;
+ }
+ }
+ }
+ }
+ if (found == null) {
+ throw new SCRDescriptorException("Annotated method " + name + " not found.",
+ annotatedClass.getName(), -1);
+ }
+ for (final AnnotationNode annotation : annos) {
+ parseAnnotation(descriptions, annotation, found);
+ }
+ }
+ }
+ }
+
+ // third parse field annotations
+ @SuppressWarnings("unchecked")
+ final List<FieldNode> fields = classNode.fields;
+ if (fields != null) {
+ for (final FieldNode field : fields) {
+ @SuppressWarnings("unchecked")
+ final List<AnnotationNode> annos = field.invisibleAnnotations;
+ if (annos != null) {
+ final String name = field.name;
+ final Field[] allFields = annotatedClass.getDeclaredFields();
+ Field found = null;
+ for (final Field f : allFields) {
+ if (f.getName().equals(name)) {
+ found = f;
+ }
+ }
+ if (found == null) {
+ throw new SCRDescriptorException("Annotated field " + name + " not found.",
+ annotatedClass.getName(), -1);
+ }
+ for (final AnnotationNode annotation : annos) {
+ parseAnnotation(descriptions, annotation, found);
+ }
+ }
+ }
+ }
+ }
+ return descriptions;
+ }
+
+ private <T> T[] convertToArray(final List<?> values, final Class<T> type) {
+ @SuppressWarnings("unchecked")
+ final T[] result = (T[]) Array.newInstance(type, values.size());
+ return values.toArray(result);
+ }
+
+ /**
+ * Parse annotation and create a description.
+ */
+ private void parseAnnotation(final List<ScannedAnnotation> descriptions, final AnnotationNode annotation,
+ final Object annotatedObject) {
+ // desc has the format 'L' + className.replace('.', '/') + ';'
+ final String name = annotation.desc.substring(1, annotation.desc.length() - 1).replace('/', '.');
+ Map<String, Object> values = null;
+ if (annotation.values != null) {
+ values = new HashMap<String, Object>();
+ final Iterator<?> i = annotation.values.iterator();
+ while (i.hasNext()) {
+ final Object vName = i.next();
+ Object value = i.next();
+
+ // convert type to class name string
+ if (value instanceof Type) {
+ value = ((Type) value).getClassName();
+ } else if (value instanceof List<?>) {
+ final List<?> objects = (List<?>) value;
+ if (objects.size() > 0) {
+ if (objects.get(0) instanceof Type) {
+ final String[] classNames = new String[objects.size()];
+ int index = 0;
+ for (final Object v : objects) {
+ classNames[index] = ((Type) v).getClassName();
+ index++;
+ }
+ value = classNames;
+ } else if (objects.get(0) instanceof AnnotationNode) {
+ final List<ScannedAnnotation> innerDesc = new ArrayList<ScannedAnnotation>();
+ for (final Object v : objects) {
+ parseAnnotation(innerDesc, (AnnotationNode) v, annotatedObject);
+ }
+ if (annotatedObject instanceof Method) {
+ value = innerDesc.toArray(new MethodAnnotation[innerDesc.size()]);
+ } else if (annotatedObject instanceof Field) {
+ value = innerDesc.toArray(new FieldAnnotation[innerDesc.size()]);
+ } else {
+ value = innerDesc.toArray(new ClassAnnotation[innerDesc.size()]);
+ }
+ } else {
+ value = convertToArray(objects, objects.get(0).getClass());
+ }
+ } else {
+ value = null;
+ }
+ }
+
+ values.put(vName.toString(), value);
+ }
+ }
+
+ final ScannedAnnotation a;
+ if (annotatedObject instanceof Method) {
+ a = new MethodAnnotation(name, values, (Method) annotatedObject);
+ ((Method) annotatedObject).setAccessible(true);
+ } else if (annotatedObject instanceof Field) {
+ a = new FieldAnnotation(name, values, (Field) annotatedObject);
+ ((Field) annotatedObject).setAccessible(true);
+ } else {
+ a = new ClassAnnotation(name, values);
+ }
+ descriptions.add(a);
+ }
+
+ /**
+ * Get a description for the class
+ */
+ public ClassDescription getDescription(final Class<?> clazz)
+ throws SCRDescriptorException, SCRDescriptorFailureException {
+ final String name = clazz.getName();
+ ClassDescription result = this.allDescriptions.get(name);
+ if ( result == null ) {
+ // use scanner first
+ result = this.processClass(clazz, GENERATED);
+
+ if ( result == null ) {
+ // now check loaded dependencies
+ result = this.getComponentDescriptors().get(name);
+ }
+
+ // not found, create dummy
+ if ( result == null ) {
+ result = new ClassDescription(clazz, GENERATED);
+ }
+
+ // and cache
+ allDescriptions.put(name, result);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a map of component descriptors which may be extended by the java
+ * sources.
+ * <p>
+ * This method calls the {@link #getDependencies()} method and checks for
+ * any Service-Component descriptors in the returned files.
+ * <p>
+ * This method may be overwritten by extensions of this class.
+ *
+ * @throws SCRDescriptorException May be thrown if an error occurrs
+ * gethering the component descriptors.
+ */
+ private Map<String, ClassDescription> getComponentDescriptors()
+ throws SCRDescriptorException {
+ if ( loadedDependencies == null ) {
+ loadedDependencies = new HashMap<String, ClassDescription>();
+
+ final Collection<File> dependencies = this.project.getDependencies();
+ for ( final File artifact : dependencies ) {
+ try {
+ this.log.debug( "Trying to get scrinfo from artifact " + artifact );
+ // First try to read the private scr info file from previous scr generator versions
+ InputStream scrInfoFile = null;
+ try {
+ scrInfoFile = this.getFile( artifact, ABSTRACT_DESCRIPTOR_ARCHIV_PATH );
+ if ( scrInfoFile != null ) {
+ final List<ClassDescription> c = this.parseServiceComponentDescriptor( scrInfoFile, artifact.toString() + ':' + ABSTRACT_DESCRIPTOR_ARCHIV_PATH);
+ if ( c != null ) {
+ for(final ClassDescription cd : c) {
+ loadedDependencies.put(cd.getDescribedClass().getName(), cd);
+ }
+ }
+ continue;
+ }
+ this.log.debug( "Artifact has no scrinfo file (it's optional): " + artifact );
+ } catch ( final IOException ioe ) {
+ throw new SCRDescriptorException( "Unable to get scrinfo from artifact", artifact.toString(), 0,
+ ioe );
+ } finally {
+ if ( scrInfoFile != null ) {
+ try { scrInfoFile.close(); } catch ( final IOException ignore ) {}
+ }
+ }
+
+ this.log.debug( "Trying to get manifest from artifact " + artifact );
+ final Manifest manifest = this.getManifest( artifact );
+ if ( manifest != null ) {
+ // read Service-Component entry
+ if ( manifest.getMainAttributes().getValue( SERVICE_COMPONENT ) != null ) {
+ final String serviceComponent = manifest.getMainAttributes().getValue(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 List<ClassDescription> c = this.readServiceComponentDescriptor( artifact, entry );
+ if ( c != null ) {
+ for(final ClassDescription cd : c) {
+ loadedDependencies.put(cd.getDescribedClass().getName(), cd);
+ }
+ }
+ }
+ }
+ } 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.toString(), 0,
+ ioe );
+ }
+
+ }
+ }
+ return this.loadedDependencies;
+ }
+
+ /**
+ * Parses the descriptors read from the given input stream. This method may
+ * be called by the {@link #getComponentDescriptors()} method to parse the
+ * descriptors gathered in an implementation dependent way.
+ *
+ * @throws SCRDescriptorException If an error occurrs reading the
+ * descriptors from the stream.
+ */
+ private List<ClassDescription> parseServiceComponentDescriptor(
+ final InputStream file, final String location )
+ throws SCRDescriptorException {
+ return ComponentDescriptorIO.read( file, this.project.getClassLoader(), iLog, location );
+ }
+
+ /**
+ * Read the service component description.
+ *
+ * @param artifact
+ * @param entry
+ * @throws IOException
+ * @throws SCRDescriptorException
+ */
+ private List<ClassDescription> readServiceComponentDescriptor( final File artifactFile, String entry ) {
+ this.log.debug( "Reading " + entry + " from " + artifactFile );
+ InputStream xml = null;
+ try {
+ xml = this.getFile( artifactFile, entry );
+ if ( xml == null ) {
+ throw new SCRDescriptorException( "Entry " + entry + " not contained in JAR File ", artifactFile.toString(),
+ 0 );
+ }
+ return this.parseServiceComponentDescriptor( xml, artifactFile.toString() + ':' + entry );
+ } catch ( final IOException mee ) {
+ this.log.warn( "Unable to read SCR descriptor file from JAR File " + artifactFile + " at " + entry );
+ this.log.debug( "Exception occurred during reading: " + mee.getMessage(), mee );
+ } catch ( final SCRDescriptorException mee ) {
+ this.log.warn( "Unable to read SCR descriptor file from JAR File " + artifactFile + " at " + entry );
+ this.log.debug( "Exception occurred during reading: " + mee.getMessage(), mee );
+ } finally {
+ if ( xml != null ) {
+ try { xml.close(); } catch (final IOException ignore) {}
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Get the manifest from the artifact.
+ * The artifact can either be a jar or a directory.
+ */
+ private Manifest getManifest( final File artifact ) throws IOException {
+ if ( artifact.isDirectory() ) {
+ // this is maybe a classes directory, try to read manifest file directly
+ final File dir = new File(artifact, "META-INF");
+ if ( !dir.exists() || !dir.isDirectory() ) {
+ return null;
+ }
+ final File mf = new File(dir, "MANIFEST.MF");
+ if ( !mf.exists() || !mf.isFile() ) {
+ return null;
+ }
+ final InputStream is = new FileInputStream(mf);
+ try {
+ return new Manifest(is);
+ } finally {
+ try { is.close(); } catch (final IOException ignore) { }
+ }
+ }
+ JarFile file = null;
+ try {
+ file = new JarFile( artifact );
+ return file.getManifest();
+ } finally {
+ if ( file != null ) {
+ try { file.close(); } catch ( final IOException ignore ) {}
+ }
+ }
+ }
+
+ private InputStream getFile( final File artifactFile, final String path ) throws IOException {
+ if ( artifactFile.isDirectory() ) {
+ final String filePath = path.replace('/', File.separatorChar).replace('\\', File.separatorChar);
+ final File file = new File(artifactFile, filePath);
+ if ( file.exists() && file.isFile() ) {
+ return new FileInputStream(file);
+ }
+ return null;
+ }
+ JarFile file = null;
+ try {
+ file = new JarFile( artifactFile );
+ 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 ( final 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 ( final IOException ioe ) {
+ // ignore
+ }
+ jarFile.close();
+ }
+
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
index 210b42d..8e7819c 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
@@ -18,7 +18,9 @@
*/
package org.apache.felix.scrplugin.helper;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import org.apache.felix.scrplugin.Log;
@@ -44,86 +46,72 @@
}
public boolean hasErrors() {
- return errors.size() > 0 ||
- (this.strictMode && (warnings.size() > 0 || this.deprecationWarnings.size() > 0));
+ return errors.size() > 0 || (this.strictMode && (warnings.size() > 0 || this.deprecationWarnings.size() > 0));
}
- public void addError(final String message, final String location, final int lineNumber) {
- errors.add( new Entry( message, location, lineNumber ) );
+ public void addError(final String message, final String location) {
+ errors.add(new Entry(message, location));
}
- public void addWarning(final String message, final String location, final int lineNumber) {
- warnings.add( new Entry( message, location, lineNumber ) );
+ public void addWarning(final String message, final String location) {
+ warnings.add(new Entry(message, location));
}
- public void addDeprecationWarning(final String message, final String location, final int lineNumber) {
- deprecationWarnings.add( new Entry( message, location, lineNumber ) );
+ public void addDeprecationWarning(final String message, final String location) {
+ deprecationWarnings.add(new Entry(message, location));
}
- public void logMessages( final Log log )
- {
+ public void logMessages(final Log log) {
// now log warnings and errors (warnings first)
// in strict mode everything is an error!
final Iterator<Entry> depWarnings = this.deprecationWarnings.iterator();
- while ( depWarnings.hasNext() )
- {
+ while (depWarnings.hasNext()) {
final Entry entry = depWarnings.next();
- if ( strictMode )
- {
- log.error( entry.message, entry.location, entry.lineNumber);
- }
- else
- {
- log.warn( entry.message, entry.location, entry.lineNumber);
+ if (strictMode) {
+ log.error(entry.toString());
+ } else {
+ log.warn(entry.toString());
}
}
- if ( this.deprecationWarnings.size() > 0 ) {
- final String msg = "It is highly recommended to fix these problems, as future versions might not " +
- "support these features anymore.";
- if ( strictMode )
- {
- log.error( msg );
- }
- else
- {
- log.warn( msg );
+ if (this.deprecationWarnings.size() > 0) {
+ final String msg = "It is highly recommended to fix these problems, as future versions might not "
+ + "support these features anymore.";
+ if (strictMode) {
+ log.error(msg);
+ } else {
+ log.warn(msg);
}
}
final Iterator<Entry> warnings = this.warnings.iterator();
- while ( warnings.hasNext() )
- {
+ while (warnings.hasNext()) {
final Entry entry = warnings.next();
- if ( strictMode )
- {
- log.error( entry.message, entry.location, entry.lineNumber);
- }
- else
- {
- log.warn( entry.message, entry.location, entry.lineNumber);
+ if (strictMode) {
+ log.error(entry.toString());
+ } else {
+ log.warn(entry.toString());
}
}
final Iterator<Entry> errors = this.errors.iterator();
- while ( errors.hasNext() )
- {
+ while (errors.hasNext()) {
final Entry entry = errors.next();
- log.error( entry.message, entry.location, entry.lineNumber);
+ log.error(entry.toString());
}
}
- private static class Entry
- {
+ private static class Entry {
final String message;
final String location;
- final int lineNumber;
-
- Entry( final String message, final String location, final int lineNumber )
- {
+ Entry(final String message, final String location) {
this.message = message;
this.location = location;
- this.lineNumber = lineNumber;
+ }
+
+ @Override
+ public String toString() {
+ return this.location + " : " + this.message;
}
}
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
deleted file mode 100644
index 46b02ef..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
+++ /dev/null
@@ -1,409 +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.helper;
-
-import java.util.*;
-
-import org.apache.felix.scrplugin.*;
-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.osgi.service.cm.ConfigurationAdmin;
-
-/**
- * Utility class for handling the properties.
- */
-public class PropertyHandler {
-
- /**
- * This is a map using the property name as the key and
- * {@link PropertyDescription} as values.
- */
- final private Map<String, PropertyDescription> properties = new LinkedHashMap<String, PropertyDescription>();
-
- /** The component. */
- final private Component component;
-
- /** The ocd or null. */
- final private OCD ocd;
-
- public PropertyHandler(final Component c, OCD o) {
- this.component = c;
- this.ocd = o;
- }
-
- /**
- * Process a property.
- * @param tag The property tag.
- * @param name The name of the property.
- * @param javaField The corresponding java field or null.
- */
- protected void processProperty(JavaTag tag,
- String name,
- JavaField javaField,
- final IssueLog iLog)
- throws SCRDescriptorException {
- final Property prop = new Property(tag);
- prop.setName(name);
- // special handling for service.ranking - FELIX-2333
- if (name.equals(org.osgi.framework.Constants.SERVICE_RANKING)) {
- prop.setType(Constants.PROPERTY_TYPE_INTEGER);
- }
- if ( tag.getNamedParameter(Constants.PROPERTY_TYPE) != null ) {
- prop.setType(tag.getNamedParameter(Constants.PROPERTY_TYPE));
- }
- // let's first check for a value attribute
- final String value = tag.getNamedParameter(Constants.PROPERTY_VALUE);
- if ( value != null ) {
- prop.setValue(value);
- } else {
- // now we check for a value ref attribute
- final String valueRef = tag.getNamedParameter(Constants.PROPERTY_VALUE_REF);
- if ( valueRef != null ) {
- this.setPropertyValueRef(tag, prop, valueRef);
- } else {
- // check for multivalue - these can either be values or value refs
- final List<String> values = new ArrayList<String>();
- final Map<String, String> valueMap = tag.getNamedParameterMap();
- for (Iterator<Map.Entry<String, String>> vi = valueMap.entrySet().iterator(); vi.hasNext();) {
- final Map.Entry<String, String> entry = vi.next();
- final String key = entry.getKey();
- if (key.startsWith(Constants.PROPERTY_MULTIVALUE_PREFIX) ) {
- values.add(entry.getValue());
- } else if ( key.startsWith(Constants.PROPERTY_MULTIVALUE_REF_PREFIX) ) {
- final String[] stringValues = this.getPropertyValueRef(tag, prop, entry.getValue());
- if ( stringValues != null ) {
- for(int i=0; i<stringValues.length; i++) {
- values.add(stringValues[i]);
- }
- }
- }
- }
- if ( values.size() > 0 ) {
- prop.setMultiValue(values.toArray(new String[values.size()]));
- } else {
- // we have no value, valueRef or values so let's try to
- // get the value of the field if a name attribute is specified
- final boolean isNamedParameter = tag.getNamedParameter(Constants.PROPERTY_NAME) != null
- || tag.getNamedParameter(Constants.PROPERTY_NAME_REF) != null;
- if ( isNamedParameter && javaField != null ) {
- this.setPropertyValueRef(tag, prop, javaField.getName());
- }
- }
- }
- }
-
- // property is private if explicitly marked or a well known
- // service property such as service.pid
- final boolean isPrivate = isPrivate(name, tag);
-
- // if this is an abstract component we store the extra info in the property
- if ( component.isAbstract() ) {
- prop.setPrivate(isPrivate);
- prop.setLabel(tag.getNamedParameter(Constants.PROPERTY_LABEL));
- prop.setDescription(tag.getNamedParameter(Constants.PROPERTY_DESCRIPTION));
- prop.setCardinality(tag.getNamedParameter(Constants.PROPERTY_CARDINALITY));
- }
-
- // if this is a public property and the component is generating metatype info
- // store the information!
- if ( !isPrivate && ocd != null ) {
- final AttributeDefinition ad = new AttributeDefinition();
- ocd.getProperties().add(ad);
- ad.setId(prop.getName());
- ad.setType(prop.getType());
-
- String adName = tag.getNamedParameter(Constants.PROPERTY_LABEL);
- if ( adName == null ) {
- adName = "%" + prop.getName() + ".name";
- }
- ad.setName(adName);
- String adDesc = tag.getNamedParameter(Constants.PROPERTY_DESCRIPTION);
- if ( adDesc == null ) {
- adDesc = "%" + prop.getName() + ".description";
- }
- ad.setDescription(adDesc);
- // set optional multivalues, cardinality might be overwritten by setValues !!
- final String cValue = tag.getNamedParameter(Constants.PROPERTY_CARDINALITY);
- if (cValue != null) {
- if ("-".equals(cValue)) {
- // unlimited vector
- ad.setCardinality(new Integer(Integer.MIN_VALUE));
- } else if ("+".equals(cValue)) {
- // unlimited array
- ad.setCardinality(new Integer(Integer.MAX_VALUE));
- } else {
- try {
- ad.setCardinality(Integer.valueOf(cValue));
- } catch (NumberFormatException nfe) {
- // default to scalar in case of conversion problem
- }
- }
- }
- ad.setDefaultValue(prop.getValue());
- ad.setDefaultMultiValue(prop.getMultiValue());
-
- // check options
- String[] parameters = tag.getParameters();
- Map<String, String> options = null;
- for (int j=0; j < parameters.length; j++) {
- if (Constants.PROPERTY_OPTIONS.equals(parameters[j])) {
- options = new LinkedHashMap<String, String>();
- } else if (options != null) {
- final String option = parameters[j];
- final int pos = option.indexOf('=');
- if ( pos != -1 )
- {
- // handle options from javadoc comments
- String optionLabel = option.substring(0, pos);
- String optionValue = option.substring(pos + 1);
- if (optionValue != null && optionValue.length() > 0 ) {
- options.put(optionLabel, optionValue);
- }
- }
- else
- {
- // handle options from java annotations
- String optionLabel = parameters[j];
- String optionValue = (j < parameters.length-2) ? parameters[j+2] : null;
- if (optionValue != null && "=".equals(parameters[j+1]) ) {
- options.put(optionLabel, optionValue);
- }
- j += 2;
- }
- }
- }
- ad.setOptions(options);
- }
-
- component.addProperty(prop);
- }
-
- private boolean isPrivate(String name, JavaTag tag) {
- if (name.equals(org.osgi.framework.Constants.SERVICE_RANKING)) {
- return SCRDescriptorGenerator.getBoolean(tag,
- Constants.PROPERTY_PRIVATE, true);
- }
- return SCRDescriptorGenerator.getBoolean(tag,
- Constants.PROPERTY_PRIVATE, false)
- || name.equals(org.osgi.framework.Constants.SERVICE_PID)
- || name.equals(org.osgi.framework.Constants.SERVICE_DESCRIPTION)
- || name.equals(org.osgi.framework.Constants.SERVICE_ID)
- || name.equals(org.osgi.framework.Constants.SERVICE_VENDOR)
- || name.equals(ConfigurationAdmin.SERVICE_BUNDLELOCATION)
- || name.equals(ConfigurationAdmin.SERVICE_FACTORYPID);
- }
-
- /**
- * Return the name of the property.
- * The name of the property is derived by:
- * <ol>
- * <li>looking at the attribute {@link Constants.PROPERTY_NAME}</li>
- * <li>looking at the attribute {@link Constants.PROPERTY_NAME_REF}</li>
- * <li>if the property is specified at a filed and the field is of type string the init value is used.</li>
- * </ol>
- *
- * @param property The property tag.
- * @param field The corresponding field if the property is a tag of a field.
- * @return The name of the property or the defaultName
- */
- protected String getPropertyName(JavaTag tag, JavaField field)
- throws SCRDescriptorException {
- // check name property
- String name = tag.getNamedParameter(Constants.PROPERTY_NAME);
-
- if (StringUtils.isEmpty(name)) {
- // check name ref propery
- name = tag.getNamedParameter(Constants.PROPERTY_NAME_REF);
- if (!StringUtils.isEmpty(name)) {
- final JavaField refField = this.getReferencedField(tag, name);
- final String[] values = refField.getInitializationExpression();
- if ( values == null || values.length == 0 ) {
- throw new SCRDescriptorException("Referenced field for " + name + " has no values for a property name.", tag);
- }
- if ( values.length > 1 ) {
- throw new SCRDescriptorException("Referenced field " + name + " has more than one value for a property name.", tag);
- }
- name = values[0];
- }
-
- if (StringUtils.isEmpty(name)) {
- // check field
- name = null;
- if ( field != null && "java.lang.String".equals(field.getType()) ) {
- final String[] initValues = field.getInitializationExpression();
- if ( initValues != null && initValues.length == 1 ) {
- name = initValues[0];
- }
- }
- }
- }
- // final empty check
- if ( StringUtils.isEmpty(name) ) {
- name = null;
- }
- return name;
- }
-
- protected void setPropertyValueRef(final JavaTag tag, Property property, String valueRef)
- throws SCRDescriptorException {
- final String[] values = this.getPropertyValueRef(tag, property, valueRef);
- if ( values != null && values.length == 1 ) {
- property.setValue(values[0]);
- } else if ( values != null && values.length > 1 ) {
- property.setMultiValue(values);
- }
- }
-
- protected 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("Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName(), tag);
- }
- return field;
- }
-
- protected String[] getPropertyValueRef(final JavaTag tag, Property prop, String valueRef)
- throws SCRDescriptorException {
- final JavaField field = this.getReferencedField(tag, valueRef);
-
- // determine type (if not set explicitly)
- if ( prop.getType() == null ) {
- final String type = field.getType();
- if ( "java.lang.String".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_STRING);
- } else if ("java.lang.Long".equals(type) || "long".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_LONG);
- } else if ("java.lang.Double".equals(type) || "double".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_DOUBLE);
- } else if ("java.lang.Float".equals(type) || "float".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_FLOAT);
- } else if ("java.lang.Integer".equals(type) || "int".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_INTEGER);
- } else if ("java.lang.Byte".equals(type) || "byte".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_BYTE);
- } else if ("java.lang.Character".equals(type) || "char".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_CHAR_1_1);
- } else if ("java.lang.Boolean".equals(type) || "boolean".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_BOOLEAN);
- } else if ("java.lang.Short".equals(type) || "short".equals(type) ) {
- prop.setType(Constants.PROPERTY_TYPE_SHORT);
- }
-
- }
- return field.getInitializationExpression();
- }
-
- /**
- * Test if there is already a property with the same name.
- * @param property The tag.
- * @param field
- * @param isInspectedClass
- * @throws SCRDescriptorException
- */
- public void testProperty(JavaTag property,
- JavaField field,
- boolean isInspectedClass)
- throws SCRDescriptorException {
- final String propName = this.getPropertyName(property, field);
-
- if ( propName != null ) {
- if ( properties.containsKey(propName) ) {
- // if the current class is the class we are currently inspecting, we
- // have found a duplicate definition
- if ( isInspectedClass ) {
- throw new SCRDescriptorException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName(), property);
- }
- } else {
- properties.put(propName, new PropertyDescription(property, field));
- }
- } else {
- throw new SCRDescriptorException("Property has no name", property);
- }
- }
-
- public void handleField(JavaField javaField, boolean isInspectedClass)
- throws SCRDescriptorException {
- final JavaTag tag = javaField.getTagByName(Constants.PROPERTY);
- if (tag != null) {
- this.testProperty(tag, javaField, isInspectedClass);
- }
- }
-
- /**
- * Process all found properties for the component.
- * @param globalProperties Global properties are set on all components.
- * @param iLog The issue log.
- * @throws SCRDescriptorException
- */
- public void processProperties(final Map<String, String> globalProperties,
- final IssueLog iLog)
- throws SCRDescriptorException {
- final Iterator<Map.Entry<String, PropertyDescription>> propIter = properties.entrySet().iterator();
- while ( propIter.hasNext() ) {
- final Map.Entry<String, PropertyDescription> entry = propIter.next();
- final String propName = entry.getKey();
- final PropertyDescription desc = entry.getValue();
- this.processProperty(desc.propertyTag, propName, desc.field, iLog);
- }
- // apply pre configured global properties
- if ( globalProperties != null ) {
- final Iterator<Map.Entry<String, String>> globalPropIter = globalProperties.entrySet().iterator();
- while ( globalPropIter.hasNext() ) {
- final Map.Entry<String, String> entry = globalPropIter.next();
- final String name = entry.getKey();
-
- // check if the service already provides this property
- if ( !properties.containsKey(name) && entry.getValue() != null ) {
- final String value = entry.getValue();
-
- final Property p = new Property();
- p.setName(name);
- p.setValue(value);
- p.setType("String");
- p.setPrivate(true);
- component.addProperty(p);
-
- }
- }
- }
- }
-
- protected static final class PropertyDescription {
- public final JavaTag propertyTag;
- public final JavaField field;
-
- public PropertyDescription(final JavaTag p, final JavaField f) {
- this.propertyTag = p;
- this.field = f;
- }
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java
index 425865e..9f7d05c 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java
@@ -19,29 +19,27 @@
package org.apache.felix.scrplugin.om;
import org.apache.felix.scrplugin.helper.IssueLog;
-import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
/**
- * The <code>AbstractObject</code>
- * is the base class for the all classes of the scr om.
+ * The <code>AbstractObject</code> is the base class for the all classes of the scr om.
*/
public abstract class AbstractObject {
- protected final JavaTag tag;
+ private final String annotationName;
- protected AbstractObject(JavaTag tag) {
- this.tag = tag;
+ private final String sourceLocation;
+
+ protected AbstractObject(final ScannedAnnotation annotation, final String sourceLocation) {
+ this.annotationName = (annotation != null ? annotation.getName() : "<unknown>");
+ this.sourceLocation = sourceLocation;
}
protected void logWarn(IssueLog iLog, String message) {
- iLog.addWarning( "@" + this.tag.getSourceName() + ": " + message, tag.getSourceLocation(), tag.getLineNumber() );
+ iLog.addWarning("@" + this.annotationName + ": " + message, sourceLocation);
}
protected void logError(IssueLog iLog, String message) {
- iLog.addError( "@" + this.tag.getSourceName() + ": " + message, tag.getSourceLocation(), tag.getLineNumber() );
- }
-
- public JavaTag getJavaTag() {
- return this.tag;
+ iLog.addError("@" + this.annotationName + ": " + message, sourceLocation);
}
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Component.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Component.java
index 72f1c22..2c18d80 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Component.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Component.java
@@ -18,17 +18,20 @@
*/
package org.apache.felix.scrplugin.om;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
-import org.apache.felix.scrplugin.Constants;
import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.helper.IssueLog;
-import org.apache.felix.scrplugin.tags.*;
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.description.ComponentConfigurationPolicy;
+import org.apache.felix.scrplugin.description.SpecVersion;
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
/**
- * <code>Component</code>
- * is a described component.
+ * <code>Component</code> is a described component.
*
*/
public class Component extends AbstractObject {
@@ -64,7 +67,7 @@
protected boolean isDs;
/** Configuration policy. (V1.1) */
- protected String configurationPolicy;
+ protected ComponentConfigurationPolicy configurationPolicy;
/** Activation method. (V1.1) */
protected String activate;
@@ -76,50 +79,41 @@
protected String modified;
/** The spec version. */
- protected int specVersion;
+ protected SpecVersion specVersion;
- /**
- * Default constructor.
- */
- public Component() {
- this(null);
- }
+ /** The class description. */
+ private final ClassDescription classDescription;
/**
* Constructor from java source.
*/
- public Component(JavaTag t) {
- super(t);
+ public Component(final ClassDescription cDesc, final ScannedAnnotation annotation, final String sourceLocation) {
+ super(annotation, sourceLocation);
+ this.classDescription = cDesc;
+ }
+
+ public ClassDescription getClassDescription() {
+ return this.classDescription;
}
/**
* Get the spec version.
*/
- public int getSpecVersion() {
+ public SpecVersion getSpecVersion() {
return this.specVersion;
}
/**
* Set the spec version.
*/
- public void setSpecVersion(int value) {
+ public void setSpecVersion(final SpecVersion value) {
// only set a higher version, never "downgrade"
- if (this.specVersion < value) {
+ if (this.specVersion == null || this.specVersion.ordinal() < value.ordinal()) {
this.specVersion = value;
}
}
/**
- * Return the associated java class description
- */
- public JavaClassDescription getJavaClassDescription() {
- if ( this.tag != null ) {
- return this.tag.getJavaClassDescription();
- }
- return null;
- }
-
- /**
* @return All properties of this component.
*/
public List<Property> getProperties() {
@@ -253,109 +247,104 @@
}
/**
- * Validate the component description.
- * If errors occur a message is added to the issues list,
- * warnings can be added to the warnings list.
+ * Validate the component description. If errors occur a message is added to
+ * the issues list, warnings can be added to the warnings list.
*/
- public void validate(final int specVersion, final IssueLog iLog)
- throws SCRDescriptorException {
- final int currentIssueCount = iLog.getNumberOfErrors();
-
+ public void validate(final Context context) throws SCRDescriptorException {
// nothing to check if this is ignored
if (!isDs()) {
return;
}
- final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
- if (javaClass == null) {
- this.logError( iLog, "Tag not declared in a Java Class" );
- } else {
+ final int currentIssueCount = context.getIssueLog().getNumberOfErrors();
- // if the service is abstract, we do not validate everything
- if ( !this.isAbstract ) {
- // ensure non-abstract, public class
- if (!javaClass.isPublic()) {
- this.logError( iLog, "Class must be public: " + javaClass.getName() );
- }
- if (javaClass.isAbstract() || javaClass.isInterface()) {
- this.logError( iLog, "Class must be concrete class (not abstract or interface) : " + javaClass.getName() );
- }
-
- // no errors so far, let's continue
- if ( iLog.getNumberOfErrors() == currentIssueCount ) {
- final String activateName = this.activate == null ? "activate" : this.activate;
- final String deactivateName = this.deactivate == null ? "deactivate" : this.deactivate;
-
- // check activate and deactivate methods
- this.checkLifecycleMethod(specVersion, javaClass, activateName, true, iLog);
- this.checkLifecycleMethod(specVersion, javaClass, deactivateName, false, iLog);
-
- if ( this.modified != null && specVersion >= Constants.VERSION_1_1 ) {
- this.checkLifecycleMethod(specVersion, javaClass, this.modified, true, iLog);
- }
- // ensure public default constructor
- boolean constructorFound = true;
- JavaMethod[] methods = javaClass.getMethods();
- for (int i = 0; methods != null && i < methods.length; i++) {
- if (methods[i].isConstructor()) {
- // if public default, succeed
- if (methods[i].isPublic()
- && (methods[i].getParameters() == null || methods[i].getParameters().length == 0)) {
- constructorFound = true;
- break;
- }
-
- // non-public/non-default constructor found, must have explicit
- constructorFound = false;
- }
- }
- if (!constructorFound) {
- this.logError( iLog, "Class must have public default constructor: " + javaClass.getName() );
- }
-
- // verify properties
- for(final Property prop : this.getProperties()) {
- prop.validate(specVersion, iLog);
- }
-
- // verify service
- boolean isServiceFactory = false;
- if (this.getService() != null) {
- if ( this.getService().getInterfaces().size() == 0 ) {
- this.logError( iLog, "Service interface information is missing!" );
- }
- this.getService().validate(specVersion, iLog);
- isServiceFactory = this.getService().isServicefactory();
- }
-
- // serviceFactory must not be true for immediate of component factory
- if (isServiceFactory && this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
- this.logError( iLog, "Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName() );
- }
-
- // immediate must not be true for component factory
- if (this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
- this.logError( iLog, "Component must not be immediate if component factory: " + javaClass.getName() );
- }
- }
+ // if the service is abstract, we do not validate everything
+ if (!this.isAbstract) {
+ // ensure non-abstract, public class
+ if (!Modifier.isPublic(context.getClassDescription().getDescribedClass().getModifiers())) {
+ this.logError(context.getIssueLog(), "Class must be public: "
+ + context.getClassDescription().getDescribedClass().getName());
}
- if ( iLog.getNumberOfErrors() == currentIssueCount ) {
- // verify references
- for(final Reference ref : this.getReferences()) {
- ref.validate(specVersion, this.isAbstract, iLog);
+ if (Modifier.isAbstract(context.getClassDescription().getDescribedClass().getModifiers())
+ || context.getClassDescription().getDescribedClass().isInterface()) {
+ this.logError(context.getIssueLog(), "Class must be concrete class (not abstract or interface) : "
+ + context.getClassDescription().getDescribedClass().getName());
+ }
+
+ // no errors so far, let's continue
+ if (context.getIssueLog().getNumberOfErrors() == currentIssueCount) {
+
+ final String activateName = this.activate == null ? "activate" : this.activate;
+ final String deactivateName = this.deactivate == null ? "deactivate" : this.deactivate;
+
+ // check activate and deactivate methods
+ this.checkLifecycleMethod(context, activateName, true);
+ this.checkLifecycleMethod(context, deactivateName, false);
+
+ if (this.modified != null) {
+ if ( context.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
+ this.checkLifecycleMethod(context, this.modified, true);
+ } else {
+ this.logError(context.getIssueLog(), "If modified version is specified, spec version must be " +
+ SpecVersion.VERSION_1_1.name() + " or higher : " + this.modified);
+ }
+ }
+
+ // ensure public default constructor
+ boolean constructorFound = true;
+ Constructor<?>[] constructors = this.classDescription.getDescribedClass().getDeclaredConstructors();
+ for (int i = 0; constructors != null && i < constructors.length; i++) {
+ // if public default, succeed
+ if (Modifier.isPublic(constructors[i].getModifiers())
+ && (constructors[i].getParameterTypes() == null || constructors[i].getParameterTypes().length == 0)) {
+ constructorFound = true;
+ break;
+ }
+
+ // non-public/non-default constructor found, must have
+ // explicit
+ constructorFound = false;
+ }
+
+ if (!constructorFound) {
+ this.logError(context.getIssueLog(), "Class must have public default constructor: " + this.classDescription.getDescribedClass().getName());
+ }
+
+ // verify properties
+ for (final Property prop : this.getProperties()) {
+ prop.validate(context);
+ }
+
+ // verify service
+ boolean isServiceFactory = false;
+ if (this.getService() != null) {
+ if (this.getService().getInterfaces().size() == 0) {
+ this.logError(context.getIssueLog(), "Service interface information is missing!");
+ }
+ this.getService().validate(context);
+ isServiceFactory = this.getService().isServiceFactory();
+ }
+
+ // serviceFactory must not be true for immediate of component factory
+ if (isServiceFactory && this.isImmediate() != null && this.isImmediate().booleanValue()
+ && this.getFactory() != null) {
+ this.logError(context.getIssueLog(),
+ "Component must not be a ServiceFactory, if immediate and/or component factory: "
+ + this.getClassDescription().getDescribedClass().getName());
+ }
+
+ // immediate must not be true for component factory
+ if (this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
+ this.logError(context.getIssueLog(),
+ "Component must not be immediate if component factory: " + this.getClassDescription().getDescribedClass().getName());
}
}
}
- // check additional stuff if version is 1.1
- if ( specVersion >= Constants.VERSION_1_1 ) {
- final String cp = this.getConfigurationPolicy();
- if ( cp != null
- && !Constants.COMPONENT_CONFIG_POLICY_IGNORE.equals(cp)
- && !Constants.COMPONENT_CONFIG_POLICY_REQUIRE.equals(cp)
- && !Constants.COMPONENT_CONFIG_POLICY_OPTIONAL.equals(cp) ) {
- this.logError( iLog, "Component has an unknown value for configuration policy: " + cp );
+ if (context.getIssueLog().getNumberOfErrors() == currentIssueCount) {
+ // verify references
+ for (final Reference ref : this.getReferences()) {
+ ref.validate(context, this.isAbstract);
}
-
}
}
@@ -365,78 +354,114 @@
private static final String TYPE_INT = "int";
private static final String TYPE_INTEGER = "java.lang.Integer";
+ private Method getMethod(final Context ctx, final String name, final String[] sig)
+ throws SCRDescriptorException {
+ Class<?>[] classSig = (sig == null ? null : new Class<?>[sig.length]);
+ if ( sig != null ) {
+ for(int i = 0; i<sig.length; i++) {
+ try {
+ if ( sig[i].equals("int") ) {
+ classSig[i] = int.class;
+ } else {
+ classSig[i] = ctx.getProject().getClassLoader().loadClass(sig[i]);
+ }
+ } catch (final ClassNotFoundException e) {
+ throw new SCRDescriptorException("Unable to load class.", e);
+ }
+ }
+ }
+ try {
+ return ctx.getClassDescription().getDescribedClass().getDeclaredMethod(name, classSig);
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final NoSuchMethodException e) {
+ // ignore
+ }
+ return null;
+ }
+
/**
* Check for existence of lifecycle methods.
- * @param specVersion The spec version
- * @param javaClass The java class to inspect.
- * @param methodName The method name.
- * @param warnings The list of warnings used to add new warnings.
+ *
+ * @param specVersion
+ * The spec version
+ * @param javaClass
+ * The java class to inspect.
+ * @param methodName
+ * The method name.
+ * @param warnings
+ * The list of warnings used to add new warnings.
*/
- protected void checkLifecycleMethod(final int specVersion,
- final JavaClassDescription javaClass,
- final String methodName,
- final boolean isActivate,
- final IssueLog iLog)
+ private void checkLifecycleMethod(final Context ctx,
+ final String methodName,
+ final boolean isActivate)
throws SCRDescriptorException {
// first candidate is (de)activate(ComponentContext)
- JavaMethod method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_COMPONENT_CONTEXT});
- if ( method == null ) {
- if ( specVersion >= Constants.VERSION_1_1) {
+ Method method = this.getMethod(ctx, methodName, new String[] { TYPE_COMPONENT_CONTEXT });
+ if (method == null) {
+ if (ctx.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
// second candidate is (de)activate(BundleContext)
- method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_BUNDLE_CONTEXT});
- if ( method == null ) {
+ method = this.getMethod(ctx, methodName, new String[] { TYPE_BUNDLE_CONTEXT });
+ if (method == null) {
// third candidate is (de)activate(Map)
- method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_MAP});
+ method = this.getMethod(ctx, methodName, new String[] { TYPE_MAP });
- if ( method == null ) {
- // if this is a deactivate method, we have two additional possibilities
- // a method with parameter of type int and one of type Integer
- if ( !isActivate ) {
- method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_INT});
- if ( method == null ) {
- method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_INTEGER});
+ if (method == null) {
+ // if this is a deactivate method, we have two
+ // additional possibilities
+ // a method with parameter of type int and one of type
+ // Integer
+ if (!isActivate) {
+ method = this.getMethod(ctx, methodName, new String[] { TYPE_INT });
+ if (method == null) {
+ method = this.getMethod(ctx, methodName, new String[] { TYPE_INTEGER });
}
}
+ }
- // fourth candidate is (de)activate with two or three arguments (type must be BundleContext, ComponentCtx and Map)
- // as we have to iterate now and the fifth candidate is zero arguments
+ if (method == null) {
+ // fourth candidate is (de)activate with two or three
+ // arguments (type must be BundleContext, ComponentCtx
+ // and Map)
+ // as we have to iterate now and the fifth candidate is
+ // zero arguments
// we already store this option
- JavaMethod zeroArgMethod = null;
- JavaMethod found = method;
- final JavaMethod[] methods = javaClass.getMethods();
+ Method zeroArgMethod = null;
+ Method found = method;
+ final Method[] methods = ctx.getClassDescription().getDescribedClass().getDeclaredMethods();
int i = 0;
- while ( i < methods.length ) {
- if ( methodName.equals(methods[i].getName()) ) {
+ while (i < methods.length) {
+ if (methodName.equals(methods[i].getName())) {
- if ( methods[i].getParameters().length == 0 ) {
+ if (methods[i].getParameterTypes() == null || methods[i].getParameterTypes().length == 0) {
zeroArgMethod = methods[i];
- } else if ( methods[i].getParameters().length >= 2 ) {
+ } else if (methods[i].getParameterTypes().length >= 2) {
boolean valid = true;
- for(int m=0; m<methods[i].getParameters().length; m++) {
- final String type = methods[i].getParameters()[m].getType();
- if ( !type.equals(TYPE_BUNDLE_CONTEXT)
- && !type.equals(TYPE_COMPONENT_CONTEXT)
- && !type.equals(TYPE_MAP) ) {
- // if this is deactivate, int and integer are possible as well
- if ( isActivate || (!type.equals(TYPE_INT) && !type.equals(TYPE_INTEGER)) ) {
+ for (int m = 0; m < methods[i].getParameterTypes().length; m++) {
+ final String type = methods[i].getParameterTypes()[m].getName();
+ if (!type.equals(TYPE_BUNDLE_CONTEXT) && !type.equals(TYPE_COMPONENT_CONTEXT)
+ && !type.equals(TYPE_MAP)) {
+ // if this is deactivate, int and
+ // integer are possible as well
+ if (isActivate || (!type.equals(TYPE_INT) && !type.equals(TYPE_INTEGER))) {
valid = false;
}
}
}
- if ( valid ) {
- if ( found == null ) {
+ if (valid) {
+ if (found == null) {
found = methods[i];
} else {
// print warning
- this.logWarn( iLog, "Lifecycle method " + methods[i].getName()
- + " occurs several times with different matching signature." );
+ this.logWarn(ctx.getIssueLog(), "Lifecycle method " + methods[i].getName()
+ + " occurs several times with different matching signature.");
}
}
}
}
i++;
}
- if ( found != null ) {
+ if (found != null) {
method = found;
} else {
method = zeroArgMethod;
@@ -444,30 +469,31 @@
}
}
}
- // if no method is found, we check for any method with that name to print some warnings!
- if ( method == null ) {
- final JavaMethod[] methods = javaClass.getMethods();
- for(int i=0; i<methods.length; i++) {
- if ( methodName.equals(methods[i].getName()) ) {
- if ( methods[i].getParameters().length != 1 ) {
- this.logWarn( iLog, "Lifecycle method " + methods[i].getName()
- + " has wrong number of arguments" );
- } else {
- this.logWarn( iLog, "Lifecycle method " + methods[i].getName() + " has wrong argument "
- + methods[i].getParameters()[0].getType() );
- }
+ }
+ // if no method is found, we check for any method with that name to print some warnings!
+ if (method == null) {
+ final Method[] methods = ctx.getClassDescription().getDescribedClass().getDeclaredMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if (methodName.equals(methods[i].getName())) {
+ if (methods[i].getParameterTypes() == null || methods[i].getParameterTypes().length != 1) {
+ this.logWarn(ctx.getIssueLog(), "Lifecycle method " + methods[i].getName() + " has wrong number of arguments");
+ } else {
+ this.logWarn(ctx.getIssueLog(),
+ "Lifecycle method " + methods[i].getName() + " has wrong argument "
+ + methods[i].getParameterTypes()[0].getName());
}
}
}
}
+
// method must be protected for version 1.0
- if ( method != null && specVersion == Constants.VERSION_1_0) {
+ if (method != null && specVersion == SpecVersion.VERSION_1_0) {
// check protected
- if (method.isPublic()) {
- this.logWarn( iLog, "Lifecycle method " + method.getName() + " should be declared protected" );
- } else if (!method.isProtected()) {
- this.logWarn( iLog, "Lifecycle method " + method.getName()
- + " has wrong qualifier, public or protected required" );
+ if (Modifier.isPublic(method.getModifiers())) {
+ this.logWarn(ctx.getIssueLog(), "Lifecycle method " + method.getName() + " should be declared protected");
+ } else if (!Modifier.isProtected(method.getModifiers())) {
+ this.logWarn(ctx.getIssueLog(), "Lifecycle method " + method.getName() +
+ " has wrong qualifier, public or protected required");
}
}
}
@@ -475,34 +501,27 @@
/**
* Return the configuration policy.
*/
- public String getConfigurationPolicy() {
+ public ComponentConfigurationPolicy getConfigurationPolicy() {
return this.configurationPolicy;
}
/**
* Set the configuration policy.
*/
- public void setConfigurationPolicy(final String value) {
+ public void setConfigurationPolicy(final ComponentConfigurationPolicy value) {
this.configurationPolicy = value;
}
@Override
public String toString() {
- return "Component " + this.name + " (" +
- "enabled=" + (enabled==null?"<notset>":enabled) +
- ", immediate=" + (immediate == null?"<notset>":immediate) +
- ", abstract=" + isAbstract +
- ", isDS=" + isDs +
- (factory != null ? ", factory="+factory:"")+
- (configurationPolicy != null ? ", configurationPolicy=" + configurationPolicy : "") +
- (activate != null ? ", activate=" + activate : "") +
- (deactivate != null ? ", deactivate=" + deactivate : "") +
- (modified != null ? ", modified=" + modified : "") +
- ", specVersion=" + specVersion +
- ", implementation=" + implementation +
- ", service=" + service +
- ", properties=" + properties +
- ", references=" + references +
- ")";
+ return "Component " + this.name + " (" + "enabled=" + (enabled == null ? "<notset>" : enabled) + ", immediate="
+ + (immediate == null ? "<notset>" : immediate) + ", abstract=" + isAbstract + ", isDS=" + isDs
+ + (factory != null ? ", factory=" + factory : "")
+ + (configurationPolicy != null ? ", configurationPolicy=" + configurationPolicy : "")
+ + (activate != null ? ", activate=" + activate : "")
+ + (deactivate != null ? ", deactivate=" + deactivate : "")
+ + (modified != null ? ", modified=" + modified : "") + ", specVersion=" + specVersion
+ + ", implementation=" + implementation + ", service=" + service + ", properties=" + properties
+ + ", references=" + references + ")";
}
}
\ No newline at end of file
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Components.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Components.java
index 208bdc9..f50adee 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Components.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Components.java
@@ -21,6 +21,8 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.felix.scrplugin.description.SpecVersion;
+
/**
* <code>Components</code>...
*
@@ -29,10 +31,10 @@
public class Components {
/** The spec version. */
- private int specVersion;
+ private SpecVersion specVersion;
/** The list of {@link Component}s. */
- protected List<Component> components = new ArrayList<Component>();
+ private List<Component> components = new ArrayList<Component>();
/**
* Return the list of {@link Component}s.
@@ -58,14 +60,14 @@
/**
* Get the spec version.
*/
- public int getSpecVersion() {
+ public SpecVersion getSpecVersion() {
return this.specVersion;
}
/**
* Set the spec version.
*/
- public void setSpecVersion(int value) {
+ public void setSpecVersion(SpecVersion value) {
this.specVersion = value;
}
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Context.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Context.java
new file mode 100644
index 0000000..5654978
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Context.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.om;
+
+import org.apache.felix.scrplugin.Options;
+import org.apache.felix.scrplugin.Project;
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.description.SpecVersion;
+import org.apache.felix.scrplugin.helper.IssueLog;
+
+public class Context {
+
+ private Project project;
+
+ private IssueLog issueLog;
+
+ private SpecVersion specVersion;
+
+ private ClassDescription classDescription;
+
+ private Options options;
+
+ public Project getProject() {
+ return project;
+ }
+
+ public void setProject(Project project) {
+ this.project = project;
+ }
+
+ public IssueLog getIssueLog() {
+ return issueLog;
+ }
+
+ public void setIssueLog(IssueLog issueLog) {
+ this.issueLog = issueLog;
+ }
+
+ public SpecVersion getSpecVersion() {
+ return specVersion;
+ }
+
+ public void setSpecVersion(SpecVersion specVersion) {
+ this.specVersion = specVersion;
+ }
+
+ public ClassDescription getClassDescription() {
+ return classDescription;
+ }
+
+ public void setClassDescription(ClassDescription classDescription) {
+ this.classDescription = classDescription;
+ }
+
+ public Options getOptions() {
+ return options;
+ }
+
+ public void setOptions(Options options) {
+ this.options = options;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Implementation.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Implementation.java
index 37e78b8..bcbe387 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Implementation.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Implementation.java
@@ -19,30 +19,20 @@
package org.apache.felix.scrplugin.om;
/**
- * <code>Implementation</code>...
- *
+ * <code>Implementation</code>
+ *
* contains the class name implementing the component.
*/
public class Implementation {
/** The class name. */
- protected String classname;
+ private final String className;
- public Implementation() {
- // nothing to do
+ public Implementation(final String name) {
+ this.className = name;
}
- public Implementation(String name) {
- this.classname = name;
+ public String getClassName() {
+ return this.className;
}
-
- public String getClassame() {
- return this.classname;
- }
-
- public void setClassname(String name) {
- this.classname = name;
- }
-
-
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Interface.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Interface.java
index 9f55f6d..d53d80f 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Interface.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Interface.java
@@ -19,38 +19,38 @@
package org.apache.felix.scrplugin.om;
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.felix.scrplugin.scanner.ScannedAnnotation;
/**
- * <code>Interface.java</code>...
+ * <code>Interface</code>
*
+ * contains an interface name the component is implementing
+ * (the interface name can also be a class name)
*/
public class Interface extends AbstractObject {
- protected String interfacename;
-
- /**
- * Default constructor.
- */
- public Interface() {
- this(null);
- }
+ /** Name of the interface. */
+ private String interfaceName;
/**
* Constructor from java source.
*/
- public Interface(JavaTag t) {
- super(t);
+ public Interface(final ScannedAnnotation annotation, final String sourceLocation) {
+ super(annotation, sourceLocation);
}
- public String getInterfacename() {
- return this.interfacename;
+ /**
+ * Get the interface name.
+ */
+ public String getInterfaceName() {
+ return this.interfaceName;
}
- public void setInterfacename(String name) {
- this.interfacename = name;
+ /**
+ * Set the interface name.
+ */
+ public void setInterfaceName(final String name) {
+ this.interfaceName = name;
}
/**
@@ -58,16 +58,18 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(final int specVersion, final IssueLog iLog)
- throws SCRDescriptorException {
- final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
- if (javaClass == null) {
- this.logError( iLog, "Must be declared in a Java class" );
+ public void validate(final Context context) throws SCRDescriptorException {
+ if (context.getClassDescription().getDescribedClass().isInterface()) {
+ this.logError(context.getIssueLog(), "Must be declared in a Java class - not an interface");
} else {
-
- if ( !javaClass.isA(this.getInterfacename()) ) {
- // interface not implemented
- this.logError( iLog, "Class must implement provided interface " + this.getInterfacename() );
+ try {
+ final Class<?> interfaceClass = context.getProject().getClassLoader().loadClass(this.interfaceName);
+ if (!interfaceClass.isAssignableFrom(context.getClassDescription().getDescribedClass())) {
+ // interface not implemented
+ this.logError(context.getIssueLog(), "Class must implement provided interface " + this.interfaceName);
+ }
+ } catch (final ClassNotFoundException cnfe) {
+ throw new SCRDescriptorException("Unable to load interface class.", cnfe);
}
}
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Property.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Property.java
index 7ccd04d..a26c5a4 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Property.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Property.java
@@ -18,9 +18,9 @@
*/
package org.apache.felix.scrplugin.om;
-import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.helper.IssueLog;
-import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.description.PropertyType;
+import org.apache.felix.scrplugin.description.SpecVersion;
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
/**
* <code>Property.java</code>...
@@ -30,26 +30,14 @@
protected String name;
protected String value;
- protected String type;
+ protected PropertyType type;
protected String[] multiValue;
- protected boolean isPrivate;
- protected String label;
- protected String description;
- protected String cardinality;
-
- /**
- * Default constructor.
- */
- public Property() {
- this(null);
- }
-
/**
* Constructor from java source.
*/
- public Property(JavaTag t) {
- super(t);
+ public Property(final ScannedAnnotation annotation, final String sourceLocation) {
+ super(annotation, sourceLocation);
}
public String getName() {
@@ -69,11 +57,11 @@
this.multiValue = null;
}
- public String getType() {
+ public PropertyType getType() {
return this.type;
}
- public void setType(String type) {
+ public void setType(PropertyType type) {
this.type = type;
}
@@ -91,64 +79,20 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(final int specVersion, final IssueLog iLog) {
- if ( name == null || name.trim().length() == 0 ) {
- this.logError( iLog, "Property name can not be empty." );
+ public void validate(final Context context) {
+ if (name == null || name.trim().length() == 0) {
+ this.logError(context.getIssueLog(), "Property name can not be empty.");
}
- if ( type != null ) {
- if ( !type.equals(Constants.PROPERTY_TYPE_BOOLEAN)
- && !type.equals(Constants.PROPERTY_TYPE_BYTE )
- && !type.equals(Constants.PROPERTY_TYPE_CHAR )
- && !type.equals(Constants.PROPERTY_TYPE_CHAR_1_1 )
- && !type.equals(Constants.PROPERTY_TYPE_DOUBLE )
- && !type.equals(Constants.PROPERTY_TYPE_FLOAT )
- && !type.equals(Constants.PROPERTY_TYPE_INTEGER )
- && !type.equals(Constants.PROPERTY_TYPE_LONG )
- && !type.equals(Constants.PROPERTY_TYPE_STRING )
- && !type.equals(Constants.PROPERTY_TYPE_SHORT ) ) {
- this.logError( iLog, "Property " + name + " has unknown type: " + type );
- }
+ if (type != null) {
// now check for old and new char
- if ( specVersion == Constants.VERSION_1_0 && type.equals(Constants.PROPERTY_TYPE_CHAR_1_1) ) {
- type = Constants.PROPERTY_TYPE_CHAR;
+ if (context.getSpecVersion() == SpecVersion.VERSION_1_0 && type == PropertyType.Character) {
+ type = PropertyType.Char;
}
- if ( specVersion >= Constants.VERSION_1_1 && type.equals(Constants.PROPERTY_TYPE_CHAR) ) {
- type = Constants.PROPERTY_TYPE_CHAR_1_1;
+ if (context.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal()
+ && type == PropertyType.Char) {
+ type = PropertyType.Character;
}
}
// TODO might want to check value
}
-
- public boolean isPrivate() {
- return isPrivate;
- }
-
- public void setPrivate(boolean isPrivate) {
- this.isPrivate = isPrivate;
- }
-
- public String getLabel() {
- return label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getCardinality() {
- return cardinality;
- }
-
- public void setCardinality(String cardinality) {
- this.cardinality = cardinality;
- }
-
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Reference.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Reference.java
index 2186ece..4cff9a4 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Reference.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Reference.java
@@ -18,11 +18,18 @@
*/
package org.apache.felix.scrplugin.om;
-import org.apache.felix.scrplugin.Constants;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.description.ReferenceCardinality;
+import org.apache.felix.scrplugin.description.ReferencePolicy;
+import org.apache.felix.scrplugin.description.ReferenceStrategy;
+import org.apache.felix.scrplugin.description.SpecVersion;
import org.apache.felix.scrplugin.helper.StringUtils;
-import org.apache.felix.scrplugin.tags.*;
+import org.apache.felix.scrplugin.scanner.ScannedAnnotation;
/**
* <code>Reference.java</code>...
@@ -33,34 +40,22 @@
protected String name;
protected String interfacename;
protected String target;
- protected String cardinality;
- protected String policy;
+ protected ReferenceCardinality cardinality;
+ protected ReferencePolicy policy;
protected String bind;
protected String unbind;
protected String updated;
/** @since 1.0.9 */
- protected String strategy;
+ protected ReferenceStrategy strategy;
- /** Is this reference already checked? */
- protected boolean checked = false;
-
- /** The class description containing this reference. */
- protected final JavaClassDescription javaClassDescription;
-
- /**
- * Default constructor.
- */
- public Reference() {
- this(null, null);
- }
+ private Field field;
/**
* Constructor from java source.
*/
- public Reference(JavaTag t, JavaClassDescription desc) {
- super(t);
- this.javaClassDescription = desc;
+ public Reference(final ScannedAnnotation annotation, final String sourceLocation) {
+ super(annotation, sourceLocation);
}
public String getName() {
@@ -71,6 +66,14 @@
this.name = name;
}
+ public Field getField() {
+ return this.field;
+ }
+
+ public void setField(Field field) {
+ this.field = field;
+ }
+
public String getInterfacename() {
return this.interfacename;
}
@@ -87,19 +90,19 @@
this.target = target;
}
- public String getCardinality() {
+ public ReferenceCardinality getCardinality() {
return this.cardinality;
}
- public void setCardinality(String cardinality) {
+ public void setCardinality(ReferenceCardinality cardinality) {
this.cardinality = cardinality;
}
- public String getPolicy() {
+ public ReferencePolicy getPolicy() {
return this.policy;
}
- public void setPolicy(String policy) {
+ public void setPolicy(ReferencePolicy policy) {
this.policy = policy;
}
@@ -127,27 +130,19 @@
this.updated = updated;
}
- public boolean isChecked() {
- return checked;
- }
-
- public void setChecked(boolean checked) {
- this.checked = checked;
- }
-
/** @since 1.0.9 */
- public String getStrategy() {
+ public ReferenceStrategy getStrategy() {
return strategy;
}
/** @since 1.0.9 */
- public void setStrategy(String strategy) {
+ public void setStrategy(ReferenceStrategy strategy) {
this.strategy = strategy;
}
/** @since 1.0.9 */
public boolean isLookupStrategy() {
- return Constants.REFERENCE_STRATEGY_LOOKUP.equals(getStrategy());
+ return this.getStrategy() == ReferenceStrategy.LOOKUP;
}
/**
@@ -155,76 +150,71 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(final int specVersion,
- final boolean componentIsAbstract,
- final IssueLog iLog)
+ public void validate(final Context context, final boolean componentIsAbstract)
throws SCRDescriptorException {
- // if this reference is already checked, return immediately
- if ( this.checked ) {
- return;
- }
- final int currentIssueCount = iLog.getNumberOfErrors();
+ final int currentIssueCount = context.getIssueLog().getNumberOfErrors();
// validate name
if (StringUtils.isEmpty(this.name)) {
- if ( specVersion < Constants.VERSION_1_1 ) {
- this.logError( iLog, "Reference has no name" );
+ if (context.getSpecVersion().ordinal() < SpecVersion.VERSION_1_1.ordinal() ) {
+ this.logError(context.getIssueLog(), "Reference has no name");
}
}
// validate interface
if (StringUtils.isEmpty(this.interfacename)) {
- this.logError( iLog, "Missing interface name" );
+ this.logError(context.getIssueLog(), "Missing interface name");
+ }
+ try {
+ context.getProject().getClassLoader().loadClass(this.interfacename);
+ } catch (final ClassNotFoundException e) {
+ this.logError(context.getIssueLog(), "Interface class can't be loaded: " + this.interfacename);
}
// validate cardinality
if (this.cardinality == null) {
- this.cardinality = "1..1";
- } else if (!"0..1".equals(this.cardinality) && !"1..1".equals(this.cardinality)
- && !"0..n".equals(this.cardinality) && !"1..n".equals(this.cardinality)) {
- this.logError( iLog, "Invalid Cardinality specification " + this.cardinality );
+ this.cardinality = ReferenceCardinality.MANDATORY_UNARY;
}
// validate policy
if (this.policy == null) {
- this.policy = "static";
- } else if (!"static".equals(this.policy) && !"dynamic".equals(this.policy)) {
- this.logError( iLog, "Invalid Policy specification " + this.policy );
+ this.policy = ReferencePolicy.STATIC;
}
// validate strategy
if (this.strategy == null) {
- this.strategy = Constants.REFERENCE_STRATEGY_EVENT;
- } else if (!Constants.REFERENCE_STRATEGY_EVENT.equals(this.strategy)
- && !Constants.REFERENCE_STRATEGY_LOOKUP.equals(this.strategy)) {
- this.logError( iLog, "Invalid strategy type " + this.strategy );
+ this.strategy = ReferenceStrategy.EVENT;
}
// validate bind and unbind methods
if (!isLookupStrategy()) {
- // set default values
- if ( this.bind == null ) {
- this.setBind("bind");
+ String bindName = this.bind;
+ String unbindName = this.unbind;
+
+ final boolean canGenerate = context.getOptions().isGenerateAccessors() &&
+ !this.isLookupStrategy() && this.getField() != null
+ && (this.getCardinality() == ReferenceCardinality.OPTIONAL_UNARY || this.getCardinality() == ReferenceCardinality.MANDATORY_UNARY);
+ if (bindName == null && !canGenerate ) {
+ bindName = "bind";
}
- if ( this.unbind == null ) {
- this.setUnbind("unbind");
+ if (unbindName == null && !canGenerate ) {
+ unbindName = "unbind";
}
- final String oldBind = this.bind;
- final String oldUnbind = this.unbind;
- this.bind = this.validateMethod(specVersion, this.bind, componentIsAbstract, iLog);
- this.unbind = this.validateMethod(specVersion, this.unbind, componentIsAbstract, iLog);
- if ( iLog.getNumberOfErrors() == currentIssueCount ) {
- if ( this.bind != null && this.unbind != null ) {
- // no errors, so we're checked
- this.checked = true;
- } else {
- if ( this.bind == null ) {
- this.bind = oldBind;
- }
- if ( this.unbind == null ) {
- this.unbind = oldUnbind;
- }
- }
+
+ if ( bindName != null ) {
+ bindName = this.validateMethod(context, bindName, componentIsAbstract);
+ } else {
+ bindName = "bind" + Character.toUpperCase(this.name.charAt(0)) + this.name.substring(1);
+ }
+ if ( unbindName != null ) {
+ unbindName = this.validateMethod(context, unbindName, componentIsAbstract);
+ } else {
+ unbindName = "unbind" + Character.toUpperCase(this.name.charAt(0)) + this.name.substring(1);
+ }
+
+ if (context.getIssueLog().getNumberOfErrors() == currentIssueCount) {
+ this.bind = bindName;
+ this.unbind = unbindName;
}
} else {
this.bind = null;
@@ -232,33 +222,33 @@
}
// validate updated method
- if ( this.updated != null ) {
- if ( specVersion < Constants.VERSION_1_1_FELIX ) {
- this.logError( iLog, "Updated method declaration requires namespace "
- + Constants.COMPONENT_DS_SPEC_VERSION_11_FELIX + " or newer" );
+ if (this.updated != null) {
+ if (context.getSpecVersion().ordinal() < SpecVersion.VERSION_1_1_FELIX.ordinal()) {
+ this.logError(context.getIssueLog(), "Updated method declaration requires version "
+ + SpecVersion.VERSION_1_1_FELIX.getName() + " or newer");
}
}
+
}
- protected String validateMethod(final int specVersion,
- final String methodName,
- final boolean componentIsAbstract,
- final IssueLog iLog)
+ private String validateMethod(final Context ctx, final String methodName, final boolean componentIsAbstract)
throws SCRDescriptorException {
- final JavaMethod method = this.findMethod(specVersion, methodName);
+ final Method method = this.findMethod(ctx, methodName);
if (method == null) {
- if ( !componentIsAbstract ) {
- this.logError( iLog, "Missing method " + methodName + " for reference " + (this.getName() == null ? "" : this.getName()));
+ if (!componentIsAbstract) {
+ this.logError(ctx.getIssueLog(),
+ "Missing method " + methodName + " for reference "
+ + (this.getName() == null ? "" : this.getName()));
}
return null;
}
// method needs to be protected for 1.0
- if ( specVersion == Constants.VERSION_1_0 ) {
- if (method.isPublic()) {
- this.logWarn( iLog, "Method " + method.getName() + " should be declared protected" );
- } else if (!method.isProtected()) {
- this.logError( iLog, "Method " + method.getName() + " has wrong qualifier, public or protected required" );
+ if (ctx.getSpecVersion() == SpecVersion.VERSION_1_0) {
+ if (Modifier.isPublic(method.getModifiers())) {
+ this.logWarn(ctx.getIssueLog(), "Method " + method.getName() + " should be declared protected");
+ } else if (!Modifier.isProtected(method.getModifiers())) {
+ this.logError(ctx.getIssueLog(), "Method " + method.getName() + " has wrong qualifier, public or protected required");
return null;
}
}
@@ -266,61 +256,73 @@
}
private static final String TYPE_SERVICE_REFERENCE = "org.osgi.framework.ServiceReference";
- private static final String TYPE_MAP = "java.util.Map";
- public JavaMethod findMethod(final int specVersion,
- final String methodName)
+ private Method getMethod(final Context ctx, final String name, final Class<?>[] sig) {
+ try {
+ return ctx.getClassDescription().getDescribedClass().getDeclaredMethod(name, sig);
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final NoSuchMethodException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ public Method findMethod(final Context ctx, final String methodName)
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};
+ try {
+ final Class<?>[] sig = new Class<?>[] { ctx.getProject().getClassLoader().loadClass(TYPE_SERVICE_REFERENCE) };
+ final Class<?>[] sig2 = new Class<?>[] {ctx.getProject().getClassLoader().loadClass(this.interfacename) };
+ final Class<?>[] sig3 = new Class<?>[] { ctx.getProject().getClassLoader().loadClass(this.interfacename), Map.class };
- // service interface or ServiceReference first
- String realMethodName = methodName;
- JavaMethod method = this.javaClassDescription.getMethodBySignature(realMethodName, sig);
- if (method == null) {
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig2);
- if ( specVersion >= Constants.VERSION_1_1 && method == null ) {
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig3);
+ // service interface or ServiceReference first
+ String realMethodName = methodName;
+ Method method = getMethod(ctx, realMethodName, sig);
+ if (method == null) {
+ method = getMethod(ctx, realMethodName, sig2);
+ if (method == null && ctx.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
+ method = getMethod(ctx, realMethodName, sig3);
+ }
}
- }
- // append reference name with service interface and ServiceReference
- if (method == null) {
- final String info;
- if (StringUtils.isEmpty(this.name)) {
- final String interfaceName = this.getInterfacename();
- final int pos = interfaceName.lastIndexOf('.');
- info = interfaceName.substring(pos + 1);
- } else {
- info = this.name;
+ // append reference name with service interface and ServiceReference
+ if (method == null) {
+ final String info;
+ if (StringUtils.isEmpty(this.name)) {
+ final String interfaceName = this.getInterfacename();
+ final int pos = interfaceName.lastIndexOf('.');
+ info = interfaceName.substring(pos + 1);
+ } else {
+ info = this.name;
+ }
+ realMethodName = methodName + Character.toUpperCase(info.charAt(0)) + info.substring(1);
+
+ method = getMethod(ctx, realMethodName, sig);
}
- realMethodName = methodName + Character.toUpperCase(info.charAt(0)) + info.substring(1);
-
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig);
- }
- if (method == null) {
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig2);
- if ( specVersion >= Constants.VERSION_1_1 && method == null ) {
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig3);
+ if (method == null) {
+ method = getMethod(ctx, realMethodName, sig2);
+ if (method == null && ctx.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
+ method = getMethod(ctx, realMethodName, sig3);
+ }
}
- }
- // append type name with service interface and ServiceReference
- if (method == null) {
- int lastDot = this.getInterfacename().lastIndexOf('.');
- realMethodName = methodName
- + this.getInterfacename().substring(lastDot + 1);
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig);
- }
- if (method == null) {
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig2);
- if ( specVersion >= Constants.VERSION_1_1 && method == null ) {
- method = this.javaClassDescription.getMethodBySignature(realMethodName, sig3);
+ // append type name with service interface and ServiceReference
+ if (method == null) {
+ int lastDot = this.getInterfacename().lastIndexOf('.');
+ realMethodName = methodName + this.getInterfacename().substring(lastDot + 1);
+ method = getMethod(ctx, realMethodName, sig);
}
- }
+ if (method == null) {
+ method = getMethod(ctx, realMethodName, sig2);
+ if (method == null && ctx.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
+ method = getMethod(ctx, realMethodName, sig3);
+ }
+ }
- return method;
+ return method;
+ } catch (final ClassNotFoundException cnfe) {
+ throw new SCRDescriptorException("Unable to load class!", cnfe);
+ }
}
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Service.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Service.java
index 49354ac..216d445 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Service.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/om/Service.java
@@ -23,54 +23,53 @@
import java.util.List;
import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.helper.IssueLog;
/**
- * <code>Service</code>...
- *
+ * <code>Service</code>
+ *
+ * contains all service information of a component.
*/
public class Service {
- protected boolean isServicefactory;
+ /** Flag for the service factory. */
+ private boolean isServiceFactory;
/** The list of implemented interfaces. */
- protected final List<Interface> interfaces = new ArrayList<Interface>();
+ private final List<Interface> interfaces = new ArrayList<Interface>();
/**
- * Default constructor.
+ * Is this a service factory?
*/
- public Service() {
- // nothing to do
+ public boolean isServiceFactory() {
+ return this.isServiceFactory;
}
- public boolean isServicefactory() {
- return this.isServicefactory;
+ /**
+ * Set the service factory flag.
+ */
+ public void setServiceFactory(final boolean flag) {
+ this.isServiceFactory = flag;
}
- public void setServicefactory(String servicefactory) {
- if ( servicefactory != null ) {
- this.isServicefactory = Boolean.valueOf(servicefactory).booleanValue();
- }
- }
-
- public void setServicefactory(boolean flag) {
- this.isServicefactory = flag;
- }
-
+ /**
+ * Return the list of interfaces.
+ */
public List<Interface> getInterfaces() {
return this.interfaces;
}
/**
* Search for an implemented interface.
- * @param name The name of the interface.
+ *
+ * @param name
+ * The name of the interface.
* @return The interface if it is implemented by this service or null.
*/
- public Interface findInterface(String name) {
+ public Interface findInterface(final String name) {
final Iterator<Interface> i = this.getInterfaces().iterator();
- while ( i.hasNext() ) {
+ while (i.hasNext()) {
final Interface current = i.next();
- if ( current.getInterfacename().equals(name) ) {
+ if (current.getInterfaceName().equals(name)) {
return current;
}
}
@@ -79,11 +78,13 @@
/**
* Add an interface to the list of interfaces.
- * @param interf The interface.
+ *
+ * @param interf
+ * The interface.
*/
- public void addInterface(Interface interf) {
+ public void addInterface(final Interface interf) {
// add interface only once
- if ( this.findInterface(interf.getInterfacename()) == null ) {
+ if (this.findInterface(interf.getInterfaceName()) == null) {
this.interfaces.add(interf);
}
}
@@ -93,11 +94,9 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(final int specVersion, final IssueLog iLog)
- throws SCRDescriptorException {
- for(final Interface interf : this.getInterfaces()) {
- interf.validate(specVersion, iLog);
+ public void validate(final Context context) throws SCRDescriptorException {
+ for (final Interface interf : this.getInterfaces()) {
+ interf.validate(context);
}
}
-
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ClassAnnotation.java
similarity index 66%
copy from scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java
copy to scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ClassAnnotation.java
index a00ab18..176db6a 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/package-info.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ClassAnnotation.java
@@ -16,8 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * Extracting SCR tags from source file declared as Java 1.5 annotations.
- */
-package org.apache.felix.scrplugin.tags.annotation;
+package org.apache.felix.scrplugin.scanner;
+import java.util.Map;
+
+public class ClassAnnotation extends ScannedAnnotation {
+
+ public ClassAnnotation(final String name, final Map<String, Object> values) {
+ super(name, values);
+ }
+
+ @Override
+ public String toString() {
+ return "ClassAnnotationDescription [name=" + name + ", values="
+ + values + "]";
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/FieldAnnotation.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/FieldAnnotation.java
new file mode 100644
index 0000000..79c7b87
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/FieldAnnotation.java
@@ -0,0 +1,61 @@
+/*
+ * 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.scanner;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
+
+public class FieldAnnotation extends ScannedAnnotation {
+
+ private final Field annotatedField;
+
+ public FieldAnnotation(final String name, final Map<String, Object> values, final Field f) {
+ super(name, values);
+ this.annotatedField = f;
+ }
+
+ public Field getAnnotatedField() {
+ return this.annotatedField;
+ }
+
+ public Object getAnnotatedFieldValue()
+ throws SCRDescriptorFailureException, SCRDescriptorException {
+ if ( Modifier.isStatic(annotatedField.getModifiers()) ) {
+ try {
+ final Object value = annotatedField.get(null);
+ return value;
+ } catch (final IllegalArgumentException e) {
+ throw new SCRDescriptorFailureException("Unable to get initial field value from: " + annotatedField, e);
+ } catch (final IllegalAccessException e) {
+ throw new SCRDescriptorFailureException("Unable to get initial field value from: " + annotatedField, e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "FieldAnnotationDescription [name=" + name + ", values="
+ + values + ", annotatedField=" + annotatedField + "]";
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/MethodAnnotation.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/MethodAnnotation.java
new file mode 100644
index 0000000..5f25a13
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/MethodAnnotation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.scanner;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class MethodAnnotation extends ScannedAnnotation {
+
+ private final Method method;
+
+ public MethodAnnotation(final String name, final Map<String, Object> values, final Method m) {
+ super(name, values);
+ this.method = m;
+ }
+
+ public Method getAnnotatedMethod() {
+ return this.method;
+ }
+
+ @Override
+ public String toString() {
+ return "MethodAnnotationDescription [name=" + name + ", values="
+ + values + ", method=" + method + "]";
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ScannedAnnotation.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ScannedAnnotation.java
new file mode 100644
index 0000000..72ac56e
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ScannedAnnotation.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.scanner;
+
+import java.util.Map;
+
+/**
+ * Base class for all annotation.
+ */
+public abstract class ScannedAnnotation {
+
+ /** The fully qualified class name */
+ protected final String name;
+
+ /** The annotation values. */
+ protected final Map<String, Object> values;
+
+ /**
+ * Create a new description
+ * @param name The fully qualified class name of the annotation
+ * @param values The properties of the annotation (optional)
+ */
+ public ScannedAnnotation(final String name, final Map<String, Object> values) {
+ this.name = name;
+ this.values = values;
+ }
+
+ /**
+ * Get the fully qualified class name of the annotation.
+ * @return The fully qualified class name of the annotation.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get a property value of the annotation.
+ * @param paramName The property name.
+ * @return The value of the property or <code>null</code>
+ */
+ public Object getValue(final String paramName) {
+ if ( values != null ) {
+ return values.get(paramName);
+ }
+ return null;
+ }
+
+ public boolean getBooleanValue(final String name, final boolean defaultValue) {
+ final Object val = this.getValue(name);
+ if ( val != null ) {
+ return ((Boolean) val).booleanValue();
+ }
+ return defaultValue;
+ }
+
+ public int getIntegerValue(final String name, final int defaultValue) {
+ final Object val = this.getValue(name);
+ if ( val != null ) {
+ return ((Integer) val).intValue();
+ }
+ return defaultValue;
+ }
+
+ public long getLongValue(final String name, final long defaultValue) {
+ final Object val = this.getValue(name);
+ if ( val != null ) {
+ return ((Long) val).intValue();
+ }
+ return defaultValue;
+ }
+
+ public String getStringValue(final String name, final String defaultValue) {
+ final Object val = this.getValue(name);
+ if ( val != null && val.toString().trim().length() > 0 ) {
+ return val.toString().trim();
+ }
+ return defaultValue;
+ }
+
+ public String getEnumValue(final String name, final String defaultValue) {
+ final Object val = this.getValue(name);
+ if ( val != null ) {
+ return ((String[])val)[1];
+ }
+ return defaultValue;
+ }
+
+ @Override
+ public String toString() {
+ return "AnnotationDescription [name=" + name + ", values=" + values
+ + "]";
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ScannedClass.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ScannedClass.java
new file mode 100644
index 0000000..93f1b1b
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/ScannedClass.java
@@ -0,0 +1,93 @@
+/*
+ * 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.scanner;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A scanned class contains all scanned information
+ * like the found annotations.
+ */
+public class ScannedClass {
+
+ /** All found annotations .*/
+ private final List<ScannedAnnotation> descriptions = new ArrayList<ScannedAnnotation>();
+
+ /** The scanned class. */
+ private final Class<?> scannedClass;
+
+ public ScannedClass(final List<ScannedAnnotation> desc, final Class<?> scannedClass) {
+ this.descriptions.addAll(desc);
+ this.scannedClass = scannedClass;
+ }
+
+ /**
+ * Get the scanned class.
+ * @return The scanned class.
+ */
+ public Class<?> getScannedClass() {
+ return this.scannedClass;
+ }
+
+ public void processed(final ScannedAnnotation desc) {
+ this.descriptions.remove(desc);
+ }
+
+ public void processed(final Collection<? extends ScannedAnnotation> desc) {
+ this.descriptions.removeAll(desc);
+ }
+
+ public List<ClassAnnotation> getClassAnnotations(final String name) {
+ final List<ClassAnnotation> list = new ArrayList<ClassAnnotation>();
+ for(final ScannedAnnotation desc : descriptions ) {
+ if ( desc instanceof ClassAnnotation ) {
+ if ( name == null || desc.getName().equals(name) ) {
+ list.add( (ClassAnnotation)desc);
+ }
+ }
+ }
+ return list;
+ }
+
+ public List<FieldAnnotation> getFieldAnnotations(final String name) {
+ final List<FieldAnnotation> list = new ArrayList<FieldAnnotation>();
+ for(final ScannedAnnotation desc : descriptions ) {
+ if ( desc instanceof FieldAnnotation ) {
+ if ( name == null || desc.getName().equals(name) ) {
+ list.add( (FieldAnnotation)desc);
+ }
+ }
+ }
+ return list;
+ }
+
+ public List<MethodAnnotation> getMethodAnnotations(final String name) {
+ final List<MethodAnnotation> list = new ArrayList<MethodAnnotation>();
+ for(final ScannedAnnotation desc : descriptions ) {
+ if ( desc instanceof MethodAnnotation ) {
+ if ( name == null || desc.getName().equals(name) ) {
+ list.add( (MethodAnnotation)desc);
+ }
+ }
+ }
+ return list;
+ }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaMethod.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/Source.java
similarity index 69%
rename from scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaMethod.java
rename to scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/Source.java
index cf36076..166b55c 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaMethod.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/scanner/Source.java
@@ -16,23 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scrplugin.tags;
+package org.apache.felix.scrplugin.scanner;
+
+import java.io.File;
/**
- * <code>JavaMethod.java</code>...
- *
+ * Description of a source to be parsed.
*/
-public interface JavaMethod {
+public interface Source {
- JavaMethod[] EMPTY_RESULT = new JavaMethod[0];
+ /**
+ * The main class name.
+ * @return The main class name.
+ */
+ String getClassName();
- boolean isPublic();
-
- boolean isProtected();
-
- String getName();
-
- JavaParameter[] getParameters();
-
- boolean isConstructor();
+ /**
+ * The file containing the class.
+ * @return The file containing the class.
+ */
+ File getFile();
}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/ClassUtil.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/ClassUtil.java
deleted file mode 100644
index 3860364..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/ClassUtil.java
+++ /dev/null
@@ -1,85 +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.lang.reflect.Array;
-import java.lang.reflect.Field;
-
-/**
- * Utility class.
- */
-public class ClassUtil {
-
- /**
- * Try to get the initial value of a static field
- * @param clazz The class.
- * @param fieldName The name of the field.
- * @return The initial value or null.
- */
- public static String[] getInitializationExpression(final Class<?> clazz, final String fieldName)
- {
- try
- {
- final Field field = clazz.getDeclaredField(fieldName);
- field.setAccessible(true);
- final Object value = field.get(null);
- if ( value != null )
- {
- if ( value.getClass().isArray() )
- {
- final String[] values = new String[Array.getLength(value)];
- for(int i=0; i<values.length; i++)
- {
- values[i] = Array.get(value, i).toString();
- }
- return values;
- }
- return new String[] {value.toString()};
- }
- return null;
- }
- catch (final NoClassDefFoundError ncdfe)
- {
- throw new IllegalArgumentException("A class could not be found while parsing class " + clazz.getName() +
- ". Please check this stracktrace and add a dependency with the missing class to your project.", ncdfe);
- }
- catch (final Exception e)
- {
- // ignore and just return null
- }
- return null;
- }
-
- /**
- * Get the compiled class.
- */
- public static Class<?> getClass(final ClassLoader classLoader, String name) {
- if ( classLoader == null ) {
- return null;
- }
- try {
- if ( name.endsWith(".class") ) {
- name = name.substring(0, name.length() - 6);
- }
- return classLoader.loadClass(name);
- } catch (ClassNotFoundException e) {
- return null;
- }
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
deleted file mode 100644
index db299d1..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
+++ /dev/null
@@ -1,139 +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 org.apache.felix.scrplugin.SCRDescriptorException;
-
-/**
- * <code>JavaClassDescription.java</code>...
- * Description of a java class
- *
- */
-public interface JavaClassDescription {
-
- JavaClassDescription[] EMPTY_RESULT = new JavaClassDescription[0];
-
- /**
- * Get the java class tag with the name.
- * @param name
- * @return the tag or null.
- */
- JavaTag getTagByName(String name);
-
- /**
- * Get all class tags with this name.
- * @param name
- * @param inherited If true, parent classes are searched as well.
- * @return An array of tags or the empty array.
- * @throws SCRDescriptorException
- */
- JavaTag[] getTagsByName(String name, boolean inherited)
- throws SCRDescriptorException;
-
- /**
- * Get the description for the parent class.
- * @return The description or <code>null</code> if this class is the
- * Object class.
- * @throws SCRDescriptorException
- */
- JavaClassDescription getSuperClass() throws SCRDescriptorException;
-
- /**
- * Get the name of the described class.
- * @return The name of the described class.
- */
- String getName();
-
- /**
- * Get the fields of this class
- * @return All fields or an empty array
- */
- JavaField[] getFields();
-
- /**
- * Get the field with the name.
- * @param name The name of the field
- * @return The field with the name or null.
- * @throws SCRDescriptorException
- */
- JavaField getFieldByName(String name) throws SCRDescriptorException;
-
- 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 SCRDescriptorException
- */
- 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 SCRDescriptorException
- */
- JavaMethod getMethodBySignature(String name, String[] parameters)
- throws SCRDescriptorException;
-
- /**
- * Is this class public?
- * @return True if this class is public.
- */
- boolean isPublic();
-
- /**
- * Is this class abstract?
- * @return True if this class is abstract.
- */
- boolean isAbstract();
-
- /**
- * Is this class an interface?
- * @return True if this is an interface.
- */
- boolean isInterface();
-
- /**
- * Return all methods of this class
- * @return An array of methods or an empty array.
- */
- JavaMethod[] getMethods();
-
- /**
- * Is this class of the type?
- * @param type
- * @return True if this class is of the type.
- * @throws SCRDescriptorException
- */
- boolean isA(String type) throws SCRDescriptorException;
-
- /**
- * Search for the class.
- * If the referenced name is not fully qualified, the imports
- * of the class are searched.
- * @param referencedName
- * @return The java class description or null
- * @throws SCRDescriptorException
- */
- JavaClassDescription getReferencedClass(String referencedName)
- throws SCRDescriptorException;
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java
deleted file mode 100644
index e48cacd..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescriptionInheritanceComparator.java
+++ /dev/null
@@ -1,106 +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.util.Comparator;
-
-import org.apache.felix.scrplugin.SCRDescriptorException;
-
-
-/**
- * The <code>JavaClassDescriptionInheritanceComparator</code> orders
- * {@link JavaClassDescription} objects by their inheritance:
- * <ol>
- * <li>If the descriptors are the same, zero is returned
- * <li>If the first descriptor is an extension of the second, 1 is returned
- * <li>If the second descriptor is an extension of the first, -1 is returned
- * <li>Otherwise if the first descriptor is nested deeper in the hierarchy 1 is
- * returned, else if the second descriptor is nested deeper in the hierarchy -1
- * is returned.
- * <li>Finally, the natural order of the class names is returned
- * </ol>
- */
-public class JavaClassDescriptionInheritanceComparator implements Comparator<JavaClassDescription>
-{
-
- public int compare( JavaClassDescription cd1, JavaClassDescription cd2 )
- {
- // the descriptors are the same
- if ( equals( cd1, cd2 ) )
- {
- return 0;
- }
-
- try
- {
-
- int level1 = 0;
- int level2 = 0;
-
- // if cd1 is an extension of cd2
- JavaClassDescription super1 = cd1.getSuperClass();
- while ( super1 != null )
- {
- if ( equals( super1, cd2 ) )
- {
- return 1;
- }
- super1 = super1.getSuperClass();
- level1++;
- }
-
- // if cd2 is an extension of cd1
- JavaClassDescription super2 = cd2.getSuperClass();
- while ( super2 != null )
- {
- if ( equals( super2, cd1 ) )
- {
- return -1;
- }
- super2 = super2.getSuperClass();
- level2++;
- }
-
- // class do not share the hierarchy, order by hierarchy level
- if ( level1 < level2 )
- {
- return -1;
- }
- else if ( level1 > level2 )
- {
- return 1;
- }
- }
- catch ( SCRDescriptorException mee )
- {
- // what shall we do ??
- }
-
- // last ressort: order by class name
- return cd1.getName().compareTo( cd2.getName() );
- }
-
-
- // compare for equality: returns true if both descriptors have the same name
- private boolean equals( JavaClassDescription cd1, JavaClassDescription cd2 )
- {
- return cd1.getName().equals( cd2.getName() );
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java
deleted file mode 100644
index cbadb04..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaField.java
+++ /dev/null
@@ -1,48 +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;
-
-/**
- * <code>JavaField.java</code>...
- *
- */
-public interface JavaField {
-
- /** The name of the field. */
- String getName();
-
- /** The type of the field. */
- String getType();
-
- /**
- * Return the given tag.
- * @param name The tag name.
- * @return The tag or null.
- */
- JavaTag getTagByName(String name);
-
- /**
- * Return the initial value if this is a static constant.
- * If this field is not an array, an array of length 1 is
- * returned with the value. If this field is an array,
- * the array of values is returned.
- * @return The initial value of the field.
- */
- String[] getInitializationExpression();
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaParameter.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaParameter.java
deleted file mode 100644
index 02cf536..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaParameter.java
+++ /dev/null
@@ -1,28 +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;
-
-/**
- * <code>JavaParameter.java</code>...
- *
- */
-public interface JavaParameter {
-
- String getType();
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java
deleted file mode 100644
index e4fc755..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java
+++ /dev/null
@@ -1,53 +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.util.Map;
-
-/**
- * <code>JavaTag.java</code>...
- *
- */
-public interface JavaTag {
-
- /**
- * The name of the tag, e.g. scr.component etc.
- */
- String getName();
-
- /**
- * The name of the tag as used in the source code.
- * For javadoc tags this is like {@link #getName()}, for annoations this is different.
- */
- String getSourceName();
-
- String[] getParameters();
-
- String getNamedParameter(String arg0);
-
- String getSourceLocation();
-
- int getLineNumber();
-
- JavaClassDescription getJavaClassDescription();
-
- JavaField getField();
-
- Map<String, String> getNamedParameterMap();
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java
deleted file mode 100644
index a3f5a79..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/ModifiableJavaClassDescription.java
+++ /dev/null
@@ -1,28 +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 org.apache.felix.scrplugin.SCRDescriptorException;
-
-
-public interface ModifiableJavaClassDescription {
-
- void addMethods(String propertyName, String className, boolean createBind, boolean createUnbind)
- throws SCRDescriptorException;
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AbstractTag.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AbstractTag.java
deleted file mode 100644
index e54d445..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AbstractTag.java
+++ /dev/null
@@ -1,138 +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.annotation;
-
-import java.util.Map;
-
-import org.apache.felix.scrplugin.tags.*;
-
-import com.thoughtworks.qdox.model.Annotation;
-
-/**
- * Description of a java tag for components.
- */
-public abstract class AbstractTag implements JavaTag {
-
- protected final JavaClassDescription description;
-
- protected final JavaField field;
-
- protected final Annotation sourceAnnotation;
-
- protected Map<String, String> parameters;
-
- /**
- * @param desc Description
- * @param field Field
- */
- public AbstractTag(Annotation sourceAnnotation, JavaClassDescription desc, JavaField field) {
- this.sourceAnnotation = sourceAnnotation;
- this.description = desc;
- this.field = field;
- }
-
- /**
- * @see JavaTag#getNamedParameter(String)
- */
- public String getNamedParameter(String name) {
- final Map<String, String> map = this.getNamedParameterMap();
- if (map != null) {
- return map.get(name);
- }
- return null;
- }
-
- /**
- * @see JavaTag#getParameters()
- */
- public String[] getParameters() {
- final Map<?, ?> map = this.getNamedParameterMap();
- if (map != null) {
- return map.keySet().toArray(new String[5]);
- }
- return new String[0];
- }
-
- /**
- * @see JavaTag#getSourceLocation()
- */
- public String getSourceLocation() {
- return "Java annotations in " + this.description.getName();
- }
-
- /**
- * @see JavaTag#getLineNumber()
- */
- public int getLineNumber() {
- return sourceAnnotation.getLineNumber();
- }
-
- /**
- * @see JavaTag#getJavaClassDescription()
- */
- public JavaClassDescription getJavaClassDescription() {
- return this.description;
- }
-
- /**
- * @see JavaTag#getField()
- */
- public JavaField getField() {
- return this.field;
- }
-
- /**
- * Maps an empty or null string value to null
- * @param value String value
- * @return Non-empty string value or null
- */
- protected String emptyToNull(String value) {
- if (value == null || value.length() == 0) {
- return null;
- }
- return value;
- }
-
- /**
- * @see JavaTag#getName()
- */
- public abstract String getName();
-
- /**
- * @see JavaTag#getSourceName()
- */
- public abstract String getSourceName();
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getNamedParameterMap()
- */
- public Map<String, String> getNamedParameterMap() {
- if ( this.parameters == null ) {
- this.parameters = this.createNamedParameterMap();
- }
- return this.parameters;
- }
-
- /**
- * Create the parameter map.
- * @see JavaTag#getNamedParameterMap()
- */
- protected abstract Map<String, String> createNamedParameterMap();
-
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java
deleted file mode 100644
index 85563e9..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaClassDescription.java
+++ /dev/null
@@ -1,127 +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.annotation;
-
-import java.util.*;
-
-import org.apache.felix.scrplugin.JavaClassDescriptorManager;
-import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
-
-import com.thoughtworks.qdox.model.JavaClass;
-
-/**
- * Reading class description based on java annotations. This extends
- * {@link QDoxJavaClassDescription} to re-use annotation-independent logic and
- * automatic generation of bind/unbind methods.
- */
-public class AnnotationJavaClassDescription extends QDoxJavaClassDescription {
-
- /**
- * @param clazz Java class
- * @param javaClass QDox source
- * @param manager description manager
- */
- public AnnotationJavaClassDescription(Class<?> clazz, JavaClass javaClass, JavaClassDescriptorManager manager) {
- super(clazz, javaClass, manager);
- }
-
- public ClassLoader getClassLoader() {
- return this.manager.getClassLoader();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagByName(String)
- */
- @Override
- public JavaTag getTagByName(String name) {
- for(com.thoughtworks.qdox.model.Annotation annotation : this.javaClass.getAnnotations()) {
- List<JavaTag> tags = manager.getAnnotationTagProviderManager().getTags(annotation, this);
- for (JavaTag tag : tags) {
- if (tag.getName().equals(name)) {
- return tag;
- }
- }
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagsByName(String, boolean)
- */
- @Override
- 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()) {
- List<JavaTag> annotationTags = manager.getAnnotationTagProviderManager().getTags(annotation, this);
- for (JavaTag tag : annotationTags) {
- if (tag.getName().equals(name)) {
- tags.add(tag);
- }
- }
- }
-
- if (inherited && this.getSuperClass() != null) {
- final JavaTag[] superTags = this.getSuperClass().getTagsByName(name, inherited);
- if (superTags.length > 0) {
- tags.addAll(Arrays.asList(superTags));
- }
- }
-
- return tags.toArray(new JavaTag[tags.size()]);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFields()
- */
- @Override
- public JavaField[] getFields() {
- final com.thoughtworks.qdox.model.JavaField fields[] = this.javaClass.getFields();
- if ( fields == null || fields.length == 0 ) {
- return new JavaField[0];
- }
- final JavaField[] javaFields = new JavaField[fields.length];
- for (int i = 0; i < fields.length; i++) {
- javaFields[i] = new AnnotationJavaField(fields[i], this);
- }
- return javaFields;
- }
-
- /**
- * @see JavaClassDescription#getFieldByName(String)
- */
- @Override
- 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);
- }
- if (this.getSuperClass() != null) {
- this.getSuperClass().getFieldByName(name);
- }
- return null;
- }
-
- protected JavaClassDescriptorManager getManager() {
- return this.manager;
- }
-
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaField.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaField.java
deleted file mode 100644
index d4d40ea..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationJavaField.java
+++ /dev/null
@@ -1,80 +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.annotation;
-
-import java.util.List;
-
-import org.apache.felix.scrplugin.tags.*;
-
-/**
- * Description of a java field
- */
-public class AnnotationJavaField implements JavaField {
-
- protected final com.thoughtworks.qdox.model.JavaField field;
-
- protected final AnnotationJavaClassDescription description;
-
- /**
- * @param field Field
- * @param description description
- */
- public AnnotationJavaField(com.thoughtworks.qdox.model.JavaField field, AnnotationJavaClassDescription description) {
- this.field = field;
- this.description = description;
- }
-
- /**
- * @see JavaField#getInitializationExpression()
- */
- public String[] getInitializationExpression() {
- return ClassUtil.getInitializationExpression(this.description.getCompiledClass(), this.getName());
- }
-
- /**
- * @see JavaField#getName()
- */
- public String getName() {
- return this.field.getName();
- }
-
- /**
- * @see JavaField#getTagByName(String)
- */
- public JavaTag getTagByName(String name) {
- for(com.thoughtworks.qdox.model.Annotation annotation : this.field.getAnnotations()) {
- List<JavaTag> tags = description.getManager().getAnnotationTagProviderManager().getTags(annotation, this.description, this);
- for (JavaTag tag : tags) {
- if (tag.getName().equals(name)) {
- return tag;
- }
- }
- }
-
- return null;
- }
-
- /**
- * @see JavaField#getType()
- */
- public String getType() {
- return this.field.getType().getValue();
- }
-
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProvider.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProvider.java
deleted file mode 100644
index 078019a..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProvider.java
+++ /dev/null
@@ -1,44 +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.annotation;
-
-import java.util.List;
-
-import org.apache.felix.scrplugin.tags.JavaField;
-import org.apache.felix.scrplugin.tags.JavaTag;
-
-import com.thoughtworks.qdox.model.Annotation;
-
-/**
- * Interface for provider classes, that map java annotations to {@link JavaTag}
- * implementations.
- */
-public interface AnnotationTagProvider {
-
- /**
- * Maps a annotation to one or many {@link JavaTag} implementations.
- * @param pAnnotation Java annotation
- * @param description Annotations-based java class description
- * @param field Reference to field (set on field-level annotations, null on
- * other annotations)
- * @return List of tag implementations. Return empty list if this provider
- * cannot map the annotation to any tag instance.
- */
- List<JavaTag> getTags(Annotation pAnnotation, AnnotationJavaClassDescription description, JavaField field);
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
deleted file mode 100644
index 3ca4818..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
+++ /dev/null
@@ -1,183 +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.annotation;
-
-
-import java.util.*;
-
-import javax.imageio.spi.ServiceRegistry;
-
-import org.apache.felix.scrplugin.SCRDescriptorFailureException;
-import org.apache.felix.scrplugin.tags.JavaField;
-import org.apache.felix.scrplugin.tags.JavaTag;
-
-import com.thoughtworks.qdox.model.Annotation;
-import com.thoughtworks.qdox.model.JavaClass;
-
-
-/**
- * Supports mapping of built-in and custom java anntoations to {@link JavaTag}
- * implementations.
- */
-public class AnnotationTagProviderManager
-{
-
- /**
- * 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.
- */
- private final Map<String, AnnotationTagProvider> annotationTagProviders = new LinkedHashMap<String, AnnotationTagProvider>();
-
- /**
- * @param annotationTagProviderClasses List of classes that implements
- * {@link AnnotationTagProvider} interface.
- * @throws SCRDescriptorFailureException
- */
- public AnnotationTagProviderManager(
- final String[] annotationTagProviderClasses,
- final ClassLoader classLoader )
- throws SCRDescriptorFailureException
- {
- // search for providers
- final Iterator<AnnotationTagProvider> serviceIter = ServiceRegistry.lookupProviders(AnnotationTagProvider.class, classLoader);
- while ( serviceIter.hasNext() )
- {
- final AnnotationTagProvider provider = serviceIter.next();
- this.addProvider(provider);
- }
-
- // add custom providers defined in pom
- for ( int i = 0; i < annotationTagProviderClasses.length; i++ )
- {
- loadProvider( classLoader, annotationTagProviderClasses[i], false );
- }
-
- // always add provider supporting built-in SCR default properties (for compatibility with older
- // annotation versions)
- loadProvider( classLoader,
- "org.apache.felix.scrplugin.tags.annotation.defaulttag.DefaultAnnotationTagProvider", true );
- loadProvider( classLoader,
- "org.apache.felix.scrplugin.tags.annotation.sling.SlingAnnotationTagProvider", true );
- }
-
- /**
- * Add a provider (if not already available)
- */
- private void addProvider(final AnnotationTagProvider provider)
- {
- // check if this provider is already loaded
- final String key = provider.getClass().getName();
- if ( !this.annotationTagProviders.containsKey(key) )
- {
- this.annotationTagProviders.put(key, provider);
- }
- }
-
- private void loadProvider( final ClassLoader classLoader, final String className, final boolean silent )
- throws SCRDescriptorFailureException
- {
- String failureMessage = null;
- try
- {
- Class<?> clazz = classLoader.loadClass( className );
- try
- {
- addProvider( ( AnnotationTagProvider ) clazz.newInstance() );
- }
- catch ( ClassCastException e )
- {
- failureMessage = "Class '" + clazz.getName() + "' " + "does not implement interface '"
- + AnnotationTagProvider.class.getName() + "'.";
- }
- catch ( InstantiationException e )
- {
- failureMessage = "Unable to instantiate class '" + clazz.getName() + "': " + e.getMessage();
- }
- catch ( IllegalAccessException e )
- {
- failureMessage = "Illegal access to class '" + clazz.getName() + "': " + e.getMessage();
- }
- }
- catch ( ClassNotFoundException e )
- {
- failureMessage = "Annotation provider class '" + className + "' not found.";
- }
-
- // throw an optional exception if not required to remaing silent
- if ( failureMessage != null && !silent )
- {
- throw new SCRDescriptorFailureException( failureMessage );
- }
- }
-
-
- /**
- * Converts a java annotation to {@link JavaTag} if a mapping can be found.
- *
- * @param annotation Java annotation
- * @param description Description
- * @return Tag declaration or null if no mapping found
- */
- public List<JavaTag> getTags( Annotation annotation, AnnotationJavaClassDescription description )
- {
- return getTags( annotation, description, null );
- }
-
-
- /**
- * Converts a java annotation to {@link JavaTag} if a mapping can be found.
- *
- * @param annotation Java annotation
- * @param description Description
- * @param field Field
- * @return Tag declaration or null if no mapping found
- */
- public List<JavaTag> getTags( Annotation annotation, AnnotationJavaClassDescription description, JavaField field )
- {
- List<JavaTag> tags = new ArrayList<JavaTag>();
-
- for ( AnnotationTagProvider provider : this.annotationTagProviders.values() )
- {
- tags.addAll( provider.getTags( annotation, description, field ) );
- }
-
- return tags;
- }
-
-
- /**
- * Checks if the given class has any SCR plugin java annotations defined.
- *
- * @param pClass Class
- * @return true if SCR plugin java annotation found
- */
- public boolean hasScrPluginAnnotation( final JavaClass pClass, final AnnotationJavaClassDescription description )
- {
- for ( com.thoughtworks.qdox.model.Annotation annotation : pClass.getAnnotations() )
- {
- if ( getTags( annotation, description ).size() > 0 )
- {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/Util.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/Util.java
deleted file mode 100644
index 61eef89..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/annotation/Util.java
+++ /dev/null
@@ -1,455 +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.annotation;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.tags.*;
-
-import com.thoughtworks.qdox.model.Annotation;
-import com.thoughtworks.qdox.model.annotation.AnnotationFieldRef;
-import com.thoughtworks.qdox.model.annotation.EvaluatingVisitor;
-
-/**
- * Helper class for getting values from annotations.
- */
-public abstract class Util {
-
- /**
- * Get a boolean value from an annotation.
- * @param annotation The annotation.
- * @param name The name of the attribute.
- * @param clazz The annotation class.
- * @return The boolean value.
- */
- public static boolean getBooleanValue(final Annotation annotation, final JavaClassDescription desc, final String name, final Class<?> clazz) {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null )
- {
- return Boolean.valueOf(sValues[0]);
- }
- try
- {
- return (Boolean) clazz.getMethod(name).getDefaultValue();
- }
- catch( final NoSuchMethodException mnfe)
- {
- // we ignore this
- return true;
- }
- }
-
- public static int getIntValue(final Annotation annotation, final JavaClassDescription desc, final String name, final Class<?> clazz) {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null )
- {
- return Integer.valueOf(sValues[0]);
-
- }
- try
- {
- return (Integer) clazz.getMethod(name).getDefaultValue();
- }
- catch(final NoSuchMethodException mnfe)
- {
- // we ignore this
- return 0;
- }
- }
-
- /**
- * Helper method to get the values of an annotation as string values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of string values or null.
- */
- public static String[] getStringValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- return sValues;
- }
-
- /**
- * Helper method to get the values of an annotation as long values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of long values or null.
- */
- public static long[] getLongValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final long[] values = new long[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Long.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as long values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of long values or null.
- */
- public static int[] getIntValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final int[] values = new int[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Integer.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as float values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of float values or null.
- */
- public static float[] getFloatValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final float[] values = new float[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Float.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as double values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of double values or null.
- */
- public static double[] getDoubleValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final double[] values = new double[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Double.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as char values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of char values or null.
- */
- public static char[] getCharValues(Annotation annotation, JavaClassDescription desc, String name) {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final char[] values = new char[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = sValues[i].charAt(0);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as short values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of short values or null.
- */
- public static short[] getShortValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final short[] values = new short[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Short.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as byte values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of byte values or null.
- */
- public static byte[] getByteValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final byte[] values = new byte[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Byte.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Helper method to get the values of an annotation as boolean values.
- * @param annotation The annotation.
- * @param desc The java class description.
- * @param name The attribute name from the annotation.
- * @return The array of boolean values or null.
- */
- public static boolean[] getBooleanValues(Annotation annotation, JavaClassDescription desc, String name)
- {
- final String[] sValues = getAnnotationValues(annotation, name, desc);
- if ( sValues != null && sValues.length > 0 )
- {
- final boolean[] values = new boolean[sValues.length];
- for (int i=0; i<values.length; i++)
- {
- values[i] = Boolean.valueOf(sValues[i]);
- }
- return values;
-
- }
- return null;
- }
-
- /**
- * Get a single annotation value
- * @param annotation The annotation
- * @param desc The class description
- * @param name The name of the annotation
- * @param clazz The class of the annotation
- * @return The value
- */
- public static String getStringValue(Annotation annotation, JavaClassDescription desc, String name, final Class<?> clazz) {
- final String values[] = getAnnotationValues(annotation, name, desc);
- if ( values != null && values.length > 0 ) {
- return values[0];
- }
- // try to get the default value
- try {
- return (String) clazz.getMethod(name).getDefaultValue();
- } catch( NoSuchMethodException mnfe) {
- // we ignore this
- return "";
- }
- }
-
- public static Class<?> getClassValue(Annotation annotation, String name, final Class<?> clazz, final ClassLoader classLoader) {
- final Object obj = annotation.getNamedParameter(name);
- if ( obj != null ) {
- if ( obj instanceof Class<?> ) {
- return (Class<?>)obj;
- }
- return ClassUtil.getClass(classLoader, obj.toString());
- }
- try {
- return (Class<?>) clazz.getMethod(name).getDefaultValue();
- } catch( NoSuchMethodException mnfe) {
- // we ignore this
- return null;
- }
- }
-
- public static Class<?>[] getClassArrayValue(Annotation annotation, String name, final Class<?> clazz, final ClassLoader classLoader) {
- Object obj = annotation.getNamedParameter(name);
- if ( obj != null ) {
- if ( obj instanceof Class<?> ) {
- return new Class<?>[] {(Class<?>)obj};
- }
- if ( obj instanceof Collection<?> ) {
- obj = ((Collection<?>)obj).toArray();
- }
- if ( obj.getClass().isArray() ) {
- final Object[] objArray = (Object[])obj;
- final Class<?>[] result = new Class<?>[objArray.length];
- for(int i=0; i<objArray.length;i++) {
- if ( objArray[i] instanceof Class<?>) {
- result[i] = (Class<?>)objArray[i];
- } else {
- result[i] = ClassUtil.getClass(classLoader, objArray[i].toString());
- }
- }
- return result;
- }
- return new Class<?>[] {ClassUtil.getClass(classLoader, obj.toString())};
- }
- try {
- final Object val = clazz.getMethod(name).getDefaultValue();
- if ( val instanceof Class<?> ) {
- return new Class<?>[] {(Class<?>)val};
- }
- return (Class<?>[])val;
- } catch( NoSuchMethodException mnfe) {
- // we ignore this
- return null;
- }
- }
-
- public static <T extends Enum<T>> T getEnumValue(Annotation annotation,
- String name,
- final Class<T> enumClass,
- final Class<?> clazz,
- final boolean returnDefault) {
- Object obj = annotation.getNamedParameter(name);
- if (obj == null) {
- if ( returnDefault ) {
- try {
- obj = clazz.getMethod(name).getDefaultValue();
- } catch( NoSuchMethodException mnfe) {
- // we ignore this
- }
- }
- }
- if ( obj != null ) {
- if (enumClass.isAssignableFrom(obj.getClass())) {
- return (T)obj;
- }
- else if ( obj instanceof String ) {
- String enumName = (String)obj;
- int dotPos = enumName.lastIndexOf('.');
- if (dotPos >= 0) {
- enumName = enumName.substring(dotPos+1);
- }
- return Enum.valueOf(enumClass, enumName);
- }
- }
- return null;
- }
-
- public static <T extends Enum<T>> T getEnumValue(Annotation annotation,
- String name,
- final Class<T> enumClass,
- final Class<?> clazz) {
- return getEnumValue(annotation, name, enumClass, clazz, true);
- }
-
- @SuppressWarnings("unchecked")
- public static String[] getAnnotationValues(final Annotation annotation, final String name, final JavaClassDescription desc)
- throws IllegalArgumentException
- {
- final EvaluatingVisitor evaluatingVisitor = new EvaluatingVisitor() {
-
- public Object visitAnnotationFieldRef( AnnotationFieldRef fieldRef ) {
- // during prescan of AnnotationTagProviderManager#hasScrPluginAnnotation this method is called without desc attribute
- // avoid NPE in this case and just skip value resolving
- // FELIX-1629
- if ( desc == null)
- {
- return "";
- }
-
- // getField throws AIOOBE
- // return ((AnnotationFieldRef)av).getField().getInitializationExpression();
- final String s = fieldRef.getParameterValue().toString().trim();
- try
- {
- int classSep = s.lastIndexOf('.');
- JavaField field = null;
- if ( classSep == -1 ) {
- // local variable
- field = desc.getFieldByName(s);
- }
- if ( field == null ) {
- field = desc.getExternalFieldByName(s);
- }
- if ( field == null ) {
- throw new IllegalArgumentException("Property references unknown field " + s + " in class " + desc.getName());
- }
- String[] values = field.getInitializationExpression();
- if ( values != null && values.length == 1 ) {
- return values[0];
- }
- throw new IllegalArgumentException("Something is wrong: " + s);
- }
- catch (NoClassDefFoundError ncdfe)
- {
- throw new IllegalArgumentException("A class could not be found while parsing class " + desc.getName() +
- ". Please check this stracktrace and add a dependency with the missing class to your project.", ncdfe);
- }
- catch (SCRDescriptorException mee)
- {
- throw new IllegalArgumentException(mee);
- }
- }
-
- @Override
- protected Object getFieldReferenceValue(com.thoughtworks.qdox.model.JavaField javaField) {
- // is never called because visitAnnotationFieldRef is overridden as well
- return null;
- }
-
- };
- final List<Object> valueList = evaluatingVisitor.getListValue(annotation, name);
- if (valueList == null || valueList.size() == 0)
- {
- return null;
- }
- String[] values = new String[valueList.size()];
- for (int i=0; i<values.length; i++) {
- Object value = valueList.get(i);
- if (value!=null) {
- values[i] = value.toString();
- }
- }
- return values;
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
deleted file mode 100644
index 53b5110..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
+++ /dev/null
@@ -1,273 +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.cl;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.felix.scrplugin.*;
-import org.apache.felix.scrplugin.om.Component;
-import org.apache.felix.scrplugin.tags.*;
-
-/**
- * <code>ClassLoaderJavaClassDescription.java</code>...
- *
- */
-public class ClassLoaderJavaClassDescription implements JavaClassDescription {
-
- protected static final JavaTag[] EMPTY_TAGS = new JavaTag[0];
-
- protected final Class<?> clazz;
-
- protected final JavaClassDescriptorManager manager;
-
- protected final Component component;
-
- public ClassLoaderJavaClassDescription(Class<?> c, Component comp, JavaClassDescriptorManager m) {
- this.clazz = c;
- this.manager = m;
- this.component = comp;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFields()
- */
- public JavaField[] getFields() {
- final Field[] fields = this.clazz.getFields();
- final JavaField[] javaFields = new JavaField[fields.length];
- for (int i=0; i < fields.length; i++ ) {
- javaFields[i] = new ClassLoaderJavaField(fields[i], this);
- }
- return javaFields;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFieldByName(java.lang.String)
- */
- public JavaField getFieldByName(String name) throws SCRDescriptorException {
- Field field = null;
- try {
- field = this.clazz.getField(name);
- } catch (SecurityException e) {
- // ignore
- } catch (NoSuchFieldException e) {
- // ignore
- }
- if ( field != null ) {
- return new ClassLoaderJavaField(field, this);
- }
- if ( this.getSuperClass() != null ) {
- this.getSuperClass().getFieldByName(name);
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
- */
- public JavaField getExternalFieldByName(String name)
- throws SCRDescriptorException {
- throw new SCRDescriptorException("getExternalFieldByName not supported for this class.", getName(), 0);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getReferencedClass(java.lang.String)
- */
- public JavaClassDescription getReferencedClass(String referencedName)
- throws SCRDescriptorException {
- throw new SCRDescriptorException("getReferencedClass not supported for this class.", getName(), 0);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
- */
- public JavaClassDescription[] getImplementedInterfaces() throws SCRDescriptorException {
- Class<?>[] implemented = clazz.getInterfaces();
- if (implemented.length == 0) {
- return JavaClassDescription.EMPTY_RESULT;
- }
-
- JavaClassDescription[] jcd = new JavaClassDescription[implemented.length];
- for (int i=0; i < jcd.length; i++) {
- jcd[i] = manager.getJavaClassDescription(implemented[i].getName());
- }
- return jcd;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getMethodBySignature(java.lang.String, java.lang.String[])
- */
- public JavaMethod getMethodBySignature(String name, String[] parameters)
- throws SCRDescriptorException {
- Class<?>[] classParameters = null;
- if ( parameters != null ) {
- classParameters = new Class[parameters.length];
- for(int i=0; i<parameters.length; i++) {
- try {
- classParameters[i] = this.manager.getClassLoader().loadClass(parameters[i]);
- } catch (ClassNotFoundException cnfe) {
- return null;
- }
- }
- }
- Method m = null;
- try {
- m = this.clazz.getDeclaredMethod(name, classParameters);
- } catch (NoClassDefFoundError ncdfe) {
- // if this occurs it usually means that a problem with the maven
- // scopes exists.
- 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'.", getName(), 0, ncdfe);
- } catch (NoSuchMethodException e) {
- // ignore this
- }
- if ( m != null ) {
- return new ClassLoaderJavaMethod(m);
- }
- // try super class
- if ( this.getSuperClass() != null ) {
- return this.getSuperClass().getMethodBySignature(name, parameters);
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getMethods()
- */
- public JavaMethod[] getMethods() {
- return JavaMethod.EMPTY_RESULT;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getName()
- */
- public String getName() {
- return this.clazz.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getSuperClass()
- */
- public JavaClassDescription getSuperClass() throws SCRDescriptorException {
- if ( this.clazz.getSuperclass() != null ) {
- return this.manager.getJavaClassDescription(this.clazz.getSuperclass().getName());
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagByName(java.lang.String)
- */
- public JavaTag getTagByName(String name) {
- // this is only used to retrieve the component tag, so we just support this
- if ( this.component != null && name.equals(Constants.COMPONENT) ) {
- return new ClassLoaderJavaTag(this, this.component);
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagsByName(java.lang.String, boolean)
- */
- public JavaTag[] getTagsByName(String name, boolean inherited)
- throws SCRDescriptorException {
- JavaTag[] javaTags = EMPTY_TAGS;
- if ( this.component != null ) {
- if ( Constants.SERVICE.equals(name) ) {
- if ( this.component.getService() != null &&
- this.component.getService().getInterfaces().size() > 0 ) {
- javaTags = new JavaTag[this.component.getService().getInterfaces().size()];
- for(int i=0; i<this.component.getService().getInterfaces().size(); i++) {
- javaTags[i] = new ClassLoaderJavaTag(this, this.component.getService().getInterfaces().get(i),
- this.component.getService().isServicefactory());
- }
- }
- } else if ( Constants.PROPERTY.equals(name) ) {
- if ( this.component.getProperties().size() > 0 ) {
- javaTags = new JavaTag[this.component.getProperties().size()];
- for(int i=0; i<this.component.getProperties().size(); i++) {
- javaTags[i] = new ClassLoaderJavaTag(this, this.component.getProperties().get(i));
- }
- }
- } else if ( Constants.REFERENCE.equals(name) ) {
- if ( this.component.getReferences().size() > 0 ) {
- javaTags = new JavaTag[this.component.getReferences().size()];
- for(int i=0; i<this.component.getReferences().size(); i++) {
- javaTags[i] = new ClassLoaderJavaTag(this, this.component.getReferences().get(i));
- }
- }
- }
- }
- if ( inherited && this.getSuperClass() != null ) {
- final JavaTag[] superTags = this.getSuperClass().getTagsByName(name, inherited);
- if ( superTags.length > 0 ) {
- final List<JavaTag> list = new ArrayList<JavaTag>(Arrays.asList(javaTags));
- list.addAll(Arrays.asList(superTags));
- javaTags = list.toArray(new JavaTag[list.size()]);
- }
- }
- return javaTags;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isA(java.lang.String)
- */
- public boolean isA(String type) {
- if ( this.clazz.getName().equals(type) ) {
- return true;
- }
-
- if ( this.clazz.getClassLoader() != null ) {
- try {
- Class<?> typeClass = this.clazz.getClassLoader().loadClass( type );
- return typeClass.isAssignableFrom( this.clazz );
- } catch (ClassNotFoundException cnfe) {
- // cannot load the check type through the class' class loader
- // thus we assume clazz is not a type
- }
- }
- return false;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isAbstract()
- */
- public boolean isAbstract() {
- return Modifier.isAbstract(this.clazz.getModifiers());
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isInterface()
- */
- public boolean isInterface() {
- return Modifier.isInterface(this.clazz.getModifiers());
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isPublic()
- */
- public boolean isPublic() {
- return Modifier.isPublic(this.clazz.getModifiers());
- }
-
- public String toString() {
- return getName();
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java
deleted file mode 100644
index 37ab90b..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaField.java
+++ /dev/null
@@ -1,68 +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.cl;
-
-import java.lang.reflect.Field;
-
-import org.apache.felix.scrplugin.tags.*;
-
-/**
- * <code>ClassLoaderJavaField.java</code>...
- *
- */
-public class ClassLoaderJavaField implements JavaField {
-
- protected final Field field;
-
- protected final JavaClassDescription description;
-
- public ClassLoaderJavaField(Field f, JavaClassDescription d) {
- this.field = f;
- this.description = d;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getInitializationExpression()
- */
- public String[] getInitializationExpression() {
- return ClassUtil.getInitializationExpression(this.field.getDeclaringClass(), this.field.getName());
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getName()
- */
- public String getName() {
- return this.field.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getTagByName(java.lang.String)
- */
- public JavaTag getTagByName(String name) {
- // TODO
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getType()
- */
- public String getType() {
- return this.field.getType().getName();
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaMethod.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaMethod.java
deleted file mode 100644
index d7c5dde..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaMethod.java
+++ /dev/null
@@ -1,80 +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.cl;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-import org.apache.felix.scrplugin.tags.JavaMethod;
-import org.apache.felix.scrplugin.tags.JavaParameter;
-
-/**
- * <code>ClassLoaderJavaMethod.java</code>...
- *
- */
-public class ClassLoaderJavaMethod implements JavaMethod {
-
- protected final Method method;
-
- protected boolean isConstructor = false;
-
- public ClassLoaderJavaMethod(Method m) {
- this.method = m;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#getName()
- */
- public String getName() {
- return this.method.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#getParameters()
- */
- public JavaParameter[] getParameters() {
- final JavaParameter[] params = new JavaParameter[this.method.getParameterTypes().length];
- for(int i=0; i<this.method.getParameterTypes().length; i++) {
- params[i] = new ClassLoaderJavaParameter(this.method.getParameterTypes()[i].getName());
- }
- return params;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#isConstructor()
- */
- public boolean isConstructor() {
- return this.isConstructor;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#isProtected()
- */
- public boolean isProtected() {
- return Modifier.isProtected(this.method.getModifiers());
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#isPublic()
- */
- public boolean isPublic() {
- return Modifier.isPublic(this.method.getModifiers());
- }
-
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
deleted file mode 100644
index c9e8e88..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
+++ /dev/null
@@ -1,212 +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.cl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.felix.scrplugin.Constants;
-import org.apache.felix.scrplugin.om.*;
-import org.apache.felix.scrplugin.tags.*;
-
-/**
- * <code>ClassLoaderJavaTag.java</code>...
- *
- */
-public class ClassLoaderJavaTag implements JavaTag {
-
- protected final JavaClassDescription description;
- protected final Component component;
- protected final Reference reference;
- protected final Property property;
- protected final Interface interf;
- protected boolean isServiceFactory;
-
- public ClassLoaderJavaTag(final JavaClassDescription desc, final Component component) {
- this.description = desc;
- this.reference = null;
- this.interf = null;
- this.property = null;
- this.component = component;
- }
-
- public ClassLoaderJavaTag(final JavaClassDescription desc, final Reference reference) {
- this.description = desc;
- this.reference = reference;
- this.interf = null;
- this.property = null;
- this.component = null;
- }
-
- public ClassLoaderJavaTag(final JavaClassDescription desc, final Property property) {
- this.description = desc;
- this.property = property;
- this.reference = null;
- this.interf = null;
- this.component = null;
- }
-
- public ClassLoaderJavaTag(final JavaClassDescription desc, final Interface i, final boolean isSF) {
- this.interf = i;
- this.description = desc;
- this.property = null;
- this.reference = null;
- this.isServiceFactory = isSF;
- this.component = null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getField()
- */
- public JavaField getField() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getJavaClassDescription()
- */
- public JavaClassDescription getJavaClassDescription() {
- return this.description;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getName()
- */
- public String getName() {
- if ( this.reference != null ) {
- return Constants.REFERENCE;
- } else if ( this.property != null ) {
- return Constants.PROPERTY;
- } else if ( this.interf != null ) {
- return Constants.SERVICE;
- } else if ( this.component != null ) {
- return Constants.COMPONENT;
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getSourceName()
- */
- public String getSourceName() {
- return this.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getNamedParameter(java.lang.String)
- */
- public String getNamedParameter(String name) {
- final Map<String, String> map = this.getNamedParameterMap();
- if ( map != null ) {
- return map.get(name);
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getNamedParameterMap()
- */
- public Map<String, String> getNamedParameterMap() {
- if ( this.reference != null ) {
- final Map<String, String> map = new HashMap<String, String>();
- map.put(Constants.REFERENCE_BIND, this.reference.getBind());
- map.put(Constants.REFERENCE_CARDINALITY, this.reference.getCardinality());
- map.put(Constants.REFERENCE_INTERFACE, this.reference.getInterfacename());
- map.put(Constants.REFERENCE_NAME, this.reference.getName());
- map.put(Constants.REFERENCE_POLICY, this.reference.getPolicy());
- map.put(Constants.REFERENCE_TARGET, this.reference.getTarget());
- map.put(Constants.REFERENCE_UNDBIND, this.reference.getUnbind());
- map.put(Constants.REFERENCE_UPDATED, this.reference.getUpdated());
- map.put(Constants.REFERENCE_CHECKED, String.valueOf(this.reference.isChecked()));
- map.put(Constants.REFERENCE_STRATEGY, this.reference.getStrategy());
- return map;
- } else if ( this.property != null ) {
- final Map<String, String> map = new HashMap<String, String>();
- map.put(Constants.PROPERTY_TYPE, this.property.getType());
- map.put(Constants.PROPERTY_NAME, this.property.getName());
- final String[] values = this.property.getMultiValue();
- if ( values != null ) {
- for(int i=0; i<values.length;i++) {
- map.put(Constants.PROPERTY_MULTIVALUE_PREFIX + '.' + i, values[i]);
- }
- } else {
- map.put(Constants.PROPERTY_VALUE, this.property.getValue());
- }
- map.put(Constants.PROPERTY_PRIVATE, String.valueOf(property.isPrivate()));
- if ( this.property.getLabel() != null ) {
- map.put(Constants.PROPERTY_LABEL, this.property.getLabel());
- }
- if ( this.property.getDescription() != null ) {
- map.put(Constants.PROPERTY_DESCRIPTION, this.property.getDescription());
- }
- if ( this.property.getCardinality() != null ) {
- map.put(Constants.PROPERTY_CARDINALITY, this.property.getCardinality());
- }
- return map;
- } else if ( this.interf != null ) {
- final Map<String, String> map = new HashMap<String, String>();
- map.put(Constants.SERVICE_INTERFACE, this.interf.getInterfacename());
- if ( this.isServiceFactory ) {
- map.put(Constants.SERVICE_FACTORY, "true");
- }
- return map;
- } else if ( this.component != null ) {
- final Map<String, String> map = new HashMap<String, String>();
- if ( this.component.getActivate() != null ) {
- map.put(Constants.COMPONENT_ACTIVATE, this.component.getActivate());
- }
- if ( this.component.getDeactivate() != null ) {
- map.put(Constants.COMPONENT_DEACTIVATE, this.component.getDeactivate());
- }
- if ( this.component.getModified() != null ) {
- map.put(Constants.COMPONENT_MODIFIED, this.component.getModified());
- }
- return map;
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getParameters()
- */
- public String[] getParameters() {
- final Map<String, String> map = this.getNamedParameterMap();
- if ( map != null ) {
- return map.keySet().toArray(new String[5]);
- }
- return new String[0];
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getSourceLocation()
- */
- public String getSourceLocation() {
- return "Compiled class: " + this.description.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getLineNumber()
- */
- public int getLineNumber()
- {
- // we don't know the exact line number of a tag in a compiled class
- return 0;
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
deleted file mode 100644
index 6ac0f60..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
+++ /dev/null
@@ -1,437 +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.qdox;
-
-import java.io.*;
-import java.util.*;
-
-import org.apache.felix.scrplugin.JavaClassDescriptorManager;
-import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.tags.*;
-import org.apache.felix.scrplugin.tags.JavaField;
-import org.apache.felix.scrplugin.tags.JavaMethod;
-import org.objectweb.asm.*;
-import org.objectweb.asm.tree.ClassNode;
-
-import com.thoughtworks.qdox.model.*;
-import com.thoughtworks.qdox.model.JavaParameter;
-import com.thoughtworks.qdox.model.Type;
-
-/**
- * <code>QDoxJavaClassDescription.java</code>...
- *
- */
-public class QDoxJavaClassDescription
- implements JavaClassDescription, ModifiableJavaClassDescription {
-
- protected final JavaClass javaClass;
-
- protected final JavaClassDescriptorManager manager;
-
- /** The compiled class. */
- protected final Class<?> clazz;
-
- public QDoxJavaClassDescription(Class<?> clazz, JavaClass javaClass, JavaClassDescriptorManager m) {
- this.javaClass = javaClass;
- this.manager = m;
- this.clazz = clazz;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getSuperClass()
- */
- public JavaClassDescription getSuperClass() throws SCRDescriptorException {
- final JavaClass parent = this.javaClass.getSuperJavaClass();
- if ( parent != null ) {
- return this.manager.getJavaClassDescription(parent.getFullyQualifiedName());
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagByName(java.lang.String)
- */
- public JavaTag getTagByName(String name) {
- final DocletTag tag = this.javaClass.getTagByName(name);
- if ( tag == null ) {
- return null;
- }
- return new QDoxJavaTag(tag, this);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getName()
- */
- public String getName() {
- return this.javaClass.getFullyQualifiedName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getTagsByName(java.lang.String, boolean)
- */
- public JavaTag[] getTagsByName(String name, boolean inherited)
- throws SCRDescriptorException {
- final DocletTag[] tags = this.javaClass.getTagsByName(name, false);
- JavaTag[] javaTags;
- if ( tags == null || tags.length == 0 ) {
- javaTags = new JavaTag[0];
- } else {
- javaTags = new JavaTag[tags.length];
- for(int i=0; i<tags.length;i++) {
- javaTags[i] = new QDoxJavaTag(tags[i], this);
- }
- }
- if ( inherited && this.getSuperClass() != null ) {
- final JavaTag[] superTags = this.getSuperClass().getTagsByName(name, inherited);
- if ( superTags.length > 0 ) {
- final List<JavaTag> list = new ArrayList<JavaTag>(Arrays.asList(javaTags));
- list.addAll(Arrays.asList(superTags));
- javaTags = list.toArray(new JavaTag[list.size()]);
- }
- }
- return javaTags;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFields()
- */
- public JavaField[] getFields() {
- final com.thoughtworks.qdox.model.JavaField fields[] = this.javaClass.getFields();
- if ( fields == null || fields.length == 0 ) {
- return new JavaField[0];
- }
- final JavaField[] f = new JavaField[fields.length];
- for(int i=0; i<fields.length; i++) {
- f[i] = new QDoxJavaField(fields[i], this);
- }
- return f;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getFieldByName(java.lang.String)
- */
- public JavaField getFieldByName(String name)
- throws SCRDescriptorException {
- final com.thoughtworks.qdox.model.JavaField field = this.javaClass.getFieldByName(name);
- if ( field != null ) {
- return new QDoxJavaField(field, this);
- }
- if ( this.getSuperClass() != null ) {
- return this.getSuperClass().getFieldByName(name);
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
- */
- public JavaField getExternalFieldByName(String name)
- throws SCRDescriptorException {
- int lastDot = name.lastIndexOf('.');
- // if there is no dot, this should be a static import
- if ( lastDot == -1 ) {
- final String importDef = this.searchImport('.' + name);
- if ( importDef != null ) {
- int sep = importDef.lastIndexOf('.');
- final String className = importDef.substring(0, sep);
- final String constantName = importDef.substring(sep+1);
- final JavaClassDescription jcd = this.manager.getJavaClassDescription(className);
- if ( jcd != null ) {
- return jcd.getFieldByName(constantName);
- }
- }
- } else {
- // check for fully qualified
- int firstDot = name.indexOf('.');
- if ( firstDot == lastDot ) {
- // we only have one dot, so either the class is imported or in the same package or in the default package (java.lang)
- final String className = name.substring(0, lastDot);
- final String constantName = name.substring(lastDot+1);
- final String importDef = this.searchImport('.' + className);
- if ( importDef != null ) {
- final JavaClassDescription jcd = this.manager.getJavaClassDescription(importDef);
- if ( jcd != null ) {
- return jcd.getFieldByName(constantName);
- }
- }
- try {
- final JavaClassDescription jcd = this.manager.getJavaClassDescription(this.javaClass.getSource().getPackage().getName() + '.' + className);
- if ( jcd != null ) {
- return jcd.getFieldByName(constantName);
- }
- } catch (final SCRDescriptorException sde) {
- // try java.lang (FELIX-2906)
- try {
- final JavaClassDescription jcd = this.manager.getJavaClassDescription("java.lang." + className);
- if ( jcd != null ) {
- return jcd.getFieldByName(constantName);
- }
- } catch (final SCRDescriptorException ignore) {
- // ignore
- }
- throw sde;
- }
- } else {
- // we have more than one dot, so this is a fully qualified class
- final String className = name.substring(0, lastDot);
- final String constantName = name.substring(lastDot+1);
- final JavaClassDescription jcd = this.manager.getJavaClassDescription(className);
- if ( jcd != null ) {
- return jcd.getFieldByName(constantName);
- }
- }
- }
- return null;
- }
-
- protected String searchImport(String name) {
- final String[] imports = this.javaClass.getSource().getImports();
- if ( imports != null ) {
- for(int i=0; i<imports.length; i++ ) {
- if ( imports[i].endsWith(name) ) {
- return imports[i];
- }
- }
- }
- return null;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getReferencedClass(java.lang.String)
- */
- public JavaClassDescription getReferencedClass(final String referencedName) {
- String className = referencedName;
- int pos = className.indexOf('.');
- if ( pos == -1 ) {
- className = this.searchImport('.' + referencedName);
- }
- if ( className == null ) {
- if ( pos != -1 ) {
- return null;
- }
- className = this.javaClass.getSource().getPackage().getName() + '.' + referencedName;
- }
- try {
- return this.manager.getJavaClassDescription(className);
- } catch (SCRDescriptorException mee) {
- return null;
- }
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
- */
- public JavaClassDescription[] getImplementedInterfaces()
- throws SCRDescriptorException {
- final JavaClass[] interfaces = this.javaClass.getImplementedInterfaces();
- if ( interfaces == null || interfaces.length == 0 ) {
- return JavaClassDescription.EMPTY_RESULT;
- }
- final JavaClassDescription[] descs = new JavaClassDescription[interfaces.length];
- for(int i=0;i<interfaces.length; i++) {
- descs[i] = this.manager.getJavaClassDescription(interfaces[i].getFullyQualifiedName());
- }
- return descs;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getMethodBySignature(java.lang.String, java.lang.String[])
- */
- public JavaMethod getMethodBySignature(String name, String[] parameters)
- throws SCRDescriptorException {
- Type[] types = null;
- if ( parameters == null || parameters.length == 0 ) {
- types = new Type[0];
- } else {
- types = new Type[parameters.length];
- for(int i=0;i<parameters.length;i++) {
- types[i] = new Type(parameters[i]);
- }
- }
- final com.thoughtworks.qdox.model.JavaMethod m = this.javaClass.getMethodBySignature(name, types);
- if ( m == null ) {
- if ( this.getSuperClass() != null ) {
- return this.getSuperClass().getMethodBySignature(name, parameters);
- }
- return null;
- }
- return new QDoxJavaMethod(m);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getMethods()
- */
- public JavaMethod[] getMethods() {
- final com.thoughtworks.qdox.model.JavaMethod[] methods = this.javaClass.getMethods();
- if ( methods == null || methods.length == 0) {
- return JavaMethod.EMPTY_RESULT;
- }
- final JavaMethod[] m = new JavaMethod[methods.length];
- for(int i=0;i<methods.length;i++) {
- m[i] = new QDoxJavaMethod(methods[i]);
- }
- return m;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isA(java.lang.String)
- */
- public boolean isA(String type) throws SCRDescriptorException {
- final Type qType = new Type(type);
- if ( this.javaClass.isA(type) ) {
- return true;
- }
- final Type[] interfaces = this.javaClass.getImplements();
- if ( interfaces != null ) {
- for(int i=0; i<interfaces.length; i++) {
- if ( interfaces[i].isA(qType) ) {
- return true;
- }
- }
- }
- if ( this.getSuperClass() != null ) {
- return this.getSuperClass().isA(type);
- }
- return false;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isAbstract()
- */
- public boolean isAbstract() {
- return this.javaClass.isAbstract();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isInterface()
- */
- public boolean isInterface() {
- return this.javaClass.isInterface();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaClassDescription#isPublic()
- */
- public boolean isPublic() {
- return this.javaClass.isPublic();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.ModifiableJavaClassDescription#addMethods(java.lang.String, java.lang.String, boolean, boolean)
- */
- public void addMethods(final String propertyName,
- final String className,
- final boolean createBind,
- final boolean createUnbind)
- throws SCRDescriptorException {
- // now do byte code manipulation
- final String targetDirectory = this.manager.getOutputDirectory();
- final String fileName = targetDirectory + File.separatorChar + this.getName().replace('.', File.separatorChar) + ".class";
- final ClassNode cn = new ClassNode();
- try {
- final ClassReader reader = new ClassReader(new FileInputStream(fileName));
- reader.accept(cn, 0);
-
- final ClassWriter writer = new ClassWriter(0);
-
- // remove existing implementation von previous builds
- final ClassAdapter adapter = new ClassAdapter(writer) {
-
- protected final String bindMethodName = "bind" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
- protected final String unbindMethodName = "unbind" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
- protected final String description = "(L" + className.replace('.', '/') + ";)V";
-
- /**
- * @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
- */
- public MethodVisitor visitMethod(int access,
- String name,
- String desc,
- String signature,
- String[] exceptions) {
- if ( createBind && name.equals(bindMethodName) && description.equals(desc) ) {
- return null;
- }
- if ( createUnbind && name.equals(unbindMethodName) && description.equals(desc) ) {
- return null;
- }
- return super.visitMethod(access, name, desc, signature, exceptions);
- }
-
- };
-
- cn.accept(adapter);
- if ( createBind ) {
- this.createMethod(writer, propertyName, className, true);
- }
- if ( createUnbind ) {
- this.createMethod(writer, propertyName, className, false);
- }
-
- final FileOutputStream fos = new FileOutputStream(fileName);
- fos.write(writer.toByteArray());
- fos.close();
- } catch (Exception e) {
- throw new SCRDescriptorException("Unable to add methods to " + this.getName(), className, 0, e);
- }
- }
-
- protected void createMethod(ClassWriter cw, String propertyName, String typeName, boolean bind) {
- final org.objectweb.asm.Type type = org.objectweb.asm.Type.getType("L" + typeName.replace('.', '/') + ";");
- final String methodName = (bind ? "" : "un") + "bind" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
- MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, methodName, "(" + type.toString() + ")V", null, null);
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- if ( bind ) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), 1);
- mv.visitFieldInsn(Opcodes.PUTFIELD, this.getName().replace('.', '/'), propertyName, type.toString());
- } else {
- mv.visitFieldInsn(Opcodes.GETFIELD, this.getName().replace('.', '/'), propertyName, type.toString());
- mv.visitVarInsn(Opcodes.ALOAD, 1);
- final Label jmpLabel = new Label();
- mv.visitJumpInsn(Opcodes.IF_ACMPNE, jmpLabel);
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- mv.visitInsn(Opcodes.ACONST_NULL);
- mv.visitFieldInsn(Opcodes.PUTFIELD, this.getName().replace('.', '/'), propertyName, type.toString());
- mv.visitLabel(jmpLabel);
- }
- mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(2, 2);
- // add to qdox
- final JavaParameter param = new JavaParameter(new Type(typeName), "param");
- final JavaParameter[] params = new JavaParameter[] {param};
- final com.thoughtworks.qdox.model.JavaMethod meth = new com.thoughtworks.qdox.model.JavaMethod();
- meth.setName(methodName);
- for(int i=0;i<params.length;i++) {
- meth.addParameter(params[i]);
- }
- meth.setModifiers(new String[] {"protected"});
- this.javaClass.addMethod(meth);
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- public String toString() {
- return getName();
- }
-
- public Class<?> getCompiledClass() {
- return this.clazz;
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java
deleted file mode 100644
index 5719e73..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaField.java
+++ /dev/null
@@ -1,89 +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.qdox;
-
-import org.apache.felix.scrplugin.tags.*;
-
-import com.thoughtworks.qdox.model.DocletTag;
-
-/**
- * <code>QDoxJavaField.java</code>...
- *
- */
-public class QDoxJavaField implements JavaField {
-
- protected final com.thoughtworks.qdox.model.JavaField field;
-
- protected final QDoxJavaClassDescription description;
-
- public QDoxJavaField(com.thoughtworks.qdox.model.JavaField f, QDoxJavaClassDescription d) {
- this.field = f;
- this.description = d;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getInitializationExpression()
- */
- public String[] getInitializationExpression() {
- String[] values = ClassUtil.getInitializationExpression(this.description.getCompiledClass(), this.getName());
- if ( values == null ) {
- // try qdox
- String value = this.field.getInitializationExpression();
- if ( value != null ) {
- int pos = value.indexOf("\"");
- if ( pos != -1 ) {
- try {
- value = value.substring(pos + 1);
- value = value.substring(0, value.lastIndexOf("\""));
- } catch (ArrayIndexOutOfBoundsException aioobe) {
- // ignore this as this is a qdox problem
- value = this.field.getInitializationExpression();
- }
- }
- values = new String[] {value};
- }
- }
- return values;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getName()
- */
- public String getName() {
- return this.field.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getTagByName(java.lang.String)
- */
- public JavaTag getTagByName(String name) {
- final DocletTag tag = this.field.getTagByName(name);
- if ( tag == null ) {
- return null;
- }
- return new QDoxJavaTag(tag, this.description, this);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaField#getType()
- */
- public String getType() {
- return this.field.getType().getValue();
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaMethod.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaMethod.java
deleted file mode 100644
index eaf3565..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaMethod.java
+++ /dev/null
@@ -1,78 +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.qdox;
-
-import org.apache.felix.scrplugin.tags.JavaMethod;
-import org.apache.felix.scrplugin.tags.JavaParameter;
-
-/**
- * <code>QDoxJavaMethod.java</code>...
- *
- */
-public class QDoxJavaMethod implements JavaMethod {
-
- protected final com.thoughtworks.qdox.model.JavaMethod method;
-
- public QDoxJavaMethod(com.thoughtworks.qdox.model.JavaMethod m) {
- this.method = m;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#getName()
- */
- public String getName() {
- return this.method.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#getParameters()
- */
- public JavaParameter[] getParameters() {
- final com.thoughtworks.qdox.model.JavaParameter[] params = this.method.getParameters();
- if ( params == null || params.length == 0) {
- return new JavaParameter[0];
- }
- final JavaParameter[] p = new JavaParameter[params.length];
- for(int i=0; i<params.length; i++) {
- p[i] = new QDoxJavaParameter(params[i]);
- }
- return p;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#isConstructor()
- */
- public boolean isConstructor() {
- return this.method.isConstructor();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#isProtected()
- */
- public boolean isProtected() {
- return this.method.isProtected();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaMethod#isPublic()
- */
- public boolean isPublic() {
- return this.method.isPublic();
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaParameter.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaParameter.java
deleted file mode 100644
index 3ba6ccb..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaParameter.java
+++ /dev/null
@@ -1,41 +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.qdox;
-
-import org.apache.felix.scrplugin.tags.JavaParameter;
-
-/**
- * <code>QDoxJavaParameter.java</code>...
- *
- */
-public class QDoxJavaParameter implements JavaParameter {
-
- protected final com.thoughtworks.qdox.model.JavaParameter parameter;
-
- public QDoxJavaParameter(com.thoughtworks.qdox.model.JavaParameter p) {
- this.parameter = p;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaParameter#getType()
- */
- public String getType() {
- return this.parameter.getType().getValue();
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java
deleted file mode 100644
index 3ccf010..0000000
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java
+++ /dev/null
@@ -1,115 +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.qdox;
-
-import java.util.Map;
-
-import org.apache.felix.scrplugin.tags.*;
-
-import com.thoughtworks.qdox.model.DocletTag;
-
-/**
- * <code>QDoxJavaTag.java</code>...
- *
- */
-public class QDoxJavaTag implements JavaTag {
-
- protected final DocletTag docletTag;
-
- protected final JavaClassDescription description;
-
- protected final JavaField field;
-
- public QDoxJavaTag(DocletTag t, JavaClassDescription desc) {
- this(t, desc, null);
- }
-
- public QDoxJavaTag(DocletTag t, JavaClassDescription desc, JavaField field) {
- this.docletTag = t;
- this.description = desc;
- this.field = field;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getName()
- */
- public String getName() {
- return this.docletTag.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getSourceName()
- */
- public String getSourceName() {
- return this.getName();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getNamedParameter(java.lang.String)
- */
- public String getNamedParameter(String arg0) {
- return this.docletTag.getNamedParameter(arg0);
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getParameters()
- */
- public String[] getParameters() {
- return this.docletTag.getParameters();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getSourceLocation()
- */
- public String getSourceLocation() {
- if ( this.docletTag.getContext().getParent() != null ) {
- return String.valueOf(this.docletTag.getContext().getParent().getParentSource().getURL());
- }
- return String.valueOf(this.docletTag.getContext().getParentClass().getSource().getURL());
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getLineNumber()
- */
- public int getLineNumber() {
- return this.docletTag.getLineNumber();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getJavaClassDescription()
- */
- public JavaClassDescription getJavaClassDescription() {
- return this.description;
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getNamedParameterMap()
- */
- @SuppressWarnings("unchecked")
- public Map<String, String> getNamedParameterMap() {
- return this.docletTag.getNamedParameterMap();
- }
-
- /**
- * @see org.apache.felix.scrplugin.tags.JavaTag#getField()
- */
- public JavaField getField() {
- return this.field;
- }
-}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index 1f7be91..32d6db5 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -18,15 +18,39 @@
*/
package org.apache.felix.scrplugin.xml;
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
import java.util.StringTokenizer;
import javax.xml.transform.TransformerException;
-import org.apache.felix.scrplugin.Constants;
import org.apache.felix.scrplugin.SCRDescriptorException;
-import org.apache.felix.scrplugin.om.*;
-import org.xml.sax.*;
+import org.apache.felix.scrplugin.description.ClassDescription;
+import org.apache.felix.scrplugin.description.ComponentConfigurationPolicy;
+import org.apache.felix.scrplugin.description.ComponentDescription;
+import org.apache.felix.scrplugin.description.MethodDescription;
+import org.apache.felix.scrplugin.description.PropertyDescription;
+import org.apache.felix.scrplugin.description.PropertyType;
+import org.apache.felix.scrplugin.description.ReferenceCardinality;
+import org.apache.felix.scrplugin.description.ReferenceDescription;
+import org.apache.felix.scrplugin.description.ReferencePolicy;
+import org.apache.felix.scrplugin.description.ReferenceStrategy;
+import org.apache.felix.scrplugin.description.ServiceDescription;
+import org.apache.felix.scrplugin.description.SpecVersion;
+import org.apache.felix.scrplugin.helper.IssueLog;
+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;
@@ -106,27 +130,28 @@
private static final String INTERFACE_QNAME = INTERFACE;
- public static Components read(InputStream file)
- throws SCRDescriptorException {
+ public static List<ClassDescription> read(final InputStream file,
+ final ClassLoader classLoader,
+ final IssueLog iLog, final String location) throws SCRDescriptorException {
try {
- final XmlHandler xmlHandler = new XmlHandler();
+ final XmlHandler xmlHandler = new XmlHandler(classLoader, iLog, location);
IOUtils.parse(file, xmlHandler);
return xmlHandler.components;
- } catch (TransformerException e) {
- throw new SCRDescriptorException( "Unable to read xml", "[stream]", 0, e );
+ } catch (final TransformerException e) {
+ throw new SCRDescriptorException("Unable to read xml", "[stream]", 0, e);
}
}
/**
* Write the component descriptors to the file.
+ *
* @param components
* @param file
* @throws SCRDescriptorException
*/
- public static void write(Components components, File file, boolean isScrPrivateFile)
- throws SCRDescriptorException {
+ public static void write(Components components, File file) throws SCRDescriptorException {
try {
- generateXML(components, IOUtils.getSerializer(file), isScrPrivateFile);
+ generateXML(components, IOUtils.getSerializer(file));
} catch (TransformerException e) {
throw new SCRDescriptorException("Unable to write xml", file.toString(), 0, e);
} catch (SAXException e) {
@@ -139,17 +164,17 @@
/**
* Generate the xml top level element and start streaming
* the components.
+ *
* @param components
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(Components components, ContentHandler contentHandler, boolean isScrPrivateFile)
- throws SAXException {
+ protected static void generateXML(Components components, ContentHandler contentHandler) throws SAXException {
// detect namespace to use
final String namespace;
- if ( components.getSpecVersion() == Constants.VERSION_1_0 ) {
+ if (components.getSpecVersion() == SpecVersion.VERSION_1_0) {
namespace = NAMESPACE_URI_1_0;
- } else if ( components.getSpecVersion() == Constants.VERSION_1_1 ) {
+ } else if (components.getSpecVersion() == SpecVersion.VERSION_1_1) {
namespace = NAMESPACE_URI_1_1;
} else {
namespace = NAMESPACE_URI_1_1_FELIX;
@@ -161,9 +186,9 @@
contentHandler.startElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS, new AttributesImpl());
IOUtils.newline(contentHandler);
- for(final Component component : components.getComponents()) {
- if ( component.isDs() ) {
- generateXML(namespace, component, contentHandler, isScrPrivateFile);
+ for (final Component component : components.getComponents()) {
+ if (component.isDs()) {
+ generateXML(namespace, component, contentHandler);
}
}
// end wrapper element
@@ -175,24 +200,24 @@
/**
* Write the xml for a {@link Component}.
+ *
* @param component
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(final String namespace,
- final Component component,
- final ContentHandler contentHandler,
- final boolean isScrPrivateFile)
- throws SAXException {
+ protected static void generateXML(final String namespace, final Component component, final ContentHandler contentHandler)
+ throws SAXException {
final AttributesImpl ai = new AttributesImpl();
IOUtils.addAttribute(ai, COMPONENT_ATTR_ENABLED, component.isEnabled());
- IOUtils.addAttribute(ai, COMPONENT_ATTR_IMMEDIATE,component.isImmediate());
+ IOUtils.addAttribute(ai, COMPONENT_ATTR_IMMEDIATE, component.isImmediate());
IOUtils.addAttribute(ai, COMPONENT_ATTR_NAME, component.getName());
IOUtils.addAttribute(ai, COMPONENT_ATTR_FACTORY, component.getFactory());
// attributes new in 1.1
- if ( NAMESPACE_URI_1_1.equals( namespace ) || NAMESPACE_URI_1_1_FELIX.equals( namespace ) ) {
- IOUtils.addAttribute(ai, COMPONENT_ATTR_POLICY, component.getConfigurationPolicy());
+ if (NAMESPACE_URI_1_1.equals(namespace) || NAMESPACE_URI_1_1_FELIX.equals(namespace)) {
+ if ( component.getConfigurationPolicy() != ComponentConfigurationPolicy.OPTIONAL ) {
+ IOUtils.addAttribute(ai, COMPONENT_ATTR_POLICY, component.getConfigurationPolicy().name());
+ }
IOUtils.addAttribute(ai, COMPONENT_ATTR_ACTIVATE, component.getActivate());
IOUtils.addAttribute(ai, COMPONENT_ATTR_DEACTIVATE, component.getDeactivate());
IOUtils.addAttribute(ai, COMPONENT_ATTR_MODIFIED, component.getModified());
@@ -202,17 +227,17 @@
contentHandler.startElement(namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME, ai);
IOUtils.newline(contentHandler);
generateXML(component.getImplementation(), contentHandler);
- if ( component.getService() != null ) {
+ if (component.getService() != null) {
generateXML(component.getService(), contentHandler);
}
- if ( component.getProperties() != null ) {
- for(final Property property : component.getProperties()) {
- generateXML(property, contentHandler, isScrPrivateFile);
+ if (component.getProperties() != null) {
+ for (final Property property : component.getProperties()) {
+ generateXML(property, contentHandler);
}
}
- if ( component.getReferences() != null ) {
- for(final Reference reference : component.getReferences()) {
- generateXML(namespace, reference, contentHandler, isScrPrivateFile);
+ if (component.getReferences() != null) {
+ for (final Reference reference : component.getReferences()) {
+ generateXML(namespace, reference, contentHandler);
}
}
IOUtils.indent(contentHandler, 1);
@@ -222,35 +247,37 @@
/**
* Write the xml for a {@link Implementation}.
+ *
* @param implementation
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(Implementation implementation, ContentHandler contentHandler)
- throws SAXException {
+ protected static void generateXML(Implementation implementation, ContentHandler contentHandler) throws SAXException {
final AttributesImpl ai = new AttributesImpl();
- IOUtils.addAttribute(ai, "class", implementation.getClassame());
+ IOUtils.addAttribute(ai, "class", implementation.getClassName());
IOUtils.indent(contentHandler, 2);
- contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION, ComponentDescriptorIO.IMPLEMENTATION_QNAME, ai);
- contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION, ComponentDescriptorIO.IMPLEMENTATION_QNAME);
+ contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION,
+ ComponentDescriptorIO.IMPLEMENTATION_QNAME, ai);
+ contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION,
+ ComponentDescriptorIO.IMPLEMENTATION_QNAME);
IOUtils.newline(contentHandler);
}
/**
* Write the xml for a {@link Service}.
+ *
* @param service
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(Service service, ContentHandler contentHandler)
- throws SAXException {
+ protected static void generateXML(Service service, ContentHandler contentHandler) throws SAXException {
final AttributesImpl ai = new AttributesImpl();
- IOUtils.addAttribute(ai, "servicefactory", String.valueOf(service.isServicefactory()));
+ IOUtils.addAttribute(ai, "servicefactory", String.valueOf(service.isServiceFactory()));
IOUtils.indent(contentHandler, 2);
contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.SERVICE, ComponentDescriptorIO.SERVICE_QNAME, ai);
- if ( service.getInterfaces() != null && service.getInterfaces().size() > 0 ) {
+ if (service.getInterfaces() != null && service.getInterfaces().size() > 0) {
IOUtils.newline(contentHandler);
- for(final Interface interf : service.getInterfaces()) {
+ for (final Interface interf : service.getInterfaces()) {
generateXML(interf, contentHandler);
}
IOUtils.indent(contentHandler, 2);
@@ -261,51 +288,40 @@
/**
* Write the xml for a {@link Interface}.
+ *
* @param interf
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(Interface interf, ContentHandler contentHandler)
- throws SAXException {
+ protected static void generateXML(Interface interf, ContentHandler contentHandler) throws SAXException {
final AttributesImpl ai = new AttributesImpl();
- IOUtils.addAttribute(ai, "interface", interf.getInterfacename());
+ IOUtils.addAttribute(ai, "interface", interf.getInterfaceName());
IOUtils.indent(contentHandler, 3);
- contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME, ai);
+ contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME,
+ ai);
contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME);
IOUtils.newline(contentHandler);
}
/**
* Write the xml for a {@link Property}.
+ *
* @param property
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(Property property, ContentHandler contentHandler, boolean isScrPrivateFile)
- throws SAXException {
+ protected static void generateXML(Property property, ContentHandler contentHandler) throws SAXException {
final AttributesImpl ai = new AttributesImpl();
IOUtils.addAttribute(ai, "name", property.getName());
IOUtils.addAttribute(ai, "type", property.getType());
IOUtils.addAttribute(ai, "value", property.getValue());
- // we have to write more information if this is our scr private file
- if ( isScrPrivateFile ) {
- IOUtils.addAttribute(ai, "private", String.valueOf(property.isPrivate()));
- if ( property.getLabel() != null ) {
- IOUtils.addAttribute(ai, "label", String.valueOf(property.getLabel()));
- }
- if ( property.getDescription() != null ) {
- IOUtils.addAttribute(ai, "description", String.valueOf(property.getDescription()));
- }
- if ( property.getCardinality() != null ) {
- IOUtils.addAttribute(ai, "cardinality", String.valueOf(property.getCardinality()));
- }
- }
+
IOUtils.indent(contentHandler, 2);
contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.PROPERTY, ComponentDescriptorIO.PROPERTY_QNAME, ai);
- if ( property.getMultiValue() != null && property.getMultiValue().length > 0 ) {
+ if (property.getMultiValue() != null && property.getMultiValue().length > 0) {
// generate a new line first
IOUtils.text(contentHandler, "\n");
- for(int i=0; i<property.getMultiValue().length; i++) {
+ for (int i = 0; i < property.getMultiValue().length; i++) {
IOUtils.indent(contentHandler, 3);
IOUtils.text(contentHandler, property.getMultiValue()[i]);
IOUtils.newline(contentHandler);
@@ -318,32 +334,30 @@
/**
* Write the xml for a {@link Reference}.
+ *
* @param reference
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(final String namespace,Reference reference, ContentHandler contentHandler, boolean isScrPrivateFile)
- throws SAXException {
+ protected static void generateXML(final String namespace, Reference reference, ContentHandler contentHandler)
+ throws SAXException {
final AttributesImpl ai = new AttributesImpl();
IOUtils.addAttribute(ai, "name", reference.getName());
IOUtils.addAttribute(ai, "interface", reference.getInterfacename());
- IOUtils.addAttribute(ai, "cardinality", reference.getCardinality());
- IOUtils.addAttribute(ai, "policy", reference.getPolicy());
+ IOUtils.addAttribute(ai, "cardinality", reference.getCardinality().getCardinalityString());
+ IOUtils.addAttribute(ai, "policy", reference.getPolicy().name());
IOUtils.addAttribute(ai, "target", reference.getTarget());
IOUtils.addAttribute(ai, "bind", reference.getBind());
IOUtils.addAttribute(ai, "unbind", reference.getUnbind());
// attributes new in 1.1-felix (FELIX-1893)
- if ( NAMESPACE_URI_1_1_FELIX.equals( namespace ) ) {
+ if (NAMESPACE_URI_1_1_FELIX.equals(namespace)) {
IOUtils.addAttribute(ai, "updated", reference.getUpdated());
}
- if ( isScrPrivateFile ) {
- IOUtils.addAttribute(ai, "checked", String.valueOf(reference.isChecked()));
- IOUtils.addAttribute(ai, "strategy", reference.getStrategy());
- }
IOUtils.indent(contentHandler, 2);
- contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME, ai);
+ contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME,
+ ai);
contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME);
IOUtils.newline(contentHandler);
}
@@ -355,120 +369,169 @@
protected static final class XmlHandler extends DefaultHandler {
/** The components container. */
- protected final Components components = new Components();
+ private final List<ClassDescription> components = new ArrayList<ClassDescription>();
+
+ /** Spec version. */
+ private SpecVersion specVersion;
+
+ /** A reference to the current class. */
+ private ClassDescription currentClass;
/** A reference to the current component. */
- protected Component currentComponent;
+ private ComponentDescription currentComponent;
/** The current service. */
- protected Service currentService;
+ private ServiceDescription currentService;
/** Pending property. */
- protected Property pendingProperty;
+ private PropertyDescription pendingProperty;
/** Flag for detecting the first element. */
- protected boolean firstElement = true;
+ private boolean firstElement = true;
/** Flag for elements inside a component element */
- protected boolean isComponent = false;
+ private boolean isComponent = false;
/** Override namespace. */
- protected String overrideNamespace;
+ private String overrideNamespace;
- public void startElement(String uri, String localName, String name, Attributes attributes)
+ /** The issue log. */
+ private final IssueLog iLog;
+
+ /** XML file location. */
+ private final String location;
+
+ /** Classloader. */
+ private final ClassLoader classLoader;
+
+ public XmlHandler(final ClassLoader classLoader, final IssueLog iLog, final String loc) {
+ this.iLog = iLog;
+ this.location = loc;
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+ */
+ public void startElement(String uri, final String localName, final String name, final Attributes attributes)
throws SAXException {
// according to the spec, the elements should have the namespace,
// except when the root element is the "component" element
// So we check this for the first element, we receive.
- if ( this.firstElement ) {
+ if (this.firstElement) {
this.firstElement = false;
- if ( localName.equals(COMPONENT) && "".equals(uri) ) {
+ if (localName.equals(COMPONENT) && "".equals(uri)) {
this.overrideNamespace = NAMESPACE_URI_1_0;
}
}
- if ( this.overrideNamespace != null && "".equals(uri) ) {
+ if (this.overrideNamespace != null && "".equals(uri)) {
uri = this.overrideNamespace;
}
// however the spec also states that the inner elements
// of a component are unqualified, so they don't have
// the namespace - we allow both: with or without namespace!
- if ( this.isComponent && "".equals(uri) ) {
+ if (this.isComponent && "".equals(uri)) {
uri = NAMESPACE_URI_1_0;
}
// from here on, uri has the namespace regardless of the used xml format
- if ( NAMESPACE_URI_1_0.equals( uri ) || NAMESPACE_URI_1_1.equals( uri )
- || NAMESPACE_URI_1_1_FELIX.equals( uri ) ) {
+ if (NAMESPACE_URI_1_0.equals(uri) || NAMESPACE_URI_1_1.equals(uri) || NAMESPACE_URI_1_1_FELIX.equals(uri)) {
- if ( NAMESPACE_URI_1_1.equals(uri) ) {
- components.setSpecVersion(Constants.VERSION_1_1);
- } else if ( NAMESPACE_URI_1_1_FELIX.equals(uri) ) {
- components.setSpecVersion(Constants.VERSION_1_1_FELIX);
+ if (NAMESPACE_URI_1_0.equals(uri)) {
+ specVersion = SpecVersion.VERSION_1_0;
+ } else if (NAMESPACE_URI_1_1.equals(uri)) {
+ specVersion = SpecVersion.VERSION_1_1;
+ } else if (NAMESPACE_URI_1_1_FELIX.equals(uri)) {
+ specVersion = SpecVersion.VERSION_1_1_FELIX;
}
if (localName.equals(COMPONENT)) {
this.isComponent = true;
- this.currentComponent = new Component();
- this.currentComponent.setName(attributes.getValue(COMPONENT_ATTR_NAME));
+ final ComponentDescription desc = new ComponentDescription(null);
+ desc.setName(attributes.getValue(COMPONENT_ATTR_NAME));
// enabled attribute is optional
if (attributes.getValue(COMPONENT_ATTR_ENABLED) != null) {
- this.currentComponent.setEnabled(Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_ENABLED)));
+ desc.setEnabled(Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_ENABLED)));
}
// immediate attribute is optional
if (attributes.getValue(COMPONENT_ATTR_IMMEDIATE) != null) {
- this.currentComponent.setImmediate(Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_IMMEDIATE)));
+ desc.setImmediate(Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_IMMEDIATE)));
}
- this.currentComponent.setFactory(attributes.getValue(COMPONENT_ATTR_FACTORY));
+ desc.setFactory(attributes.getValue(COMPONENT_ATTR_FACTORY));
+ desc.setConfigurationPolicy(ComponentConfigurationPolicy.OPTIONAL);
// check for version 1.1 attributes
- if ( components.getSpecVersion() == Constants.VERSION_1_1 ) {
- this.currentComponent.setConfigurationPolicy(attributes.getValue(COMPONENT_ATTR_POLICY));
- this.currentComponent.setActivate(attributes.getValue(COMPONENT_ATTR_ACTIVATE));
- this.currentComponent.setDeactivate(attributes.getValue(COMPONENT_ATTR_DEACTIVATE));
- this.currentComponent.setModified(attributes.getValue(COMPONENT_ATTR_MODIFIED));
+ if (specVersion == SpecVersion.VERSION_1_1
+ || specVersion == SpecVersion.VERSION_1_1_FELIX) {
+ final String policy = attributes.getValue(COMPONENT_ATTR_POLICY);
+ if ( policy != null ) {
+ try {
+ desc.setConfigurationPolicy(ComponentConfigurationPolicy.valueOf(policy));
+ } catch (final IllegalArgumentException iae) {
+ iLog.addWarning("Invalid value for attribute " + COMPONENT_ATTR_POLICY + " : " + policy, this.location);
+ }
+ }
+ if ( attributes.getValue(COMPONENT_ATTR_ACTIVATE) != null ) {
+ desc.setActivate(new MethodDescription(attributes.getValue(COMPONENT_ATTR_ACTIVATE)));
+ }
+ if ( attributes.getValue(COMPONENT_ATTR_DEACTIVATE) != null ) {
+ desc.setDeactivate(new MethodDescription(attributes.getValue(COMPONENT_ATTR_DEACTIVATE)));
+ }
+ if ( attributes.getValue(COMPONENT_ATTR_MODIFIED) != null ) {
+ desc.setModified(new MethodDescription(attributes.getValue(COMPONENT_ATTR_MODIFIED)));
+ }
}
} else if (localName.equals(IMPLEMENTATION)) {
+ // now we can create the class description and attach the component description
// Set the implementation class name (mandatory)
- final Implementation impl = new Implementation();
- this.currentComponent.setImplementation(impl);
- impl.setClassname(attributes.getValue("class"));
+ try {
+ this.currentClass = new ClassDescription(this.classLoader.loadClass(attributes.getValue("class")), null);
+ } catch (final ClassNotFoundException e) {
+ iLog.addError("Unable to load class " + attributes.getValue("class") + " from dependencies.", this.location);
+ }
+ this.currentClass.add(this.currentComponent);
} else if (localName.equals(PROPERTY)) {
// 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();
+ final String propName = attributes.getValue("name");
+ if (!org.osgi.framework.Constants.SERVICE_PID.equals(propName)) {
+ final PropertyDescription prop = new PropertyDescription(null);
- prop.setName( propName );
- prop.setType( attributes.getValue( "type" ) );
-
- if ( attributes.getValue( "value" ) != null )
- {
- prop.setValue( attributes.getValue( "value" ) );
- this.currentComponent.addProperty( prop );
+ prop.setName(propName);
+ final String type = attributes.getValue("type");
+ if ( type != null ) {
+ try {
+ prop.setType(PropertyType.valueOf(type));
+ } catch (final IllegalArgumentException iae) {
+ iLog.addWarning("Invalid value for attribute type : " + type, this.location);
+ }
}
- else
- {
+
+ if (attributes.getValue("value") != null) {
+ prop.setValue(attributes.getValue("value"));
+ this.currentClass.add(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.setLabel(attributes.getValue("label"));
+ prop.setDescription(attributes.getValue("description"));
+ final String cardinality = attributes.getValue("cardinality");
+ if ( cardinality != null ) {
+ prop.setCardinality(Integer.valueOf(cardinality));
+ }
+ final String pValue = attributes.getValue("private");
+ if (pValue != null) {
+ prop.setPrivate(Boolean.valueOf(pValue));
}
}
@@ -478,36 +541,54 @@
} else if (localName.equals(SERVICE)) {
- this.currentService = new Service();
+ this.currentService = new ServiceDescription(null);
+ this.currentClass.add(this.currentService);
- this.currentService.setServicefactory(attributes.getValue("servicefactory"));
-
- this.currentComponent.setService(this.currentService);
+ if (attributes.getValue("servicefactory") != null) {
+ this.currentService.setServiceFactory(Boolean.valueOf(attributes.getValue("servicefactory")));
+ }
} else if (localName.equals(INTERFACE)) {
- final Interface interf = new Interface();
- this.currentService.addInterface(interf);
- interf.setInterfacename(attributes.getValue("interface"));
+ this.currentService.addInterface(attributes.getValue("interface"));
} else if (localName.equals(REFERENCE)) {
- final Reference ref = new Reference();
+ final ReferenceDescription ref = new ReferenceDescription(null);
ref.setName(attributes.getValue("name"));
- ref.setInterfacename(attributes.getValue("interface"));
- ref.setCardinality(attributes.getValue("cardinality"));
- ref.setPolicy(attributes.getValue("policy"));
+ ref.setInterfaceName(attributes.getValue("interface"));
+ final String cardinality = attributes.getValue("cardinality");
+ if ( cardinality != null ) {
+ ref.setCardinality(ReferenceCardinality.fromValue(cardinality));
+ if ( ref.getCardinality() == null ) {
+ iLog.addWarning("Invalid value for attribute cardinality : " + cardinality, this.location);
+ }
+ }
+ final String policy = attributes.getValue("policy");
+ if ( policy != null ) {
+ try {
+ ref.setPolicy(ReferencePolicy.valueOf(policy));
+ } catch (final IllegalArgumentException iae) {
+ iLog.addWarning("Invalid value for attribute policy : " + policy, this.location);
+ }
+ }
ref.setTarget(attributes.getValue("target"));
- ref.setBind(attributes.getValue("bind"));
- ref.setUnbind(attributes.getValue("unbind"));
-
- if ( attributes.getValue("checked") != null ) {
- ref.setChecked(Boolean.valueOf(attributes.getValue("checked")).booleanValue());
+ if ( attributes.getValue("bind") != null ) {
+ ref.setBind(new MethodDescription(attributes.getValue("bind")));
}
- if ( attributes.getValue("strategy") != null ) {
- ref.setStrategy(attributes.getValue("strategy"));
+ if ( attributes.getValue("unbind") != null ) {
+ ref.setUnbind(new MethodDescription(attributes.getValue("unbind")));
}
- this.currentComponent.addReference(ref);
+ final String strategy = attributes.getValue("strategy");
+ if ( strategy != null ) {
+ try {
+ ref.setStrategy(ReferenceStrategy.valueOf(strategy));
+ } catch (final IllegalArgumentException iae) {
+ throw new SAXException("Invalid value for attribute strategy : " + strategy);
+ }
+ }
+
+ this.currentClass.add(ref);
}
}
}
@@ -516,35 +597,33 @@
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String name) throws SAXException {
- if ( this.overrideNamespace != null && "".equals(uri) ) {
+ if (this.overrideNamespace != null && "".equals(uri)) {
uri = this.overrideNamespace;
}
- if ( this.isComponent && "".equals(uri) ) {
+ if (this.isComponent && "".equals(uri)) {
uri = NAMESPACE_URI_1_0;
}
- if ( NAMESPACE_URI_1_0.equals( uri ) || NAMESPACE_URI_1_1.equals( uri )
- || NAMESPACE_URI_1_1_FELIX.equals( uri ) )
- {
- if (localName.equals(COMPONENT) ) {
- this.components.addComponent(this.currentComponent);
+ if (NAMESPACE_URI_1_0.equals(uri) || NAMESPACE_URI_1_1.equals(uri) || NAMESPACE_URI_1_1_FELIX.equals(uri)) {
+ if (localName.equals(COMPONENT)) {
+ this.currentClass = null;
this.currentComponent = null;
this.isComponent = false;
} else if (localName.equals(PROPERTY) && this.pendingProperty != null) {
// now split the value
final String text = this.pendingProperty.getValue();
- if ( text != null ) {
+ if (text != null) {
final StringTokenizer st = new StringTokenizer(text);
final String[] values = new String[st.countTokens()];
int index = 0;
- while ( st.hasMoreTokens() ) {
+ while (st.hasMoreTokens()) {
values[index] = st.nextToken();
index++;
}
this.pendingProperty.setMultiValue(values);
}
- this.currentComponent.addProperty(this.pendingProperty);
+ this.currentClass.add(this.pendingProperty);
this.pendingProperty = null;
}
}
@@ -554,9 +633,9 @@
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int length) throws SAXException {
- if ( this.pendingProperty != null ) {
+ if (this.pendingProperty != null) {
final String text = new String(ch, start, length);
- if ( this.pendingProperty.getValue() == null ) {
+ if (this.pendingProperty.getValue() == null) {
this.pendingProperty.setValue(text);
} else {
this.pendingProperty.setValue(this.pendingProperty.getValue() + text);