Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,152 @@ +/* + * 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.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServiceReference; +import org.osgi.service.component.ComponentServiceObjects; + + +/** + * Utility class for handling references using a ComponentServiceObjects + * to get services. + */ +public class ComponentServiceObjectsHelper +{ + private final BundleContext bundleContext; + + private final Map<ServiceReference, ServiceObjects> serviceObjectsMap = new HashMap<ServiceReference, ServiceObjects>(); + + private final Map<ServiceObjects, List<Object>> services = new HashMap<ServiceObjects, List<Object>>(); + + private final ConcurrentMap<ServiceReference, Object> prototypeInstances = new ConcurrentHashMap<ServiceReference, Object>(); + + public ComponentServiceObjectsHelper(final BundleContext bundleContext) + { + this.bundleContext = bundleContext; + } + + public void cleanup() + { + synchronized ( this ) + { + for(final Map.Entry<ServiceObjects, List<Object>> entry : services.entrySet()) + { + for(final Object service : entry.getValue()) + { + entry.getKey().ungetService(service); + } + } + services.clear(); + serviceObjectsMap.clear(); + } + prototypeInstances.clear(); + } + + public ComponentServiceObjects getServiceObjects(final ServiceReference<?> ref) + { + synchronized ( this ) + { + ServiceObjects<?> so = this.serviceObjectsMap.get(ref); + if ( so == null ) + { + so = this.bundleContext.getServiceObjects(ref); + if ( so != null ) + { + this.serviceObjectsMap.put(ref, so); + } + } + + if ( so != null ) + { + List<Object> services = this.services.get(so); + if ( services == null ) + { + services = new ArrayList<Object>(); + this.services.put(so, services); + } + final ServiceObjects serviceObjects = so; + final List<Object> serviceList = services; + + return new ComponentServiceObjects() + { + + public Object getService() + { + final Object service = serviceObjects.getService(); + if ( service != null ) + { + synchronized ( serviceList ) + { + serviceList.add(service); + } + } + return service; + } + + public void ungetService(final Object service) + { + boolean remove; + synchronized ( serviceList ) + { + remove = serviceList.remove(service); + } + if ( remove ) { + serviceObjects.ungetService(service); + } + } + + public ServiceReference<?> getServiceReference() + { + return ref; + } + }; + } + } + return null; + } + + + public <T> T getPrototypeRefInstance(final ServiceReference<T> ref, ServiceObjects<T> serviceObjects) + { + T service = (T) prototypeInstances.get(ref); + if ( service == null ) + { + service = serviceObjects.getService(); + T oldService = (T)prototypeInstances.putIfAbsent(ref, service); + if ( oldService != null ) + { + // another thread created the instance already + serviceObjects.ungetService(service); + service = oldService; + } + } + return service; + } + + }
Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DeactivateMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DeactivateMethod.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DeactivateMethod.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DeactivateMethod.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,44 @@ +/* + * 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 org.apache.felix.scr.impl.metadata.DSVersion; + + +public class DeactivateMethod extends ActivateMethod +{ + + @Override + boolean isDeactivate() + { + return true; + } + + public DeactivateMethod( final String methodName, + final boolean methodRequired, final Class<?> componentClass, final DSVersion dsVersion, final boolean configurableServiceProperties, boolean supportsInterfaces ) + { + super( methodName, methodRequired, componentClass, dsVersion, configurableServiceProperties, supportsInterfaces ); + } + + protected String getMethodNamePrefix() + { + return "deactivate"; + } + +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DuplexReferenceMethods.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DuplexReferenceMethods.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DuplexReferenceMethods.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/DuplexReferenceMethods.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,120 @@ +/* + * 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 org.apache.felix.scr.impl.manager.ComponentContextImpl; +import org.apache.felix.scr.impl.manager.RefPair; +import org.osgi.framework.BundleContext; + +public class DuplexReferenceMethods implements ReferenceMethods +{ + /** First is field methods. */ + private final ReferenceMethods first; + + /** Second is method methods. */ + private final ReferenceMethods second; + + public DuplexReferenceMethods(final ReferenceMethods first, final ReferenceMethods second) + { + this.first = first; + this.second = second; + } + + public ReferenceMethod getBind() + { + return new DuplexReferenceMethod(first.getBind(), second.getBind()); + } + + public ReferenceMethod getUnbind() + { + return new DuplexReferenceMethod(first.getUnbind(), second.getUnbind()); + } + + public ReferenceMethod getUpdated() + { + return new DuplexReferenceMethod(first.getUpdated(), second.getUpdated()); + } + + public InitReferenceMethod getInit() + { + return new InitReferenceMethod() + { + + public boolean init(Object componentInstance, SimpleLogger logger) + { + final InitReferenceMethod i1 = first.getInit(); + if ( i1 != null ) + { + if ( !i1.init(componentInstance, logger)) + { + return false; + } + } + final InitReferenceMethod i2 = second.getInit(); + if ( i2 != null ) + { + if ( !i2.init(componentInstance, logger)) + { + return false; + } + } + return true; + } + }; + } + + private static final class DuplexReferenceMethod implements ReferenceMethod + { + + private final ReferenceMethod first; + + private final ReferenceMethod second; + + public DuplexReferenceMethod(final ReferenceMethod first, final ReferenceMethod second) + { + this.first = first; + this.second = second; + } + + public MethodResult invoke(Object componentInstance, + BindParameters rawParameter, + MethodResult methodCallFailureResult, SimpleLogger logger) + { + if ( first.invoke(componentInstance, rawParameter, methodCallFailureResult, logger) != null ) + { + return second.invoke(componentInstance, rawParameter, methodCallFailureResult, logger); + } + return null; + } + + public <S, T> boolean getServiceObject(ComponentContextImpl<S> key, + RefPair<S, T> refPair, BundleContext context, + SimpleLogger logger) + { + // only if both return true, we return true + boolean result = first.getServiceObject(key, refPair, context, logger); + if ( result ) + { + result = second.getServiceObject(key, refPair, context, logger); + } + return result; + } + + } +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldHandler.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldHandler.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldHandler.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldHandler.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,958 @@ +/* + * 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.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +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.Comparator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.CopyOnWriteArraySet; + +import org.apache.felix.scr.impl.manager.ComponentContextImpl; +import org.apache.felix.scr.impl.manager.RefPair; +import org.apache.felix.scr.impl.metadata.ReferenceMetadata; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.log.LogService; + +/** + * Handler for field references + */ +public class FieldHandler +{ + private enum ParamType { + serviceReference, + serviceObjects, + serviceType, + map, + tuple + } + + /** The reference metadata. */ + private final ReferenceMetadata metadata; + + /** The component class. */ + private final Class<?> componentClass; + + /** The field used for the injection. */ + private volatile Field field; + + /** Value type. */ + private volatile ParamType valueType; + + /** State handling. */ + private volatile State state; + + /** Mapping of ref pairs to value bound */ + private final Map<RefPair<?, ?>, Object> boundValues = new TreeMap<RefPair<?,?>, Object>( + new Comparator<RefPair<?, ?>>() + { + + public int compare(final RefPair<?, ?> o1, final RefPair<?, ?> o2) + { + return o1.getRef().compareTo(o2.getRef()); + } + }); + + /** + * Create a new field handler + * @param fieldName name of the field + * @param componentClass component class + * @param referenceClassName service class name + */ + public FieldHandler( final ReferenceMetadata metadata, + final Class<?> componentClass) + { + this.metadata = metadata; + this.componentClass = componentClass; + this.state = NotResolved.INSTANCE; + } + + /** + * Set the field. + * If the field is found, the state transitions to resolved, if the field is + * {@code null} the state transitions to not found. + * @param f The field or {@code null}. + * @param logger The logger + */ + private void setField( final Field f, final SimpleLogger logger ) + { + this.field = f; + + if ( f != null ) + { + state = Resolved.INSTANCE; + logger.log( LogService.LOG_DEBUG, "Found field: {0}", + new Object[] { field }, null ); + } + else + { + state = NotFound.INSTANCE; + logger.log(LogService.LOG_ERROR, "Field [{0}] not found; Component will fail", + new Object[] { this.metadata.getField() }, null); + } + } + + /** + * Finds the field named in the {@link #fieldName} field in the given + * <code>targetClass</code>. If the target class has no acceptable method + * the class hierarchy is traversed until a field is found or the root + * of the class hierarchy is reached without finding a field. + * + * @return The requested field or <code>null</code> if no acceptable field + * can be found in the target class or any super class. + * @throws InvocationTargetException If an unexpected Throwable is caught + * trying to find the requested field. + * @param logger + */ + private Field findField( final SimpleLogger logger ) + throws InvocationTargetException + { + final Class<?> targetClass = this.componentClass; + final ClassLoader targetClasslLoader = targetClass.getClassLoader(); + final String targetPackage = getPackageName( targetClass ); + Class<?> theClass = targetClass; + boolean acceptPrivate = true; + boolean acceptPackage = true; + while (true) + { + + if ( logger.isLogEnabled( LogService.LOG_DEBUG ) ) + { + logger.log( LogService.LOG_DEBUG, + "Locating field " + this.metadata.getField() + " in class " + theClass.getName(), null ); + } + + try + { + final Field field = getField( theClass, acceptPrivate, acceptPackage, logger ); + if ( field != null ) + { + return field; + } + } + catch ( SuitableMethodNotAccessibleException ex ) + { + // log and return null + logger.log( LogService.LOG_ERROR, + "findField: Suitable but non-accessible field {0} found in class {1}, subclass of {2}", new Object[] + { this.metadata.getField(), theClass.getName(), targetClass.getName() }, null ); + break; + } + + // if we get here, we have no field, so check the super class + theClass = theClass.getSuperclass(); + if ( theClass == null ) + { + break; + } + + // super class field check ignores private fields and accepts + // package fields only if in the same package and package + // fields are (still) allowed + acceptPackage &= targetClasslLoader == theClass.getClassLoader() + && targetPackage.equals( getPackageName( theClass ) ); + + // private fields will not be accepted any more in super classes + acceptPrivate = false; + } + + // nothing found after all these years ... + return null; + } + + /** + * Finds the field named in the {@link #fieldName} field in the given + * <code>targetClass</code>. If the target class has no acceptable field + * the class hierarchy is traversed until a field is found or the root + * of the class hierarchy is reached without finding a field. + * + * + * @param targetClass The class in which to look for the method + * @param acceptPrivate <code>true</code> if private fields should be + * considered. + * @param acceptPackage <code>true</code> if package private fields should + * be considered. + * @param logger + * @return The requested field or <code>null</code> if no acceptable field + * can be found in the target class or any super class. + * @throws InvocationTargetException If an unexpected Throwable is caught + * trying to find the requested field. + */ + private Field getField( final Class<?> clazz, + final boolean acceptPrivate, + final boolean acceptPackage, + final SimpleLogger logger ) + throws SuitableMethodNotAccessibleException, InvocationTargetException + { + try + { + // find the declared field in this class + final Field field = clazz.getDeclaredField( this.metadata.getField() ); + + // accept public and protected fields only and ensure accessibility + if ( accept( field, acceptPrivate, acceptPackage ) ) + { + return field; + } + + // the method would fit the requirements but is not acceptable + throw new SuitableMethodNotAccessibleException(); + } + catch ( NoSuchFieldException nsfe ) + { + // thrown if no field is declared with the given name and + // parameters + if ( logger.isLogEnabled( LogService.LOG_DEBUG ) ) + { + logger.log( LogService.LOG_DEBUG, "Declared Field {0}.{1} not found", new Object[] + { clazz.getName(), this.metadata.getField() }, null ); + } + } + catch ( NoClassDefFoundError cdfe ) + { + // may be thrown if a method would be found but the signature + // contains throws declaration for an exception which cannot + // be loaded + if ( logger.isLogEnabled( LogService.LOG_WARNING ) ) + { + StringBuffer buf = new StringBuffer(); + buf.append( "Failure loooking up field " ).append( this.metadata.getField() ); + buf.append( " in class class " ).append( clazz.getName() ).append( ". Assuming no such field." ); + logger.log( LogService.LOG_WARNING, buf.toString(), cdfe ); + } + } + catch ( SuitableMethodNotAccessibleException e) + { + throw e; + } + catch ( Throwable throwable ) + { + // unexpected problem accessing the field, don't let everything + // blow up in this situation, just throw a declared exception + throw new InvocationTargetException( throwable, "Unexpected problem trying to get field " + this.metadata.getField() ); + } + + // caught and ignored exception, assume no field and continue search + return null; + } + + /** + * Validate the field, type etc. + * @param f The field + * @param logger The logger + * @return The field if it's valid, {@code null} otherwise. + */ + private Field validateField( final Field f, final SimpleLogger logger ) + { + final Class<?> fieldType = f.getType(); + final Class<?> referenceType = ClassUtils.getClassFromComponentClassLoader( + this.componentClass, metadata.getInterface(), logger); + + // unary reference + if ( !metadata.isMultiple() ) + { + if ( fieldType.isAssignableFrom(referenceType) ) + { + valueType = ParamType.serviceType; + } + else if ( fieldType == ClassUtils.SERVICE_REFERENCE_CLASS ) + { + valueType = ParamType.serviceReference; + } + else if ( fieldType == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS ) + { + valueType = ParamType.serviceObjects; + } + else if ( fieldType == ClassUtils.MAP_CLASS ) + { + valueType = ParamType.map; + } + else if ( fieldType == ClassUtils.MAP_ENTRY_CLASS ) + { + valueType = ParamType.tuple; + } + else + { + logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[] + {metadata.getField(), this.componentClass, fieldType.getName()}, null ); + return null; + } + + // if the field is dynamic and optional it has to be volatile + if ( !metadata.isStatic() && metadata.isOptional() ) + { + 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; + } + } + + // 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 + { + // multiple cardinality, field type must be collection or subtype + if ( !ClassUtils.COLLECTION_CLASS.isAssignableFrom(fieldType) ) + { + logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[] + {metadata.getField(), this.componentClass, fieldType.getName()}, null ); + return null; + } + + // if the field is dynamic with the replace strategy it has to be volatile + if ( !metadata.isStatic() && metadata.isReplace() ) + { + 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.isReplace() ) + { + 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.getFieldCollectionType()) ) + { + valueType = ParamType.serviceType; + } + else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(metadata.getFieldCollectionType()) ) + { + valueType = ParamType.serviceReference; + } + else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(metadata.getFieldCollectionType()) ) + { + valueType = ParamType.serviceObjects; + } + else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(metadata.getFieldCollectionType()) ) + { + valueType = ParamType.map; + } + else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(metadata.getFieldCollectionType()) ) + { + valueType = ParamType.tuple; + } + } + return f; + } + + private enum METHOD_TYPE + { + BIND, + UNBIND, + UPDATED + }; + + @SuppressWarnings("rawtypes") + private final class MapEntryImpl implements Map.Entry, Comparable<Map.Entry<?, ?>> + { + + private final Object key; + private final Object value; + private final ServiceReference<?> ref; + + public MapEntryImpl(final Object key, + final Object value, + final ServiceReference<?> ref) + { + this.key = key; + this.value = value; + this.ref = ref; + } + + public Object getKey() + { + return this.key; + } + + public Object getValue() + { + return this.value; + } + + public Object setValue(final Object value) + { + throw new UnsupportedOperationException(); + } + + public int compareTo(final Map.Entry<?, ?> o) + { + if ( o == null ) + { + return 1; + } + if ( o instanceof MapEntryImpl ) + { + final MapEntryImpl other = (MapEntryImpl)o; + return ref.compareTo(other.ref); + + } + return new Integer(this.hashCode()).compareTo(o.hashCode()); + } + + } + + private Object getValue(final ComponentContextImpl key, + final RefPair<?, ?> refPair) + { + final Object obj; + switch ( this.valueType ) + { + case serviceType : obj = refPair.getServiceObject(key); break; + case serviceReference : obj = refPair.getRef(); break; + case serviceObjects : obj = ((ComponentServiceObjectsHelper)key.getComponentServiceObjectsHelper()).getServiceObjects(refPair.getRef()); break; + case map : obj = new ReadOnlyDictionary<String, Object>( refPair.getRef() ); break; + case tuple : final Object tupleKey = new ReadOnlyDictionary<String, Object>( refPair.getRef() ); + final Object tupleValue = refPair.getServiceObject(key); + obj = new MapEntryImpl(tupleKey, tupleValue, refPair.getRef()); + break; + default: obj = null; + } + return obj; + } + + private boolean initField(final Object componentInstance, + final SimpleLogger logger ) + { + try + { + if ( metadata.isMultiple() + && !metadata.isStatic() ) + { + if ( metadata.isReplace() ) + { + 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() + { + 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, + final SimpleLogger logger ) + throws InvocationTargetException + { + final ComponentContextImpl key = bp.getComponentContext(); + final RefPair<?, ?> refPair = bp.getRefPair(); + + if ( !this.metadata.isMultiple() ) + { + // unary references + // unbind needs only be done, if reference is dynamic and optional + if ( mType == METHOD_TYPE.UNBIND ) + { + if ( this.metadata.isOptional() && !this.metadata.isStatic() ) + { + // we only reset if it was previously set with this value + if ( this.boundValues.size() == 1 ) + { + this.setFieldValue(componentInstance, 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() ) + { + 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 + else + { + final Object obj = getValue(key, refPair); + this.setFieldValue(componentInstance, obj); + 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 ( metadata.isReplace() ) + { + 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 ( metadata.isReplace() ) + { + 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 ( metadata.isReplace() ) + { + this.setFieldValue(componentInstance, getReplaceCollection()); + } + else + { + @SuppressWarnings("unchecked") + final Collection<Object> col = (Collection<Object>)this.getFieldValue(componentInstance); + col.add(obj); + col.remove(oldObj); + } + } + } + } + + return MethodResult.VOID; + } + + private void setFieldValue(final Object componentInstance, final Object value) + throws InvocationTargetException + { + try + { + field.set(componentInstance, value); + } + catch ( final IllegalArgumentException iae ) + { + throw new InvocationTargetException(iae); + } + catch ( final IllegalAccessException iae ) + { + throw new InvocationTargetException(iae); + } + } + + private Object getFieldValue(final Object componentInstance) + throws InvocationTargetException + { + try + { + return field.get(componentInstance); + } + catch ( final IllegalArgumentException iae ) + { + throw new InvocationTargetException(iae); + } + catch ( final IllegalAccessException iae ) + { + throw new InvocationTargetException(iae); + } + } + + /** + * Returns <code>true</code> if the field is acceptable to be returned from the + * {@link #getField(Class, String, boolean, boolean, SimpleLogger)} and also + * makes the field accessible. + * <p> + * This method returns <code>true</code> if the field: + * <ul> + * <li>Is not static</li> + * <li>Is public or protected</li> + * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li> + * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li> + * </ul> + * <p> + * + * @param field The field to check + * @param acceptPrivate Whether a private field is acceptable + * @param acceptPackage Whether a package private field is acceptable + * @return whether the field is acceptable + */ + private static boolean accept( final Field field, + final boolean acceptPrivate, + final boolean acceptPackage ) + { + // check modifiers now + final int mod = field.getModifiers(); + + // no static fields + if ( Modifier.isStatic( mod ) ) + { + return false; + } + + // accept public and protected fields + if ( Modifier.isPublic( mod ) || Modifier.isProtected( mod ) ) + { + setAccessible( field ); + return true; + } + + // accept private if accepted + if ( Modifier.isPrivate( mod ) ) + { + if ( acceptPrivate ) + { + setAccessible( field ); + return true; + } + + return false; + } + + // accept default (package) + if ( acceptPackage ) + { + setAccessible( field ); + return true; + } + + // else don't accept + return false; + } + + private static void setAccessible(final Field field) + { + AccessController.doPrivileged( new PrivilegedAction<Object>() + { + public Object run() + { + field.setAccessible( true ); + return null; + } + } ); + } + + + /** + * Returns the name of the package to which the class belongs or an + * empty string if the class is in the default package. + */ + public static String getPackageName( Class<?> clazz ) + { + String name = clazz.getName(); + int dot = name.lastIndexOf( '.' ); + return ( dot > 0 ) ? name.substring( 0, dot ) : ""; + } + + /** + * Internal state interface. + */ + private static interface State + { + + MethodResult invoke( final FieldHandler handler, + final METHOD_TYPE mType, + final Object componentInstance, + final BindParameters rawParameter, + final SimpleLogger logger ) + throws InvocationTargetException; + + boolean fieldExists( final FieldHandler handler, final SimpleLogger logger); + } + + /** + * Initial state. + */ + private static class NotResolved implements State + { + private static final State INSTANCE = new NotResolved(); + + private synchronized void resolve( final FieldHandler handler, final SimpleLogger logger ) + { + logger.log( LogService.LOG_DEBUG, "getting field: {0}", new Object[] + {handler.metadata.getField()}, null ); + + // resolve the field + Field field = null; + try + { + field = handler.findField( logger ); + field = handler.validateField( field, logger ); + } + catch ( final InvocationTargetException ex ) + { + logger.log( LogService.LOG_WARNING, "{0} cannot be found", new Object[] + {handler.metadata.getField()}, ex.getTargetException() ); + field = null; + } + + handler.setField( field, logger ); + } + + public MethodResult invoke( final FieldHandler handler, + final METHOD_TYPE mType, + final Object componentInstance, + final BindParameters rawParameter, + SimpleLogger logger ) + throws InvocationTargetException + { + resolve( handler, logger ); + return handler.state.invoke( handler, mType, componentInstance, rawParameter, logger ); + } + + public boolean fieldExists( final FieldHandler handler, final SimpleLogger logger) + { + resolve( handler, logger ); + return handler.state.fieldExists( handler, logger ); + } + } + + /** + * Final state of field couldn't be found or errors occured. + */ + private static class NotFound implements State + { + private static final State INSTANCE = new NotFound(); + + public MethodResult invoke( final FieldHandler handler, + final METHOD_TYPE mType, + final Object componentInstance, + final BindParameters rawParameter, + final SimpleLogger logger ) + { + logger.log( LogService.LOG_ERROR, "Field [{0}] not found", new Object[] + { handler.metadata.getField() }, null ); + return null; + } + + public boolean fieldExists( final FieldHandler handler, final SimpleLogger logger) + { + return false; + } + } + + /** + * Final state of field could be found and is valid. + */ + private static class Resolved implements State + { + private static final State INSTANCE = new Resolved(); + + public MethodResult invoke( final FieldHandler handler, + final METHOD_TYPE mType, + final Object componentInstance, + final BindParameters rawParameter, + final SimpleLogger logger ) + throws InvocationTargetException + { + return handler.updateField( mType, componentInstance, rawParameter, logger ); + } + + public boolean fieldExists( final FieldHandler handler, final SimpleLogger logger) + { + return true; + } + } + + public boolean fieldExists( SimpleLogger logger ) + { + return this.state.fieldExists( this, logger ); + } + + 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) + { + this.methodType = mt; + this.handler = handler; + } + + public MethodResult invoke(final Object componentInstance, + final BindParameters rawParameter, + final MethodResult methodCallFailureResult, + final SimpleLogger logger) + { + try + { + return handler.state.invoke( handler, + methodType, + componentInstance, + rawParameter, + logger ); + } + catch ( final InvocationTargetException ite ) + { + logger.log( LogService.LOG_ERROR, "The {0} field has thrown an exception", new Object[] + { handler.metadata.getField() }, ite.getCause() ); + } + + return methodCallFailureResult; + } + + public <S, T> boolean getServiceObject(final ComponentContextImpl<S> key, + final RefPair<S, T> refPair, + final BundleContext context, + final SimpleLogger logger) + { + if ( methodType != METHOD_TYPE.UNBIND ) + { + //??? this resolves which we need.... better way? + if ( refPair.getServiceObject(key) == null + && handler.fieldExists( logger ) + && (handler.valueType == ParamType.serviceType || handler.valueType == ParamType.tuple ) ) + { + return refPair.getServiceObject(key, context, logger); + } + } + return true; + } + + } + public ReferenceMethod getBind() + { + return new ReferenceMethodImpl(METHOD_TYPE.BIND, this); + } + + public ReferenceMethod getUnbind() + { + return new ReferenceMethodImpl(METHOD_TYPE.UNBIND, this); + } + + public ReferenceMethod getUpdated() + { + return new ReferenceMethodImpl(METHOD_TYPE.UPDATED, this); + } + + public InitReferenceMethod getInit() + { + return new InitReferenceMethod() + { + + public boolean init(final Object componentInstance, final SimpleLogger logger) + { + if ( fieldExists( logger) ) + { + return initField(componentInstance, logger); + } + return false; + } + }; + } +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldMethods.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldMethods.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldMethods.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/FieldMethods.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,71 @@ +/* + * 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 org.apache.felix.scr.impl.metadata.DSVersion; +import org.apache.felix.scr.impl.metadata.ReferenceMetadata; + +/** + * @version $Rev: 1637793 $ $Date: 2014-11-10 06:51:04 +0100 (Mon, 10 Nov 2014) $ + */ +public class FieldMethods implements ReferenceMethods +{ + 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 ) + { + final FieldHandler handler = new FieldHandler( + m_dependencyMetadata, + instanceClass + ); + bind = handler.getBind(); + unbind = handler.getUnbind(); + updated = handler.getUpdated(); + init = handler.getInit(); + } + + public ReferenceMethod getBind() + { + return bind; + } + + public ReferenceMethod getUnbind() + { + return unbind; + } + + public ReferenceMethod getUpdated() + { + return updated; + } + + public InitReferenceMethod getInit() + { + return init; + } +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/InitReferenceMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/InitReferenceMethod.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/InitReferenceMethod.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/InitReferenceMethod.java Wed Jul 8 22:10:14 2015 @@ -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 ); +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Logger.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Logger.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Logger.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Logger.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,70 @@ +/* + * 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 org.apache.felix.scr.impl.metadata.ComponentMetadata; + + +/** + * The <code>Logger</code> interface defines a simple API to enable some logging + * in the XML Parser and ComponentMetadata handling classes and at the same + * time not be too intrusive for the unit tests. + */ +public interface Logger +{ + + /** + * Returns <code>true</code> if logging for the given level is enabled. + */ + boolean isLogEnabled( int level ); + + + /** + * Method to actually emit the log message. If the LogService is available, + * the message will be logged through the LogService. Otherwise the message + * is logged to stdout (or stderr in case of LOG_ERROR level messages), + * + * @param level The log level to log the message at + * @param pattern The <code>java.text.MessageFormat</code> message format + * string for preparing the message + * @param arguments The format arguments for the <code>pattern</code> + * string. + * @param metadata component metadata if known + * @param componentId component ID if known + * @param ex An optional <code>Throwable</code> whose stack trace is written, + */ + void log( int level, String pattern, Object[] arguments, ComponentMetadata metadata, Long componentId, Throwable ex ); + + + /** + * Writes a messages for the given <code>ComponentMetadata</code>. + * + * @param level The log level of the messages. This corresponds to the log + * levels defined by the OSGi LogService. + * @param message The message to print + * @param metadata The {@link org.apache.felix.scr.impl.metadata.ComponentMetadata} whose processing caused + * the message. This may be <code>null</code> if the component + * metadata is not known or applicable. + * @param componentId + * @param ex The <code>Throwable</code> causing the message to be logged. + */ + void log( int level, String message, ComponentMetadata metadata, Long componentId, Throwable ex ); + +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/MethodResult.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/MethodResult.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/MethodResult.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/MethodResult.java Wed Jul 8 22:10:14 2015 @@ -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<String, Object> result; + + private final boolean hasResult; + + MethodResult(final boolean hasResult, final Map<String, Object> result) + { + this.hasResult = hasResult; + this.result = result; + } + + public boolean hasResult() + { + return hasResult; + } + + public Map<String, Object> getResult() + { + return result; + } +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ModifiedMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ModifiedMethod.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ModifiedMethod.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ModifiedMethod.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,44 @@ +/* + * 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 org.apache.felix.scr.impl.metadata.DSVersion; + + +public class ModifiedMethod extends ActivateMethod +{ + + public ModifiedMethod( final String methodName, + final Class<?> componentClass, final DSVersion dsVersion, final boolean configurableServiceProperties, boolean supportsInterfaces ) + { + super( methodName, methodName != null, componentClass, dsVersion, configurableServiceProperties, supportsInterfaces ); + } + + + protected boolean acceptEmpty() + { + return true; + } + + + protected String getMethodNamePrefix() + { + return "modified"; + } +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,215 @@ +/* + * 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.Collection; +import java.util.Collections; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +import org.osgi.framework.ServiceReference; + + +/** + * The <code>ReadOnlyDictionary</code> is both a <code>Dictionary</code> and + * a <code>Map</code> whose modification methods (like {@link #put(Object, Object)}, + * {@link #remove(Object)}, etc.) throw an {@link UnsupportedOperationException}. + */ +public class ReadOnlyDictionary<S, T> extends Dictionary<S, T> + implements Map<S, T>, Comparable<ReadOnlyDictionary<S, T>> +{ + + private final Hashtable<S, T> m_delegate; + + private final ServiceReference<?> m_serviceReference; + + /** + * Creates a wrapper for the given delegate dictionary providing read + * only access to the data. + */ + public ReadOnlyDictionary( final Map<S, T> delegate ) + { + if ( delegate instanceof Hashtable ) + { + this.m_delegate = ( Hashtable<S, T> ) delegate; + } + else + { + this.m_delegate = new Hashtable<S, T>(); + for ( Map.Entry<S, T> entry: delegate.entrySet() ) + { + this.m_delegate.put( entry.getKey(), entry.getValue() ); + } + } + m_serviceReference = null; + } + + + /** + * Creates a wrapper for the given service reference providing read only + * access to the reference properties. + */ + public ReadOnlyDictionary( final ServiceReference<?> serviceReference ) + { + Hashtable properties = new Hashtable(); + final String[] keys = serviceReference.getPropertyKeys(); + if ( keys != null ) + { + for ( int j = 0; j < keys.length; j++ ) + { + final String key = keys[j]; + properties.put( key, serviceReference.getProperty( key ) ); + } + } + m_delegate = properties; + m_serviceReference = serviceReference; + } + + + //---------- Dictionary API + + @Override + public Enumeration<T> elements() + { + return m_delegate.elements(); + } + + @Override + public T get( final Object key ) + { + return m_delegate.get( key ); + } + + + @Override + public boolean isEmpty() + { + return m_delegate.isEmpty(); + } + + + @Override + public Enumeration<S> keys() + { + return m_delegate.keys(); + } + + + /** + * This method has no effect and always returns <code>null</code> as this + * instance is read-only and cannot modify and properties. + */ + @Override + public T put( final S key, final T value ) + { + throw new UnsupportedOperationException(); + } + + + /** + * This method has no effect and always returns <code>null</code> as this + * instance is read-only and cannot modify and properties. + */ + @Override + public T remove( final Object key ) + { + throw new UnsupportedOperationException(); + } + + + @Override + public int size() + { + return m_delegate.size(); + } + + + @Override + public String toString() + { + return m_delegate.toString(); + } + + + //---------- Map API + + public void clear() + { + throw new UnsupportedOperationException(); + } + + + public boolean containsKey( Object key ) + { + return m_delegate.containsKey( key ); + } + + + public boolean containsValue( Object value ) + { + return m_delegate.containsValue( value ); + } + + + public Set<Entry<S, T>> entrySet() + { + return Collections.unmodifiableSet( m_delegate.entrySet() ); + } + + + public Set<S> keySet() + { + return Collections.unmodifiableSet( m_delegate.keySet() ); + } + + + public void putAll( Map<? extends S, ? extends T> m ) + { + throw new UnsupportedOperationException(); + } + + + public Collection<T> values() + { + return Collections.unmodifiableCollection( m_delegate.values() ); + } + + + public int compareTo(final ReadOnlyDictionary<S, T> o) + { + if ( m_serviceReference == null ) + { + if ( o.m_serviceReference == null ) + { + return 0; + } + return 1; + } + else if ( o.m_serviceReference == null ) + { + return -1; + } + return m_serviceReference.compareTo(o.m_serviceReference); + } + +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethod.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethod.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethod.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,37 @@ +/* + * 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 org.apache.felix.scr.impl.manager.ComponentContextImpl; +import org.apache.felix.scr.impl.manager.RefPair; +import org.osgi.framework.BundleContext; + + + + +/** + * Component method to be invoked on service (un)binding. + */ +public interface ReferenceMethod +{ + MethodResult invoke( final Object componentInstance, final BindParameters rawParameter, + final MethodResult methodCallFailureResult, SimpleLogger logger ); + + <S, T> boolean getServiceObject( ComponentContextImpl<S> key, RefPair<S, T> refPair, BundleContext context, SimpleLogger logger ); +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethods.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethods.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethods.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ReferenceMethods.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,36 @@ +/* + * 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; + + +/** + * @version $Rev: 1637793 $ $Date: 2014-11-10 06:51:04 +0100 (Mon, 10 Nov 2014) $ + */ +public interface ReferenceMethods +{ + + ReferenceMethod getBind(); + + ReferenceMethod getUnbind(); + + ReferenceMethod getUpdated(); + + /** Optional. */ + InitReferenceMethod getInit(); +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SimpleLogger.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SimpleLogger.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SimpleLogger.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SimpleLogger.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,33 @@ +/* + * 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; + +/** + * @version $Rev: 1382234 $ $Date: 2012-09-08 05:55:26 +0200 (Sat, 08 Sep 2012) $ + */ +public interface SimpleLogger +{ + void log( int level, String message, Throwable ex ); + + void log( int level, String message, Object[] arguments, Throwable ex ); + + boolean isLogEnabled( int level ); +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,24 @@ +/* + * 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; + + +public class SuitableMethodNotAccessibleException extends Exception +{ +} \ No newline at end of file Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UnbindMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UnbindMethod.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UnbindMethod.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UnbindMethod.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,45 @@ +/* + * 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 org.apache.felix.scr.impl.metadata.DSVersion; +import org.apache.felix.scr.impl.metadata.ReferenceMetadata; + + +/** + * Component method to be invoked on service unbinding. + */ +public class UnbindMethod extends BindMethod +implements org.apache.felix.scr.impl.helper.ReferenceMethod +{ + + public UnbindMethod( final String methodName, + final Class<?> componentClass, final String referenceClassName, final DSVersion dsVersion, final boolean configurableServiceProperties, ReferenceMetadata.ReferenceScope referenceScope ) + { + super( methodName, componentClass, referenceClassName, dsVersion, configurableServiceProperties, referenceScope ); + } + + + @Override + protected String getMethodNamePrefix() + { + return "unbind"; + } + +} \ No newline at end of file Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UpdatedMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UpdatedMethod.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UpdatedMethod.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/UpdatedMethod.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,45 @@ +/* + * 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 org.apache.felix.scr.impl.metadata.DSVersion; +import org.apache.felix.scr.impl.metadata.ReferenceMetadata; + + +/** + * Component method to be invoked on service property update of a bound service. + */ +public class UpdatedMethod extends BindMethod +implements org.apache.felix.scr.impl.helper.ReferenceMethod +{ + + public UpdatedMethod( final String methodName, + final Class<?> componentClass, final String referenceClassName, final DSVersion dsVersion, final boolean configurableServiceProperties, ReferenceMetadata.ReferenceScope referenceScope ) + { + super( methodName, componentClass, referenceClassName, dsVersion, configurableServiceProperties, referenceScope ); + } + + + @Override + protected String getMethodNamePrefix() + { + return "update"; + } + +} \ No newline at end of file
