FELIX-3377 Applied patch provided by David Jencks (thanks alot) slightly modified:
  - Added some more JavaDoc to ExtComponentContext
  - Have ExtComponentContext extend ComponentContext
  - Internally tread property overwrites like supplied CM configuration
    This allows for properly transient property modification instead
    of overwriting the actual descriptor properties which would cause
    the properties for all instances created from the same descriptor
    to be subsequently modified.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1298275 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/pom.xml b/scr/pom.xml
index 8bae96a..90faaeb 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -225,6 +225,8 @@
                         </Bundle-Activator>
                         <Export-Package>
                             org.apache.felix.scr;version=1.6,
+                            org.apache.felix.scr.component;version=1.0;
+                                mandatory:="status"; status="provisional",
                             org.osgi.service.component
                         </Export-Package>
                         <Private-Package>
@@ -389,7 +391,7 @@
                         <exclude>**/components/**</exclude>
                     </excludes>
                     <includes>
-                        <include>**/integration/*</include>
+                        <include>**/integration/**</include>
                     </includes>
                 </configuration>
             </plugin>
diff --git a/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java b/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java
new file mode 100644
index 0000000..858a999
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java
@@ -0,0 +1,79 @@
+/*
+ * 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.component;
+
+
+import java.util.Dictionary;
+
+import org.osgi.service.component.ComponentContext;
+
+
+/**
+ * The <code>ExtComponentContext</code> is a custom extension of the
+ * standard ComponentContext allowing to update the service registration
+ * properties of a component registered as a service.
+ */
+public interface ExtComponentContext extends ComponentContext
+{
+
+    /**
+     * Updates the service registration properties of the component
+     * registered as a service. The effects are:
+     * <ol>
+     * <li>The properties read from the component descriptor are updated
+     * with the values from the given dictionary</li>
+     * <li>Configuration Admin properties are applied</li>
+     * <li>The ServiceRegistration service properties are updated with the
+     * result.</li>
+     * </ol>
+     * <p>
+     * Calling this method is does not cause a component reconfiguration as
+     * would be caused by a Configuration update. Particularly the
+     * configured modified method (if any) is not called as a result of
+     * calling this method.
+     * <p>
+     * Please note:
+     * <ul>
+     * <li>The provided properties may overwrite or add properties to
+     * the properties read from the component descriptor. It is not
+     * possible to remove such descriptor properties</li>
+     * <li>The provided properties are only valid for the livecycle of the
+     * component instance. After reactivation of a component (and thus
+     * creation of a new component instance) the properties are removed.
+     * </li>
+     * <li>If the component can be dynamically updated with configuration
+     * these properties will influence such configuration.</li>
+     * <li>Configuration is not updated in the Configuration Admin Service
+     * when calling service</li>
+     * <li>Properties provided with this method may still be overwriiten
+     * with configuration provided by the Configuration Admin Service.</lI>
+     * </ul>
+     * <p>
+     * If the component to which this context belongs is not registered as
+     * a service, this method
+     *
+     * @param properties properties to update the default component
+     *      properties with.
+     *
+     * @throws IllegalStateException if this method is called for a
+     *      Component Factory component
+     */
+    void updateProperties( Dictionary properties );
+
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index b982cf9..cacaf78 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -798,6 +798,8 @@
 
     public abstract Dictionary getProperties();
 
+    public abstract void resetComponentProperties( Dictionary properties );
+
     /**
      * Returns the subset of component properties to be used as service
      * properties. These properties are all component properties where property
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
index 3d5b925..eb81753 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
@@ -21,6 +21,7 @@
 
 import java.util.Dictionary;
 
+import org.apache.felix.scr.component.ExtComponentContext;
 import org.apache.felix.scr.impl.Activator;
 import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
 import org.osgi.framework.Bundle;
@@ -34,8 +35,7 @@
  * Implementation for the ComponentContext interface
  *
  */
-public class ComponentContextImpl implements ComponentContext, ComponentInstance
-{
+public class ComponentContextImpl implements ExtComponentContext, ComponentInstance {
 
     private AbstractComponentManager m_componentManager;
 
@@ -132,4 +132,12 @@
     {
         getComponentManager().dispose();
     }
+
+    //---------- Speculative MutableProperties interface ------------------------------
+
+    public void updateProperties(Dictionary properties)
+    {
+        getComponentManager().resetComponentProperties(properties);
+    }
+
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 803d9a2..e02d3e8 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -209,6 +209,10 @@
         return props;
     }
 
+    public void resetComponentProperties(Dictionary properties) {
+        throw new IllegalStateException( "ComponentFactory service properties are immutable" );
+    }
+
 
     public Dictionary getServiceProperties()
     {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index e64a197..e43c000 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -69,6 +69,10 @@
     // the component properties, also used as service properties
     private Dictionary m_properties;
 
+    // properties supplied ot ExtComponentContext.updateProperties
+    // null if properties are not to be overwritten
+    private Dictionary m_propertiesOverwrite;
+
     // the component properties from the Configuration Admin Service
     // this is null, if none exist or none are provided
     private Dictionary m_configurationProperties;
@@ -136,6 +140,8 @@
         m_implementationObject = null;
         m_componentContext = null;
         m_properties = null;
+        m_propertiesOverwrite = null;
+        m_configurationProperties = null;
     }
 
 
@@ -343,13 +349,16 @@
                 }
             }
 
-            // 3. overlay with Configuration Admin properties
+            // 3. overwrite as per ExtComponentContext.updateProperties
+            copyTo( props, m_propertiesOverwrite );
+
+            // 4. overlay with Configuration Admin properties
             copyTo( props, m_configurationProperties );
 
-            // 4. copy any component factory properties, not supported yet
+            // 5. copy any component factory properties, not supported yet
             copyTo( props, m_factoryProperties );
 
