FELIX-1898 : Extend SCR Plugin to support new updated method declaration. Apply patch by Felix Meschberger

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@887955 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr-annotations/pom.xml b/scr-annotations/pom.xml
index 110f346..1372461 100644
--- a/scr-annotations/pom.xml
+++ b/scr-annotations/pom.xml
@@ -29,7 +29,7 @@
 	<groupId>org.apache.felix</groupId>
 	<artifactId>org.apache.felix.scr.annotations</artifactId>
 
-	<version>1.0.1-SNAPSHOT</version>
+	<version>1.1.0-SNAPSHOT</version>
 	<packaging>jar</packaging>
 
 	<name>Annotations for SCR</name>
diff --git a/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Reference.java b/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Reference.java
index 760b3b9..9db25db 100644
--- a/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Reference.java
+++ b/scr-annotations/src/main/java/org/apache/felix/scr/annotations/Reference.java
@@ -95,6 +95,12 @@
     String unbind() default "";
 
     /**
+     * The name of the method to be called when the bound service updates its
+     * service registration properties. By default this is not set.
+     */
+    String updated() default "";
+
+    /**
      * The reference strategy for the reference. This can either be
      * {@link ReferenceStrategy#EVENT} in which case the bind and unbind
      * methods are used or it can be {@link ReferenceStrategy#LOOKUP}
diff --git a/scrplugin/pom.xml b/scrplugin/pom.xml
index 602ae7e..fcad3d5 100644
--- a/scrplugin/pom.xml
+++ b/scrplugin/pom.xml
@@ -67,7 +67,7 @@
 		<dependency>
 			<groupId>org.apache.felix</groupId>
 			<artifactId>org.apache.felix.scr.annotations</artifactId>
-			<version>1.0.1-SNAPSHOT</version>
+			<version>1.1.0-SNAPSHOT</version>
 		</dependency>
         
         <!-- Sling Servlet SCR Annotation -->
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
index dd62465..5a362e2 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
@@ -33,6 +33,9 @@
     /** 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.
@@ -70,6 +73,9 @@
     // 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";
@@ -151,6 +157,8 @@
 
     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 */
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
index 7d56dbf..ce34d20 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
@@ -909,6 +909,11 @@
         {
             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 )
         {
@@ -939,6 +944,7 @@
      * <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
@@ -959,6 +965,10 @@
         {
             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 );
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
index d392eaf..0ccf33b 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
@@ -105,7 +105,10 @@
      * Set the spec version.
      */
     public void setSpecVersion(int value) {
-        this.specVersion = value;
+        // only set a higher version, never "downgrade"
+        if (this.specVersion < value) {
+            this.specVersion = value;
+        }
     }
 
     /**
@@ -289,7 +292,7 @@
                     this.checkLifecycleMethod(specVersion, javaClass, activateName, true, iLog);
                     this.checkLifecycleMethod(specVersion, javaClass, deactivateName, false, iLog);
 
-                    if ( this.modified != null && specVersion == Constants.VERSION_1_1 ) {
+                    if ( this.modified != null && specVersion >= Constants.VERSION_1_1 ) {
                         this.checkLifecycleMethod(specVersion, javaClass, this.modified, true, iLog);
                     }
                     // ensure public default constructor
@@ -346,7 +349,7 @@
             }
         }
         // check additional stuff if version is 1.1
-        if ( specVersion == Constants.VERSION_1_1 ) {
+        if ( specVersion >= Constants.VERSION_1_1 ) {
             final String cp = this.getConfigurationPolicy();
             if ( cp != null
                  && !Constants.COMPONENT_CONFIG_POLICY_IGNORE.equals(cp)
@@ -380,7 +383,7 @@
         // 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) {
+            if ( specVersion >= Constants.VERSION_1_1) {
                 // second candidate is (de)activate(BundleContext)
                 method = javaClass.getMethodBySignature(methodName, new String[] {TYPE_BUNDLE_CONTEXT});
                 if ( method == null ) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
index f3bbb22..7ccd04d 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
@@ -112,7 +112,7 @@
             if ( specVersion == Constants.VERSION_1_0 && type.equals(Constants.PROPERTY_TYPE_CHAR_1_1) ) {
                 type = Constants.PROPERTY_TYPE_CHAR;
             }
-            if ( specVersion == Constants.VERSION_1_1 && type.equals(Constants.PROPERTY_TYPE_CHAR) ) {
+            if ( specVersion >= Constants.VERSION_1_1 && type.equals(Constants.PROPERTY_TYPE_CHAR) ) {
                 type = Constants.PROPERTY_TYPE_CHAR_1_1;
             }
         }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
index 47db55c..a4ef68d 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
@@ -39,6 +39,7 @@
     protected String policy;
     protected String bind;
     protected String unbind;
+    protected String updated;
 
     /** @since 1.0.9 */
     protected String strategy;
@@ -120,6 +121,14 @@
         this.unbind = unbind;
     }
 
+    public String getUpdated() {
+        return this.updated;
+    }
+
+    public void setUpdated(String updated) {
+        this.updated = updated;
+    }
+
     public boolean isChecked() {
         return checked;
     }
@@ -221,6 +230,14 @@
             this.bind = null;
             this.unbind = null;
         }
