You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2014/11/10 06:51:05 UTC

svn commit: r1637793 - in /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl: helper/ manager/ metadata/ runtime/

Author: cziegeler
Date: Mon Nov 10 05:51:04 2014
New Revision: 1637793

URL: http://svn.apache.org/r1637793
Log:
FELIX-4631 : [DS][R6/RFC212] Implement field injection. WiP

Added:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java   (with props)
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethods.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReferenceMethods.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/SingleComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethods.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethods.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethods.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethods.java Mon Nov 10 05:51:04 2014
@@ -71,4 +71,9 @@ public class BindMethods implements Refe
     {
         return m_updated;
     }
+
+    public InitReferenceMethod getInit()
+    {
+        return null;
+    }
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java Mon Nov 10 05:51:04 2014
@@ -20,6 +20,7 @@ package org.apache.felix.scr.impl.helper
 
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.felix.scr.impl.Activator;
@@ -45,6 +46,7 @@ public class ClassUtils
     public static final Class<?> MAP_ENTRY_CLASS = Map.Entry.class;
 
     public static final Class<?> COLLECTION_CLASS = Collection.class;
+    public static final Class<?> LIST_CLASS = List.class;
 
     static {
         Class<?> serviceObjectsClass = null;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java Mon Nov 10 05:51:04 2014
@@ -24,8 +24,13 @@ import java.lang.reflect.InvocationTarge
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 import org.apache.felix.scr.impl.manager.ComponentContextImpl;
 import org.apache.felix.scr.impl.manager.RefPair;
@@ -61,8 +66,8 @@ public class FieldHandler
     /** State handling. */
     private volatile State state;
 
-    /** Last ref pair used to set. */
-    private volatile RefPair<?, ?> lastRefPair;
+    /** Mapping of ref pairs to value bound */
+    private final Map<RefPair<?, ?>, Object> boundValues = new IdentityHashMap<RefPair<?,?>, Object>();
 
     /**
      * Create a new field handler
@@ -299,6 +304,14 @@ public class FieldHandler
                     return null;
                 }
             }
+
+            // the field must not be final
+            if ( Modifier.isFinal(f.getModifiers()) )
+            {
+                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
+                        {metadata.getField(), this.componentClass}, null );
+                return null;
+            }
         }
         else
         {
@@ -310,6 +323,57 @@ public class FieldHandler
                 return null;
             }
 
+            // if the field is dynamic with the replace strategy it has to be volatile
+            if ( !metadata.isStatic() && metadata.getFieldStrategy().equals(ReferenceMetadata.FIELD_STRATEGY_REPLACE) )
+            {
+                if ( !Modifier.isVolatile(f.getModifiers()) )
+                {
+                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
+                            {metadata.getField(), this.componentClass}, null );
+                    return null;
+                }
+            }
+
+            // replace strategy: field must not be final
+            //                   only collection and list allowed
+            if ( metadata.getFieldStrategy().equals(ReferenceMetadata.FIELD_STRATEGY_REPLACE) )
+            {
+                if ( Modifier.isFinal(f.getModifiers()) )
+                {
+                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
+                            {metadata.getField(), this.componentClass}, null );
+                    return null;
+                }
+                if ( fieldType != ClassUtils.LIST_CLASS && fieldType != ClassUtils.COLLECTION_CLASS )
+                {
+                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}."+
+                    " It must be one of java.util.Collection or java.util.List.",
+                    new Object[] {metadata.getField(), this.componentClass, fieldType.getName()}, null );
+                    return null;
+
+                }
+            }
+
+            if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICE.equals(metadata.getFieldValueType()) )
+            {
+                valueType = ParamType.serviceType;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(metadata.getFieldValueType()) )
+            {
+                valueType = ParamType.serviceReference;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(metadata.getFieldValueType()) )
+            {
+                valueType = ParamType.serviceObjects;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(metadata.getFieldValueType()) )
+            {
+                valueType = ParamType.map;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(metadata.getFieldValueType()) )
+            {
+                valueType = ParamType.tuple;
+            }
         }
         return f;
     }
@@ -331,13 +395,72 @@ public class FieldHandler
             case tuple : final Object tupleKey = new ReadOnlyDictionary<String, Object>( refPair.getRef() );
                          final Object tupleValue = refPair.getServiceObject(key);
                          final Map<?, ?> tupleMap = Collections.singletonMap(tupleKey, tupleValue);
-                         obj = tupleMap.entrySet().iterator().next();
+                         obj = tupleMap.entrySet().iterator().next(); // TODO check/make entry comparable
                          break;
             default: obj = null;
         }
         return obj;
     }
 
+    private boolean initField(final Object componentInstance,
+            final SimpleLogger logger )
+    {
+        try
+        {
+            if ( metadata.isMultiple()
+                 && !metadata.isStatic() )
+            {
+                if ( ReferenceMetadata.FIELD_STRATEGY_REPLACE.equals(metadata.getFieldStrategy()) )
+                {
+                    this.setFieldValue(componentInstance, Collections.emptyList());
+                }
+                else
+                {
+                    final Class<?> fieldType = this.field.getType();
+
+                    // update strategy: if DS implementation provides collection implementation
+                    //                  only list and collection are allowed, field must not be final
+                    final Object providedImpl = this.getFieldValue(componentInstance);
+                    if ( providedImpl == null)
+                    {
+                        if ( Modifier.isFinal(this.field.getModifiers()) )
+                        {
+                            logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
+                                    {metadata.getField(), this.componentClass}, null );
+                            return false;
+                        }
+                        if ( fieldType != ClassUtils.LIST_CLASS && fieldType != ClassUtils.COLLECTION_CLASS )
+                        {
+                            logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}."+
+                            " It must be one of java.util.Collection or java.util.List.",
+                                new Object[] {metadata.getField(), this.componentClass, fieldType.getName()}, null );
+                            return false;
+                        }
+                        this.setFieldValue(componentInstance, new CopyOnWriteArraySet<Object>());
+                    }
+                }
+            }
+        }
+        catch ( final InvocationTargetException ite)
+        {
+            logger.log( LogService.LOG_ERROR, "Field {0} in component {1} can't be initialized.",
+                    new Object[] {metadata.getField(), this.componentClass}, ite );
+            return false;
+
+        }
+        return true;
+    }
+
+    private Collection<Object> getReplaceCollection() {
+        // TODO sort!
+        final List<Object> objects = new ArrayList<Object>();
+        for(final Object val : this.boundValues.values())
+        {
+            objects.add(val);
+        }
+        return objects;
+    }
+
     private MethodResult updateField( final METHOD_TYPE mType,
             final Object componentInstance,
             final BindParameters bp,
@@ -356,29 +479,25 @@ public class FieldHandler
                 if ( this.metadata.isOptional() && !this.metadata.isStatic() )
                 {
                     // we only reset if it was previously set with this value
-                    if ( refPair == lastRefPair )
+                    if ( this.boundValues.size() == 1 )
                     {
                         this.setFieldValue(componentInstance, null);
-                        this.lastRefPair = null;
                     }
                 }
-                else
-                {
-                    this.lastRefPair = null;
-                }
+                this.boundValues.remove(refPair);
             }
             // updated needs only be done, if reference is dynamic and optional
+            // and the value type is map or tuple
             else if ( mType == METHOD_TYPE.UPDATED )
             {
                 if ( this.metadata.isOptional() && !this.metadata.isStatic() )
                 {
-                    final Object obj = getValue(key, refPair);
-                    this.setFieldValue(componentInstance, obj);
-                    this.lastRefPair = refPair;
-                }
-                else
-                {
-                    this.lastRefPair = null;
+                    if ( this.valueType == ParamType.map || this.valueType == ParamType.tuple )
+                    {
+                        final Object obj = getValue(key, refPair);
+                        this.setFieldValue(componentInstance, obj);
+                        this.boundValues.put(refPair, obj);
+                    }
                 }
             }
             // bind needs always be done
@@ -386,7 +505,69 @@ public class FieldHandler
             {
                 final Object obj = getValue(key, refPair);
                 this.setFieldValue(componentInstance, obj);
-                this.lastRefPair = refPair;
+                this.boundValues.put(refPair, obj);
+            }
+        }
+        else
+        {
+            // multiple references
+
+            // bind: replace or update the field
+            if ( mType == METHOD_TYPE.BIND )
+            {
+                final Object obj = getValue(key, refPair);
+                this.boundValues.put(refPair, obj);
+                if ( ReferenceMetadata.FIELD_STRATEGY_REPLACE.equals(metadata.getFieldStrategy()) )
+                {
+                    this.setFieldValue(componentInstance, getReplaceCollection());
+                }
+                else
+                {
+                    @SuppressWarnings("unchecked")
+                    final Collection<Object> col = (Collection<Object>)this.getFieldValue(componentInstance);
+                    col.add(obj);
+                }
+            }
+            // unbind needs only be done, if reference is dynamic
+            else if ( mType == METHOD_TYPE.UNBIND)
+            {
+                if ( !metadata.isStatic() )
+                {
+                    final Object obj = this.boundValues.remove(refPair);
+                    if ( ReferenceMetadata.FIELD_STRATEGY_REPLACE.equals(metadata.getFieldStrategy()) )
+                    {
+                        this.setFieldValue(componentInstance, getReplaceCollection());
+                    }
+                    else
+                    {
+                        @SuppressWarnings("unchecked")
+                        final Collection<Object> col = (Collection<Object>)this.getFieldValue(componentInstance);
+                        col.remove(obj);
+                    }
+                }
+            }
+            // updated needs only be done, if reference is dynamic
+            // and the value type is map or tuple
+            else if ( mType == METHOD_TYPE.UPDATED)
+            {
+                if ( !this.metadata.isStatic()
+                     && (this.valueType == ParamType.map || this.valueType == ParamType.tuple ) )
+                {
+                    final Object obj = getValue(key, refPair);
+                    final Object oldObj = this.boundValues.put(refPair, obj);
+
+                    if ( ReferenceMetadata.FIELD_STRATEGY_REPLACE.equals(metadata.getFieldStrategy()) )
+                    {
+                        this.setFieldValue(componentInstance, getReplaceCollection());
+                    }
+                    else
+                    {
+                        @SuppressWarnings("unchecked")
+                        final Collection<Object> col = (Collection<Object>)this.getFieldValue(componentInstance);
+                        col.add(obj);
+                        col.remove(oldObj);
+                    }
+                }
             }
         }
 
@@ -617,13 +798,16 @@ public class FieldHandler
         return this.state.fieldExists( this, logger );
     }
 
-    public static final class ReferenceMethodImpl implements ReferenceMethod {
+    public static final class ReferenceMethodImpl
+        implements ReferenceMethod
+    {
 
         private final METHOD_TYPE methodType;
 
         private final FieldHandler handler;
 
-        public ReferenceMethodImpl(final METHOD_TYPE mt, final FieldHandler handler) {
+        public ReferenceMethodImpl(final METHOD_TYPE mt, final FieldHandler handler)
+        {
             this.methodType = mt;
             this.handler = handler;
         }
@@ -631,7 +815,8 @@ public class FieldHandler
         public MethodResult invoke(final Object componentInstance,
                 final BindParameters rawParameter,
                 final MethodResult methodCallFailureResult,
-                final SimpleLogger logger) {
+                final SimpleLogger logger)
+        {
             try
             {
                 return handler.state.invoke( handler,
@@ -652,7 +837,8 @@ public class FieldHandler
         public <S, T> boolean getServiceObject(final ComponentContextImpl<S> key,
                 final RefPair<S, T> refPair,
                 final BundleContext context,
-                final SimpleLogger logger) {
+                final SimpleLogger logger)
+        {
             if ( methodType != METHOD_TYPE.UNBIND )
             {
                 //??? this resolves which we need.... better way?
@@ -667,15 +853,37 @@ public class FieldHandler
         }
 
     }
-    public ReferenceMethod getBind() {
+    public ReferenceMethod getBind()
+    {
         return new ReferenceMethodImpl(METHOD_TYPE.BIND, this);
     }
 
-    public ReferenceMethod getUnbind() {
+    public ReferenceMethod getUnbind()
+    {
         return new ReferenceMethodImpl(METHOD_TYPE.UNBIND, this);
     }
 
-    public ReferenceMethod getUpdated() {
+    public ReferenceMethod getUpdated()
+    {
         return new ReferenceMethodImpl(METHOD_TYPE.UPDATED, this);
     }
+
+    public InitReferenceMethod getInit() {
+        if ( metadata.isMultiple() )
+        {
+            return new InitReferenceMethod()
+            {
+
+                public boolean init(final Object componentInstance, final SimpleLogger logger)
+                {
+                    if ( fieldExists( logger) )
+                    {
+                        return initField(componentInstance, logger);
+                    }
+                    return false;
+                }
+            };
+        }
+        return null;
+    }
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java Mon Nov 10 05:51:04 2014
@@ -29,31 +29,43 @@ import org.apache.felix.scr.impl.metadat
  */
 public class FieldMethods implements ReferenceMethods
 {
-    private final FieldHandler handler;
+    private final ReferenceMethod bind;
+    private final ReferenceMethod updated;
+    private final ReferenceMethod unbind;
+    private final InitReferenceMethod init;
 
     public FieldMethods( final ReferenceMetadata m_dependencyMetadata,
             final Class<?> instanceClass,
             final DSVersion dsVersion,
             final boolean configurableServiceProperties )
     {
-        handler = new FieldHandler(
+        final FieldHandler handler = new FieldHandler(
                 m_dependencyMetadata,
                 instanceClass
         );
+        bind = handler.getBind();
+        unbind = handler.getUnbind();
+        updated = handler.getUpdated();
+        init = handler.getInit();
     }
 
     public ReferenceMethod getBind()
     {
-        return handler.getBind();
+        return bind;
     }
 
     public ReferenceMethod getUnbind()
     {
-        return handler.getUnbind();
+        return unbind;
     }
 
     public ReferenceMethod getUpdated()
     {
-        return handler.getUpdated();
+        return updated;
+    }
+
+    public InitReferenceMethod getInit()
+    {
+        return init;
     }
 }

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java?rev=1637793&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java Mon Nov 10 05:51:04 2014
@@ -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.impl.helper;
+
+
+
+/**
+ * Callback for initializing the reference
+ */
+public interface InitReferenceMethod
+{
+    boolean init( final Object componentInstance, final SimpleLogger logger );
+}

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/InitReferenceMethod.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReferenceMethods.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReferenceMethods.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReferenceMethods.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReferenceMethods.java Mon Nov 10 05:51:04 2014
@@ -30,4 +30,7 @@ public interface ReferenceMethods
     ReferenceMethod getUnbind();
 
     ReferenceMethod getUpdated();
+
+    /** Optional. */
+    InitReferenceMethod getInit();
 }

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=1637793&r1=1637792&r2=1637793&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 Mon Nov 10 05:51:04 2014
@@ -1415,6 +1415,14 @@ public class DependencyManager<S, T> imp
      */
     boolean open( ComponentContextImpl<S> componentContext, EdgeInfo edgeInfo )
     {
+        if ( !invokeInitMethod(componentContext) )
+        {
+            m_componentManager.log( LogService.LOG_DEBUG,
+                    "For dependency {0}, failed to initialize object",
+                    new Object[] {getName()}, null );
+            return false;
+        }
+
         int serviceCount = 0;
         AtomicInteger trackingCount =  new AtomicInteger( );
         Collection<RefPair<S, T>> refs;
@@ -1518,6 +1526,24 @@ public class DependencyManager<S, T> imp
     }
 
     /**
+     * Calls the optional init reference method.
+     */
+    boolean invokeInitMethod( final ComponentContextImpl<S> componentContext )
+    {
+        // The bind method is only invoked if the implementation object is not
+        // null. This is valid for both immediate and delayed components
+        if ( m_bindMethods.getInit() != null )
+        {
+            final Object componentInstance = componentContext.getImplementationObject( false );
+            if ( componentInstance != null )
+            {
+                return m_bindMethods.getInit().init(componentInstance, m_componentManager);
+            }
+        }
+        return true;
+    }
+
+    /**
      * Calls the bind method. In case there is an exception while calling the
      * bind method, the service is not considered to be bound to the instance
      * object

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java Mon Nov 10 05:51:04 2014
@@ -25,7 +25,6 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.felix.scr.impl.BundleComponentActivator;
@@ -43,7 +42,6 @@ import org.osgi.service.component.Compon
 import org.osgi.service.component.ComponentInstance;
 import org.osgi.service.log.LogService;
 import org.osgi.util.promise.Deferred;
-import org.osgi.util.promise.Promise;
 
 
 /**
@@ -61,7 +59,7 @@ public class SingleComponentManager<S> e
 
     // Merged properties from xml descriptor and all configurations
     private Map<String, Object> m_configurationProperties;
-    
+
     // optional properties provided in the ComponentFactory.newInstance method
     private Map<String, Object> m_factoryProperties;
 
@@ -73,7 +71,7 @@ public class SingleComponentManager<S> e
     private Dictionary<String, Object> m_serviceProperties;
 
     private final ThreadLocal<Boolean> m_circularReferences = new ThreadLocal<Boolean>();
-    
+
    /**
      * The constructor receives both the activator and the metadata
  * @param componentMethods
@@ -82,13 +80,14 @@ public class SingleComponentManager<S> e
     {
         this(container, componentMethods, false);
     }
-    
+
     public SingleComponentManager( ComponentContainer<S> container, ComponentMethods componentMethods,
             boolean factoryInstance )
     {
         super( container, componentMethods, factoryInstance );
     }
 
+    @Override
     void clear()
     {
         m_container.disposed( this );
@@ -145,6 +144,7 @@ public class SingleComponentManager<S> e
     }
 
 
+    @Override
     protected void deleteComponent( int reason )
     {
         if ( !isStateLocked() )
@@ -245,7 +245,7 @@ public class SingleComponentManager<S> e
             log( LogService.LOG_ERROR, "Error during instantiation of the implementation object", t );
             return null;
         }
-        
+
         componentContext.setImplementationObject(implementationObject);
 
         // 3. set the implementation object prematurely
@@ -353,11 +353,13 @@ public class SingleComponentManager<S> e
 
     }
 
+    @Override
     boolean hasInstance()
     {
         return m_componentContext != null;
     }
 
+    @Override
     <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
@@ -368,6 +370,7 @@ public class SingleComponentManager<S> e
         }
     }
 
+    @Override
     <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
@@ -378,6 +381,7 @@ public class SingleComponentManager<S> e
         }
     }
 
+    @Override
     <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRefPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
@@ -394,6 +398,7 @@ public class SingleComponentManager<S> e
     }
 
 
+    @Override
     void registerComponentId()
     {
         super.registerComponentId();
@@ -401,6 +406,7 @@ public class SingleComponentManager<S> e
     }
 
 
+    @Override
     void unregisterComponentId()
     {
         super.unregisterComponentId();
@@ -417,6 +423,7 @@ public class SingleComponentManager<S> e
      *
      * @return a private map of component properties
      */
+    @Override
     public Map<String, Object> getProperties()
     {
 
@@ -426,7 +433,7 @@ public class SingleComponentManager<S> e
 
             // 1. Merge all the config properties
             Map<String, Object> props = new HashMap<String, Object>();
-            if ( m_configurationProperties != null ) 
+            if ( m_configurationProperties != null )
             {
                 props.putAll(m_configurationProperties);
             }
@@ -436,7 +443,7 @@ public class SingleComponentManager<S> e
                 if (getComponentMetadata().getDSVersion().isDS13() && m_factoryProperties.containsKey(Constants.SERVICE_PID))
                 {
                     List<String> servicePids = (List<String>) m_configurationProperties.get(Constants.SERVICE_PID);
-                    if (servicePids == null) 
+                    if (servicePids == null)
                     {
                         servicePids = new ArrayList<String>();
                     }
@@ -458,6 +465,7 @@ public class SingleComponentManager<S> e
         return m_properties;
     }
 
+    @Override
     public void setServiceProperties( Dictionary<String, ?> serviceProperties )
     {
         if ( serviceProperties == null || serviceProperties.isEmpty() )
@@ -475,6 +483,7 @@ public class SingleComponentManager<S> e
         updateServiceRegistration();
     }
 
+    @Override
     public Dictionary<String, Object> getServiceProperties()
     {
         if ( m_serviceProperties != null )
@@ -533,6 +542,7 @@ public class SingleComponentManager<S> e
      * @param changeCount Change count for the configuration
      * @param targetedPID TargetedPID for the configuration
      */
+    @Override
     public void reconfigure( Map<String, Object> configuration, boolean configurationDeleted )
     {
         // store the properties
@@ -622,7 +632,7 @@ public class SingleComponentManager<S> e
     	if ( configurationDeleted && !getComponentMetadata().isDeleteCallsModify()){
     		return false;
     	}
-    	
+
         // 1. no live update if there is no declared method
         if ( getComponentMetadata().getModified() == null )
         {
@@ -747,7 +757,7 @@ public class SingleComponentManager<S> e
         }
     }
 
-    
+
     @Override
     boolean getServiceInternal()
     {
@@ -755,7 +765,7 @@ public class SingleComponentManager<S> e
         {
             log( LogService.LOG_ERROR,  "Circular reference detected, getService returning null", null );
             dumpThreads();
-            return false;             
+            return false;
         }
         m_circularReferences.set( Boolean.TRUE );
         try

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java Mon Nov 10 05:51:04 2014
@@ -725,6 +725,14 @@ public class ReferenceMetadata
                 }
             }
 
+            // static references only allow replace strateg
+            if ( m_isStatic )
+            {
+                if ( ! m_field_strategy.equals(FIELD_STRATEGY_REPLACE) )
+                {
+                    throw componentMetadata.validationFailure( "Field strategy update not allowed for static field references." );
+                }
+            }
         }
 
 

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java?rev=1637793&r1=1637792&r2=1637793&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java Mon Nov 10 05:51:04 2014
@@ -18,7 +18,6 @@
  */
 package org.apache.felix.scr.impl.runtime;
 
-import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -49,20 +48,20 @@ import org.osgi.util.promise.Promise;
 
 public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime
 {
-	
+
 	private static final String[] EMPTY = {};
-	
+
 	private final BundleContext context;
 	private final ComponentRegistry componentRegistry;
 
 
-	public ServiceComponentRuntimeImpl(BundleContext context,ComponentRegistry componentRegistry) 
+	public ServiceComponentRuntimeImpl(BundleContext context,ComponentRegistry componentRegistry)
 	{
 		this.context = context;
 		this.componentRegistry = componentRegistry;
 	}
 
-	public Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles) 
+	public Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles)
 	{
 		List<ComponentHolder<?>> holders;
 		if (bundles == null || bundles.length == 0)
@@ -89,13 +88,13 @@ public class ServiceComponentRuntimeImpl
 		{
 			return holderToDescription(holder);
 		}
-		else 
+		else
 		{
 			return null;
 		}
 	}
 
