Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java (from r883744, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java) URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java&r1=883744&r2=884327&rev=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java (original) +++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java Wed Nov 25 23:04:32 2009 @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.felix.dependencymanager; +package org.apache.felix.dependencymanager.impl; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -33,8 +33,19 @@ import java.util.Map; import java.util.Properties; +import org.apache.felix.dependencymanager.Dependency; +import org.apache.felix.dependencymanager.DependencyManager; +import org.apache.felix.dependencymanager.DependencyService; +import org.apache.felix.dependencymanager.Service; +import org.apache.felix.dependencymanager.ServiceStateListener; +import org.apache.felix.dependencymanager.dependencies.BundleDependency; +import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency; +import org.apache.felix.dependencymanager.dependencies.ResourceDependency; +import org.apache.felix.dependencymanager.dependencies.ServiceDependency; import org.apache.felix.dependencymanager.management.ServiceComponent; import org.apache.felix.dependencymanager.management.ServiceComponentDependency; +import org.apache.felix.dependencymanager.resources.Resource; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; @@ -43,11 +54,12 @@ * * @author <a href="mailto:[email protected]">Felix Project Team</a> */ -public class ServiceImpl implements Service, ServiceComponent { +public class ServiceImpl implements Service, DependencyService, ServiceComponent { private static final Class[] VOID = new Class[] {}; private static final ServiceRegistration NULL_REGISTRATION; private static final ServiceStateListener[] SERVICE_STATE_LISTENER_TYPE = new ServiceStateListener[] {}; + private final Object SYNC = new Object(); private final BundleContext m_context; private final DependencyManager m_manager; @@ -71,6 +83,8 @@ // runtime state (changes because of state changes) private Object m_serviceInstance; private ServiceRegistration m_registration; + private boolean m_isBound; + private boolean m_isInstantiated; // service state listeners private final List m_stateListeners = new ArrayList(); @@ -95,7 +109,7 @@ public ServiceImpl(BundleContext context, DependencyManager manager, Logger logger) { m_logger = logger; - m_state = new State((List) m_dependencies.clone(), false); + m_state = new State((List) m_dependencies.clone(), false, false, false); m_context = context; m_manager = manager; m_callbackInit = "init"; @@ -106,62 +120,134 @@ m_autoConfig.put(BundleContext.class, Boolean.TRUE); m_autoConfig.put(ServiceRegistration.class, Boolean.TRUE); m_autoConfig.put(DependencyManager.class, Boolean.TRUE); + m_autoConfig.put(Service.class, Boolean.TRUE); } + private void calculateStateChanges() { + // see if any of the things we did caused a further change of state + State oldState, newState; + synchronized (m_dependencies) { + oldState = m_state; + newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound); + m_state = newState; + } + calculateStateChanges(oldState, newState); + } + private void calculateStateChanges(final State oldState, final State newState) { - if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) { - m_executor.enqueue(new Runnable() { - public void run() { - activateService(newState); - }}); - } - if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) { - m_executor.enqueue(new Runnable() { - public void run() { - deactivateService(oldState); - }}); - } - if (oldState.isInactive() && (newState.isTrackingOptional())) { - m_executor.enqueue(new Runnable() { - public void run() { - activateService(newState); - }}); - } - if (oldState.isInactive() && (newState.isWaitingForRequired())) { - m_executor.enqueue(new Runnable() { - public void run() { - startTrackingRequired(newState); - }}); - } - if ((oldState.isWaitingForRequired()) && newState.isInactive()) { - m_executor.enqueue(new Runnable() { - public void run() { - stopTrackingRequired(oldState); - }}); - } - if ((oldState.isTrackingOptional()) && newState.isInactive()) { - m_executor.enqueue(new Runnable() { - public void run() { - deactivateService(oldState); - stopTrackingRequired(oldState); - }}); - } - m_executor.execute(); + if (oldState.isInactive() && (newState.isTrackingOptional())) { + m_executor.enqueue(new Runnable() { + public void run() { + activateService(newState); + }}); + } + if (oldState.isInactive() && (newState.isWaitingForRequired())) { + m_executor.enqueue(new Runnable() { + public void run() { + startTrackingRequired(newState); + }}); + } + if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) { + m_executor.enqueue(new Runnable() { + public void run() { + activateService(newState); + }}); + } + if ((oldState.isWaitingForRequired()) && newState.isInactive()) { + m_executor.enqueue(new Runnable() { + public void run() { + stopTrackingRequired(oldState); + }}); + } + if (oldState.isTrackingOptional() && newState.isWaitingForRequiredInstantiated()) { + m_executor.enqueue(new Runnable() { + public void run() { + // TODO as far as I can see there is nothing left to do here + }}); + } + if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) { + m_executor.enqueue(new Runnable() { + public void run() { + deactivateService(oldState); + }}); + } + if (oldState.isTrackingOptional() && newState.isBound()) { + m_executor.enqueue(new Runnable() { + public void run() { + bindService(oldState); + }}); + } + if (oldState.isTrackingOptional() && newState.isInactive()) { + m_executor.enqueue(new Runnable() { + public void run() { + deactivateService(oldState); + stopTrackingRequired(oldState); + }}); + } + if (oldState.isWaitingForRequiredInstantiated() && newState.isWaitingForRequired()) { + m_executor.enqueue(new Runnable() { + public void run() { + deactivateService(oldState); + }}); + } + if (oldState.isWaitingForRequiredInstantiated() && newState.isInactive()) { + m_executor.enqueue(new Runnable() { + public void run() { + deactivateService(oldState); + stopTrackingRequired(oldState); + }}); + } + if (oldState.isWaitingForRequiredInstantiated() && newState.isBound()) { + m_executor.enqueue(new Runnable() { + public void run() { + bindService(oldState); + }}); + } + if (oldState.isBound() && newState.isWaitingForRequiredInstantiated()) { + m_executor.enqueue(new Runnable() { + public void run() { + unbindService(oldState); + }}); + } + if (oldState.isBound() && newState.isWaitingForRequired()) { + m_executor.enqueue(new Runnable() { + public void run() { + unbindService(oldState); + deactivateService(oldState); + }}); + } + if (oldState.isBound() && newState.isInactive()) { + m_executor.enqueue(new Runnable() { + public void run() { + unbindService(oldState); + deactivateService(oldState); + stopTrackingRequired(oldState); + }}); + } + m_executor.execute(); } - + public Service add(final Dependency dependency) { State oldState, newState; synchronized (m_dependencies) { oldState = m_state; m_dependencies.add(dependency); } - if (oldState.isTrackingOptional() || (oldState.isWaitingForRequired() && dependency.isRequired())) { + if (oldState.isAllRequiredAvailable() || (oldState.isWaitingForRequired() && dependency.isRequired())) { dependency.start(this); } synchronized (m_dependencies) { - newState = new State((List) m_dependencies.clone(), !oldState.isInactive()); + newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound); m_state = newState; - calculateStateChanges(oldState, newState); + } + calculateStateChanges(oldState, newState); + return this; + } + + public Service add(List dependencies) { + // TODO review if this can be done more smartly + for (int i = 0; i < dependencies.size(); i++) { + add((Dependency) dependencies.get(i)); } return this; } @@ -172,11 +258,11 @@ oldState = m_state; m_dependencies.remove(dependency); } - if (oldState.isTrackingOptional() || (oldState.isWaitingForRequired() && dependency.isRequired())) { + if (oldState.isAllRequiredAvailable() || (oldState.isWaitingForRequired() && dependency.isRequired())) { dependency.stop(this); } synchronized (m_dependencies) { - newState = new State((List) m_dependencies.clone(), !oldState.isInactive()); + newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound); m_state = newState; } calculateStateChanges(oldState, newState); @@ -201,11 +287,11 @@ State oldState, newState; synchronized (m_dependencies) { oldState = m_state; - newState = new State((List) m_dependencies.clone(), !oldState.isInactive()); + newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound); m_state = newState; } calculateStateChanges(oldState, newState); - if (newState.isTrackingOptional()) { + if (newState.isAllRequiredAvailable()) { m_executor.enqueue(new Runnable() { public void run() { updateInstance(dependency); @@ -220,7 +306,7 @@ synchronized (m_dependencies) { state = m_state; } - if (state.isTrackingOptional()) { + if (state.isAllRequiredAvailable()) { m_executor.enqueue(new Runnable() { public void run() { updateInstance(dependency); @@ -234,11 +320,11 @@ State oldState, newState; synchronized (m_dependencies) { oldState = m_state; - newState = new State((List) m_dependencies.clone(), !oldState.isInactive()); + newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound); m_state = newState; } calculateStateChanges(oldState, newState); - if (newState.isTrackingOptional()) { + if (newState.isAllRequiredAvailable()) { m_executor.enqueue(new Runnable() { public void run() { updateInstance(dependency); @@ -253,7 +339,7 @@ State oldState, newState; synchronized (m_dependencies) { oldState = m_state; - newState = new State((List) m_dependencies.clone(), true); + newState = new State((List) m_dependencies.clone(), true, m_isInstantiated, m_isBound); m_state = newState; } calculateStateChanges(oldState, newState); @@ -263,7 +349,7 @@ State oldState, newState; synchronized (m_dependencies) { oldState = m_state; - newState = new State((List) m_dependencies.clone(), false); + newState = new State((List) m_dependencies.clone(), false, m_isInstantiated, m_isBound); m_state = newState; } calculateStateChanges(oldState, newState); @@ -350,7 +436,7 @@ synchronized (m_dependencies) { state = m_state; } - if (state.isTrackingOptional()) { + if (state.isAllRequiredAvailable()) { listener.starting(this); listener.started(this); } @@ -362,7 +448,7 @@ } } - void removeStateListeners() { + public void removeStateListeners() { synchronized (m_stateListeners) { m_stateListeners.clear(); } @@ -422,21 +508,31 @@ } } - private void activateService(State state) { - String init, start; - synchronized (this) { - init = m_callbackInit; - start = m_callbackStart; - } + private void activateService(State state) { + String init; + synchronized (this) { + init = m_callbackInit; + } // service activation logic, first we initialize the service instance itself // meaning it is created if necessary and the bundle context is set initService(); - // then we invoke the init callback so the service can further initialize - // itself - invoke(init); // now is the time to configure the service, meaning all required // dependencies will be set and any callbacks called configureService(state); + // then we invoke the init callback so the service can further initialize + // itself + invoke(init); + // flag that our instance has been created + m_isInstantiated = true; + // see if any of this caused further state changes + calculateStateChanges(); + } + + private void bindService(State state) { + String start; + synchronized (this) { + start = m_callbackStart; + } // inform the state listeners we're starting stateListenersStarting(); // invoke the start callback, since we're now ready to be used @@ -448,13 +544,12 @@ // inform the state listeners we've started stateListenersStarted(); } - - private void deactivateService(State state) { - String stop, destroy; - synchronized (this) { - stop = m_callbackStop; - destroy = m_callbackDestroy; - } + + private void unbindService(State state) { + String stop; + synchronized (this) { + stop = m_callbackStop; + } // service deactivation logic, first inform the state listeners // we're stopping stateListenersStopping(); @@ -466,12 +561,21 @@ invoke(stop); // inform the state listeners we've stopped stateListenersStopped(); + } + + private void deactivateService(State state) { + String destroy; + synchronized (this) { + destroy = m_callbackDestroy; + } // invoke the destroy callback invoke(destroy); // destroy the service instance destroyService(state); + // flag that our instance was destroyed + m_isInstantiated = false; } - + private void invoke(String name) { if (name != null) { // invoke method if it exists @@ -549,7 +653,7 @@ return clazz.newInstance(); } - void initService() { + public void initService() { if (m_serviceInstance == null) { if (m_implementation instanceof Class) { // instantiate @@ -611,6 +715,9 @@ if (((Boolean) m_autoConfig.get(DependencyManager.class)).booleanValue()) { configureImplementation(DependencyManager.class, m_manager, (String) m_autoConfigInstance.get(DependencyManager.class)); } + if (((Boolean) m_autoConfig.get(Service.class)).booleanValue()) { + configureImplementation(Service.class, this, (String) m_autoConfigInstance.get(Service.class)); + } } } @@ -665,6 +772,7 @@ wrapper.setIllegalState(); } } + m_isBound = true; } private Dictionary calculateServiceProperties() { @@ -700,6 +808,7 @@ } private void unregisterService() { + m_isBound = false; if (m_serviceName != null) { m_registration.unregister(); configureImplementation(ServiceRegistration.class, NULL_REGISTRATION); @@ -718,11 +827,25 @@ else if (dependency instanceof ConfigurationDependency) { ConfigurationDependency cd = (ConfigurationDependency) dependency; if (cd.isPropagated()) { - // change service properties accordingly - Dictionary props = calculateServiceProperties(); - m_registration.setProperties(props); + // change service properties accordingly, but only if the service was already registered + if (m_registration != null) { + Dictionary props = calculateServiceProperties(); + m_registration.setProperties(props); + } } } + else if (dependency instanceof BundleDependency) { + BundleDependency bd = (BundleDependency) dependency; + if (bd.isAutoConfig()) { + configureImplementation(Bundle.class, bd.getBundle()); // TODO support AutoConfigName + } + } + else if (dependency instanceof ResourceDependency) { + ResourceDependency rd = (ResourceDependency) dependency; + if (rd.isAutoConfig()) { + configureImplementation(Resource.class, rd.getResource()); // TODO support AutoConfigName + } + } } /** @@ -747,7 +870,7 @@ try { fields[j].setAccessible(true); // synchronized makes sure the field is actually written to immediately - synchronized (new Object()) { + synchronized (SYNC) { fields[j].set(serviceInstance, instance); } } @@ -764,30 +887,30 @@ } public Object[] getCompositionInstances() { - Object[] instances = null; - if (m_compositionManagerGetMethod != null) { - if (m_compositionManager != null) { - m_compositionManagerInstance = m_compositionManager; - } - else { - m_compositionManagerInstance = m_serviceInstance; - } - if (m_compositionManagerInstance != null) { - try { - Method m = m_compositionManagerInstance.getClass().getDeclaredMethod(m_compositionManagerGetMethod, null); - m.setAccessible(true); - instances = (Object[]) m.invoke(m_compositionManagerInstance, null); - } - catch (Exception e) { - m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e); - instances = new Object[] { m_serviceInstance }; - } - } - } - else { - instances = new Object[] { m_serviceInstance }; - } - return instances; + Object[] instances = null; + if (m_compositionManagerGetMethod != null) { + if (m_compositionManager != null) { + m_compositionManagerInstance = m_compositionManager; + } + else { + m_compositionManagerInstance = m_serviceInstance; + } + if (m_compositionManagerInstance != null) { + try { + Method m = m_compositionManagerInstance.getClass().getDeclaredMethod(m_compositionManagerGetMethod, null); + m.setAccessible(true); + instances = (Object[]) m.invoke(m_compositionManagerInstance, null); + } + catch (Exception e) { + m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e); + instances = new Object[] { m_serviceInstance }; + } + } + } + else { + instances = new Object[] { m_serviceInstance }; + } + return instances; } private void configureImplementation(Class clazz, Object instance) { @@ -812,7 +935,41 @@ } // for required dependencies, we invoke any callbacks here if (sd.isRequired()) { - sd.invokeAdded(); + sd.invokeAdded(this, sd.lookupServiceReference(), sd.lookupService()); + } + } + else if (dependency instanceof BundleDependency) { + BundleDependency bd = (BundleDependency) dependency; + if (bd.isAutoConfig()) { + if (bd.isRequired()) { + configureImplementation(Bundle.class, bd.getBundle()); // TODO AutoConfigName support + } + else { + // for optional services, we do an "ad-hoc" lookup to inject the service if it is + // already available even though the tracker has not yet been started + // TODO !!! configureImplementation(sd.getInterface(), sd.lookupService(), sd.getAutoConfigName()); + } + } + // for required dependencies, we invoke any callbacks here + if (bd.isRequired()) { + bd.invokeAdded(); + } + } + else if (dependency instanceof ResourceDependency) { + ResourceDependency bd = (ResourceDependency) dependency; + if (bd.isAutoConfig()) { + if (bd.isRequired()) { + configureImplementation(Resource.class, bd.getResource()); // TODO AutoConfigName support + } + else { + // for optional services, we do an "ad-hoc" lookup to inject the service if it is + // already available even though the tracker has not yet been started + // TODO !!! configureImplementation(sd.getInterface(), sd.lookupService(), sd.getAutoConfigName()); + } + } + // for required dependencies, we invoke any callbacks here + if (bd.isRequired()) { + bd.invokeAdded(); } } } @@ -826,7 +983,7 @@ ServiceDependency sd = (ServiceDependency) dependency; // for required dependencies, we invoke any callbacks here if (sd.isRequired()) { - sd.invokeRemoved(); + sd.invokeRemoved(this, sd.lookupServiceReference(), sd.lookupService()); } } } @@ -841,12 +998,13 @@ throw new IllegalStateException("Cannot modify state while active."); } } - boolean isRegistered() { + + public boolean isRegistered() { State state; synchronized (m_dependencies) { state = m_state; } - return (state.isTrackingOptional()); + return (state.isAllRequiredAvailable()); } // ServiceComponent interface
Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java (from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java) URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java&r1=883483&r2=884327&rev=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java (original) +++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java Wed Nov 25 23:04:32 2009 @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.felix.dependencymanager; +package org.apache.felix.dependencymanager.impl; import java.util.Dictionary; Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java (from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java) URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java&r1=883483&r2=884327&rev=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java (original) +++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java Wed Nov 25 23:04:32 2009 @@ -16,10 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.felix.dependencymanager; +package org.apache.felix.dependencymanager.impl; import java.util.List; +import org.apache.felix.dependencymanager.Dependency; + /** * Encapsulates the current state of the dependencies of a service. A state is * basically an immutable value object. @@ -27,73 +29,101 @@ * @author <a href="mailto:[email protected]">Felix Project Team</a> */ public final class State { - private static final String[] STATES = { "?", "inactive", "waiting for required", "tracking optional" }; + private static final String[] STATES = { "?", "inactive", "waiting for required", "tracking optional", "bound", "waiting for required (instantiated)" }; private static final int INACTIVE = 1; private static final int WAITING_FOR_REQUIRED = 2; private static final int TRACKING_OPTIONAL = 3; - private final List m_deps; - private final int m_state; + private static final int BOUND = 4; + private static final int WAITING_FOR_REQUIRED_INSTANTIATED = 5; + private final List m_deps; + private final int m_state; private String m_stringValue; - - /** - * Creates a new state instance. - * - * @param deps the dependencies that determine the state - * @param isActive <code>true</code> if the service is active (started) - */ - public State(List deps, boolean isActive) { - m_deps = deps; - // only bother calculating dependencies if we're active - if (isActive) { - boolean allRequiredAvailable = true; - for (int i = 0; i < deps.size(); i++) { - Dependency dep = (Dependency) deps.get(i); - if (dep.isRequired()) { - if (!dep.isAvailable()) { - allRequiredAvailable = false; - } - } - } - if (allRequiredAvailable) { - m_state = TRACKING_OPTIONAL; - } - else { - m_state = WAITING_FOR_REQUIRED; - } - } - else { - m_state = INACTIVE; - } - } - - public boolean isInactive() { - return m_state == INACTIVE; - } - - public boolean isWaitingForRequired() { - return m_state == WAITING_FOR_REQUIRED; - } - - public boolean isTrackingOptional() { - return m_state == TRACKING_OPTIONAL; - } - - public List getDependencies() { - return m_deps; - } - - public synchronized String toString() { - if (m_stringValue == null) { - // we only need to determine this once, but we do it lazily - StringBuffer buf = new StringBuffer(); - buf.append("State[" + STATES[m_state] + "|"); - List deps = m_deps; - for (int i = 0; i < deps.size(); i++) { - Dependency dep = (Dependency) deps.get(i); - buf.append("(" + dep + (dep.isRequired() ? " R" : " O") + (dep.isAvailable() ? " +" : " -") + ")"); - } - m_stringValue = buf.toString(); - } + + /** + * Creates a new state instance. + * + * @param deps the dependencies that determine the state + * @param isActive <code>true</code> if the service is active (started) + */ + public State(List deps, boolean isActive, boolean isInstantiated, boolean isBound /* unused? */) { + m_deps = deps; + // only bother calculating dependencies if we're active + if (isActive) { + boolean allRequiredAvailable = true; + boolean keepInstanceAround = isInstantiated; + for (int i = 0; i < deps.size(); i++) { + Dependency dep = (Dependency) deps.get(i); + if (dep.isRequired()) { + if (!dep.isAvailable()) { + allRequiredAvailable = false; + if (!dep.isInstanceBound()) { + keepInstanceAround = false; + } + } + } + } + if (allRequiredAvailable) { + if (isInstantiated) { + m_state = BOUND; + } + else { + m_state = TRACKING_OPTIONAL; + } + } + else { + if (keepInstanceAround) { + m_state = WAITING_FOR_REQUIRED_INSTANTIATED; + } + else { + m_state = WAITING_FOR_REQUIRED; + } + } + } + else { + m_state = INACTIVE; + } + } + + public boolean isInactive() { + return m_state == INACTIVE; + } + + public boolean isWaitingForRequired() { + return m_state == WAITING_FOR_REQUIRED; + } + + public boolean isTrackingOptional() { + return m_state == TRACKING_OPTIONAL; + } + + public boolean isBound() { + return m_state == BOUND; + } + + public boolean isAllRequiredAvailable() { + return isTrackingOptional() || isBound(); + } + + public boolean isWaitingForRequiredInstantiated() { + return m_state == WAITING_FOR_REQUIRED_INSTANTIATED; + } + + public List getDependencies() { + return m_deps; + } + + public synchronized String toString() { + if (m_stringValue == null) { + // we only need to determine this once, but we do it lazily + StringBuffer buf = new StringBuffer(); + buf.append("State[" + STATES[m_state] + "|"); + List deps = m_deps; + for (int i = 0; i < deps.size(); i++) { + Dependency dep = (Dependency) deps.get(i); + buf.append("(" + dep + (dep.isRequired() ? " R" : " O") + (dep.isAvailable() ? " +" : " -") + ")"); + } + m_stringValue = buf.toString(); + } return m_stringValue; - } + } } Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java?rev=884327&view=auto ============================================================================== --- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java (added) +++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java Wed Nov 25 23:04:32 2009 @@ -0,0 +1,122 @@ +/* + * 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.dependencymanager.resources; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; +import java.util.Properties; + +import org.osgi.framework.Bundle; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; + +public class BundleResourceRepository { + + private final Bundle bundle; + + public BundleResourceRepository(Bundle bundle) { + this.bundle = bundle; + } + + public synchronized void addHandler(ServiceReference ref, ResourceHandler handler) { + + String filter = (String) ref.getProperty("filter"); // "(&(repository=a)(path=b)(name=*.xml))" + + Filter filterObject = null; + + try { + filterObject = FrameworkUtil.createFilter(filter); + } catch (InvalidSyntaxException e) { + e.printStackTrace(); + return; + } + + Enumeration entries = bundle.findEntries("/", null, true); + while (entries.hasMoreElements()) { + URL entry = (URL) entries.nextElement(); + + Properties props = new Properties(); + props.setProperty(Resource.REPOSITORY, bundle.getSymbolicName() + "_" + bundle.getVersion()); + props.setProperty(Resource.PATH, entry.getPath()); + props.setProperty(Resource.NAME, entry.getFile()); + + if (filterObject.match(props)) + handler.added(new EntryResource(entry)); + + } + } + + public synchronized void removeHandler(ServiceReference ref, ResourceHandler handler) { + + String filter = (String) ref.getProperty("filter"); // "(&(repository=a)(path=b)(name=*.xml))" + + Filter filterObject = null; + + try { + filterObject = FrameworkUtil.createFilter(filter); + } catch (InvalidSyntaxException e) { + e.printStackTrace(); + return; + } + + Enumeration entries = bundle.findEntries("/", null, true); + while (entries.hasMoreElements()) { + URL entry = (URL) entries.nextElement(); + + Properties props = new Properties(); + props.setProperty(Resource.REPOSITORY, bundle.getSymbolicName() + "_" + bundle.getVersion()); + props.setProperty(Resource.PATH, entry.getPath()); + props.setProperty(Resource.NAME, entry.getFile()); + + if (filterObject.match(props)) + handler.removed(new EntryResource(entry)); + + } + } + + class EntryResource implements Resource { + + URL entry; + + EntryResource(URL entry) { + this.entry = entry; + } + + public String getName() { + return entry.getFile(); + } + + public String getPath() { + return entry.getPath(); + } + + public String getRepository() { + + return bundle.getSymbolicName() + "_" + bundle.getVersion(); + } + + public InputStream openStream() throws IOException { + return entry.openStream(); + } + } +} Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java?rev=884327&view=auto ============================================================================== --- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java (added) +++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java Wed Nov 25 23:04:32 2009 @@ -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.dependencymanager.resources; + +import java.io.IOException; +import java.io.InputStream; + +/** Interface that defines a resource. */ +public interface Resource { + public static final String PATH = "path"; + public static final String NAME = "name"; + public static final String REPOSITORY = "repository"; + + String getName(); + + String getPath(); + + String getRepository(); + + InputStream openStream() throws IOException; +} Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java?rev=884327&view=auto ============================================================================== --- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java (added) +++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java Wed Nov 25 23:04:32 2009 @@ -0,0 +1,26 @@ +/* + * 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.dependencymanager.resources; + +/** Service interface for anybody wanting to be notified of changes to resources. */ +public interface ResourceHandler { + void added(Resource resource); + void changed(Resource resource); + void removed(Resource resource); +} Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java?rev=884327&r1=884326&r2=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java (original) +++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java Wed Nov 25 23:04:32 2009 @@ -23,8 +23,8 @@ import static org.ops4j.pax.exam.CoreOptions.provision; import org.apache.felix.dependencymanager.DependencyManager; -import org.apache.felix.dependencymanager.Logger; import org.apache.felix.dependencymanager.Service; +import org.apache.felix.dependencymanager.impl.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Option; Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java (original) +++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java Wed Nov 25 23:04:32 2009 @@ -29,8 +29,8 @@ import junit.framework.Assert; import org.apache.felix.dependencymanager.DependencyManager; -import org.apache.felix.dependencymanager.Logger; import org.apache.felix.dependencymanager.Service; +import org.apache.felix.dependencymanager.impl.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Option; @@ -82,7 +82,7 @@ m_ensure = e; } - public void start() { + public void init() { try { m_ensure.step(1); org.osgi.service.cm.Configuration conf = m_ca.getConfiguration("test", null); @@ -125,7 +125,7 @@ m_ensure = e; } - public void start() { + public void init() { m_ensure.step(3); m_runnable.run(); } Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java?rev=884327&r1=884326&r2=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java (original) +++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java Wed Nov 25 23:04:32 2009 @@ -50,6 +50,7 @@ * @param timeout the number of milliseconds to wait */ public synchronized void waitForStep(int nr, int timeout) { + final int initialTimeout = timeout; while (step <= nr && timeout > 0) { try { wait(RESOLUTION); @@ -58,7 +59,7 @@ catch (InterruptedException e) {} } if (step <= nr) { - throw new IllegalStateException("Timed out waiting for " + timeout + " ms for step " + nr); + throw new IllegalStateException("Timed out waiting for " + initialTimeout + " ms for step " + nr + ", we are still at step " + step); } } } Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java (original) +++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java Wed Nov 25 23:04:32 2009 @@ -7,8 +7,8 @@ import java.util.Properties; import org.apache.felix.dependencymanager.DependencyManager; -import org.apache.felix.dependencymanager.Logger; import org.apache.felix.dependencymanager.Service; +import org.apache.felix.dependencymanager.impl.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Option; @@ -82,7 +82,7 @@ m_ensure = e; } - public void start() { + public void init() { Thread t = new Thread(this); t.start(); } @@ -95,7 +95,7 @@ m_service.invoke(); } - public void stop() { + public void destroy() { m_ensure.step(6); } } Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java (original) +++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java Wed Nov 25 23:04:32 2009 @@ -23,8 +23,8 @@ import static org.ops4j.pax.exam.CoreOptions.provision; import org.apache.felix.dependencymanager.DependencyManager; -import org.apache.felix.dependencymanager.Logger; import org.apache.felix.dependencymanager.Service; +import org.apache.felix.dependencymanager.impl.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Option; @@ -85,12 +85,12 @@ m_ensure = e; } - public void start() { + public void init() { m_ensure.step(1); m_service.invoke(); } - public void stop() { + public void destroy() { m_ensure.step(3); } } Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff ============================================================================== --- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java (original) +++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java Wed Nov 25 23:04:32 2009 @@ -23,8 +23,8 @@ import static org.ops4j.pax.exam.CoreOptions.provision; import org.apache.felix.dependencymanager.DependencyManager; -import org.apache.felix.dependencymanager.Logger; import org.apache.felix.dependencymanager.Service; +import org.apache.felix.dependencymanager.impl.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Option; @@ -104,7 +104,7 @@ m_ensure = e; } - public void start() { + public void init() { m_ensure.step(1); Thread t = new Thread(this); t.start(); @@ -116,7 +116,7 @@ m_service.invoke(); } - public void stop() { + public void destroy() { m_ensure.step(5); } }
