Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/EdgeInfo.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/EdgeInfo.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/EdgeInfo.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/EdgeInfo.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,158 @@ +/* + * 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.manager; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.osgi.service.log.LogService; + +/** + * EdgeInfo holds information about the service event tracking counts for creating (open) and disposing (close) + * implementation object instances per dependency manager. These need to be maintained for each implementation object instance + * because each instance (for a service factory) will have different sets of service references available. These need to be + * maintained for each dependency manager because the open/close tracking counts are obtained when the set of current + * service references is obtained, using a lock internal to the service tracker. + * + * + * The information in the open/close counts is used in the outOfRange method which determines if a service event tracking count + * occurred before the "open" event (in which case it is reflected in the open set already and does not need to be processed separately) + * or after the "close" event (in which case it is reflected in the close set already). + * + * The open latch is used to make sure that elements in the open set are completely processed before updated or unbind events + * are processed + * The close latch is used to make sure that unbind events that are out of range wait for the close to complete before returning; + * in this case the unbind is happening in the "close" thread rather than the service event thread, so we wait for the close to complete + * so that when the service event returns the unbind will actually have been completed. + * + * Related to this functionality is the missing tracking in AbstractComponentManager. This is used on close of an instance to make + * sure all service events occuring before close starts complete processing before the close takes action. + * + */ + +class EdgeInfo +{ + private int open = -1; + private int close = -1; + private final CountDownLatch openLatch = new CountDownLatch(1); + private final CountDownLatch closeLatch = new CountDownLatch(1); + + public void setClose( int close ) + { + this.close = close; + } + + public CountDownLatch getOpenLatch() + { + return openLatch; + } + + public void waitForOpen(AbstractComponentManager<?> m_componentManager, String componentName, String methodName) + { + + CountDownLatch latch = getOpenLatch(); + String latchName = "open"; + waitForLatch( m_componentManager, latch, componentName, methodName, latchName ); + } + + public void waitForClose(AbstractComponentManager<?> m_componentManager, String componentName, String methodName) + { + + CountDownLatch latch = getCloseLatch(); + String latchName = "close"; + waitForLatch( m_componentManager, latch, componentName, methodName, latchName ); + } + + private void waitForLatch(AbstractComponentManager<?> m_componentManager, CountDownLatch latch, String componentName, + String methodName, String latchName) + { + try + { + if (!latch.await( m_componentManager.getLockTimeout(), TimeUnit.MILLISECONDS )) + { + m_componentManager.log( LogService.LOG_ERROR, + "DependencyManager : {0} : timeout on {1} latch {2}", new Object[] {methodName, latchName, componentName}, null ); + m_componentManager.dumpThreads(); + } + } + catch ( InterruptedException e ) + { + try + { + if (!latch.await( m_componentManager.getLockTimeout(), TimeUnit.MILLISECONDS )) + { + m_componentManager.log( LogService.LOG_ERROR, + "DependencyManager : {0} : timeout on {1} latch {2}", new Object[] {methodName, latchName, componentName}, null ); + m_componentManager.dumpThreads(); + } + } + catch ( InterruptedException e1 ) + { + m_componentManager.log( LogService.LOG_ERROR, + "DependencyManager : {0} : Interrupted twice on {1} latch {2}", new Object[] {methodName, latchName, componentName}, null ); + Thread.currentThread().interrupt(); + } + Thread.currentThread().interrupt(); + } + } + + public CountDownLatch getCloseLatch() + { + return closeLatch; + } + + public void setOpen( int open ) + { + this.open = open; + } + + public void ignore() + { + open = Integer.MAX_VALUE; + close = Integer.MAX_VALUE - 1; + openLatch.countDown(); + closeLatch.countDown(); + } + + /** + * Returns whether the tracking count is before the open count or after the close count (if set) + * This must be called from within a block synchronized on m_tracker.tracked(). + * Setting open occurs in a synchronized block as well, to the tracker's current tracking count. + * Therefore if this outOfRange call finds open == -1 then open will be set to a tracking count + * at least as high as the argument tracking count. + * @param trackingCount tracking count from tracker to compare with range + * @return true if open not set, tracking count before open, or close set and tracking count after close. + */ + public boolean outOfRange( int trackingCount ) + { + return open == -1 + || trackingCount < open + || (close != -1 && trackingCount > close); + } + + public boolean beforeRange( int trackingCount ) + { + return open == -1 || trackingCount < open; + } + + public boolean afterRange( int trackingCount ) + { + return close != -1 && trackingCount > close; + } +} \ No newline at end of file
Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,96 @@ +/* + * 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.manager; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.scr.impl.helper.SimpleLogger; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServiceReference; +import org.osgi.service.log.LogService; + +/** + * @version $Rev: 1689302 $ $Date: 2015-07-06 03:31:39 +0200 (Mon, 06 Jul 2015) $ + */ +public class MultiplePrototypeRefPair<S, T> extends RefPair<S, T> +{ + private final ServiceObjects<T> serviceObjects; + private final ConcurrentMap<ComponentContextImpl<S>, T> instances = new ConcurrentHashMap<ComponentContextImpl<S>, T>(); + + public MultiplePrototypeRefPair( BundleContext context, ServiceReference<T> ref ) + { + super(ref); + this.serviceObjects = context.getServiceObjects(ref); + } + + @Override + public ServiceObjects<T> getServiceObjects() + { + return serviceObjects; + } + + @Override + public T getServiceObject(ComponentContextImpl<S> key) + { + return instances.get( key ); + } + + @Override + public boolean setServiceObject(ComponentContextImpl<S> key, T serviceObject) + { + return instances.putIfAbsent(key, serviceObject) == null; + } + + @Override + public T unsetServiceObject(ComponentContextImpl<S> key) + { + return instances.get(key); + } + + @Override + public String toString() + { + return "[MultiplePrototypeRefPair: ref: [" + getRef() + "] has service: [" + !instances.isEmpty() + "]]"; + } + + @Override + public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context, + SimpleLogger logger) + { + final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef(), serviceObjects); + if ( service == null ) + { + setFailed(); + logger.log( + LogService.LOG_WARNING, + "Could not get service from serviceobjects for ref {0}", new Object[] {getRef()}, null ); + return false; + } + if (!setServiceObject(key, service)) + { + // Another thread got the service before, so unget our + serviceObjects.ungetService( service ); + } + return true; + } +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/PrototypeServiceFactoryComponentManager.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/PrototypeServiceFactoryComponentManager.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/PrototypeServiceFactoryComponentManager.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/PrototypeServiceFactoryComponentManager.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.manager; + +import org.apache.felix.scr.impl.config.ComponentContainer; +import org.apache.felix.scr.impl.helper.ComponentMethods; +import org.osgi.framework.PrototypeServiceFactory; + +public class PrototypeServiceFactoryComponentManager<S> extends ServiceFactoryComponentManager<S> implements PrototypeServiceFactory<S> +{ + + public PrototypeServiceFactoryComponentManager(ComponentContainer<S> container, ComponentMethods componentMethods) + { + super(container, componentMethods); + } + +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RefPair.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RefPair.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RefPair.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RefPair.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,82 @@ +/* + * 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.manager; + +import org.apache.felix.scr.impl.helper.SimpleLogger; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServiceReference; + +/** + * @version $Rev: 1689302 $ $Date: 2015-07-06 03:31:39 +0200 (Mon, 06 Jul 2015) $ + */ +public abstract class RefPair<S, T> +{ + private final ServiceReference<T> ref; + + boolean failed; + volatile boolean deleted; + + public RefPair( ServiceReference<T> ref ) + { + this.ref = ref; + } + + public ServiceReference<T> getRef() + { + return ref; + } + + public ServiceObjects<T> getServiceObjects() + { + return null; + } + + public abstract boolean getServiceObject( ComponentContextImpl<S> key, BundleContext context, SimpleLogger logger ); + + public abstract T getServiceObject(ComponentContextImpl<S> key); + + public abstract boolean setServiceObject( ComponentContextImpl<S> key, T serviceObject ); + + public abstract T unsetServiceObject(ComponentContextImpl<S> key); + + public void setFailed( ) + { + this.failed = true; + } + + public boolean isFailed() + { + return failed; + } + + public boolean isDeleted() + { + return deleted; + } + + public void setDeleted(boolean deleted) + { + this.deleted = deleted; + } + + +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RegistrationManager.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RegistrationManager.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RegistrationManager.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/RegistrationManager.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,216 @@ +/* + * 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.manager; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.osgi.service.log.LogService; + +abstract class RegistrationManager<T> +{ + enum RegState {unregistered, registered}; + private static class RegStateWrapper + { + private final CountDownLatch latch = new CountDownLatch(1); + private final RegState regState; + + RegStateWrapper( RegState regState ) + { + this.regState = regState; + } + + public RegState getRegState() + { + return regState; + } + + public CountDownLatch getLatch() + { + return latch; + } + + @Override + public int hashCode() + { + return regState.hashCode(); + } + + @Override + public boolean equals(Object other) + { + return other instanceof RegStateWrapper && regState == ((RegStateWrapper)other).getRegState(); + } + + @Override + public String toString() + { + return regState.toString(); + } + + + + } + private final Lock registrationLock = new ReentrantLock(); + //Deque, ArrayDeque if we had java 6 + private final List<RegStateWrapper> opqueue = new ArrayList<RegStateWrapper>(); + + private volatile T m_serviceRegistration; + /** + * + * @param desired desired registration state + * @param services services to register this under + * @return true if this request results in a state change, false if we are already in the desired state or some other thread + * will deal with the consequences of the state change. + */ + boolean changeRegistration( RegState desired, String[] services ) + { + RegStateWrapper rsw = null; + registrationLock.lock(); + try + { + if (opqueue.isEmpty()) + { + if ((desired == RegState.unregistered) == (m_serviceRegistration == null)) + { + log( LogService.LOG_DEBUG, "Already in desired state {0}", new Object[] + {desired}, null ); + return false; + } + } + else if (opqueue.get( opqueue.size() - 1 ).getRegState() == desired) + { + log( LogService.LOG_DEBUG, "Duplicate request on other thread: registration change queue {0}", new Object[] + {opqueue}, null ); + rsw = opqueue.get( opqueue.size() - 1 ); + return false; //another thread will do our work and owns the state change + } + rsw = new RegStateWrapper( desired ); + opqueue.add( rsw ); + if (opqueue.size() > 1) + { + log( LogService.LOG_DEBUG, "Allowing other thread to process request: registration change queue {0}", new Object[] + {opqueue}, null ); + return true; //some other thread will do it later but this thread owns the state change. + } + //we're next + do + { + log( LogService.LOG_DEBUG, "registration change queue {0}", new Object[] + {opqueue}, null ); + RegStateWrapper next = opqueue.get( 0 ); + T serviceRegistration = m_serviceRegistration; + if ( next.getRegState() == RegState.unregistered) + { + m_serviceRegistration = null; + } + + registrationLock.unlock(); + try + { + if (next.getRegState() == RegState.registered) + { + serviceRegistration = register(services ); + + } + else + { + if ( serviceRegistration != null ) + { + unregister( serviceRegistration ); + } + else + { + log( LogService.LOG_ERROR, "Unexpected unregistration request with no registration present", new Object[] + {}, new Exception("Stack trace") ); + + } + } + } + finally + { + registrationLock.lock(); + opqueue.remove(0); + if ( next.getRegState() == RegState.registered) + { + m_serviceRegistration = serviceRegistration; + } + next.getLatch().countDown(); + } + } + while (!opqueue.isEmpty()); + return true; + } + finally + { + registrationLock.unlock(); + if (rsw != null) + { + try + { + if ( !rsw.getLatch().await( getTimeout(), TimeUnit.MILLISECONDS )) + { + log( LogService.LOG_ERROR, "Timeout waiting for reg change to complete {0}", new Object[] + {rsw.getRegState()}, null); + reportTimeout(); + } + } + catch ( InterruptedException e ) + { + try + { + if ( !rsw.getLatch().await( getTimeout(), TimeUnit.MILLISECONDS )) + { + log( LogService.LOG_ERROR, "Timeout waiting for reg change to complete {0}", new Object[] + {rsw.getRegState()}, null); + reportTimeout(); + } + } + catch ( InterruptedException e1 ) + { + log( LogService.LOG_ERROR, "Interrupted twice waiting for reg change to complete {0}", new Object[] + {rsw.getRegState()}, null); + } + Thread.currentThread().interrupt(); + } + } + } + + } + + abstract T register(String[] services); + + abstract void unregister(T serviceRegistration); + + abstract void log( int level, String message, Object[] arguments, Throwable ex ); + + abstract long getTimeout(); + + abstract void reportTimeout(); + + T getServiceRegistration() + { + return m_serviceRegistration; + } + +} Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java?rev=1689973&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java (added) +++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java Wed Jul 8 22:10:14 2015 @@ -0,0 +1,224 @@ +/* + * 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.manager; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.IdentityHashMap; + +import org.apache.felix.scr.impl.config.ComponentContainer; +import org.apache.felix.scr.impl.helper.ActivatorParameter; +import org.apache.felix.scr.impl.helper.ComponentMethods; +import org.apache.felix.scr.impl.helper.MethodResult; +import org.apache.felix.scr.impl.helper.ModifiedMethod; +import org.osgi.framework.Bundle; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.ComponentConstants; +import org.osgi.service.component.ComponentInstance; +import org.osgi.service.log.LogService; + + +/** + * The <code>ServiceFactoryComponentManager</code> for components specified with <service serviceFactory='true'/> + * in the xml metadata. The component must be delayed, not immediate or factory. + */ +public class ServiceFactoryComponentManager<S> extends SingleComponentManager<S> +{ + + // maintain the map of ComponentContext objects created for the + // service instances + private IdentityHashMap<S, ComponentContextImpl<S>> serviceContexts = new IdentityHashMap<S, ComponentContextImpl<S>>(); + + /** + * @param container ComponentHolder for configuration management + * @param componentMethods + */ + public ServiceFactoryComponentManager( ComponentContainer<S> container, ComponentMethods componentMethods ) + { + super( container, componentMethods ); + } + + + /* (non-Javadoc) + * @see org.apache.felix.scr.AbstractComponentManager#deleteComponent() + */ + protected void deleteComponent( int reason ) + { + if ( !isStateLocked() ) + { + throw new IllegalStateException( "need write lock (deleteComponent)" ); + } + for (ComponentContextImpl<S> componentContext: getComponentContexts() ) + { + disposeImplementationObject( componentContext, reason ); + log( LogService.LOG_DEBUG, "Unset implementation object for component {0} in deleteComponent for reason {1}", new Object[] { getName(), REASONS[ reason ] }, null ); + } + serviceContexts.clear(); + clearServiceProperties(); + } + + + /* (non-Javadoc) + * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration) + */ + public S getService( Bundle bundle, ServiceRegistration<S> registration ) + { + log( LogService.LOG_DEBUG, "ServiceFactory.getService()", null ); + + // When the getServiceMethod is called, the implementation object must be created + + ComponentContextImpl<S> componentContext = new ComponentContextImpl<S>(this, bundle); + if (collectDependencies(componentContext) ) + { + log( LogService.LOG_DEBUG, + "getService (ServiceFactory) dependencies collected.", + null ); + + } + else + { + //cannot obtain service from a required reference + return null; + } + // private ComponentContext and implementation instances + S service = createImplementationObject( bundle, new SetImplementationObject<S>() + { + public void presetComponentContext( ComponentContextImpl<S> componentContext ) + { + synchronized ( serviceContexts ) + { + serviceContexts.put( componentContext.getImplementationObject( false ), componentContext ); + } + } + + public void resetImplementationObject( S implementationObject ) + { + synchronized ( serviceContexts ) + { + serviceContexts.remove( implementationObject ); + } + } + + }, componentContext ); + + // register the components component context if successful + if ( service == null ) + { + // log that the service factory component cannot be created (we don't + // know why at this moment; this should already have been logged) + log( LogService.LOG_ERROR, "Failed creating the component instance; see log for reason", null ); + } + else + { + m_activated = true; + } + + return service; + } + + + /* (non-Javadoc) + * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration, java.lang.Object) + */ + public void ungetService( Bundle bundle, ServiceRegistration<S> registration, S service ) + { + log( LogService.LOG_DEBUG, "ServiceFactory.ungetService()", null ); + + // When the ungetServiceMethod is called, the implementation object must be deactivated + // private ComponentContext and implementation instances + final ComponentContextImpl<S> serviceContext; + synchronized ( serviceContexts ) + { + serviceContext = serviceContexts.get( service ); + } + disposeImplementationObject( serviceContext, ComponentConstants.DEACTIVATION_REASON_DISPOSED ); + synchronized ( serviceContexts ) + { + serviceContexts.remove( service ); + // if this was the last use of the component, go back to REGISTERED state + if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE ) + { + m_activated = false; + } + } + } + + private Collection<ComponentContextImpl<S>> getComponentContexts() + { + synchronized ( serviceContexts ) + { + return new ArrayList<ComponentContextImpl<S>>( serviceContexts.values() ); + } + } + + <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount ) + { + for ( ComponentContextImpl<S> cc : getComponentContexts() ) + { + dependencyManager.invokeBindMethod( cc, refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) ); + } + } + + <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount ) + { + for ( ComponentContextImpl<S> cc : getComponentContexts() ) + { + dependencyManager.invokeUpdatedMethod( cc, refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) ); + } + } + + <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRefPair, int trackingCount ) + { + for ( ComponentContextImpl<S> cc : getComponentContexts() ) + { + dependencyManager.invokeUnbindMethod( cc, oldRefPair, trackingCount, cc.getEdgeInfo( dependencyManager ) ); + } + } + + protected MethodResult invokeModifiedMethod() + { + ModifiedMethod modifiedMethod = getComponentMethods().getModifiedMethod(); + MethodResult result = MethodResult.VOID; + for ( ComponentContextImpl<S> componentContext : getComponentContexts() ) + { + S instance = componentContext.getImplementationObject(true); + result = modifiedMethod.invoke( instance, + new ActivatorParameter( componentContext, -1 ), MethodResult.VOID, this ); + + } + return result; + } + + @Override + boolean hasInstance() + { + return !serviceContexts.isEmpty(); + } + + //---------- Component interface + + public ComponentInstance getComponentInstance() + { + // TODO: should return the component instance corresponding to the + // bundle owning ScrService + return super.getComponentInstance(); + } + +}
