FELIX-2642 Implement Ant Task for DS and Metatype service
descriptor generation

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1025755 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/pom.xml b/scrplugin/pom.xml
index 8b383a9..0ea3fdf 100644
--- a/scrplugin/pom.xml
+++ b/scrplugin/pom.xml
@@ -49,18 +49,26 @@
             <artifactId>maven-plugin-api</artifactId>
             <version>2.0.7</version>
         </dependency>
-
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-archiver</artifactId>
             <version>2.2</version>
         </dependency>
+        
+        <!-- Ant Task Implementation -->
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.7.0</version>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- JavaDoc Tags -->
 		<dependency>
 			<groupId>com.thoughtworks.qdox</groupId>
 			<artifactId>qdox</artifactId>
 			<version>1.12</version>
+            <scope>provided</scope>
 		</dependency>
 
         <!-- SCR Annotations -->
@@ -68,42 +76,55 @@
 			<groupId>org.apache.felix</groupId>
 			<artifactId>org.apache.felix.scr.annotations</artifactId>
 			<version>1.3.1-SNAPSHOT</version>
+            <scope>provided</scope>
 		</dependency>
         
-        <!-- Sling Servlet SCR Annotation -->
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>servlet-api</artifactId>
-            <version>2.4</version>
-            <scope>compile</scope>
-        </dependency>
-
         <!-- bind/unbind method generation -->
         <dependency>
             <groupId>asm</groupId>
             <artifactId>asm-all</artifactId>
             <version>3.1</version>
+            <scope>provided</scope>
         </dependency>
 
-        <!-- OSGi APIs -->		
+        <!-- OSGi APIs (some constant references used only) -->		
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <version>4.0.0</version>           
-            <scope>compile</scope>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
             <version>4.0.0</version>
-            <scope>compile</scope>
+            <scope>provided</scope>
         </dependency>
 	</dependencies>
 	
 	<build>
 		<plugins>
+            <!-- unpack qdox, asm and annotations into bundle package -->
+            <plugin>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>unpack-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <includeArtifactIds>
+                                qdox,asm-all,org.apache.felix.scr.annotations
+                            </includeArtifactIds>
+                            <outputDirectory>
+                                ${project.build.outputDirectory}
+                            </outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
 
-		  <!-- JDK 1.5 needed for annotation support -->
+            <!-- JDK 1.5 needed for annotation support -->
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
@@ -112,8 +133,6 @@
 				  <target>1.5</target>
 				</configuration>
 			</plugin>
-			
 		</plugins>
   </build>
-	
 </project>
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
index f6e737a..8320269 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
@@ -1,26 +1,27 @@
 /*
- * 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.
+ * 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.io.FilterInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
 
 import org.apache.felix.scrplugin.om.Component;
 import org.apache.felix.scrplugin.om.Components;
@@ -30,7 +31,7 @@
 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;
 
@@ -55,7 +56,8 @@
     private final Map<String, JavaClassDescription> javaClassDescriptions = new HashMap<String, JavaClassDescription>();
 
     /**
-     * Supports mapping of built-in and custom java anntoations to {@link JavaTag} implementations.
+     * Supports mapping of built-in and custom java anntoations to
+     * {@link JavaTag} implementations.
      */
     private final AnnotationTagProviderManager annotationTagProviderManager;
 
@@ -65,13 +67,16 @@
     /** 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.
-     * @param log
-     * @param annotationTagProviders List of annotation tag providers
-     * @param parseJavadocs Should the javadocs be parsed?
-     * @param processAnnotations Should the annotations be processed?
+     *
      * @throws SCRDescriptorFailureException
      */
     public JavaClassDescriptorManager( final Log log, final ClassLoader classLoader,
@@ -83,29 +88,200 @@
         this.log = log;
         this.annotationTagProviderManager = new AnnotationTagProviderManager( annotationTagProviders );
         this.classloader = classLoader;
+
         ClassUtil.classLoader = this.classloader;
     }
 
 
     /**
-     * Returns the QDox JavaSource instances representing the source files
-     * for which the Declarative Services and Metatype descriptors have to be
+     * 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.
+     * @throws SCRDescriptorException May be thrown if an error occurrs
+     *             gathering the java sources.
      */
-    protected abstract JavaSource[] getSources() throws SCRDescriptorException;
+    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.
+     * @throws SCRDescriptorException May be thrown if an error occurrs
+     *             gethering the component descriptors.
      */