-	public Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description) 
+	public Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description)
 	{
 		if ( description == null)
 		{
@@ -113,13 +112,13 @@ public class ServiceComponentRuntimeImpl
 		return result;
 	}
 
-	public boolean isComponentEnabled(ComponentDescriptionDTO description) 
+	public boolean isComponentEnabled(ComponentDescriptionDTO description)
 	{
 		ComponentHolder<?> holder = getHolderFromDescription( description);
 		return holder.isEnabled();
 	}
 
-	public Promise<Void> enableComponent(ComponentDescriptionDTO description) 
+	public Promise<Void> enableComponent(ComponentDescriptionDTO description)
 	{
 		ComponentHolder<?> holder = getHolderFromDescription( description);
 		return holder.enableComponents(true);
@@ -130,8 +129,8 @@ public class ServiceComponentRuntimeImpl
 		ComponentHolder<?> holder = getHolderFromDescription( description);
 		return holder.disableComponents(true); //synchronous
 	}
-	
-	private ComponentConfigurationDTO managerToConfiguration(ComponentManager<?> manager, ComponentDescriptionDTO description) 
+
+	private ComponentConfigurationDTO managerToConfiguration(ComponentManager<?> manager, ComponentDescriptionDTO description)
 	{
 		ComponentConfigurationDTO dto = new ComponentConfigurationDTO();
         dto.satisfiedReferences = satisfiedRefManagersToDTO(manager.getReferenceManagers());
@@ -167,7 +166,7 @@ public class ServiceComponentRuntimeImpl
         return dtos.toArray( new SatisfiedReferenceDTO[dtos.size()] );
     }
 
-    private UnsatisfiedReferenceDTO[] unsatisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers) 
+    private UnsatisfiedReferenceDTO[] unsatisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers)
     {
         List<UnsatisfiedReferenceDTO> dtos = new ArrayList<UnsatisfiedReferenceDTO>();
         for (ReferenceManager<?, ?> ref: referenceManagers)
@@ -243,7 +242,7 @@ public class ServiceComponentRuntimeImpl
 		dto.serviceInterfaces = m.getServiceMetadata() == null? EMPTY: m.getServiceMetadata().getProvides();
 		return dto;
 	}
