Author: cziegeler Date: Sat Oct 21 14:41:16 2017 New Revision: 1812829 URL: http://svn.apache.org/viewvc?rev=1812829&view=rev Log: FELIX-5455 : [R7] Constructor Injection
Added: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java - copied, changed from r1812828, felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethod.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructorImpl.java - copied, changed from r1812828, felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java Removed: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethod.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlConstants.java felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java Copied: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java (from r1812828, felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethod.java) URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java?p2=felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java&p1=felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethod.java&r1=1812828&r2=1812829&rev=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethod.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java Sat Oct 21 14:41:16 2017 @@ -25,10 +25,10 @@ import org.apache.felix.scr.impl.manager /** * This object describes a constructor for a component. - * The name ConstructorMethod has been chosen to avoid a clash with the + * The name ComponentConstructor has been chosen to avoid a clash with the * existing Constructor class. */ -public interface ConstructorMethod<T> { +public interface ComponentConstructor<T> { public class ReferencePair<S> { public DependencyManager<S, ?> dependencyManager; @@ -46,19 +46,4 @@ public interface ConstructorMethod<T> { ComponentContextImpl<T> componentContext, Map<Integer, ReferencePair<S>> parameterMap) throws Exception; - - public ConstructorMethod<Object> DEFAULT = new ConstructorMethod<Object>() { - - @Override - public <S> Object newInstance(Class<Object> componentClass, - ComponentContextImpl<Object> componentContext, - Map<Integer, ReferencePair<S>> parameterMap) - throws Exception - { - // 112.4.4 The class must be public and have a public constructor without arguments so component instances - // may be created by the SCR with the newInstance method on Class - return componentClass.newInstance(); - } - }; - } Copied: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructorImpl.java (from r1812828, felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java) URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructorImpl.java?p2=felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructorImpl.java&p1=felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java&r1=1812828&r2=1812829&rev=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructorImpl.java Sat Oct 21 14:41:16 2017 @@ -31,29 +31,29 @@ import org.apache.felix.scr.impl.metadat * This implementation is used to construct a component instance object, * call the constructor and set the activation fields. */ -public class ConstructorMethodImpl<T> implements ConstructorMethod<T> +public class ComponentConstructorImpl<T> implements ComponentConstructor<T> { - private volatile boolean m_initialized = false; + private volatile boolean initialized = false; - private volatile ValueType[] m_paramTypes; - private volatile Field[] m_fields; + private volatile ValueType[] paramTypes; + private volatile Field[] fields; - private volatile Constructor<T> m_constructor; - private volatile ValueType[] m_constructorArgTypes; + private volatile Constructor<T> constructor; + private volatile ValueType[] constructorArgTypes; @SuppressWarnings("unchecked") @Override - public <S> T newInstance(Class<T> componentClass, - ComponentContextImpl<T> componentContext, - Map<Integer, ReferencePair<S>> parameterMap) + public <S> T newInstance(final Class<T> componentClass, + final ComponentContextImpl<T> componentContext, + final Map<Integer, ReferencePair<S>> parameterMap) throws Exception { - if ( !m_initialized ) { + if ( !initialized ) { // activation fields if ( componentContext.getComponentMetadata().getActivationFields() != null ) { - m_paramTypes = new ValueType[componentContext.getComponentMetadata().getActivationFields().size()]; - m_fields = new Field[m_paramTypes.length]; + paramTypes = new ValueType[componentContext.getComponentMetadata().getActivationFields().size()]; + fields = new Field[paramTypes.length]; int index = 0; for(final String fieldName : componentContext.getComponentMetadata().getActivationFields() ) @@ -61,20 +61,20 @@ public class ConstructorMethodImpl<T> im final FieldUtils.FieldSearchResult result = FieldUtils.searchField(componentClass, fieldName, componentContext.getLogger()); if ( result == null || result.field == null ) { - m_paramTypes[index] = null; - m_fields[index] = null; + paramTypes[index] = null; + fields[index] = null; } else { if ( result.usable ) { - m_paramTypes[index] = ValueUtils.getValueType(result.field.getType()); - m_fields[index] = result.field; + paramTypes[index] = ValueUtils.getValueType(result.field.getType()); + fields[index] = result.field; } else { - m_paramTypes[index] = ValueType.ignore; - m_fields[index] = null; + paramTypes[index] = ValueType.ignore; + fields[index] = null; } } index++; @@ -82,49 +82,57 @@ public class ConstructorMethodImpl<T> im } else { - m_paramTypes = ValueUtils.EMPTY_VALUE_TYPES; - m_fields = null; + paramTypes = ValueUtils.EMPTY_VALUE_TYPES; + fields = null; } - // constructor injection - if ( componentContext.getComponentMetadata().isActivateConstructor() ) - { - // TODO search constructor - m_constructor = null; - boolean hasFailure = false; - final Class<?>[] argTypes = m_constructor.getParameterTypes(); - m_constructorArgTypes = new ValueType[argTypes.length]; - for(int i=0;i<m_constructorArgTypes.length;i++) + // Search constructor + final Constructor<?>[] constructors = componentClass.getConstructors(); + for(final Constructor<?> c : constructors) + { + // we pick the first one with the right number of arguments + if ( c.getParameterTypes().length == componentContext.getComponentMetadata().getNumberOfConstructorParameters() ) { - final ReferencePair<S> pair = parameterMap.get(i); - ReferenceMetadata reference = pair == null ? null : pair.dependencyManager.getReferenceMetadata(); - if ( reference == null ) - { - m_constructorArgTypes[i] = ValueUtils.getValueType(argTypes[i]); - } - else + constructor = (Constructor<T>) c; + break; + } + if ( constructor != null && componentContext.getComponentMetadata().getNumberOfConstructorParameters() > 0 ) + { + boolean hasFailure = false; + final Class<?>[] argTypes = constructor.getParameterTypes(); + constructorArgTypes = new ValueType[argTypes.length]; + for(int i=0;i<constructorArgTypes.length;i++) { - m_constructorArgTypes[i] = ValueUtils.getReferenceValueType(componentClass, reference, argTypes[i], null, componentContext.getLogger()); + final ReferencePair<S> pair = parameterMap.get(i); + ReferenceMetadata reference = pair == null ? null : pair.dependencyManager.getReferenceMetadata(); + if ( reference == null ) + { + constructorArgTypes[i] = ValueUtils.getValueType(argTypes[i]); + } + else + { + constructorArgTypes[i] = ValueUtils.getReferenceValueType(componentClass, reference, argTypes[i], null, componentContext.getLogger()); + } + if ( constructorArgTypes[i] == ValueType.ignore ) + { + hasFailure = true; + break; + } } - if ( m_constructorArgTypes[i] == ValueType.ignore ) + if ( hasFailure ) { - hasFailure = true; - break; + constructor = null; } } - if ( hasFailure ) - { - m_constructor = null; - } } // done - m_initialized = true; + initialized = true; } // if we have fields and one is in state failure (type == null) we can directly throw int index = 0; - for(final ValueType t : m_paramTypes) + for(final ValueType t : paramTypes) { if ( t == null ) { @@ -135,43 +143,43 @@ public class ConstructorMethodImpl<T> im } // constructor - final T component; - if ( componentContext.getComponentMetadata().isActivateConstructor() ) + if ( constructor == null ) { - if ( m_constructor == null ) - { - throw new InstantiationException("Constructor not found; Component will fail"); - } - final Object[] args = new Object[m_constructorArgTypes.length]; + throw new InstantiationException("Constructor not found; Component will fail"); + } + final Object[] args; + if ( constructorArgTypes == null ) + { + args = null; + } + else + { + args = new Object[constructorArgTypes.length]; for(int i=0; i<args.length; i++) { - // TODO - get ref pair + // TODO - handle reference cardinality multiple + // TODO - can we assume that pair.openStatus.refs.iterator().next() always returns a value? final ReferencePair<S> pair = parameterMap.get(i); args[i] = ValueUtils.getValue(componentClass.getName(), - m_constructorArgTypes[i], - m_constructor.getParameterTypes()[i], + constructorArgTypes[i], + constructor.getParameterTypes()[i], componentContext, - null); + pair != null ? pair.openStatus.refs.iterator().next() : null); } - component = m_constructor.newInstance(args); - } - else - { - component = (T)ConstructorMethod.DEFAULT.newInstance((Class<Object>)componentClass, - (ComponentContextImpl<Object>)componentContext, null); } + final T component = constructor.newInstance(args); // activation fields - for(int i = 0; i<m_paramTypes.length; i++) + for(int i = 0; i<paramTypes.length; i++) { - if ( m_paramTypes[i] != ValueType.ignore ) + if ( paramTypes[i] != ValueType.ignore ) { final Object value = ValueUtils.getValue(componentClass.getName(), - m_paramTypes[i], - m_fields[i].getType(), + paramTypes[i], + fields[i].getType(), componentContext, - null); - FieldUtils.setField(m_fields[i], component, value, componentContext.getLogger()); + null); // null is ok as activation fields are not references + FieldUtils.setField(fields[i], component, value, componentContext.getLogger()); } } Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java Sat Oct 21 14:41:16 2017 @@ -35,6 +35,6 @@ public interface ComponentMethods<T> ReferenceMethods getBindMethods(String refName ); - ConstructorMethod<T> getConstructor(); + ComponentConstructor<T> getConstructor(); } Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java Sat Oct 21 14:41:16 2017 @@ -43,10 +43,11 @@ public class ComponentMethodsImpl<T> imp private LifecycleMethod m_activateMethod; private LifecycleMethod m_modifiedMethod; private LifecycleMethod m_deactivateMethod; - private ConstructorMethod<T> m_constructor; + private ComponentConstructor<T> m_constructor; - private final Map<String, ReferenceMethods> bindMethodMap = new HashMap<String, ReferenceMethods>(); + private final Map<String, ReferenceMethods> bindMethodMap = new HashMap<>(); + @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public synchronized void initComponentMethods( ComponentMetadata componentMetadata, Class<T> implementationObjectClass ) { @@ -57,13 +58,13 @@ public class ComponentMethodsImpl<T> imp DSVersion dsVersion = componentMetadata.getDSVersion(); boolean configurableServiceProperties = componentMetadata.isConfigurableServiceProperties(); boolean supportsInterfaces = componentMetadata.isConfigureWithInterfaces(); - - m_activateMethod = new ActivateMethod( - componentMetadata.isActivateConstructor() ? null : componentMetadata.getActivate(), - componentMetadata.isActivateDeclared(), - implementationObjectClass, - dsVersion, - configurableServiceProperties, + + m_activateMethod = new ActivateMethod( + componentMetadata.getActivate(), + componentMetadata.isActivateDeclared(), + implementationObjectClass, + dsVersion, + configurableServiceProperties, supportsInterfaces); m_deactivateMethod = new DeactivateMethod( componentMetadata.getDeactivate(), componentMetadata.isDeactivateDeclared(), implementationObjectClass, dsVersion, configurableServiceProperties, supportsInterfaces ); @@ -73,40 +74,31 @@ public class ComponentMethodsImpl<T> imp for ( ReferenceMetadata referenceMetadata: componentMetadata.getDependencies() ) { final String refName = referenceMetadata.getName(); - final List<ReferenceMethods> methods = new ArrayList<ReferenceMethods>(); + final List<ReferenceMethods> methods = new ArrayList<>(); if ( referenceMetadata.getField() != null ) { methods.add(new FieldMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties)); } if ( referenceMetadata.getBind() != null ) { - methods.add(new BindMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties)); + methods.add(new BindMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties)); } if ( methods.isEmpty() ) { - bindMethodMap.put( refName, ReferenceMethods.NOPReferenceMethod ); + bindMethodMap.put( refName, ReferenceMethods.NOPReferenceMethod ); } else if ( methods.size() == 1 ) { - bindMethodMap.put( refName, methods.get(0) ); + bindMethodMap.put( refName, methods.get(0) ); } else { - bindMethodMap.put( refName, new DuplexReferenceMethods(methods) ); + bindMethodMap.put( refName, new DuplexReferenceMethods(methods) ); } } - - // special constructor handling with activation fields and/or constructor injection - if ( componentMetadata.getActivationFields() != null - || componentMetadata.isActivateConstructor()) - { - m_constructor = new ConstructorMethodImpl(); - } - else - { - m_constructor = (ConstructorMethod<T>) ConstructorMethod.DEFAULT; - } + + m_constructor = new ComponentConstructorImpl(); } @Override @@ -134,7 +126,7 @@ public class ComponentMethodsImpl<T> imp } @Override - public ConstructorMethod<T> getConstructor() + public ComponentConstructor<T> getConstructor() { return m_constructor; } Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java Sat Oct 21 14:41:16 2017 @@ -29,7 +29,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.apache.felix.scr.impl.inject.ComponentMethods; -import org.apache.felix.scr.impl.inject.ConstructorMethod; +import org.apache.felix.scr.impl.inject.ComponentConstructor; import org.apache.felix.scr.impl.inject.LifecycleMethod; import org.apache.felix.scr.impl.inject.MethodResult; import org.apache.felix.scr.impl.manager.DependencyManager.OpenStatus; @@ -75,13 +75,13 @@ public class SingleComponentManager<S> e * The constructor receives both the activator and the metadata * @param componentMethods */ - public SingleComponentManager( ComponentContainer<S> container, ComponentMethods componentMethods ) + public SingleComponentManager( final ComponentContainer<S> container, final ComponentMethods componentMethods ) { this(container, componentMethods, false); } - public SingleComponentManager( ComponentContainer<S> container, ComponentMethods componentMethods, - boolean factoryInstance ) + public SingleComponentManager( final ComponentContainer<S> container, final ComponentMethods componentMethods, + final boolean factoryInstance ) { super( container, componentMethods, factoryInstance ); } @@ -234,9 +234,9 @@ public class SingleComponentManager<S> e } // bind target services - final List<DependencyManager.OpenStatus<S, ?>> openStatusList = new ArrayList<DependencyManager.OpenStatus<S,?>>(); + final List<DependencyManager.OpenStatus<S, ?>> openStatusList = new ArrayList<>(); - final Map<Integer, ConstructorMethod.ReferencePair<S>> paramMap = ( getComponentMetadata().isActivateConstructor() ? new HashMap<Integer, ConstructorMethod.ReferencePair<S>>() : null); + final Map<Integer, ComponentConstructor.ReferencePair<S>> paramMap = ( getComponentMetadata().getNumberOfConstructorParameters() > 0 ? new HashMap<Integer, ComponentConstructor.ReferencePair<S>>() : null); boolean failed = false; for ( DependencyManager<S, ?> dm : getDependencyManagers()) { @@ -255,7 +255,7 @@ public class SingleComponentManager<S> e openStatusList.add(open); if ( dm.getReferenceMetadata().getParameterIndex() != null) { - final ConstructorMethod.ReferencePair<S> pair = new ConstructorMethod.ReferencePair<S>(); + final ComponentConstructor.ReferencePair<S> pair = new ComponentConstructor.ReferencePair<>(); pair.dependencyManager = dm; pair.openStatus = open; paramMap.put(dm.getReferenceMetadata().getParameterIndex(), pair); @@ -471,7 +471,7 @@ public class SingleComponentManager<S> e // 1. Merge all the config properties - Map<String, Object> props = new HashMap<String, Object>(); + Map<String, Object> props = new HashMap<>(); if ( m_configurationProperties != null ) { props.putAll(m_configurationProperties); @@ -481,7 +481,7 @@ public class SingleComponentManager<S> e props.putAll(m_factoryProperties); if (getComponentMetadata().getDSVersion().isDS13() && m_factoryProperties.containsKey(Constants.SERVICE_PID)) { - final List<String> servicePids = new ArrayList<String>(); + final List<String> servicePids = new ArrayList<>(); final Object configPropServicePids = m_configurationProperties.get(Constants.SERVICE_PID); if ( configPropServicePids instanceof List ) { @@ -823,7 +823,7 @@ public class SingleComponentManager<S> e */ private boolean servicePropertiesMatches( ServiceRegistration<S> reg, Dictionary<String, Object> props ) { - Dictionary<String, Object> regProps = new Hashtable<String, Object>(); + Dictionary<String, Object> regProps = new Hashtable<>(); String[] keys = reg.getReference().getPropertyKeys(); for ( int i = 0; keys != null && i < keys.length; i++ ) { @@ -892,7 +892,7 @@ public class SingleComponentManager<S> e boolean success = true; if ( m_componentContext == null ) { - ComponentContextImpl<S> componentContext = new ComponentContextImpl<S>(this, this.getBundle(), serviceRegistration); + ComponentContextImpl<S> componentContext = new ComponentContextImpl<>(this, this.getBundle(), serviceRegistration); if ( collectDependencies(componentContext)) { log( LogService.LOG_DEBUG, Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java Sat Oct 21 14:41:16 2017 @@ -55,9 +55,6 @@ public class ComponentMetadata // marker value indicating duplicate service setting private static final ServiceMetadata SERVICE_DUPLICATE = new ServiceMetadata(); - /** If the activate method has this value, a constructor is used instead. */ - private static final String CONSTRUCTOR_MARKER = "-init-"; - // the namespace code of the namespace declaring this component private final DSVersion m_dsVersion; @@ -103,28 +100,28 @@ public class ComponentMetadata private List<String> m_activationFields; // Associated properties (0..*) - private final Map<String, Object> m_properties = new HashMap<String, Object>(); + private final Map<String, Object> m_properties = new HashMap<>(); // Associated factory properties (0..*) - private final Map<String, Object> m_factoryProperties = new HashMap<String, Object>(); + private final Map<String, Object> m_factoryProperties = new HashMap<>(); // List of Property metadata - used while building the meta data // while validating the properties contained in the PropertyMetadata // instances are copied to the m_properties Dictionary while this // list will be cleared - private final List<PropertyMetadata> m_propertyMetaData = new ArrayList<PropertyMetadata>(); + private final List<PropertyMetadata> m_propertyMetaData = new ArrayList<>(); // List of Property metadata - used while building the meta data // while validating the properties contained in the PropertyMetadata // instances are copied to the m_factoryProperties Dictionary while this // list will be cleared - private final List<PropertyMetadata> m_factoryPropertyMetaData = new ArrayList<PropertyMetadata>(); + private final List<PropertyMetadata> m_factoryPropertyMetaData = new ArrayList<>(); // Provided services (0..1) private ServiceMetadata m_service; // List of service references, (required services 0..*) - private final List<ReferenceMetadata> m_references = new ArrayList<ReferenceMetadata>(); + private final List<ReferenceMetadata> m_references = new ArrayList<>(); private boolean m_configurableServiceProperties; private boolean m_persistentFactoryComponent; @@ -133,12 +130,14 @@ public class ComponentMetadata private boolean m_configureWithInterfaces; private boolean m_delayedKeepInstances; + private String m_init; + // Flag that is set once the component is verified (its properties cannot be changed) private boolean m_validated = false; static { - CONFIGURATION_POLICY_VALID = new TreeSet<String>(); + CONFIGURATION_POLICY_VALID = new TreeSet<>(); CONFIGURATION_POLICY_VALID.add( CONFIGURATION_POLICY_IGNORE ); CONFIGURATION_POLICY_VALID.add( CONFIGURATION_POLICY_OPTIONAL ); CONFIGURATION_POLICY_VALID.add( CONFIGURATION_POLICY_REQUIRE ); @@ -162,7 +161,7 @@ public class ComponentMetadata { return; } - m_configurationPid = new ArrayList<String>( Arrays.asList( configurationPid ) ); + m_configurationPid = new ArrayList<>( Arrays.asList( configurationPid ) ); } /** @@ -441,11 +440,18 @@ public class ComponentMetadata public void setActivationFields( final String[] fields ) { - if ( m_validated ) + if ( !m_validated ) { - return; + this.m_activationFields = new ArrayList<>( Arrays.asList( fields ) ); } - this.m_activationFields = new ArrayList<String>( Arrays.asList( fields ) ); + } + + public void setInit( final String value ) + { + if ( !m_validated ) + { + this.m_init = value; + } } /////////////////////////////////////////// GETTERS ////////////////////////////////////// @@ -619,14 +625,14 @@ public class ComponentMetadata } /** - * Returns whether the activate is done through a constructor rather - * than a method - * @return {@code true} if a constructor is used + * Returns the number of constructor parameters (0 is default) + * @return The number of constructor parameters * @since 2.1.0 (DS 1.4) */ - public boolean isActivateConstructor() + public int getNumberOfConstructorParameters() { - return CONSTRUCTOR_MARKER.equals(m_activate); + // validate() ensures this is a valid integer + return m_init == null ? 0 : Integer.valueOf(m_init); } /** @@ -926,7 +932,7 @@ public class ComponentMetadata m_configurationPid.set( i, getName() ); } } - if ( new HashSet<String>( m_configurationPid ).size() != m_configurationPid.size()) + if ( new HashSet<>( m_configurationPid ).size() != m_configurationPid.size()) { throw validationFailure( "Duplicate pids not allowed: " + m_configurationPid ); } @@ -947,11 +953,11 @@ public class ComponentMetadata } if ( m_dsVersion.isDS14() && isFactory() ) { - for ( PropertyMetadata propMeta: m_factoryPropertyMetaData ) - { - propMeta.validate( this ); - m_factoryProperties.put( propMeta.getName(), propMeta.getValue() ); - } + for ( PropertyMetadata propMeta: m_factoryPropertyMetaData ) + { + propMeta.validate( this ); + m_factoryProperties.put( propMeta.getName(), propMeta.getValue() ); + } } // if this is not a factory, these props are ignored, so nothing else to do m_factoryPropertyMetaData.clear(); @@ -967,7 +973,7 @@ public class ComponentMetadata } // Check that the references are ok - Set<String> refs = new HashSet<String>(); + Set<String> refs = new HashSet<>(); for ( ReferenceMetadata refMeta: m_references ) { refMeta.validate( this ); @@ -1019,36 +1025,56 @@ public class ComponentMetadata } // constructor injection requires DS 1.4 - if ( this.isActivateConstructor() ) + if ( this.m_init != null ) { - if ( !m_dsVersion.isDS14() ) - { + if ( !m_dsVersion.isDS14() ) + { throw validationFailure( "Constructor injection requires version 1.4 or later"); - } - final Set<Integer> parIndexSet = new HashSet<Integer>(); - for(final ReferenceMetadata ref : this.m_references) - { - if ( ref.getParameterIndex() != null && !parIndexSet.add(ref.getParameterIndex()) ) - { - throw validationFailure( "Duplicate reference for argument " + ref.getParameterIndex() + " in constructor" ); - } - } + } + int constructorParameters = 0; + try + { + constructorParameters = Integer.valueOf(m_init); + if ( constructorParameters < 0) + { + throw validationFailure( "Init parameter must have non negative value: " + m_init); + } + } + catch ( final NumberFormatException nfe) + { + throw validationFailure( "Init parameter is not a number: " + m_init); + } + final Set<Integer> parIndexSet = new HashSet<>(); + for(final ReferenceMetadata ref : this.m_references) + { + if ( ref.getParameterIndex() != null ) + { + if ( ref.getParameterIndex() >= constructorParameters ) + { + throw validationFailure( "Reference parameter index of " + ref.getParameterIndex().toString() + " is higher than init parameter: " + m_init); + } + if ( !parIndexSet.add(ref.getParameterIndex()) ) + { + throw validationFailure( "Duplicate reference for argument " + ref.getParameterIndex() + " in constructor" ); + } + } + } } else { - // no constructor injection, check references for having a parameter index - for(final ReferenceMetadata ref : this.m_references) - { - if ( ref.getParameterIndex() != null ) - { + // no constructor injection, check references for having a parameter index + for(final ReferenceMetadata ref : this.m_references) + { + if ( ref.getParameterIndex() != null ) + { throw validationFailure( "Reference must not use parameter attribute if no constructor injection is used" ); - } - } + } + } } if (m_dsVersion == DSVersion.DS12Felix) { - m_configurableServiceProperties = true; + m_configurableServiceProperties = true; } if ( m_configurableServiceProperties && getServiceScope() != Scope.singleton ) { @@ -1056,19 +1082,19 @@ public class ComponentMetadata } if (m_dsVersion.isDS13()) { - m_deleteCallsModify = true; //spec behavior as of 1.3 + m_deleteCallsModify = true; //spec behavior as of 1.3 } if ( !m_dsVersion.isDS13() && m_configureWithInterfaces) { - throw validationFailure("Configuration with interfaces or annotations only possible with version 1.3 or later"); + throw validationFailure("Configuration with interfaces or annotations only possible with version 1.3 or later"); } if (m_dsVersion.isDS13() && m_obsoleteFactoryComponentFactory != null) { - throw validationFailure("Configuration of component factory instances through config admin factory pids supported only through the 1.2 namespace"); + throw validationFailure("Configuration of component factory instances through config admin factory pids supported only through the 1.2 namespace"); } if (m_persistentFactoryComponent && !isFactory()) { - throw validationFailure("Only a factory component can be a persistent factory component"); + throw validationFailure("Only a factory component can be a persistent factory component"); } m_validated = true; Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java Sat Oct 21 14:41:16 2017 @@ -146,25 +146,25 @@ public class ReferenceMetadata static { - CARDINALITY_VALID = new TreeSet<String>(); + CARDINALITY_VALID = new TreeSet<>(); CARDINALITY_VALID.add( CARDINALITY_0_1 ); CARDINALITY_VALID.add( CARDINALITY_0_N ); CARDINALITY_VALID.add( CARDINALITY_1_1 ); CARDINALITY_VALID.add( CARDINALITY_1_N ); - POLICY_VALID = new TreeSet<String>(); + POLICY_VALID = new TreeSet<>(); POLICY_VALID.add( POLICY_DYNAMIC ); POLICY_VALID.add( POLICY_STATIC ); - POLICY_OPTION_VALID = new TreeSet<String>(); + POLICY_OPTION_VALID = new TreeSet<>(); POLICY_OPTION_VALID.add( POLICY_OPTION_RELUCTANT ); POLICY_OPTION_VALID.add( POLICY_OPTION_GREEDY ); - FIELD_STRATEGY_VALID = new TreeSet<String>(); + FIELD_STRATEGY_VALID = new TreeSet<>(); FIELD_STRATEGY_VALID.add( FIELD_STRATEGY_REPLACE ); FIELD_STRATEGY_VALID.add( FIELD_STRATEGY_UPDATE ); - FIELD_VALUE_TYPE_VALID = new TreeSet<String>(); + FIELD_VALUE_TYPE_VALID = new TreeSet<>(); FIELD_VALUE_TYPE_VALID.add ( FIELD_VALUE_TYPE_PROPERTIES ); FIELD_VALUE_TYPE_VALID.add ( FIELD_VALUE_TYPE_REFERENCE ); FIELD_VALUE_TYPE_VALID.add ( FIELD_VALUE_TYPE_SERVICE ); @@ -679,19 +679,18 @@ public class ReferenceMetadata } if (m_scopeName != null) { - if ( !dsVersion.isDS13() ) - { - throw componentMetadata.validationFailure( "reference scope can be set only for DS >= 1.3"); - } - try - { - m_scope = ReferenceScope.valueOf(m_scopeName); - } - catch (final IllegalArgumentException e) - { - throw componentMetadata.validationFailure( "reference scope must be 'bundle' or 'prototype' not " + m_scopeName); - - } + if ( !dsVersion.isDS13() ) + { + throw componentMetadata.validationFailure( "reference scope can be set only for DS >= 1.3"); + } + try + { + m_scope = ReferenceScope.valueOf(m_scopeName); + } + catch (final IllegalArgumentException e) + { + throw componentMetadata.validationFailure( "reference scope must be 'bundle' or 'prototype' not " + m_scopeName); + } } // checks for event based injection @@ -760,7 +759,7 @@ public class ReferenceMetadata } try { - m_parameterIndex = Integer.valueOf(m_parameter); + m_parameterIndex = Integer.valueOf(m_parameter); } catch ( final NumberFormatException nfe) { Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlConstants.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlConstants.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlConstants.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlConstants.java Sat Oct 21 14:41:16 2017 @@ -78,6 +78,7 @@ public abstract class XmlConstants public static final String ATTR_ENTRY = "entry"; public static final String ATTR_FACTORY = "factory"; public static final String ATTR_IMMEDIATE = "immediate"; + public static final String ATTR_INIT = "init"; public static final String ATTR_INTERFACE = "interface"; public static final String ATTR_MODIFIED = "modified"; public static final String ATTR_NAME = "name"; @@ -103,7 +104,7 @@ public abstract class XmlConstants static { - NAMESPACE_CODE_MAP = new HashMap<String, DSVersion>(); + NAMESPACE_CODE_MAP = new HashMap<>(); NAMESPACE_CODE_MAP.put( NAMESPACE_URI_EMPTY, DSVersion.DS10 ); NAMESPACE_CODE_MAP.put( NAMESPACE_URI, DSVersion.DS10 ); NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_1, DSVersion.DS11 ); Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java?rev=1812829&r1=1812828&r2=1812829&view=diff ============================================================================== --- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java (original) +++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java Sat Oct 21 14:41:16 2017 @@ -60,7 +60,7 @@ public class XmlHandler implements KXml2 private ServiceMetadata m_currentService; // A list of component descriptors contained in the file - private List<ComponentMetadata> m_components = new ArrayList<ComponentMetadata>(); + private List<ComponentMetadata> m_components = new ArrayList<>(); // PropertyMetaData whose value attribute is missing, hence has element data private PropertyMetadata m_pendingProperty; @@ -222,13 +222,20 @@ public class XmlHandler implements KXml2 m_currentComponent.setDelayedKeepInstances(m_globalDelayedKeepInstances || "true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_DELAYED_KEEP_INSTANCES))); // activation-fields is optional (since DS 1.4) - String activationFields = attributes.getAttribute( "activation-fields" ); + String activationFields = attributes.getAttribute( XmlConstants.ATTR_ACTIVATION_FIELDS ); if ( activationFields != null ) { final String[] fields = activationFields.split(" "); m_currentComponent.setActivationFields( fields ); } + // init is optional (since DS 1.4) + String init = attributes.getAttribute( XmlConstants.ATTR_INIT ); + if ( init != null ) + { + m_currentComponent.setInit( init ); + } + // Add this component to the list m_components.add( m_currentComponent ); }