-            // 5. set component.name and component.id
+            // 6. set component.name and component.id
             props.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
             props.put( ComponentConstants.COMPONENT_ID, new Long( getId() ) );
 
@@ -360,6 +369,18 @@
     }
 
 
+    public void resetComponentProperties( Dictionary properties )
+    {
+        m_propertiesOverwrite = copyTo( null, properties );
+        m_properties = null;
+        Dictionary serviceProperties = getServiceProperties();
+        if ( getServiceRegistration() != null )
+        {
+            getServiceRegistration().setProperties( serviceProperties );
+        }
+    }
+
+
     /**
      * Called by the Configuration Admin Service to update the component with
      * Configuration properties.
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
index b0be98f..c134fd7 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
@@ -97,6 +97,8 @@
     @ProbeBuilder
     public TestProbeBuilder extendProbe(TestProbeBuilder builder) {
         builder.setHeader("Export-Package", "org.apache.felix.scr.integration.components,org.apache.felix.scr.integration.components.activatesignature");
+        builder.setHeader("Import-Package", "org.apache.felix.scr,org.apache.felix.scr.component;mandatory:=\"status\"; status=\"provisional\"");
+        builder.setHeader("Bundle-ManifestVersion", "2");
         return builder;
     }
 
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java b/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java
new file mode 100644
index 0000000..e406c01
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.integration;
+
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.apache.felix.scr.Component;
+import org.apache.felix.scr.integration.components.MutatingService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.ServiceReference;
+
+
+@RunWith(JUnit4TestRunner.class)
+public class MutablePropertiesTest extends ComponentTestBase
+{
+
+    static
+    {
+        // uncomment to enable debugging of this test class
+//        paxRunnerVmOption = DEBUG_VM_OPTION;
+
+        descriptorFile = "/integration_test_mutable_properties.xml";
+    }
+
+
+    @Test
+    public void test_mutable_properties()
+    {
+        final Component component = findComponentByName( "components.mutable.properties" );
+        TestCase.assertNotNull( component );
+        TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
+
+        ServiceReference serviceReference = bundleContext.getServiceReference( MutatingService.class.getName() );
+        checkProperties( serviceReference, 8, "otherValue", "p1", "p2" );
+
+        //update theValue
+        MutatingService s = ( MutatingService ) bundleContext.getService(serviceReference );
+        Assert.assertNotNull(s);
+        TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+        Dictionary d = new Hashtable(Collections.singletonMap( PROP_NAME, "anotherValue" ));
+        s.updateProperties(d);
+        checkProperties(serviceReference, 8, "anotherValue", "p1", "p2");
+
+        //configure with configAdmin
+        configure( "components.mutable.properties" );
+        delay();
+        checkProperties(serviceReference, 8, PROP_NAME, "p1", "p2");
+
+        //check that a property from config admin can't be changed
+        s.updateProperties(d);
+        checkProperties(serviceReference, 8, PROP_NAME, "p1", "p2");
+
+        //check that another one can
+        s.updateProperties(new Hashtable(Collections.singletonMap( "p1", "changed" )));
+        checkProperties(serviceReference, 8, PROP_NAME, "changed", "p2");
+
+        bundleContext.ungetService(serviceReference);
+    }
+
+    private void checkProperties(ServiceReference serviceReference, int count, String otherValue, String p1, String p2) {
+        Assert.assertEquals("wrong property count", count, serviceReference.getPropertyKeys().length);
+        Assert.assertEquals(otherValue, serviceReference.getProperty(PROP_NAME));
+        Assert.assertEquals(p1, serviceReference.getProperty("p1"));
+        Assert.assertEquals(p2, serviceReference.getProperty("p2"));
+    }
+
+
+}
\ No newline at end of file
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingService.java b/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingService.java
new file mode 100644
index 0000000..b212457
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingService.java
@@ -0,0 +1,29 @@
+/*
+ * 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.integration.components;
+
+
+import java.util.Dictionary;
+
+public interface MutatingService
+{
+
+    void updateProperties(Dictionary changes);
+
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java b/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java
new file mode 100644
index 0000000..6ae2ff6
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java
@@ -0,0 +1,46 @@
+/*
+ * 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.integration.components;
+
+
+import java.util.Dictionary;
+
+import org.apache.felix.scr.component.ExtComponentContext;
+import org.osgi.service.component.ComponentContext;
+
+
+public class MutatingServiceImpl implements MutatingService
+{
+    private ComponentContext activateContext;
+
+    private void activate( ComponentContext activateContext )
+    {
+        this.activateContext = activateContext;
+    }
+
+    private void modified( ComponentContext activateContext )
+    {
+
+    }
+
+    public void updateProperties(Dictionary changes) {
+        ((ExtComponentContext)activateContext).updateProperties(changes);
+    }
+
+}
diff --git a/scr/src/test/resources/integration_test_mutable_properties.xml b/scr/src/test/resources/integration_test_mutable_properties.xml
new file mode 100644
index 0000000..5dc0473
--- /dev/null
+++ b/scr/src/test/resources/integration_test_mutable_properties.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<components>
+    <scr:component name="components.mutable.properties"
+            xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
+            enabled="true"
+            configuration-policy="optional"
+            activate="activate"
+            modified="modified">
+        <implementation class="org.apache.felix.scr.integration.components.MutatingServiceImpl" />
+        <service>
+            <provide interface="org.apache.felix.scr.integration.components.MutatingService" />
+        </service>
+        <property name="service.pid" value="components.mutable.properties" />
+        <property name="theValue" value="otherValue" />
+        <property name="p1" value="p1" />
+        <property name="p2" value="p2" />
+    </scr:component>
+</components>