-    protected abstract Map<String, Component> getComponentDescriptors() throws SCRDescriptorException;
+    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();
+    }
 
 
     /**
@@ -167,12 +343,12 @@
 
 
     /**
-     * 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.
+     * 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.
+     * @throws SCRDescriptorException If an error occurrs reading the
+     *             descriptors from the stream.
      */
     protected Components parseServiceComponentDescriptor( InputStream file ) throws SCRDescriptorException
     {
@@ -182,6 +358,7 @@
 
     /**
      * Return all source descriptions of this project.
+     *
      * @return All contained java class descriptions.
      */
     public JavaClassDescription[] getSourceDescriptions() throws SCRDescriptorException
@@ -198,6 +375,7 @@
 
     /**
      * Get a java class description for the class.
+     *
      * @param className
      * @return The java class description.
      * @throws SCRDescriptorException
@@ -217,7 +395,8 @@
                 {
                     try
                     {
-                        // check for java annotation descriptions - fallback to QDox if none found
+                        // check for java annotation descriptions - fallback to
+                        // QDox if none found
                         Class<?> clazz = this.classloader.loadClass( className );
                         if ( this.processAnnotations
                             && getAnnotationTagProviderManager().hasScrPluginAnnotation( javaClass ) )
@@ -251,7 +430,7 @@
                 }
                 catch ( ClassNotFoundException e )
                 {
-                    throw new SCRDescriptorException( "Unable to load class", className, 0);
+                    throw new SCRDescriptorException( "Unable to load class", className, 0 );
                 }
             }
             this.javaClassDescriptions.put( className, result );
@@ -261,7 +440,9 @@
 
 
     /**
-     * Get a list of all {@link JavaClass} definitions four all source files (including nested/inner classes)
+     * 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
@@ -270,7 +451,7 @@
         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)
+            if ( sources[i].getClasses() == null || sources[i].getClasses().length == 0 )
             {
                 continue;
             }
@@ -288,4 +469,148 @@
         return classes.toArray( new JavaClass[classes.size()] );
     }
 
+
+    /**
+     * Read the service component description.
+     *
+     * @param artifact
+     * @param entry
+     * @throws IOException
+     * @throws SCRDescriptorException
+     */
+    private Components readServiceComponentDescriptor( File jarFile, String entry )
+    {
+        this.log.debug( "Reading " + entry + " from " + jarFile );
+        InputStream xml = null;
+        try
+        {
+            xml = this.getFile( jarFile, entry );
+            if ( xml == null )
+            {
+                throw new SCRDescriptorException( "Entry " + entry + " not contained in JAR File ", jarFile.toString(),
+                    0 );
+            }
+            return this.parseServiceComponentDescriptor( xml );
+        }
+        catch ( IOException mee )
+        {
+            this.log.warn( "Unable to read SCR descriptor file from JAR File " + jarFile + " 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 " + jarFile + " 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
+    {
+        JarFile file = null;
+        try
+        {
+            file = new JarFile( artifact );
+            return file.getManifest();
+        }
+        finally
+        {
+            if ( file != null )
+            {
+                try
+                {
+                    file.close();
+                }
+                catch ( IOException ignore )
+                {
+                }
+            }
+        }
+    }
+
+
+    private InputStream getFile( File jarFile, String path ) throws IOException
+    {
+        JarFile file = null;
+        try
+        {
+            file = new JarFile( jarFile );
+            final JarEntry entry = file.getJarEntry( path );
+            if ( entry != null )
+            {
+                final InputStream stream = new ArtifactFileInputStream( file, entry );
+                file = null; // prevent file from being closed now
+                return stream;
+            }
+            return null;
+        }
+        finally
+        {
+            if ( file != null )
+            {
+                try
+                {
+                    file.close();
+                }
+                catch ( IOException ignore )
+                {
+                }
+            }
+        }
+    }
+
+    private static class ArtifactFileInputStream extends FilterInputStream
+    {
+        final JarFile jarFile;
+
+
+        ArtifactFileInputStream( JarFile jarFile, JarEntry jarEntry ) throws IOException
+        {
+            super( jarFile.getInputStream( jarEntry ) );
+            this.jarFile = jarFile;
+        }
+
+
+        @Override
+        public void close() throws IOException
+        {
+            try
+            {
+                super.close();
+            }
+            catch ( IOException ioe )
+            {
+            }
+            jarFile.close();
+        }
+
+
+        @Override
+        protected void finalize() throws Throwable
+        {
+            try
+            {
+                close();
+            }
+            finally
+            {
+                super.finalize();
+            }
+        }
+    }
+
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/AntJavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/AntJavaClassDescriptorManager.java
new file mode 100644
index 0000000..f79059e
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/AntJavaClassDescriptorManager.java
@@ -0,0 +1,125 @@
+/*
+ * 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.ant;
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.felix.scrplugin.JavaClassDescriptorManager;
+import org.apache.felix.scrplugin.Log;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.FileResource;
+
+
+public class AntJavaClassDescriptorManager extends JavaClassDescriptorManager
+{
+
+    private final FileSet sourceFiles;
+
+    private final String classesDirectory;
+
+    private final Path classPath;
+
+
+    public AntJavaClassDescriptorManager( Log log, ClassLoader classLoader, FileSet sourceFiles, File classesDirectory,
+        Path classPath, String[] annotationTagProviders, boolean parseJavadocs, boolean processAnnotations )
+        throws SCRDescriptorFailureException
+    {
+        super( log, classLoader, annotationTagProviders, parseJavadocs, processAnnotations );
+        this.sourceFiles = sourceFiles;
+        this.classesDirectory = classesDirectory.getAbsolutePath();
+        this.classPath = classPath;
+    }
+
+
+    @Override
+    protected Iterator<File> getSourceFiles()
+    {
+        @SuppressWarnings("unchecked")
+        final Iterator<Resource> resources = sourceFiles.iterator();
+        return new Iterator<File>()
+        {
+            File next = seek();
+
+
+            public boolean hasNext()
+            {
+                return next != null;
+            }
+
+
+            public File next()
+            {
+                if ( !hasNext() )
+                {
+                    throw new NoSuchElementException();
+                }
+                File result = next;
+                next = seek();
+                return result;
+            }
+
+
+            public void remove()
+            {
+                throw new UnsupportedOperationException( "remove" );
+            }
+
+
+            private File seek()
+            {
+                while ( resources.hasNext() )
+                {
+                    Resource r = resources.next();
+                    if ( r instanceof FileResource )
+                    {
+                        return ( ( FileResource ) r ).getFile();
+                    }
+                }
+                return null;
+            }
+        };
+    }
+
+
+    @Override
+    protected List<File> getDependencies()
+    {
+        ArrayList<File> files = new ArrayList<File>();
+        for ( String entry : classPath.list() )
+        {
+            File file = new File( entry );
+            if ( file.isFile() )
+            {
+                files.add( file );
+            }
+        }
+        return files;
+    }
+
+
+    @Override
+    public String getOutputDirectory()
+    {
+        return classesDirectory;
+    }
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/AntLog.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/AntLog.java
new file mode 100644
index 0000000..605e75a
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/AntLog.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.ant;
+
+
+import org.apache.felix.scrplugin.Log;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+
+
+public class AntLog implements Log
+{
+
+    private final Task task;
+
+
+    AntLog( final Task task )
+    {
+        this.task = task;
+    }
+
+
+    public boolean isDebugEnabled()
+    {
+        // cannot tell, assume yes
+        return true;
+    }
+
+
+    public void debug( String content )
+    {
+        task.log( content, Project.MSG_DEBUG );
+    }
+
+
+    public void debug( String content, Throwable error )
+    {
+        task.log( content, error, Project.MSG_DEBUG );
+    }
+
+
+    public void debug( Throwable error )
+    {
+        task.log( error, Project.MSG_DEBUG );
+    }
+
+
+    public boolean isInfoEnabled()
+    {
+        // cannot tell, assume yes
+        return true;
+    }
+
+
+    public void info( String content )
+    {
+        task.log( content, Project.MSG_INFO );
+    }
+
+
+    public void info( String content, Throwable error )
+    {
+        task.log( content, error, Project.MSG_INFO );
+    }
+
+
+    public void info( Throwable error )
+    {
+        task.log( error, Project.MSG_INFO );
+    }
+
+
+    public boolean isWarnEnabled()
+    {
+        // cannot tell, assume yes
+        return true;
+    }
+
+
+    public void warn( String content )
+    {
+        task.log( content, Project.MSG_WARN );
+    }
+
+
+    public void warn( String content, String location, int lineNumber )
+    {
+        warn( String.format( "%s [%s,%d]", content, location, lineNumber ) );
+    }
+
+
+    public void warn( String content, Throwable error )
+    {
+        task.log( content, error, Project.MSG_WARN );
+    }
+
+
+    public void warn( Throwable error )
+    {
+        task.log( error, Project.MSG_WARN );
+    }
+
+
+    public boolean isErrorEnabled()
+    {
+        // cannot tell, assume yes
+        return true;
+    }
+
+
+    public void error( String content )
+    {
+        task.log( content, Project.MSG_ERR );
+    }
+
+
+    public void error( String content, String location, int lineNumber )
+    {
+        error( String.format( "%s [%s,%d]", content, location, lineNumber ) );
+    }
+
+
+    public void error( String content, Throwable error )
+    {
+        task.log( content, error, Project.MSG_ERR );
+    }
+
+
+    public void error( Throwable error )
+    {
+        task.log( error, Project.MSG_ERR );
+    }
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/SCRDescriptorTask.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/SCRDescriptorTask.java
new file mode 100644
index 0000000..82f8c46
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/ant/SCRDescriptorTask.java
@@ -0,0 +1,252 @@
+/*
+ * 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.ant;
+
+
+import java.io.File;
+import java.util.*;
+
+import org.apache.felix.scrplugin.*;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.MatchingTask;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+
+
+/**
+ * The <code>SCRDescriptorTask</code> generates a service descriptor file based
+ * on annotations found in the sources.
+ */
+public class SCRDescriptorTask extends MatchingTask
+{
+
+    private File destdir;
+
+    private Path classpath;
+
+    /**
+     * Name of the generated descriptor.
+     */
+    private String finalName = "serviceComponents.xml";
+
+    /**
+     * Name of the generated meta type file.
+     */
+    private String metaTypeName = "metatype.xml";
+
+    /**
+     * This flag controls the generation of the bind/unbind methods.
+     */
+    private boolean generateAccessors = true;
+
+    /**
+     * This flag controls whether the javadoc source code will be scanned for
+     * tags.
+     */
+    protected boolean parseJavadoc = true;
+
+    /**
+     * This flag controls whether the annotations in the sources will be
+     * processed.
+     */
+    protected boolean processAnnotations = true;
+
+    /**
+     * In strict mode the plugin even fails on warnings.
+     */
+    protected boolean strictMode = false;
+
+    /**
+     * Allows to define additional implementations of the interface
+     * {@link org.apache.felix.scrplugin.tags.annotation.AnnotationTagProvider}
+     * that provide mappings from custom annotations to
+     * {@link org.apache.felix.scrplugin.tags.JavaTag} implementations. List of
+     * full qualified class file names.
+     *
+     * @parameter
+     */
+    private String[] annotationTagProviders = {};
+
+    /**
+     * The version of the DS spec this plugin generates a descriptor for. By
+     * default the version is detected by the used tags.
+     *
+     * @parameter
+     */
+    private String specVersion;
+
+
+    @Override
+    public void execute() throws BuildException
+    {
+
+        // ensure we know the source
+        if (getImplicitFileSet().getDir() == null) {
+            throw new BuildException( "srcdir attribute must be set!", getLocation());
+        }
+
+        // while debugging
+        final org.apache.felix.scrplugin.Log scrLog = new AntLog( this );
+
+        scrLog.debug( "SCRDescriptorTask Configuration" );
+        scrLog.debug( "  implicitFileset: " + getImplicitFileSet() );
+        scrLog.debug( "  outputDirectory: " + destdir );
+        scrLog.debug( "  classpath: " + classpath );
+        scrLog.debug( "  finalName: " + finalName );
+        scrLog.debug( "  metaTypeName: " + metaTypeName );
+        scrLog.debug( "  generateAccessors: " + generateAccessors );
+        scrLog.debug( "  parseJavadoc: " + parseJavadoc );
+        scrLog.debug( "  processAnnotations: " + processAnnotations );
+        scrLog.debug( "  strictMode: " + strictMode );
+        scrLog.debug( "  specVersion: " + specVersion );
+
+        try
+        {
+            final ClassLoader classLoader = getClassLoader( this.getClass().getClassLoader() );
+            final JavaClassDescriptorManager jManager = new AntJavaClassDescriptorManager( scrLog, classLoader,
+                getImplicitFileSet(), destdir, createClasspath(), this.annotationTagProviders, this.parseJavadoc, this.processAnnotations );
+
+            final SCRDescriptorGenerator generator = new SCRDescriptorGenerator( scrLog );
+
+            // setup from plugin configuration
+            generator.setOutputDirectory( destdir );
+            generator.setDescriptorManager( jManager );
+            generator.setFinalName( finalName );
+            generator.setMetaTypeName( metaTypeName );
+            generator.setGenerateAccessors( generateAccessors );
+            generator.setStrictMode( strictMode );
+            generator.setProperties( new HashMap<String, String>() );
+            generator.setSpecVersion( specVersion );
+
+            generator.execute();
+        }
+        catch ( SCRDescriptorException sde )
+        {
+            if ( sde.getSourceLocation() != null )
+            {
+                Location loc = new Location( sde.getSourceLocation(), sde.getLineNumber(), 0 );
+                throw new BuildException( sde.getMessage(), sde.getCause(), loc );
+            }
+            throw new BuildException( sde.getMessage(), sde.getCause() );
+        }
+        catch ( SCRDescriptorFailureException sdfe )
+        {
+            throw new BuildException( sdfe.getMessage(), sdfe.getCause() );
+        }
+    }
+
+
+    private ClassLoader getClassLoader( final ClassLoader parent ) throws BuildException
+    {
+        Path classPath = createClasspath();
+        log( "Using classes from: " + classPath, Project.MSG_DEBUG );
+        return getProject().createClassLoader( parent, classpath );
+    }
+
+
+    // ---------- setters for configuration fields
+
+    public Path createClasspath()
+    {
+        if ( this.classpath == null )
+        {
+            this.classpath = new Path( getProject() );
+        }
+        return this.classpath;
+    }
+
+
+    public void setClasspath( Path classPath )
+    {
+        createClasspath().add( classPath );
+    }
+
+
+    public void setClasspathRef( Reference classpathRef )
+    {
+        if ( classpathRef != null && classpathRef.getReferencedObject() instanceof Path )
+        {
+            createClasspath().add( ( Path ) classpathRef.getReferencedObject() );
+        }
+    }
+
+
+    public void setSrcdir( File srcdir )
+    {
+        getImplicitFileSet().setDir( srcdir );
+    }
+
+
+    public void setDestdir( File outputDirectory )
+    {
+        this.destdir = outputDirectory;
+        if ( destdir != null )
+        {
+            Path dst = new Path( getProject() );
+            dst.setLocation( destdir );
+            createClasspath().add( dst );
+        }
+    }
+
+
+    public void setFinalName( String finalName )
+    {
+        this.finalName = finalName;
+    }
+
+
+    public void setMetaTypeName( String metaTypeName )
+    {
+        this.metaTypeName = metaTypeName;
+    }
+
+
+    public void setGenerateAccessors( boolean generateAccessors )
+    {
+        this.generateAccessors = generateAccessors;
+    }
+
+
+    public void setParseJavadoc( boolean parseJavadoc )
+    {
+        this.parseJavadoc = parseJavadoc;
+    }
+
+
+    public void setProcessAnnotations( boolean processAnnotations )
+    {
+        this.processAnnotations = processAnnotations;
+    }
+
+
+    public void setStrictMode( boolean strictMode )
+    {
+        this.strictMode = strictMode;
+    }
+
+
+    public void setAnnotationTagProviders( String[] annotationTagProviders )
+    {
+        this.annotationTagProviders = annotationTagProviders;
+    }
+
+
+    public void setSpecVersion( String specVersion )
+    {
+        this.specVersion = specVersion;
+    }
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
index c7df967..63fd4c0 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
@@ -21,20 +21,15 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.jar.*;
 
 import org.apache.felix.scrplugin.*;
 import org.apache.felix.scrplugin.helper.StringUtils;
 import org.apache.felix.scrplugin.om.Component;
-import org.apache.felix.scrplugin.om.Components;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.util.DirectoryScanner;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
-import com.thoughtworks.qdox.model.JavaSource;
-
 
 public class MavenJavaClassDescriptorManager extends JavaClassDescriptorManager
 {
@@ -43,8 +38,6 @@
 
     private final String excludeString;
 
-    private JavaSource[] sources;
-
     /** The component definitions from other bundles hashed by classname. */
     private Map<String, Component> componentDescriptions;
 
@@ -66,210 +59,96 @@
     }
 
 
-    protected JavaSource[] getSources() throws SCRDescriptorException
+    @Override
+    protected Iterator<File> getSourceFiles()
     {
-        if ( this.sources == null )
+        ArrayList<File> files = new ArrayList<File>();
+
+        @SuppressWarnings("unchecked")
+        final Iterator<String> i = project.getCompileSourceRoots().iterator();
+
+        // FELIX-509: check for excludes
+        final String[] includes = new String[] { "**/*.java" };
+        final String[] excludes;
+        if ( excludeString != null )
         {
-
-            this.log.debug( "Setting up QDox" );
-
-            JavaDocBuilder builder = new JavaDocBuilder();
-            builder.getClassLibrary().addClassLoader( this.getClassLoader() );
-
-            @SuppressWarnings("unchecked")
-            final Iterator<String> i = project.getCompileSourceRoots().iterator();
-            // FELIX-509: check for excludes
-            if ( excludeString != null )
-            {
-                final String[] excludes = StringUtils.split( excludeString, "," );
-                final String[] includes = new String[]
-                    { "**/*.java" };
-
-                while ( i.hasNext() )
-                {
-                    final String tree = i.next();
-                    this.log.debug( "Scanning source tree " + tree );
-                    final File directory = new File( tree );
-                    final DirectoryScanner scanner = new DirectoryScanner();
-                    scanner.setBasedir( directory );
-
-                    if ( excludes != null && excludes.length > 0 )
-                    {
-                        scanner.setExcludes( excludes );
-                    }
-                    scanner.addDefaultExcludes();
-                    scanner.setIncludes( includes );
-
-                    scanner.scan();
-
-                    final String[] files = scanner.getIncludedFiles();
-                    if ( files != null )
-                    {
-                        for ( int m = 0; m < files.length; m++ )
-                        {
-                            this.log.debug( "Adding source file " + files[m] );
-                            try
-                            {
-                                builder.addSource( new File( directory, files[m] ) );
-                            }
-                            catch ( FileNotFoundException e )
-                            {
-                                throw new SCRDescriptorException( "Unable to scan directory.", files[m], 0, e );
-                            }
-                            catch ( IOException e )
-                            {
-                                throw new SCRDescriptorException( "Unable to scan directory.", files[m], 0, e );
-                            }
-                        }
-                    }
-                }
-            }
-            else
-            {
-                while ( i.hasNext() )
-                {
-                    final String tree = i.next();
-                    this.log.debug( "Adding source tree " + tree );
-                    final File directory = new File( tree );
-                    builder.addSourceTree( directory );
-                }
-            }
-            this.sources = builder.getSources();
+            excludes = StringUtils.split( excludeString, "," );
+        }
+        else
+        {
+            excludes = null;
         }
 
-        return this.sources;
+        while ( i.hasNext() )
+        {
+            final String tree = i.next();
+            this.log.debug( "Scanning source tree " + tree );
+            final File directory = new File( tree );
+            final DirectoryScanner scanner = new DirectoryScanner();
+            scanner.setBasedir( directory );
+
+            if ( excludes != null && excludes.length > 0 )
+            {
+                scanner.setExcludes( excludes );
+            }
+            scanner.addDefaultExcludes();
+            scanner.setIncludes( includes );
+
+            scanner.scan();
+
+            for ( String fileName : scanner.getIncludedFiles() )
+            {
+                files.add( new File( directory, fileName ) );
+
+            }
+        }
+
+        return files.iterator();
     }
 
 
-    protected Map<String, Component> getComponentDescriptors() throws SCRDescriptorException
+    @Override
+    protected List<File> getDependencies()
     {
-        if ( this.componentDescriptions == null )
-        {
-            this.componentDescriptions = new HashMap<String, Component>();
+        ArrayList<File> dependencies = new ArrayList<File>();
 
-            // and now scan artifacts
-            final List<Component> components = new ArrayList<Component>();
-            @SuppressWarnings("unchecked")
-            final Map<String, Artifact> resolved = project.getArtifactMap();
-            final Iterator<Artifact> it = resolved.values().iterator();
-            while ( it.hasNext() )
+        @SuppressWarnings("unchecked")
+        final Map<String, Artifact> resolved = project.getArtifactMap();
+        final Iterator<Artifact> it = resolved.values().iterator();
+        while ( it.hasNext() )
+        {
+            final Artifact declared = it.next();
+            this.log.debug( "Checking artifact " + declared );
+            if ( this.isJavaArtifact( declared ) )
             {
-                final Artifact declared = it.next();
-                this.log.debug( "Checking artifact " + declared );
-                if ( this.isJavaArtifact( declared ) )
+                if ( Artifact.SCOPE_COMPILE.equals( declared.getScope() )
+                    || Artifact.SCOPE_RUNTIME.equals( declared.getScope() )
+                    || Artifact.SCOPE_PROVIDED.equals( declared.getScope() ) )
                 {
-                    if ( Artifact.SCOPE_COMPILE.equals( declared.getScope() )
-                        || Artifact.SCOPE_RUNTIME.equals( declared.getScope() )
-                        || Artifact.SCOPE_PROVIDED.equals( declared.getScope() ) )
+                    this.log.debug( "Resolving artifact " + declared );
+                    final Artifact artifact = resolved.get( ArtifactUtils.versionlessKey( declared ) );
+                    if ( artifact != null )
                     {
-                        this.log.debug( "Resolving artifact " + declared );
-                        final Artifact artifact = resolved.get( ArtifactUtils.versionlessKey( declared ) );
-                        if ( artifact != null )
-                        {
-                            this.log.debug( "Trying to get manifest from artifact " + artifact );
-                            try
-                            {
-                                final Manifest manifest = this.getManifest( artifact );
-                                if ( manifest != null )
-                                {
-                                    // read Service-Component entry
-                                    if ( manifest.getMainAttributes().getValue( Constants.SERVICE_COMPONENT ) != null )
-                                    {
-                                        final String serviceComponent = manifest.getMainAttributes().getValue(
-                                            Constants.SERVICE_COMPONENT );
-                                        this.log.debug( "Found Service-Component: " + serviceComponent
-                                            + " in artifact " + artifact );
-                                        final StringTokenizer st = new StringTokenizer( serviceComponent, "," );
-                                        while ( st.hasMoreTokens() )
-                                        {
-                                            final String entry = st.nextToken().trim();
-                                            if ( entry.length() > 0 )
-                                            {
-                                                final Components c = this.readServiceComponentDescriptor( artifact,
-                                                    entry );
-                                                if ( c != null )
-                                                {
-                                                    components.addAll( c.getComponents() );
-                                                }
-                                            }
-                                        }
-                                    }
-                                    else
-                                    {
-                                        this.log.debug( "Artifact has no service component entry in manifest "
-                                            + artifact );
-                                    }
-                                }
-                                else
-                                {
-                                    this.log.debug( "Unable to get manifest from artifact " + artifact );
-                                }
-                            }
-                            catch ( IOException ioe )
-                            {
-                                throw new SCRDescriptorException( "Unable to get manifest from artifact", artifact
-                                    .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 )
-                                    {
-                                    }
-                                }
-                            }
-                        }
-                        else
-                        {
-                            this.log.debug( "Unable to resolve artifact " + declared );
-                        }
+                        dependencies.add( artifact.getFile() );
                     }
                     else
                     {
-                        this.log.debug( "Artifact " + declared + " has not scope compile or runtime, but "
-                            + declared.getScope() );
+                        this.log.debug( "Unable to resolve artifact " + declared );
                     }
                 }
                 else
                 {
-                    this.log.debug( "Artifact " + declared + " is not a java artifact, type is " + declared.getType() );
+                    this.log.debug( "Artifact " + declared + " has not scope compile or runtime, but "
+                        + declared.getScope() );
                 }
             }
-            // now create map with component descriptions
-            for ( final Component component : components )
+            else
             {
-                this.componentDescriptions.put( component.getImplementation().getClassame(), component );
+                this.log.debug( "Artifact " + declared + " is not a java artifact, type is " + declared.getType() );
             }
         }
 
-        return this.componentDescriptions;
+        return dependencies;
     }
 
 
@@ -289,119 +168,4 @@
         return false;
     }
 
-    /**
-     * Read the service component description.
-     * @param artifact
-     * @param entry
-     * @throws IOException
-     * @throws SCRDescriptorException
-     */
-    protected Components readServiceComponentDescriptor(Artifact artifact, String entry) {
-        this.log.debug("Reading " + entry + " from " + artifact);
-        InputStream xml = null;
-        try {
-            xml = this.getFile(artifact, entry);
-            if ( xml == null ) {
-                throw new SCRDescriptorException( "Entry " + entry + " not contained in artifact", artifact.toString(),
-                    0 );
-            }
-            return this.parseServiceComponentDescriptor(xml);
-        } catch (IOException mee) {
-            this.log.warn("Unable to read SCR descriptor file from artifact " + artifact + " at " + entry);
-            this.log.debug("Exception occurred during reading: " + mee.getMessage(), mee);
-        } catch (SCRDescriptorException mee) {
-            this.log.warn("Unable to read SCR descriptor file from artifact " + artifact + " at " + entry);
-            this.log.debug("Exception occurred during reading: " + mee.getMessage(), mee);
-        }
-        finally
-        {
-            if ( xml != null )
-            {
-                try
-                {
-                    xml.close();
-                }
-                catch ( IOException ignore )
-                {
-                }
-            }
-        }
-       return null;
-    }
-
-    protected Manifest getManifest(Artifact artifact) throws IOException {
-        JarFile file = null;
-        try {
-            file = new JarFile(artifact.getFile());
-            return file.getManifest();
-        } finally {
-            if (file != null) {
-                try {
-                    file.close();
-                } catch (IOException ignore) {
-                }
-            }
-        }
-    }
-
-    protected InputStream getFile(Artifact artifact, String path) throws IOException {
-        JarFile file = null;
-        try {
-            file = new JarFile(artifact.getFile());
-            final JarEntry entry = file.getJarEntry(path);
-            if ( entry != null ) {
-                final InputStream stream = new ArtifactFileInputStream( file, entry);
-                file = null; // prevent file from being closed now
-                return stream;
-            }
-            return null;
-        } finally {
-            if (file != null) {
-                try {
-                    file.close();
-                } catch (IOException ignore) {
-                }
-            }
-        }
-    }
-
-    private static class ArtifactFileInputStream extends FilterInputStream
-    {
-        final JarFile jarFile;
-
-
-        ArtifactFileInputStream( JarFile jarFile, JarEntry jarEntry ) throws IOException
-        {
-            super( jarFile.getInputStream( jarEntry ) );
-            this.jarFile = jarFile;
-        }
-
-
-        @Override
-        public void close() throws IOException
-        {
-            try
-            {
-                super.close();
-            }
-            catch ( IOException ioe )
-            {
-            }
-            jarFile.close();
-        }
-
-
-        @Override
-        protected void finalize() throws Throwable
-        {
-            try
-            {
-                close();
-            }
-            finally
-            {
-                super.finalize();
-            }
-        }
-    }
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingFilterServiceTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingFilterServiceTag.java
index a1f963b..efe63e0 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingFilterServiceTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingFilterServiceTag.java
@@ -21,7 +21,6 @@
 import java.util.Collections;
 import java.util.Map;
 
-import javax.servlet.Filter;
 
 import org.apache.felix.scrplugin.Constants;
 import org.apache.felix.scrplugin.tags.JavaClassDescription;
@@ -35,7 +34,7 @@
 public class SlingFilterServiceTag extends AbstractTag {
 
     private static final Map<String, String> INTERFACE_MAP =
-        Collections.singletonMap(Constants.SERVICE_INTERFACE, Filter.class.getName());
+        Collections.singletonMap(Constants.SERVICE_INTERFACE, "javax.servlet.Filter");
 
     /**
      * @param desc Description
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
index 34e871c..3ad2181 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
@@ -21,8 +21,6 @@
 import java.util.Collections;
 import java.util.Map;
 
-import javax.servlet.Servlet;
-
 import org.apache.felix.scrplugin.Constants;
 import org.apache.felix.scrplugin.tags.JavaClassDescription;
 import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
@@ -35,7 +33,7 @@
 public class SlingServletServiceTag extends AbstractTag {
 
     private static final Map<String, String> INTERFACE_MAP =
-        Collections.singletonMap(Constants.SERVICE_INTERFACE, Servlet.class.getName());
+        Collections.singletonMap(Constants.SERVICE_INTERFACE, "javax.servlet.Servlet");
 
     /**
      * @param desc Description
diff --git a/scrplugin/src/main/resources/scrtask.properties b/scrplugin/src/main/resources/scrtask.properties
new file mode 100644
index 0000000..d2b975f
--- /dev/null
+++ b/scrplugin/src/main/resources/scrtask.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+
+# Define the ANT Tasks provided in this library
+scr=org.apache.felix.scrplugin.ant.SCRDescriptorTask
\ No newline at end of file