+
+        // 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" );
+            }
+        }
     }
 
     protected String validateMethod(final int      specVersion,
@@ -263,7 +280,7 @@
         JavaMethod method = this.javaClassDescription.getMethodBySignature(realMethodName, sig);
         if (method == null) {
             method = this.javaClassDescription.getMethodBySignature(realMethodName, sig2);
-            if ( specVersion == Constants.VERSION_1_1 && method == null ) {
+            if ( specVersion >= Constants.VERSION_1_1 && method == null ) {
                 method = this.javaClassDescription.getMethodBySignature(realMethodName, sig3);
             }
         }
@@ -277,7 +294,7 @@
         }
         if (method == null) {
             method = this.javaClassDescription.getMethodBySignature(realMethodName, sig2);
-            if ( specVersion == Constants.VERSION_1_1 && method == null ) {
+            if ( specVersion >= Constants.VERSION_1_1 && method == null ) {
                 method = this.javaClassDescription.getMethodBySignature(realMethodName, sig3);
             }
         }
@@ -291,7 +308,7 @@
         }
         if (method == null) {
             method = this.javaClassDescription.getMethodBySignature(realMethodName, sig2);
-            if ( specVersion == Constants.VERSION_1_1 && method == null ) {
+            if ( specVersion >= Constants.VERSION_1_1 && method == null ) {
                 method = this.javaClassDescription.getMethodBySignature(realMethodName, sig3);
             }
         }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java
index 05e41cc..2e27301 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java
@@ -76,6 +76,10 @@
                 return Util.getStringValue(annotation, desc, "unbind", Reference.class);
             }
 
+            public String updated() {
+                return Util.getStringValue(annotation, desc, "updated", Reference.class);
+            }
+
             public Class<? extends java.lang.annotation.Annotation> annotationType() {
                 return null;
             }
@@ -103,6 +107,7 @@
         map.put(Constants.REFERENCE_TARGET, emptyToNull(this.annotation.target()));
         map.put(Constants.REFERENCE_BIND, emptyToNull(this.annotation.bind()));
         map.put(Constants.REFERENCE_UNDBIND, emptyToNull(this.annotation.unbind()));
+        map.put(Constants.REFERENCE_UPDATED, emptyToNull(this.annotation.updated()));
         map.put(Constants.REFERENCE_STRATEGY, this.annotation.strategy().getStrategyString());
 
         return map;
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
index f7f68b3..f3f8af2 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
@@ -112,6 +112,7 @@
             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;
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index 9207fcf..b5ccff7 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -54,6 +54,9 @@
     /** The namespace for R4.2 - Version 1.1 */
     public static final String NAMESPACE_URI_1_1 = "http://www.osgi.org/xmlns/scr/v1.1.0";
 
+    /** The namespace for R4.2+FELIX-1893 - Version 1.1-felix */
+    public static final String NAMESPACE_URI_1_1_FELIX = "http://www.osgi.org/xmlns/scr/v1.1.0-felix";
+
     /** The inner namespace - used for all inner elements. */
     public static final String INNER_NAMESPACE_URI = "";
 
@@ -156,8 +159,10 @@
         final String namespace;
         if ( components.getSpecVersion() == Constants.VERSION_1_0 ) {
             namespace = NAMESPACE_URI_1_0;
-        } else {
+        } else if ( components.getSpecVersion() == Constants.VERSION_1_1 ) {
             namespace = NAMESPACE_URI_1_1;
+        } else {
+            namespace = NAMESPACE_URI_1_1_FELIX;
         }
         contentHandler.startDocument();
         contentHandler.startPrefixMapping(PREFIX, namespace);
@@ -196,7 +201,7 @@
         IOUtils.addAttribute(ai, COMPONENT_ATTR_FACTORY, component.getFactory());
 
         // attributes new in 1.1
-        if ( NAMESPACE_URI_1_1.equals(namespace) ) {
+        if ( NAMESPACE_URI_1_1.equals( namespace ) || NAMESPACE_URI_1_1_FELIX.equals( namespace ) ) {
             IOUtils.addAttribute(ai, COMPONENT_ATTR_POLICY, component.getConfigurationPolicy());
             IOUtils.addAttribute(ai, COMPONENT_ATTR_ACTIVATE, component.getActivate());
             IOUtils.addAttribute(ai, COMPONENT_ATTR_DEACTIVATE, component.getDeactivate());
@@ -217,7 +222,7 @@
         }
         if ( component.getReferences() != null ) {
             for(final Reference reference : component.getReferences()) {
-                generateXML(reference, contentHandler, isScrPrivateFile);
+                generateXML(namespace, reference, contentHandler, isScrPrivateFile);
             }
         }
         IOUtils.indent(contentHandler, 1);
@@ -327,7 +332,7 @@
      * @param contentHandler
      * @throws SAXException
      */
-    protected static void generateXML(Reference reference, ContentHandler contentHandler, boolean isScrPrivateFile)
+    protected static void generateXML(final String namespace,Reference reference, ContentHandler contentHandler, boolean isScrPrivateFile)
     throws SAXException {
         final AttributesImpl ai = new AttributesImpl();
         IOUtils.addAttribute(ai, "name", reference.getName());
@@ -337,6 +342,12 @@
         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 ) ) {
+            IOUtils.addAttribute(ai, "updated", reference.getUpdated());
+        }
+
         if ( isScrPrivateFile ) {
             IOUtils.addAttribute(ai, "checked", String.valueOf(reference.isChecked()));
         }
@@ -397,10 +408,13 @@
             }
 
             // 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) ) {
+            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 (localName.equals(COMPONENT)) {
@@ -516,7 +530,9 @@
                 uri = NAMESPACE_URI_1_0;
             }
 
-            if ( NAMESPACE_URI_1_0.equals(uri) || NAMESPACE_URI_1_1.equals(uri) ) {
+            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);
                     this.currentComponent = null;