FELIX-1056 : Add annoations for Sling servlet components. Apply patch from Stefan Seifert.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@776199 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Property.java b/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Property.java
index c4a7910..62630ad 100644
--- a/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Property.java
+++ b/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Property.java
@@ -63,63 +63,63 @@
      * This attribute should not be used in combination with any of the other
      * value attributes.
      */
-    String[] value() default "";
+    String[] value() default {};
 
     /**
      * The long value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    long[] longValue() default 0;
+    long[] longValue() default {};
 
     /**
      * The double value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes.
      */
-    double[] doubleValue() default 0.0;
+    double[] doubleValue() default {};
 
     /**
      * The float value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    float[] floatValue() default 0;
+    float[] floatValue() default {};
 
     /**
      * The int value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    int[] intValue() default 0;
+    int[] intValue() default {};
 
     /**
      * The byte value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    byte[] byteValue() default 0;
+    byte[] byteValue() default {};
 
     /**
      * The char value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    char[] charValue() default '\0';
+    char[] charValue() default {};
 
     /**
      * The bool value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    boolean[] boolValue() default false;
+    boolean[] boolValue() default {};
 
     /**
      * The short value(s) of the property.
      * This attribute should not be used in combination with any of the other
      * value attributes or the type attribute.
      */
-    short[] shortValue() default 0;
+    short[] shortValue() default {};
 
     /**
      * Defines the cardinality of the property and its collection type. If the
diff --git a/scr-annotations/src/main/java/org/apache/felix/scr/annotations/sling/SlingServlet.java b/scr-annotations/src/main/java/org/apache/felix/scr/annotations/sling/SlingServlet.java
new file mode 100644
index 0000000..67f7de0
--- /dev/null
+++ b/scr-annotations/src/main/java/org/apache/felix/scr/annotations/sling/SlingServlet.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.annotations.sling;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks servlet classes as felix SCR component, and allows to configure sling
+ * resource resolving mapping.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+@Documented
+public @interface SlingServlet {
+
+    /**
+     * Whether to generate a default SCR component tag with "immediate=true". If
+     * set to false, a {@link org.apache.felix.scr.annotations.Component}
+     * annotation can be added manually with defined whatever configuration
+     * needed.
+     */
+    boolean generateComponent() default true;
+
+    /**
+     * Whether to generate a default SCR service tag with with
+     * "interface=javax.servlet.Servlet". If set to false, a
+     * {@link org.apache.felix.scr.annotations.Service} annotation can be added
+     * manually with defined whatever configuration needed.
+     */
+    boolean generateService() default true;
+
+    /**
+     * The name of the service registration property of a Servlet registered as
+     * a service providing the absolute paths under which the servlet is
+     * accessible as a Resource (value is "sling.servlet.paths")
+     * <p>
+     * The type of this property is a String or String[] (array of strings)
+     * denoting the resource types.
+     */
+    String[] paths() default {};
+
+    /**
+     * The name of the service registration property of a Servlet registered as
+     * a service containing the resource type(s) supported by the servlet (value
+     * is "sling.servlet.resourceTypes").
+     * <p>
+     * The type of this property is a String or String[] (array of strings)
+     * denoting the resource types. This property is ignored if the
+     * {@link #paths} property is set. Otherwise this property must be set or
+     * the servlet is ignored.
+     */
+    String[] resourceTypes() default {};
+
+    /**
+     * The name of the service registration property of a Servlet registered as
+     * a service containing the request URL selectors supported by the servlet
+     * (value is "sling.servlet.selectors"). The selectors must be configured as
+     * they would be specified in the URL that is as a list of dot-separated
+     * strings such as <em>print.a4</em>.
+     * <p>
+     * The type of this property is a String or String[] (array of strings)
+     * denoting the resource types. This property is ignored if the
+     * {@link #paths} property is set. Otherwise this property is optional and
+     * ignored if not set.
+     */
+    String[] selectors() default {};
+
+    /**
+     * The name of the service registration property of a Servlet registered as
+     * a service containing the request URL extensions supported by the servlet
+     * for GET requests (value is "sling.servlet.extensions").
+     * <p>
+     * The type of this property is a String or String[] (array of strings)
+     * denoting the resource types. This property is ignored if the
+     * {@link #paths} property is set. Otherwise this property or the
+     * {@link #methods} is optional and ignored if not set.
+     */
+    String[] extensions() default {};
+
+    /**
+     * The name of the service registration property of a Servlet registered as
+     * a service containing the request methods supported by the servlet (value
+     * is "sling.servlet.methods").
+     * <p>
+     * The type of this property is a String or String[] (array of strings)
+     * denoting the resource types. This property is ignored if the
+     * {@link #paths} property is set. Otherwise this property or the
+     * {@link #extensions} is optional and ignored if not set.
+     */
+    String[] methods() default {};
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
index 6e88d51..d9068f0 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/AnnotationTagProviderManager.java
@@ -24,6 +24,7 @@
 import org.apache.felix.scrplugin.tags.JavaField;
 import org.apache.felix.scrplugin.tags.JavaTag;
 import org.apache.felix.scrplugin.tags.annotation.defaulttag.DefaultAnnotationTagProvider;
