You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2012/05/09 20:25:23 UTC

svn commit: r1336331 - in /felix/trunk/scr/src: main/java/org/apache/felix/scr/component/ main/java/org/apache/felix/scr/impl/helper/ main/java/org/apache/felix/scr/impl/manager/ main/java/org/apache/felix/scr/impl/metadata/ test/java/org/apache/felix/...

Author: fmeschbe
Date: Wed May  9 18:25:22 2012
New Revision: 1336331

URL: http://svn.apache.org/viewvc?rev=1336331&view=rev
Log:
FELIX-3377 Commit my latest patch (FELIX-3377-4-fmeschbe.patch) including input from David Jencks (thanks alot).

  - Activate, Modified, Deactivate methods may return Map to set service properties
  - Namespace "http://felix.apache.org/xmlns/scr/v1.2.0-felix" is required for component
    declaration to support this feature
  - ExtComponentContext provides setServiceProperties method to explicitly set the
    service registration properties at any time

Added:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/MethodResult.java
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java
    felix/trunk/scr/src/test/resources/integration_test_mutable_properties.xml

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/component/ExtComponentContext.java Wed May  9 18:25:22 2012
@@ -33,47 +33,23 @@ public interface ExtComponentContext ext
 {
 
     /**
-     * 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>
+     * Sets the service registration properties of the component
+     * registered as a service. If the component is not registered as
+     * a service, this method has no effect.
      * <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
+     * The <code>component.id</code> and <code>component.name</code>
+     * property are set by the Service Component Runtime and cannot be
+     * removed or replaced.
      *
      * @param properties properties to update the default component
-     *      properties with.
+     *      properties with. If this is <code>null</code> or empty the
+     *      default set of properties as defined in Section 112.6,
+     *      Component Properties, are used as the service registration
+     *      properties.
      *
      * @throws IllegalStateException if this method is called for a
      *      Component Factory component
      */
-    void updateProperties( Dictionary properties );
+    void setServiceProperties( Dictionary properties );
 
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java Wed May  9 18:25:22 2012
@@ -21,7 +21,6 @@ package org.apache.felix.scr.impl.helper
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.log.LogService;
@@ -70,7 +69,7 @@ public class ActivateMethod extends Base
             {
                 if ( methods[i].getName().equals( getMethodName() ) && isSuitable( methods[i] ) )
                 {
-                    if ( accept( methods[i], acceptPrivate, acceptPackage ) )
+                    if ( accept( methods[i], acceptPrivate, acceptPackage, returnValue() ) )
                     {
                         // check modifiers etc.
                         return methods[i];
@@ -143,12 +142,20 @@ public class ActivateMethod extends Base
         return "activate";
     }
 
-
-    public boolean invoke( Object componentInstance, Object rawParameter, final boolean methodCallFailureResult )
+    protected boolean returnValue()
     {
-        return methodExists() && super.invoke( componentInstance, rawParameter, methodCallFailureResult );
+        // allow returning Map if declared as DS 1.2-Felix or newer
+        return isDS12Felix();
     }
 
+    public MethodResult invoke(Object componentInstance, Object rawParameter, final MethodResult methodCallFailureResult)
+    {
+        if (methodExists())
+        {
+            return super.invoke(componentInstance, rawParameter, methodCallFailureResult);
+        }
+        return null;
+    }
 
     /**
      * Returns a method taking a single parameter of one of the
@@ -250,7 +257,6 @@ public class ActivateMethod extends Base
         private final ComponentContext m_componentContext;
         private final int m_reason;
 
-
         public ActivatorParameter( ComponentContext componentContext, int reason )
         {
             this.m_componentContext = componentContext;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java Wed May  9 18:25:22 2012
@@ -24,7 +24,6 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.Map;
-
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -56,7 +55,6 @@ abstract class BaseMethod
 
     private State m_state;
 
-
     protected BaseMethod( final AbstractComponentManager componentManager, final String methodName,
         final Class componentClass )
     {
@@ -94,6 +92,12 @@ abstract class BaseMethod
     }
 
 
+    protected final boolean isDS12Felix()
+    {
+        return getComponentManager().getComponentMetadata().isDS12Felix();
+    }
+
+
     protected final String getMethodName()
     {
         return m_methodName;
@@ -145,11 +149,6 @@ abstract class BaseMethod
      * the class hierarchy is traversed until a method is found or the root
      * of the class hierarchy is reached without finding a method.
      *
-     * @param targetClass The class in which to look for the method
-     * @param acceptPrivate <code>true</code> if private methods should be
-     *      considered.
-     * @param acceptPackage <code>true</code> if package private methods should
-     *      be considered.
      * @return The requested method or <code>null</code> if no acceptable method
      *      can be found in the target class or any super class.
      * @throws InvocationTargetException If an unexpected Throwable is caught
@@ -185,7 +184,7 @@ abstract class BaseMethod
             {
                 // log and return null
                 getComponentManager().log( LogService.LOG_ERROR,
-                    "DependencyManager : Suitable but non-accessible method found in class {0}", new Object[]
+                    "findMethod: Suitable but non-accessible method found in class {0}", new Object[]
                         { targetClass.getName() }, null );
                 break;
             }
@@ -216,15 +215,16 @@ abstract class BaseMethod
         final boolean acceptPackage ) throws SuitableMethodNotAccessibleException, InvocationTargetException;
 
 
-    private boolean invokeMethod( final Object componentInstance, final Object rawParameter )
+    private MethodResult invokeMethod( final Object componentInstance, final Object rawParameter )
         throws InvocationTargetException
     {
         try
         {
             if ( componentInstance != null )
             {
-                final Object[] params = getParameters( m_method, rawParameter );
-                m_method.invoke( componentInstance, params );
+                final Object[] params = getParameters(m_method, rawParameter);
+                Object result = m_method.invoke(componentInstance, params);
+                return new MethodResult((m_method.getReturnType() != Void.TYPE), (Map) result);
             }
             else
             {
@@ -236,7 +236,7 @@ abstract class BaseMethod
         catch ( IllegalStateException ise )
         {
             getComponentManager().log( LogService.LOG_DEBUG, ise.getMessage(), null );
-            return false;
+            return null;
         }
         catch ( IllegalAccessException ex )
         {
@@ -256,9 +256,18 @@ abstract class BaseMethod
         }
 
         // assume success (also if the mehotd is not available or accessible)
-        return true;
+        return MethodResult.VOID; // TODO: or null ??
     }
 
+    protected void processResult( Object configResults, Object result, Method method )
+    {
+        //no op
+    }
+
+    protected boolean returnValue()
+    {
+        return false;
+    }
 
     /**
      * Returns the parameter array created from the <code>rawParameter</code>
@@ -311,7 +320,7 @@ abstract class BaseMethod
             Method method = clazz.getDeclaredMethod( name, parameterTypes );
 
             // accept public and protected methods only and ensure accessibility
-            if ( accept( method, acceptPrivate, acceptPackage ) )
+            if ( accept( method, acceptPrivate, acceptPackage, returnValue() ) )
             {
                 return method;
             }
@@ -384,15 +393,16 @@ abstract class BaseMethod
      * This method is package private for unit testing purposes. It is not
      * meant to be called from client code.
      *
+     *
      * @param method The method to check
      * @param acceptPrivate Whether a private method is acceptable
      * @param acceptPackage Whether a package private method is acceptable
-     * @return
+     * @param allowReturnValue whether the method can return a value (to update service registration properties)
+     * @return whether the method is acceptable
      */
-    protected static boolean accept( Method method, boolean acceptPrivate, boolean acceptPackage )
+    static boolean accept( Method method, boolean acceptPrivate, boolean acceptPackage, boolean allowReturnValue )
     {
-        // method must be void
-        if ( Void.TYPE != method.getReturnType() )
+        if (!(Void.TYPE == method.getReturnType() || (MAP_CLASS == method.getReturnType() && allowReturnValue)))
         {
             return false;
         }
@@ -455,6 +465,8 @@ abstract class BaseMethod
      * Calls the declared method on the given component with the provided
      * method call arguments.
      *
+     *
+     *
      * @param componentInstance The component instance on which to call the
      *      method
      * @param rawParameter The parameter container providing the actual
@@ -468,8 +480,8 @@ abstract class BaseMethod
      *      <code>methodCallFailureResult</code> is returned if the method was
      *      found and called, but the method threw an exception.
      */
-    public boolean invoke( final Object componentInstance, final Object rawParameter,
-        final boolean methodCallFailureResult )
+    public MethodResult invoke( final Object componentInstance, final Object rawParameter,
+            final MethodResult methodCallFailureResult )
     {
         try
         {
@@ -493,7 +505,7 @@ abstract class BaseMethod
     private static interface State
     {
 
-        boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+        MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
             throws InvocationTargetException;
 
 
@@ -506,9 +518,9 @@ abstract class BaseMethod
         private static final State INSTANCE = new NotApplicable();
 
 
-        public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
         {
-            return true;
+            return MethodResult.VOID;
         }
 
 
@@ -545,7 +557,7 @@ abstract class BaseMethod
             }
 
 
-        public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
             throws InvocationTargetException
         {
             resolve( baseMethod );
@@ -565,14 +577,14 @@ abstract class BaseMethod
         private static final State INSTANCE = new NotFound();
 
 
-        public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
         {
             // 112.3.1 If the method is not found , SCR must log an error
             // message with the log service, if present, and ignore the
             // method
             baseMethod.getComponentManager().log( LogService.LOG_ERROR, "{0} method [{1}] not found", new Object[]
                 { baseMethod.getMethodNamePrefix(), baseMethod.getMethodName() }, null );
-            return false;
+            return null;
         }
 
 
@@ -587,7 +599,7 @@ abstract class BaseMethod
         private static final State INSTANCE = new Resolved();
 
 
-        public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
             throws InvocationTargetException
         {
             baseMethod.getComponentManager().log( LogService.LOG_DEBUG, "invoking {0}: {1}", new Object[]

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java Wed May  9 18:25:22 2012
@@ -195,7 +195,7 @@ public class BindMethod extends BaseMeth
         if ( suitableMethodNotAccessible )
         {
             getComponentManager().log( LogService.LOG_ERROR,
-                "DependencyManager : Suitable but non-accessible method found in class {0}", new Object[]
+                "doFindMethod: Suitable but non-accessible method found in class {0}", new Object[]
                     { targetClass.getName() }, null );
             throw new SuitableMethodNotAccessibleException();
         }
@@ -428,7 +428,7 @@ public class BindMethod extends BaseMeth
                 // reference's interface attribute
                 if ( theParameter.isAssignableFrom( parameterClass ) )
                 {
-                    if ( accept( method, acceptPrivate, acceptPackage ) )
+                    if ( accept( method, acceptPrivate, acceptPackage, false ) )
                     {
                         return method;
                     }
@@ -521,7 +521,7 @@ public class BindMethod extends BaseMeth
                 // parameters must be refclass,map
                 if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == MAP_CLASS )
                 {
-                    if ( accept( method, acceptPrivate, acceptPackage ) )
+                    if ( accept( method, acceptPrivate, acceptPackage, false ) )
                     {
                         return method;
                     }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java Wed May  9 18:25:22 2012
@@ -46,4 +46,5 @@ public class DeactivateMethod extends Ac
     {
         return "deactivate";
     }
+
 }

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/MethodResult.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/MethodResult.java?rev=1336331&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/MethodResult.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/MethodResult.java Wed May  9 18:25:22 2012
@@ -0,0 +1,63 @@
+/*
+ * 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.impl.helper;
+
+import java.util.Map;
+
+/**
+ * The <code>MethodResult</code> conveys the return value of one of the
+ * activate, modify, and deactivate methods.
+ * <p>
+ * Note that the method returning <code>null</code> or being defined as
+ * <code>void</code> is not the same thing. If the method returns
+ * <code>null</code> an instance of this class is returned whose
+ * {@link #getResult()} method returns <code>null</code>. If the method is
+ * defined as <code>void</code> the special instance {@link #VOID} is returned.
+ */
+public class MethodResult
+{
+
+    /**
+     * Predefined instance indicating a successfull call to a void method.
+     */
+    public static final MethodResult VOID = new MethodResult(false, null);
+
+    /**
+     * The actual result from the method, which may be <code>null</code>.
+     */
+    private final Map result;
+
+    private final boolean hasResult;
+
+    MethodResult(final boolean hasResult, final Map result)
+    {
+        this.hasResult = hasResult;
+        this.result = result;
+    }
+
+    public boolean hasResult()
+    {
+        return hasResult;
+    }
+
+    public Map getResult()
+    {
+        return result;
+    }
+}

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Wed May  9 18:25:22 2012
@@ -797,7 +797,7 @@ public abstract class AbstractComponentM
 
     public abstract Dictionary getProperties();
 
-    public abstract void resetComponentProperties( Dictionary properties );
+    public abstract void setServiceProperties(Dictionary serviceProperties, boolean updateServiceRegistration);
 
     /**
      * Returns the subset of component properties to be used as service

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java Wed May  9 18:25:22 2012
@@ -27,7 +27,6 @@ import org.apache.felix.scr.impl.helper.
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.ComponentInstance;
 
 
@@ -135,9 +134,9 @@ public class ComponentContextImpl implem
 
     //---------- Speculative MutableProperties interface ------------------------------
 
-    public void updateProperties(Dictionary properties)
+    public void setServiceProperties(Dictionary properties)
     {
-        getComponentManager().resetComponentProperties(properties);
+        getComponentManager().setServiceProperties(properties, true);
     }
 
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java Wed May  9 18:25:22 2012
@@ -209,7 +209,8 @@ public class ComponentFactoryImpl extend
         return props;
     }
 
-    public void resetComponentProperties(Dictionary properties) {
+    public void setServiceProperties(Dictionary serviceProperties, boolean updateServiceRegistration)
+    {
         throw new IllegalStateException( "ComponentFactory service properties are immutable" );
     }
 

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java Wed May  9 18:25:22 2012
@@ -31,6 +31,7 @@ import org.apache.felix.scr.Component;
 import org.apache.felix.scr.Reference;
 import org.apache.felix.scr.impl.BundleComponentActivator;
 import org.apache.felix.scr.impl.helper.BindMethod;
+import org.apache.felix.scr.impl.helper.MethodResult;
 import org.apache.felix.scr.impl.helper.UnbindMethod;
 import org.apache.felix.scr.impl.helper.UpdatedMethod;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
@@ -1059,7 +1060,7 @@ public class DependencyManager implement
                     {
                         return getService( ref );
                     }
-                }, true );
+                }, MethodResult.VOID ) != null;
             }
 
             // Concurrency Issue: The component instance still exists but
@@ -1112,6 +1113,7 @@ public class DependencyManager implement
     {
         // The updated method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
+        //TODO should updated methods be able to change config properties?
         if ( m_componentInstance != null )
         {
             m_updated.invoke( m_componentInstance, new BindMethod.Service()
@@ -1126,7 +1128,7 @@ public class DependencyManager implement
                 {
                     return getService( ref );
                 }
-            }, true );
+            }, MethodResult.VOID );
         }
         else
         {
@@ -1167,7 +1169,7 @@ public class DependencyManager implement
                 {
                     return getService( ref );
                 }
-            }, true );
+            }, MethodResult.VOID );
         }
         else
         {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java Wed May  9 18:25:22 2012
@@ -23,11 +23,14 @@ import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.felix.scr.impl.BundleComponentActivator;
 import org.apache.felix.scr.impl.config.ComponentHolder;
 import org.apache.felix.scr.impl.helper.ActivateMethod;
+import org.apache.felix.scr.impl.helper.ActivateMethod.ActivatorParameter;
 import org.apache.felix.scr.impl.helper.DeactivateMethod;
+import org.apache.felix.scr.impl.helper.MethodResult;
 import org.apache.felix.scr.impl.helper.ModifiedMethod;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
@@ -71,7 +74,7 @@ public class ImmediateComponentManager e
 
     // properties supplied ot ExtComponentContext.updateProperties
     // null if properties are not to be overwritten
-    private Dictionary m_propertiesOverwrite;
+    private Dictionary m_serviceProperties;
 
     // the component properties from the Configuration Admin Service
     // this is null, if none exist or none are provided
@@ -140,7 +143,7 @@ public class ImmediateComponentManager e
         m_implementationObject = null;
         m_componentContext = null;
         m_properties = null;
-        m_propertiesOverwrite = null;
+        m_serviceProperties = null;
     }
 
 
@@ -228,8 +231,9 @@ public class ImmediateComponentManager e
         }
 
         // 4. Call the activate method, if present
-        if ( !m_activateMethod.invoke( implementationObject,
-            new ActivateMethod.ActivatorParameter( componentContext, 1 ), false ) )
+        final MethodResult result = m_activateMethod.invoke(implementationObject, new ActivatorParameter(
+            componentContext, 1), null);
+        if (result == null)
         {
             // 112.5.8 If the activate method throws an exception, SCR must log an error message
             // containing the exception with the Log Service and activation fails
@@ -242,6 +246,10 @@ public class ImmediateComponentManager e
 
             return null;
         }
+        else if (result.hasResult())
+        {
+            setServiceProperties(result.getResult(), true);
+        }
 
         return implementationObject;
     }
@@ -262,8 +270,12 @@ public class ImmediateComponentManager e
         // don't care for the result, the error (acccording to 112.5.12 If the deactivate
         // method throws an exception, SCR must log an error message containing the
         // exception with the Log Service and continue) has already been logged
-        m_deactivateMethod.invoke( implementationObject, new ActivateMethod.ActivatorParameter( componentContext,
-            reason ), true );
+        final MethodResult result = m_deactivateMethod.invoke( implementationObject, new ActivatorParameter( componentContext,
+            reason ), null );
+        if (result != null && result.hasResult())
+        {
+            setServiceProperties(result.getResult(), true);
+        }
 
         // 2. Unbind any bound services
         Iterator it = getReversedDependencyManagers();
@@ -348,16 +360,13 @@ public class ImmediateComponentManager e
                 }
             }
 
-            // 3. overwrite as per ExtComponentContext.updateProperties
-            copyTo( props, m_propertiesOverwrite );
-
-            // 4. overlay with Configuration Admin properties
+            // 3. overlay with Configuration Admin properties
             copyTo( props, m_configurationProperties );
 
-            // 5. copy any component factory properties, not supported yet
+            // 4. copy any component factory properties, not supported yet
             copyTo( props, m_factoryProperties );
 
-            // 6. set component.name and component.id
+            // 5. set component.name and component.id
             props.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
             props.put( ComponentConstants.COMPONENT_ID, new Long( getId() ) );
 
@@ -368,17 +377,69 @@ public class ImmediateComponentManager e
     }
 
 
-    public void resetComponentProperties( Dictionary properties )
+    public void setServiceProperties(Map serviceProperties, boolean updateServiceRegistration)
     {
-        m_propertiesOverwrite = copyTo( null, properties );
-        m_properties = null;
-        Dictionary serviceProperties = getServiceProperties();
-        if ( getServiceRegistration() != null )
+        Dictionary serviceProps = (serviceProperties == null) ? null : new Hashtable(serviceProperties);
+        setServiceProperties(serviceProps, updateServiceRegistration);
+    }
+
+    public void setServiceProperties(Dictionary serviceProperties, boolean updateServiceRegistration)
+    {
+        if ( serviceProperties == null || serviceProperties.isEmpty() )
+        {
+            m_serviceProperties = null;
+        }
+        else
+        {
+            m_serviceProperties = copyTo(null, serviceProperties);
+            // set component.name and component.id
+            m_serviceProperties.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
+            m_serviceProperties.put( ComponentConstants.COMPONENT_ID, new Long( getId() ) );
+        }
+
+        if (updateServiceRegistration)
         {
-            getServiceRegistration().setProperties( serviceProperties );
+            updateServiceRegistration();
         }
     }
 
+    public Dictionary getServiceProperties() {
+        if ( m_serviceProperties != null )
+        {
+            return m_serviceProperties;
+        }
+        return super.getServiceProperties();
+    }
+
+    private void updateServiceRegistration()
+    {
+        ServiceRegistration sr = getServiceRegistration();
+        if (sr != null)
+        {
+            try
+            {
+                // Don't propagate if service properties did not change.
+                final Dictionary regProps = getServiceProperties();
+                if (!servicePropertiesMatches(sr, regProps))
+                {
+                    sr.setProperties(regProps);
+                }
+            }
+            catch (IllegalStateException ise)
+            {
+                // service has been unregistered asynchronously, ignore
+            }
+            catch (IllegalArgumentException iae)
+            {
+                log(LogService.LOG_ERROR,
+                    "Unexpected configuration property problem when updating service registration", iae);
+            }
+            catch (Throwable t)
+            {
+                log(LogService.LOG_ERROR, "Unexpected problem when updating service registration", t);
+            }
+        }
+    }
 
     /**
      * Called by the Configuration Admin Service to update the component with
@@ -487,8 +548,9 @@ public class ImmediateComponentManager e
         // invariant: modify method existing and no static bound service changes
 
         // 4. call method (nothing to do when failed, since it has already been logged)
-        if ( !m_modifyMethod.invoke( getInstance(), new ActivateMethod.ActivatorParameter( m_componentContext, -1 ),
-            true ) )
+        final MethodResult result = m_modifyMethod.invoke(getInstance(),
+            new ActivatorParameter(m_componentContext, -1), null);
+        if (result == null)
         {
             // log an error if the declared method cannot be found
             log( LogService.LOG_ERROR, "Declared modify method ''{0}'' cannot be found, configuring by reactivation",
@@ -496,6 +558,10 @@ public class ImmediateComponentManager e
                     { getComponentMetadata().getModified() }, null );
             return false;
         }
+        else if (result.hasResult())
+        {
+            setServiceProperties(result.getResult(), false);
+        }
 
         // 5. update the target filter on the services now, this may still
         // result in unsatisfied dependencies, in which case we abort
@@ -510,34 +576,7 @@ public class ImmediateComponentManager e
         }
 
         // 6. update service registration properties
-        ServiceRegistration sr = getServiceRegistration();
-        if ( sr != null )
-        {
-            try
-            {
-                // Don't propagate if service properties did not change.
-                final Dictionary regProps = getServiceProperties();
-                if ( !servicePropertiesMatches( sr, regProps ) )
-                {
-                    sr.setProperties( regProps );
-                }
-            }
-            catch ( IllegalStateException ise )
-            {
-                // service has been unregistered asynchronously, ignore
-            }
-            catch ( IllegalArgumentException iae )
-            {
-                log( LogService.LOG_ERROR,
-                    "Unexpected configuration property problem when updating service registration",
-                    iae );
-            }
-            catch ( Throwable t )
-            {
-                log( LogService.LOG_ERROR, "Unexpected problem when updating service registration",
-                    t );
-            }
-        }
+        updateServiceRegistration();
 
         // 7. everything set and done, the component has been udpated
         return true;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java Wed May  9 18:25:22 2012
@@ -364,7 +364,7 @@ public class ComponentMetadata
 
     /**
      * Returns <code>true</code> if the metadata declaration has used the
-     * Declarative Services version 1.1-felixnamespace or a later namespace.
+     * Declarative Services version 1.1-felix namespace or a later namespace.
      *
      * @see <a href="https://issues.apache.org/jira/browse/FELIX-1893">FELIX-1893</a>
      */
@@ -375,6 +375,28 @@ public class ComponentMetadata
 
 
     /**
+     * Returns <code>true</code> if the metadata declaration has used the
+     * Declarative Services version 1.2 namespace or a later namespace.
+     */
+    public boolean isDS12()
+    {
+        return getNamespaceCode() >= XmlHandler.DS_VERSION_1_2;
+    }
+
+
+    /**
+     * Returns <code>true</code> if the metadata declaration has used the
+     * Declarative Services version 1.2-felix namespace or a later namespace.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/FELIX-3377">FELIX-3377</a>
+     */
+    public boolean isDS12Felix()
+    {
+        return getNamespaceCode() >= XmlHandler.DS_VERSION_1_2_FELIX;
+    }
+
+
+    /**
      * Returns the name of the component
      *
      * @return A string containing the name of the component

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java Wed May  9 18:25:22 2012
@@ -54,6 +54,12 @@ public class XmlHandler implements KXml2
     // Namespace URI of DS 1.1-felix (see FELIX-1893)
     public static final String NAMESPACE_URI_1_1_FELIX = "http://felix.apache.org/xmlns/scr/v1.1.0-felix";
 
+    // Namespace URI of DS 1.2
+    public static final String NAMESPACE_URI_1_2 = "http://www.osgi.org/xmlns/scr/v1.2.0";
+
+    // Namespace URI of DS 1.2-felix (see FELIX-3377)
+    public static final String NAMESPACE_URI_1_2_FELIX = "http://felix.apache.org/xmlns/scr/v1.2.0-felix";
+
     // namespace code for non-DS namespace
     public static final int DS_VERSION_NONE = -1;
 
@@ -66,6 +72,12 @@ public class XmlHandler implements KXml2
     // namespace code for the DS 1.1-felix specification
     public static final int DS_VERSION_1_1_FELIX = 2;
 
+    // namespace code for the DS 1.2 specification
+    public static final int DS_VERSION_1_2 = 3;
+
+    // namespace code for the DS 1.1-felix specification
+    public static final int DS_VERSION_1_2_FELIX = 4;
+
     // mapping of namespace URI to namespace code
     private static final Map NAMESPACE_CODE_MAP;
 
@@ -103,6 +115,8 @@ public class XmlHandler implements KXml2
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI, new Integer( DS_VERSION_1_0 ) );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_1, new Integer( DS_VERSION_1_1 ) );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_1_FELIX, new Integer( DS_VERSION_1_1_FELIX ) );
+        NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_2, new Integer( DS_VERSION_1_2 ) );
+        NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_2_FELIX, new Integer( DS_VERSION_1_2_FELIX ) );
     }
 
 

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java Wed May  9 18:25:22 2012
@@ -55,7 +55,7 @@ public class ActivateMethodTest extends 
     {
         super.setUp();
 
-        m_ctx = (ComponentContext) EasyMock.createNiceMock( ComponentContext.class );
+        m_ctx = (ComponentContext) EasyMock.createNiceMock(ComponentContext.class);
         EasyMock.expect( m_ctx.getProperties() ).andReturn( new Hashtable() ).anyTimes();
         EasyMock.replay( new Object[]
             { m_ctx } );
@@ -272,7 +272,7 @@ public class ActivateMethodTest extends 
         };
         ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
         ActivateMethod am = new ActivateMethod( icm, methodName, methodName != null, obj.getClass() );
-        am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), false );
+        am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), null );
         Method m = get(am, "m_method");
         assertNotNull( m );
         assertEquals( methodName, m.getName() );
@@ -300,7 +300,7 @@ public class ActivateMethodTest extends 
         };
         ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
         ActivateMethod am = new ActivateMethod( icm, methodName, methodName != null, obj.getClass() );
-        am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), false );
+        am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), null );
         assertNull( get( am, "m_method" ) );
         assertNull( obj.getCalledMethod() );
     }
@@ -310,7 +310,7 @@ public class ActivateMethodTest extends 
         throws NoSuchMethodException
     {
         Method method = ACCEPT_METHOD_CLASS.getDeclaredMethod( methodName, null );
-        boolean accepted = BaseMethod.accept( method, acceptPrivate, acceptPackage );
+        boolean accepted = BaseMethod.accept( method, acceptPrivate, acceptPackage, false );
         assertEquals( expected, accepted );
     }
 

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java Wed May  9 18:25:22 2012
@@ -441,7 +441,7 @@ public class BindMethodTest extends Test
         ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
         BindMethod bm = new BindMethod( icm, methodName, component.getClass(), "reference",
             FakeService.class.getName() );
-        bm.invoke( component, m_service, true );
+        bm.invoke( component, m_service, null );
         assertEquals( expectCallPerformed, component.callPerformed );
     }
 }

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java Wed May  9 18:25:22 2012
@@ -106,7 +106,7 @@ public class XmlHandlerTest extends Test
         final List metadataList = readMetadataFromString( "<scr:component xmlns:scr=\"http://www.osgi.org/xmlns/scr/v1.1.0\" name=\"n\" ><implementation class=\"n\"/></scr:component>" );
         assertEquals( "1 Descriptor expected", 1, metadataList.size() );
         final ComponentMetadata metadata = ( ComponentMetadata ) metadataList.get( 0 );
-        assertEquals( "Expect NS 1.0.0", XmlHandler.DS_VERSION_1_1, metadata.getNamespaceCode() );
+        assertEquals( "Expect NS 1.1.0", XmlHandler.DS_VERSION_1_1, metadata.getNamespaceCode() );
     }
 
 
@@ -115,7 +115,25 @@ public class XmlHandlerTest extends Test
         final List metadataList = readMetadataFromString( "<scr:component xmlns:scr=\"http://felix.apache.org/xmlns/scr/v1.1.0-felix\" name=\"n\" ><implementation class=\"n\"/></scr:component>" );
         assertEquals( "1 Descriptor expected", 1, metadataList.size() );
         final ComponentMetadata metadata = ( ComponentMetadata ) metadataList.get( 0 );
-        assertEquals( "Expect NS 1.0.0", XmlHandler.DS_VERSION_1_1_FELIX, metadata.getNamespaceCode() );
+        assertEquals( "Expect NS 1.1.0-felix", XmlHandler.DS_VERSION_1_1_FELIX, metadata.getNamespaceCode() );
+    }
+
+
+    public void test_namespace_1_2_0() throws Exception
+    {
+        final List metadataList = readMetadataFromString( "<scr:component xmlns:scr=\"http://www.osgi.org/xmlns/scr/v1.2.0\" name=\"n\" ><implementation class=\"n\"/></scr:component>" );
+        assertEquals( "1 Descriptor expected", 1, metadataList.size() );
+        final ComponentMetadata metadata = ( ComponentMetadata ) metadataList.get( 0 );
+        assertEquals( "Expect NS 1.2.0", XmlHandler.DS_VERSION_1_2, metadata.getNamespaceCode() );
+    }
+
+
+    public void test_namespace_1_2_0_felix() throws Exception
+    {
+        final List metadataList = readMetadataFromString( "<scr:component xmlns:scr=\"http://felix.apache.org/xmlns/scr/v1.2.0-felix\" name=\"n\" ><implementation class=\"n\"/></scr:component>" );
+        assertEquals( "1 Descriptor expected", 1, metadataList.size() );
+        final ComponentMetadata metadata = ( ComponentMetadata ) metadataList.get( 0 );
+        assertEquals( "Expect NS 1.2.0-felix", XmlHandler.DS_VERSION_1_2_FELIX, metadata.getNamespaceCode() );
     }
 
 

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java Wed May  9 18:25:22 2012
@@ -35,7 +35,7 @@ public class ComponentConfigurationTest 
     static
     {
         // uncomment to enable debugging of this test class
-        // paxRunnerVmOption = DEBUG_VM_OPTION;
+        //  paxRunnerVmOption = DEBUG_VM_OPTION;
     }
 
 

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/MutablePropertiesTest.java Wed May  9 18:25:22 2012
@@ -30,6 +30,7 @@ import org.apache.felix.scr.integration.
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 
 
@@ -40,20 +41,22 @@ public class MutablePropertiesTest exten
     static
     {
         // uncomment to enable debugging of this test class
-//        paxRunnerVmOption = DEBUG_VM_OPTION;
+        // paxRunnerVmOption = DEBUG_VM_OPTION;
 
         descriptorFile = "/integration_test_mutable_properties.xml";
     }
 
 
     @Test
-    public void test_mutable_properties()
+    public void test_mutable_properties() throws InvalidSyntaxException
     {
         final Component component = findComponentByName( "components.mutable.properties" );
         TestCase.assertNotNull( component );
         TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
 
-        ServiceReference serviceReference = bundleContext.getServiceReference( MutatingService.class.getName() );
+        ServiceReference[] serviceReferences = bundleContext.getServiceReferences( MutatingService.class.getName(), "(service.pid=components.mutable.properties)" );
+        TestCase.assertEquals( 1, serviceReferences.length );
+        ServiceReference serviceReference = serviceReferences[0];
         checkProperties( serviceReference, 8, "otherValue", "p1", "p2" );
 
         //update theValue
@@ -62,20 +65,52 @@ public class MutablePropertiesTest exten
         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");
+        checkProperties(serviceReference, 5, "anotherValue", "p1", "p2");
 
         //configure with configAdmin
         configure( "components.mutable.properties" );
         delay();
-        checkProperties(serviceReference, 8, PROP_NAME, "p1", "p2");
+        //no change
+        checkProperties(serviceReference, 5, "anotherValue", "p1", "p2");
 
-        //check that a property from config admin can't be changed
+        //check that removing config switches back to defaults modified by config admin
+        s.updateProperties(null);
+        checkProperties( serviceReference, 8, "theValue", "p1", "p2" );
+
+        bundleContext.ungetService(serviceReference);
+    }
+
+    @Test
+    public void test_mutable_properties_returned() throws InvalidSyntaxException
+    {
+        final Component component = findComponentByName( "components.mutable.properties2" );
+        TestCase.assertNotNull( component );
+        TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
+
+        ServiceReference[] serviceReferences = bundleContext.getServiceReferences( MutatingService.class.getName(), "(service.pid=components.mutable.properties2)" );
+        TestCase.assertEquals( 1, serviceReferences.length );
+        ServiceReference serviceReference = serviceReferences[0];
+        checkProperties( serviceReference, 8, "otherValue", "p1", "p2" );
+
+        //update theValue
+        MutatingService s = ( MutatingService ) bundleContext.getService( serviceReference );
+        Assert.assertNotNull(s);
+        checkProperties( serviceReference, 8, "anotherValue1", "p1", "p2" );
+        TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+        Dictionary d = new Hashtable(Collections.singletonMap( PROP_NAME, "anotherValue" ));
         s.updateProperties(d);
-        checkProperties(serviceReference, 8, PROP_NAME, "p1", "p2");
+        checkProperties(serviceReference, 5, "anotherValue", "p1", "p2");
+
+        //configure with configAdmin
+        configure( "components.mutable.properties2" );
+        delay();
+        delay();
+        //no change
+        checkProperties(serviceReference, 8, "anotherValue2", "p1", "p2");
 
-        //check that another one can
-        s.updateProperties(new Hashtable(Collections.singletonMap( "p1", "changed" )));
-        checkProperties(serviceReference, 8, PROP_NAME, "changed", "p2");
+        //check that removing config switches back to defaults modified by config admin
+        s.updateProperties(null);
+        checkProperties( serviceReference, 8, "theValue", "p1", "p2" );
 
         bundleContext.ungetService(serviceReference);
     }
@@ -83,8 +118,10 @@ public class MutablePropertiesTest exten
     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"));
+        if ( count > 5 ) {
+            Assert.assertEquals(p1, serviceReference.getProperty("p1"));
+            Assert.assertEquals(p2, serviceReference.getProperty("p2"));
+        }
     }
 
 

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/components/MutatingServiceImpl.java Wed May  9 18:25:22 2012
@@ -20,6 +20,8 @@ package org.apache.felix.scr.integration
 
 
 import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
 
 import org.apache.felix.scr.component.ExtComponentContext;
 import org.osgi.service.component.ComponentContext;
@@ -39,8 +41,30 @@ public class MutatingServiceImpl impleme
 
     }
 
+    private Map activateMutate( ComponentContext activateContext )
+    {
+        this.activateContext = activateContext;
+        Map result = new Hashtable( (Map )activateContext.getProperties() );
+        result.put( "theValue", "anotherValue1");
+        return result;
+    }
+
+    private Map modifiedMutate( ComponentContext activateContext )
+    {
+        Map result = new Hashtable( (Map )activateContext.getProperties() );
+        result.put( "theValue", "anotherValue2");
+        return result;
+    }
+
+    private Map deactivateMutate( ComponentContext activateContext )
+    {
+        Map result = new Hashtable( (Map )activateContext.getProperties() );
+        result.put( "theValue", "anotherValue3");
+        return result;
+    }
+
     public void updateProperties(Dictionary changes) {
-        ((ExtComponentContext)activateContext).updateProperties(changes);
+        ((ExtComponentContext)activateContext).setServiceProperties(changes);
     }
 
 }

Modified: felix/trunk/scr/src/test/resources/integration_test_mutable_properties.xml
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/resources/integration_test_mutable_properties.xml?rev=1336331&r1=1336330&r2=1336331&view=diff
==============================================================================
--- felix/trunk/scr/src/test/resources/integration_test_mutable_properties.xml (original)
+++ felix/trunk/scr/src/test/resources/integration_test_mutable_properties.xml Wed May  9 18:25:22 2012
@@ -19,7 +19,7 @@
 -->
 <components>
     <scr:component name="components.mutable.properties"
-            xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
+            xmlns:scr="http://felix.apache.org/xmlns/scr/v1.2.0-felix"
             enabled="true"
             configuration-policy="optional"
             activate="activate"
@@ -33,4 +33,20 @@
         <property name="p1" value="p1" />
         <property name="p2" value="p2" />
     </scr:component>
+    <scr:component name="components.mutable.properties2"
+            xmlns:scr="http://felix.apache.org/xmlns/scr/v1.2.0-felix"
+            enabled="true"
+            configuration-policy="optional"
+            activate="activateMutate"
+            modified="modifiedMutate"
+            deactivate="deactivateMutate">
+        <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.properties2" />
+        <property name="theValue" value="otherValue" />
+        <property name="p1" value="p1" />
+        <property name="p2" value="p2" />
+    </scr:component>
 </components>