-	
+
     private Map<String, Object> deepCopy(Map<String, Object> source)
     {
         HashMap<String, Object> result = new HashMap<String, Object>(source.size());
@@ -291,17 +290,17 @@ public class ServiceComponentRuntimeImpl
 	    }
 	    return String.valueOf(source);
 	}
-    
+
     boolean checkType(Class<?> type)
     {
         if (type == String.class) return true;
         if (type == Boolean.class) return true;
         if (Number.class.isAssignableFrom(type)) return true;
         if (DTO.class.isAssignableFrom(type)) return true;
-        return false;            
+        return false;
     }
-	
-	private ReferenceDTO[] refsToDTO(List<ReferenceMetadata> dependencies) 
+
+	private ReferenceDTO[] refsToDTO(List<ReferenceMetadata> dependencies)
 	{
 		ReferenceDTO[] dtos = new ReferenceDTO[dependencies.size()];
 		int i = 0;
@@ -310,11 +309,27 @@ public class ServiceComponentRuntimeImpl
 			ReferenceDTO dto = new ReferenceDTO();
 			dto.bind = r.getBind();
 			dto.cardinality = r.getCardinality();
+			dto.field = r.getField();
 			dto.interfaceName = r.getInterface();
 			dto.name = r.getName();
 			dto.policy = r.getPolicy();
 			dto.policyOption = r.getPolicyOption();
 			dto.scope = r.getScope().name();
+			if ( r.getField() != null )
+			{
+			    if ( ReferenceMetadata.FIELD_STRATEGY_REPLACE.equals(r.getFieldStrategy()) )
+			    {
+			        dto.strategy = ReferenceDTO.STRATEGY_FIELD_REPLACE;
+			    }
+			    else
+			    {
+                    dto.strategy = ReferenceDTO.STRATEGY_FIELD_UPDATE;
+			    }
+			}
+			else
+			{
+			    dto.strategy = r.getBind() != null ? ReferenceDTO.STRATEGY_METHOD : ReferenceDTO.STRATEGY_LOOKUP;
+			}
 			dto.target = r.getTarget();
 			dto.unbind = r.getUnbind();
 			dto.updated = r.getUpdated();
@@ -323,7 +338,7 @@ public class ServiceComponentRuntimeImpl
 		return dtos;
 	}
 
-	private BundleDTO bundleToDTO(BundleContext bundleContext) 
+	private BundleDTO bundleToDTO(BundleContext bundleContext)
 	{
 		if (bundleContext == null)
 		{