+import org.apache.felix.scrplugin.tags.annotation.sling.SlingAnnotationTagProvider;
 import org.apache.maven.plugin.MojoFailureException;
 
 import com.thoughtworks.qdox.model.Annotation;
@@ -52,6 +53,7 @@
 
         // always add provider supporting built-in SCR default properties
         annotationTagProviders.add(new DefaultAnnotationTagProvider());
+        annotationTagProviders.add(new SlingAnnotationTagProvider());
 
         // add custom providers defined in pom
         for (int i = 0; i < annotationTagProviderClasses.length; i++) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java
new file mode 100644
index 0000000..6ecc1fa
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java
@@ -0,0 +1,90 @@
+/*
+ * 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.sling;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.scr.annotations.sling.SlingServlet;
+import org.apache.felix.scrplugin.tags.JavaField;
+import org.apache.felix.scrplugin.tags.JavaTag;
+import org.apache.felix.scrplugin.tags.annotation.AnnotationJavaClassDescription;
+import org.apache.felix.scrplugin.tags.annotation.AnnotationTagProvider;
+import org.apache.felix.scrplugin.tags.annotation.defaulttag.Util;
+
+/**
+ * Annotation tag provider for sling-specific SCR annotations.
+ */
+public class SlingAnnotationTagProvider implements AnnotationTagProvider {
+
+    public List<JavaTag> getTags(com.thoughtworks.qdox.model.Annotation annotation,
+            AnnotationJavaClassDescription description, JavaField field) {
+        List<JavaTag> tags = new ArrayList<JavaTag>();
+
+        if (annotation.getType().getJavaClass().getFullyQualifiedName().equals(SlingServlet.class.getName())) {
+
+            // generate @Component tag if required
+            boolean generateComponent = Util.getBooleanValue(annotation, "generateComponent", SlingServlet.class);
+            if (generateComponent) {
+                tags.add(new SlingServletComponentTag(description));
+            }
+
+            // generate @Service tag if required
+            boolean generateService = Util.getBooleanValue(annotation, "generateService", SlingServlet.class);
+            if (generateService) {
+                tags.add(new SlingServletServiceTag(description));
+            }
+
+            // generate @Property tags
+            // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_PATHS}
+            String[] paths = Util.getStringValues(annotation, description, "paths");
+            if (paths != null && paths.length != 0) {
+                tags.add(new SlingServletPropertyTag("sling.servlet.paths", paths, description));
+            }
+
+            // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES}
+            String[] resourceTypes = Util.getStringValues(annotation, description, "resourceTypes");
+            if (resourceTypes != null && resourceTypes.length != 0) {
+                tags.add(new SlingServletPropertyTag("sling.servlet.resourceTypes", resourceTypes, description));
+            }
+
+            // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_SELECTORS}
+            String[] selectors = Util.getStringValues(annotation, description, "selectors");
+            if (selectors != null && selectors.length != 0) {
+                tags.add(new SlingServletPropertyTag("sling.servlet.selectors", selectors, description));
+            }
+
+            // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_EXTENSIONS}
+            String[] extensions = Util.getStringValues(annotation, description, "extensions");
+            if (extensions != null && extensions.length != 0) {
+                tags.add(new SlingServletPropertyTag("sling.servlet.extensions", extensions, description));
+            }
+
+            // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_METHODS}
+            String[] methods = Util.getStringValues(annotation, description, "methods");
+            if (methods != null && methods.length != 0) {
+                tags.add(new SlingServletPropertyTag("sling.servlet.methods", methods, description));
+            }
+
+        }
+
+        return tags;
+    }
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java
new file mode 100644
index 0000000..e002f0c
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.tags.annotation.sling;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.scrplugin.Constants;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
+
+/**
+ * Description of a java tag for components.
+ */
+public class SlingServletComponentTag extends AbstractTag {
+
+    /**
+     * @param desc Description
+     */
+    public SlingServletComponentTag(JavaClassDescription desc) {
+        super(desc, null);
+    }
+
+    @Override
+    public String getName() {
+        return Constants.COMPONENT;
+    }
+
+    @Override
+    public Map<String, String> getNamedParameterMap() {
+        final Map<String, String> map = new HashMap<String, String>();
+
+        map.put(Constants.COMPONENT_IMMEDIATE, String.valueOf(true));
+
+        return map;
+    }
+
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
new file mode 100644
index 0000000..ea97083
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.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.tags.annotation.sling;
+
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.felix.scrplugin.Constants;
+import org.apache.felix.scrplugin.tags.JavaClassDescription;
+import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * Description of a java tag for components.
+ */
+public class SlingServletPropertyTag extends AbstractTag {
+
+    protected final String name;
+    protected final String[] values;
+
+    /**
+     * @param name Property name
+     * @param values Property values
+     * @param desc Description
+     */
+    public SlingServletPropertyTag(String name, String[] values, JavaClassDescription desc) {
+        super(desc, null);
+        this.name = name;
+        this.values = values;
+    }
+
+    @Override
+    public String getName() {
+        return Constants.PROPERTY;
+    }
+
+    @Override
+    public Map<String, String> getNamedParameterMap() {
+        final SortedMap<String, String> map = new TreeMap<String, String>();
+
+        map.put(Constants.PROPERTY_NAME, this.name);
+
+        if (this.values == null || this.values.length == 0) {
+            map.put(Constants.PROPERTY_VALUE, "");
+        } else if (this.values.length == 1) {
+            map.put(Constants.PROPERTY_VALUE, this.values[0]);
+        } else {
+            for (int i = 0; i < this.values.length; i++) {
+                // generate index number with trailing zeros to ensure correct sort order in map
+                String index = StringUtils.leftPad(Integer.toString(i), 10, "0");
+                map.put(Constants.PROPERTY_MULTIVALUE_PREFIX + '.' + index, this.values[i]);
+            }
+        }
+
+        return map;
+    }
+
+}
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
new file mode 100644
index 0000000..bf71dc4
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
@@ -0,0 +1,56 @@
+/*
+ * 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.sling;
+
+import java.util.HashMap;
+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;
+
+/**
+ * Description of a java tag for components.
+ */
+public class SlingServletServiceTag extends AbstractTag {
+
+    /**
+     * @param desc Description
+     */
+    public SlingServletServiceTag(JavaClassDescription desc) {
+        super(desc, null);
+    }
+
+    @Override
+    public String getName() {
+        return Constants.SERVICE;
+    }
+
+    @Override
+    public Map<String, String> getNamedParameterMap() {
+        final Map<String, String> map = new HashMap<String, String>();
+
+        map.put(Constants.SERVICE_INTERFACE, Servlet.class.getName());
+
+        return map;
+    }
+
+}