Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promise.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promise.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promise.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promise.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.util.promise;
+
+import java.lang.reflect.InvocationTargetException;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.util.function.Function;
+import org.osgi.util.function.Predicate;
+
+/**
+ * A Promise of a value.
+ * 
+ * <p>
+ * A Promise represents a future value. It handles the interactions for
+ * asynchronous processing. A {@link Deferred} object can be used to create a
+ * Promise and later resolve the Promise. A Promise is used by the caller of an
+ * asynchronous function to get the result or handle the error. The caller can
+ * either get a callback when the Promise is resolved with a value or an error,
+ * or the Promise can be used in chaining. In chaining, callbacks are provided
+ * that receive the resolved Promise, and a new Promise is generated that
+ * resolves based upon the result of a callback.
+ * 
+ * <p>
+ * Both {@link #onResolve(Runnable) callbacks} and
+ * {@link #then(Success, Failure) chaining} can be repeated any number of 
times,
+ * even after the Promise has been resolved.
+ * <p>
+ * Example callback usage:
+ * 
+ * <pre>
+ * final Promise&lt;String&gt; foo = foo();
+ * foo.onResolve(new Runnable() {
+ *   public void run() {
+ *     System.out.println(foo.getValue());
+ *   }
+ * });
+ * </pre>
+ * 
+ * Example chaining usage;
+ * 
+ * <pre>
+ * Success&lt;String,String&gt; doubler = new Success&lt;String,String&gt;() {
+ *   public Promise&lt;String&gt; call(Promise&lt;String&gt; p) throws 
Exception {
+ *     return Promises.resolved(p.getValue()+p.getValue());
+ *   }
+ * };
+ * final Promise&lt;String&gt; foo = foo().then(doubler).then(doubler);
+ * foo.onResolve(new Runnable() {
+ *   public void run() {
+ *     System.out.println(foo.getValue());
+ *   }
+ * });
+ * </pre>
+ * 
+ * @param <T> The value type associated with this Promise.
+ * 
+ * @ThreadSafe
+ * @author $Id: 8a24f66339967ecdd03def57f31ac8c371a7f4cd $
+ */
+@ProviderType
+public interface Promise<T> {
+
+       /**
+        * Returns whether this Promise has been resolved.
+        * 
+        * <p>
+        * This Promise may be successfully resolved or resolved with a failure.
+        * 
+        * @return {@code true} if this Promise was resolved either 
successfully or
+        *         with a failure; {@code false} if this Promise is unresolved.
+        */
+       boolean isDone();
+
+       /**
+        * Returns the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is not {@link #isDone() resolved}, this method must 
block
+        * and wait for this Promise to be resolved before completing.
+        * 
+        * <p>
+        * If this Promise was successfully resolved, this method returns with 
the
+        * value of this Promise. If this Promise was resolved with a failure, 
this
+        * method must throw an {@code InvocationTargetException} with the
+        * {@link #getFailure() failure exception} as the cause.
+        * 
+        * @return The value of this resolved Promise.
+        * @throws InvocationTargetException If this Promise was resolved with a
+        *         failure. The cause of the {@code InvocationTargetException} 
is
+        *         the failure exception.
+        * @throws InterruptedException If the current thread was interrupted 
while
+        *         waiting.
+        */
+       T getValue() throws InvocationTargetException, InterruptedException;
+
+       /**
+        * Returns the failure of this Promise.
+        * 
+        * <p>
+        * If this Promise is not {@link #isDone() resolved}, this method must 
block
+        * and wait for this Promise to be resolved before completing.
+        * 
+        * <p>
+        * If this Promise was resolved with a failure, this method returns 
with the
+        * failure of this Promise. If this Promise was successfully resolved, 
this
+        * method must return {@code null}.
+        * 
+        * @return The failure of this resolved Promise or {@code null} if this
+        *         Promise was successfully resolved.
+        * @throws InterruptedException If the current thread was interrupted 
while
+        *         waiting.
+        */
+       Throwable getFailure() throws InterruptedException;
+
+       /**
+        * Register a callback to be called when this Promise is resolved.
+        * 
+        * <p>
+        * The specified callback is called when this Promise is resolved either
+        * successfully or with a failure.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * <p>
+        * Resolving this Promise <i>happens-before</i> any registered callback 
is
+        * called. That is, in a registered callback, {@link #isDone()} must 
return
+        * {@code true} and {@link #getValue()} and {@link #getFailure()} must 
not
+        * block.
+        * 
+        * <p>
+        * A callback may be called on a different thread than the thread which
+        * registered the callback. So the callback must be thread safe but can 
rely
+        * upon that the registration of the callback <i>happens-before</i> the
+        * registered callback is called.
+        * 
+        * @param callback A callback to be called when this Promise is 
resolved.
+        *        Must not be {@code null}.
+        * @return This Promise.
+        */
+       Promise<T> onResolve(Runnable callback);
+
+       /**
+        * Chain a new Promise to this Promise with Success and Failure 
callbacks.
+        * 
+        * <p>
+        * The specified {@link Success} callback is called when this Promise is
+        * successfully resolved and the specified {@link Failure} callback is
+        * called when this Promise is resolved with a failure.
+        * 
+        * <p>
+        * This method returns a new Promise which is chained to this Promise. 
The
+        * returned Promise must be resolved when this Promise is resolved 
after the
+        * specified Success or Failure callback is executed. The result of the
+        * executed callback must be used to resolve the returned Promise. 
Multiple
+        * calls to this method can be used to create a chain of promises which 
are
+        * resolved in sequence.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the Success callback is
+        * executed and the result Promise, if any, or thrown exception is used 
to
+        * resolve the returned Promise from this method. If this Promise is
+        * resolved with a failure, the Failure callback is executed and the
+        * returned Promise from this method is failed.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * <p>
+        * Resolving this Promise <i>happens-before</i> any registered callback 
is
+        * called. That is, in a registered callback, {@link #isDone()} must 
return
+        * {@code true} and {@link #getValue()} and {@link #getFailure()} must 
not
+        * block.
+        * 
+        * <p>
+        * A callback may be called on a different thread than the thread which
+        * registered the callback. So the callback must be thread safe but can 
rely
+        * upon that the registration of the callback <i>happens-before</i> the
+        * registered callback is called.
+        * 
+        * @param <R> The value type associated with the returned Promise.
+        * @param success A Success callback to be called when this Promise is
+        *        successfully resolved. May be {@code null} if no Success 
callback
+        *        is required. In this case, the returned Promise must be 
resolved
+        *        with the value {@code null} when this Promise is successfully
+        *        resolved.
+        * @param failure A Failure callback to be called when this Promise is
+        *        resolved with a failure. May be {@code null} if no Failure
+        *        callback is required.
+        * @return A new Promise which is chained to this Promise. The returned
+        *         Promise must be resolved when this Promise is resolved after 
the
+        *         specified Success or Failure callback, if any, is executed.
+        */
+       <R> Promise<R> then(Success<? super T, ? extends R> success, Failure 
failure);
+
+       /**
+        * Chain a new Promise to this Promise with a Success callback.
+        * 
+        * <p>
+        * This method performs the same function as calling
+        * {@link #then(Success, Failure)} with the specified Success callback 
and
+        * {@code null} for the Failure callback.
+        * 
+        * @param <R> The value type associated with the returned Promise.
+        * @param success A Success callback to be called when this Promise is
+        *        successfully resolved. May be {@code null} if no Success 
callback
+        *        is required. In this case, the returned Promise must be 
resolved
+        *        with the value {@code null} when this Promise is successfully
+        *        resolved.
+        * @return A new Promise which is chained to this Promise. The returned
+        *         Promise must be resolved when this Promise is resolved after 
the
+        *         specified Success, if any, is executed.
+        * @see #then(Success, Failure)
+        */
+       <R> Promise<R> then(Success<? super T, ? extends R> success);
+
+       /**
+        * Filter the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the returned Promise will
+        * either be resolved with the value of this Promise if the specified
+        * Predicate accepts that value or failed with a
+        * {@code NoSuchElementException} if the specified Predicate does not 
accept
+        * that value. If the specified Predicate throws an exception, the 
returned
+        * Promise will be failed with the exception.
+        * 
+        * <p>
+        * If this Promise is resolved with a failure, the returned Promise 
will be
+        * failed with that failure.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * @param predicate The Predicate to evaluate the value of this Promise.
+        *        Must not be {@code null}.
+        * @return A Promise that filters the value of this Promise.
+        */
+       Promise<T> filter(Predicate<? super T> predicate);
+
+       /**
+        * Map the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the returned Promise will 
be
+        * resolved with the value of specified Function as applied to the 
value of
+        * this Promise. If the specified Function throws an exception, the 
returned
+        * Promise will be failed with the exception.
+        * 
+        * <p>
+        * If this Promise is resolved with a failure, the returned Promise 
will be
+        * failed with that failure.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * @param <R> The value type associated with the returned Promise.
+        * @param mapper The Function that will map the value of this Promise 
to the
+        *        value that will be used to resolve the returned Promise. Must 
not
+        *        be {@code null}.
+        * @return A Promise that returns the value of this Promise as mapped 
by the
+        *         specified Function.
+        */
+       <R> Promise<R> map(Function<? super T, ? extends R> mapper);
+
+       /**
+        * FlatMap the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the returned Promise will 
be
+        * resolved with the Promise from the specified Function as applied to 
the
+        * value of this Promise. If the specified Function throws an 
exception, the
+        * returned Promise will be failed with the exception.
+        * 
+        * <p>
+        * If this Promise is resolved with a failure, the returned Promise 
will be
+        * failed with that failure.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * @param <R> The value type associated with the returned Promise.
+        * @param mapper The Function that will flatMap the value of this 
Promise to
+        *        a Promise that will be used to resolve the returned Promise. 
Must
+        *        not be {@code null}.
+        * @return A Promise that returns the value of this Promise as mapped 
by the
+        *         specified Function.
+        */
+       <R> Promise<R> flatMap(Function<? super T, Promise<? extends R>> 
mapper);
+
+       /**
+        * Recover from a failure of this Promise with a recovery value.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the returned Promise will 
be
+        * resolved with the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is resolved with a failure, the specified Function is
+        * applied to this Promise to produce a recovery value.
+        * <ul>
+        * <li>If the recovery value is not {@code null}, the returned Promise 
will
+        * be resolved with the recovery value.</li>
+        * <li>If the recovery value is {@code null}, the returned Promise will 
be
+        * failed with the failure of this Promise.</li>
+        * <li>If the specified Function throws an exception, the returned 
Promise
+        * will be failed with that exception.</li>
+        * </ul>
+        * 
+        * <p>
+        * To recover from a failure of this Promise with a recovery value of
+        * {@code null}, the {@link #recoverWith(Function)} method must be 
used. The
+        * specified Function for {@link #recoverWith(Function)} can return
+        * {@code Promises.resolved(null)} to supply the desired {@code null} 
value.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * @param recovery If this Promise resolves with a failure, the 
specified
+        *        Function is called to produce a recovery value to be used to
+        *        resolve the returned Promise. Must not be {@code null}.
+        * @return A Promise that resolves with the value of this Promise or
+        *         recovers from the failure of this Promise.
+        */
+       Promise<T> recover(Function<Promise<?>, ? extends T> recovery);
+
+       /**
+        * Recover from a failure of this Promise with a recovery Promise.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the returned Promise will 
be
+        * resolved with the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is resolved with a failure, the specified Function is
+        * applied to this Promise to produce a recovery Promise.
+        * <ul>
+        * <li>If the recovery Promise is not {@code null}, the returned Promise
+        * will be resolved with the recovery Promise.</li>
+        * <li>If the recovery Promise is {@code null}, the returned Promise 
will be
+        * failed with the failure of this Promise.</li>
+        * <li>If the specified Function throws an exception, the returned 
Promise
+        * will be failed with that exception.</li>
+        * </ul>
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * @param recovery If this Promise resolves with a failure, the 
specified
+        *        Function is called to produce a recovery Promise to be used to
+        *        resolve the returned Promise. Must not be {@code null}.
+        * @return A Promise that resolves with the value of this Promise or
+        *         recovers from the failure of this Promise.
+        */
+       Promise<T> recoverWith(Function<Promise<?>, Promise<? extends T>> 
recovery);
+
+       /**
+        * Fall back to the value of the specified Promise if this Promise 
fails.
+        * 
+        * <p>
+        * If this Promise is successfully resolved, the returned Promise will 
be
+        * resolved with the value of this Promise.
+        * 
+        * <p>
+        * If this Promise is resolved with a failure, the successful result of 
the
+        * specified Promise is used to resolve the returned Promise. If the
+        * specified Promise is resolved with a failure, the returned Promise 
will
+        * be failed with the failure of this Promise rather than the failure 
of the
+        * specified Promise.
+        * 
+        * <p>
+        * This method may be called at any time including before and after this
+        * Promise has been resolved.
+        * 
+        * @param fallback The Promise whose value will be used to resolve the
+        *        returned Promise if this Promise resolves with a failure. 
Must not
+        *        be {@code null}.
+        * @return A Promise that returns the value of this Promise or falls 
back to
+        *         the value of the specified Promise.
+        */
+       Promise<T> fallbackTo(Promise<? extends T> fallback);
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/PromiseImpl.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/PromiseImpl.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/PromiseImpl.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/PromiseImpl.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.util.promise;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import org.osgi.util.function.Function;
+import org.osgi.util.function.Predicate;
+
+/**
+ * Promise implementation.
+ * 
+ * <p>
+ * This class is not used directly by clients. Clients should use
+ * {@link Deferred} to create a resolvable {@link Promise}.
+ * 
+ * @param <T> The result type associated with the Promise.
+ * 
+ * @ThreadSafe
+ * @author $Id: d8b44a36f3eb797316b213118192fac213fa0c59 $
+ */
+final class PromiseImpl<T> implements Promise<T> {
+       /**
+        * A ConcurrentLinkedQueue to hold the callbacks for this Promise, so no
+        * additional synchronization is required to write to or read from the
+        * queue.
+        */
+       private final ConcurrentLinkedQueue<Runnable>   callbacks;
+       /**
+        * A CountDownLatch to manage the resolved state of this Promise.
+        * 
+        * <p>
+        * This object is used as the synchronizing object to provide a critical
+        * section in {@link #resolve(Object, Throwable)} so that only a single
+        * thread can write the resolved state variables and open the latch.
+        * 
+        * <p>
+        * The resolved state variables, {@link #value} and {@link #fail}, must 
only
+        * be written when the latch is closed (getCount() != 0) and must only 
be
+        * read when the latch is open (getCount() == 0). The latch state must
+        * always be checked before writing or reading since the resolved state
+        * variables' memory consistency is guarded by the latch.
+        */
+       private final CountDownLatch                                    
resolved;
+       /**
+        * The value of this Promise if successfully resolved.
+        * 
+        * @GuardedBy("resolved")
+        * @see #resolved
+        */
+       private T                                                               
                value;
+       /**
+        * The failure of this Promise if resolved with a failure or {@code 
null} if
+        * successfully resolved.
+        * 
+        * @GuardedBy("resolved")
+        * @see #resolved
+        */
+       private Throwable                                                       
        fail;
+
+       /**
+        * Initialize this Promise.
+        */
+       PromiseImpl() {
+               callbacks = new ConcurrentLinkedQueue<Runnable>();
+               resolved = new CountDownLatch(1);
+       }
+
+       /**
+        * Initialize and resolve this Promise.
+        * 
+        * @param v The value of this resolved Promise.
+        * @param f The failure of this resolved Promise.
+        */
+       PromiseImpl(T v, Throwable f) {
+               value = v;
+               fail = f;
+               callbacks = new ConcurrentLinkedQueue<Runnable>();
+               resolved = new CountDownLatch(0);
+       }
+
+       /**
+        * Resolve this Promise.
+        * 
+        * @param v The value of this Promise.
+        * @param f The failure of this Promise.
+        */
+       void resolve(T v, Throwable f) {
+               // critical section: only one resolver at a time
+               synchronized (resolved) {
+                       if (resolved.getCount() == 0) {
+                               throw new IllegalStateException("Already 
resolved");
+                       }
+                       /*
+                        * The resolved state variables must be set before 
opening the
+                        * latch. This safely publishes them to be read by 
other threads
+                        * that must verify the latch is open before reading.
+                        */
+                       value = v;
+                       fail = f;
+                       resolved.countDown();
+               }
+               notifyCallbacks(); // call any registered callbacks
+       }
+
+       /**
+        * Call any registered callbacks if this Promise is resolved.
+        */
+       private void notifyCallbacks() {
+               if (resolved.getCount() != 0) {
+                       return; // return if not resolved
+               }
+
+               /*
+                * Note: multiple threads can be in this method removing 
callbacks from
+                * the queue and calling them, so the order in which callbacks 
are
+                * called cannot be specified.
+                */
+               for (Runnable callback = callbacks.poll(); callback != null; 
callback = callbacks.poll()) {
+                       try {
+                               callback.run();
+                       } catch (Throwable t) {
+                               Logger.logCallbackException(t);
+                       }
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean isDone() {
+               return resolved.getCount() == 0;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public T getValue() throws InvocationTargetException, 
InterruptedException {
+               resolved.await();
+               if (fail == null) {
+                       return value;
+               }
+               throw new InvocationTargetException(fail);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Throwable getFailure() throws InterruptedException {
+               resolved.await();
+               return fail;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Promise<T> onResolve(Runnable callback) {
+               callbacks.offer(callback);
+               notifyCallbacks(); // call any registered callbacks
+               return this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public <R> Promise<R> then(Success<? super T, ? extends R> success, 
Failure failure) {
+               PromiseImpl<R> chained = new PromiseImpl<R>();
+               onResolve(new Then<R>(chained, success, failure));
+               return chained;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public <R> Promise<R> then(Success<? super T, ? extends R> success) {
+               return then(success, null);
+       }
+
+       /**
+        * A callback used to chain promises for the {@link #then(Success, 
Failure)}
+        * method.
+        * 
+        * @Immutable
+        */
+       private final class Then<R> implements Runnable {
+               private final PromiseImpl<R>                    chained;
+               private final Success<T, ? extends R>   success;
+               private final Failure                                   failure;
+
+               @SuppressWarnings("unchecked")
+               Then(PromiseImpl<R> chained, Success<? super T, ? extends R> 
success, Failure failure) {
+                       this.chained = chained;
+                       this.success = (Success<T, ? extends R>) success;
+                       this.failure = failure;
+               }
+
+               public void run() {
+                       Throwable f;
+                       final boolean interrupted = Thread.interrupted();
+                       try {
+                               f = getFailure();
+                       } catch (Throwable e) {
+                               f = e; // propagate new exception
+                       } finally {
+                               if (interrupted) { // restore interrupt status
+                                       Thread.currentThread().interrupt();
+                               }
+                       }
+                       if (f != null) {
+                               if (failure != null) {
+                                       try {
+                                               failure.fail(PromiseImpl.this);
+                                       } catch (Throwable e) {
+                                               f = e; // propagate new 
exception
+                                       }
+                               }
+                               // fail chained
+                               chained.resolve(null, f);
+                               return;
+                       }
+                       Promise<? extends R> returned = null;
+                       if (success != null) {
+                               try {
+                                       returned = 
success.call(PromiseImpl.this);
+                               } catch (Throwable e) {
+                                       chained.resolve(null, e);
+                                       return;
+                               }
+                       }
+                       if (returned == null) {
+                               // resolve chained with null value
+                               chained.resolve(null, null);
+                       } else {
+                               // resolve chained when returned promise is 
resolved
+                               returned.onResolve(new Chain<R>(chained, 
returned));
+                       }
+               }
+       }
+
+       /**
+        * A callback used to resolve the chained Promise when the Promise 
promise
+        * is resolved.
+        * 
+        * @Immutable
+        */
+       private final static class Chain<R> implements Runnable {
+               private final PromiseImpl<R>            chained;
+               private final Promise<? extends R>      promise;
+               private final Throwable                         failure;
+
+               Chain(PromiseImpl<R> chained, Promise<? extends R> promise) {
+                       this.chained = chained;
+                       this.promise = promise;
+                       this.failure = null;
+               }
+
+               Chain(PromiseImpl<R> chained, Promise<? extends R> promise, 
Throwable failure) {
+                       this.chained = chained;
+                       this.promise = promise;
+                       this.failure = failure;
+               }
+
+               public void run() {
+                       R value = null;
+                       Throwable f;
+                       final boolean interrupted = Thread.interrupted();
+                       try {
+                               f = promise.getFailure();
+                               if (f == null) {
+                                       value = promise.getValue();
+                               } else if (failure != null) {
+                                       f = failure;
+                               }
+                       } catch (Throwable e) {
+                               f = e; // propagate new exception
+                       } finally {
+                               if (interrupted) { // restore interrupt status
+                                       Thread.currentThread().interrupt();
+                               }
+                       }
+                       chained.resolve(value, f);
+               }
+       }
+
+       /**
+        * Resolve this Promise with the specified Promise.
+        * 
+        * <p>
+        * If the specified Promise is successfully resolved, this Promise is
+        * resolved with the value of the specified Promise. If the specified
+        * Promise is resolved with a failure, this Promise is resolved with the
+        * failure of the specified Promise.
+        * 
+        * @param with A Promise whose value or failure will be used to resolve 
this
+        *        Promise. Must not be {@code null}.
+        * @return A Promise that is resolved only when this Promise is 
resolved by
+        *         the specified Promise. The returned Promise will be 
successfully
+        *         resolved, with the value {@code null}, if this Promise was
+        *         resolved by the specified Promise. The returned Promise will 
be
+        *         resolved with a failure of {@link IllegalStateException} if 
this
+        *         Promise was already resolved when the specified Promise was
+        *         resolved.
+        */
+       Promise<Void> resolveWith(Promise<? extends T> with) {
+               PromiseImpl<Void> chained = new PromiseImpl<Void>();
+               ResolveWith resolveWith = new ResolveWith(chained);
+               with.then(resolveWith, resolveWith);
+               return chained;
+       }
+
+       /**
+        * A callback used to resolve this Promise with another Promise for the
+        * {@link PromiseImpl#resolveWith(Promise)} method.
+        * 
+        * @Immutable
+        */
+       private final class ResolveWith implements Success<T, Void>, Failure {
+               private final PromiseImpl<Void> chained;
+
+               ResolveWith(PromiseImpl<Void> chained) {
+                       this.chained = chained;
+               }
+
+               public Promise<Void> call(Promise<T> with) throws Exception {
+                       try {
+                               resolve(with.getValue(), null);
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return null;
+                       }
+                       chained.resolve(null, null);
+                       return null;
+               }
+
+               public void fail(Promise<?> with) throws Exception {
+                       try {
+                               resolve(null, with.getFailure());
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return;
+                       }
+                       chained.resolve(null, null);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Promise<T> filter(Predicate<? super T> predicate) {
+               return then(new Filter<T>(predicate));
+       }
+
+       /**
+        * A callback used by the {@link PromiseImpl#filter(Predicate)} method.
+        * 
+        * @Immutable
+        */
+       private static final class Filter<T> implements Success<T, T> {
+               private final Predicate<? super T>      predicate;
+
+               Filter(Predicate<? super T> predicate) {
+                       this.predicate = requireNonNull(predicate);
+               }
+
+               public Promise<T> call(Promise<T> resolved) throws Exception {
+                       if (predicate.test(resolved.getValue())) {
+                               return resolved;
+                       }
+                       throw new NoSuchElementException();
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public <R> Promise<R> map(Function<? super T, ? extends R> mapper) {
+               return then(new Map<T, R>(mapper));
+       }
+
+       /**
+        * A callback used by the {@link PromiseImpl#map(Function)} method.
+        * 
+        * @Immutable
+        */
+       private static final class Map<T, R> implements Success<T, R> {
+               private final Function<? super T, ? extends R>  mapper;
+
+               Map(Function<? super T, ? extends R> mapper) {
+                       this.mapper = requireNonNull(mapper);
+               }
+
+               public Promise<R> call(Promise<T> resolved) throws Exception {
+                       return new 
PromiseImpl<R>(mapper.apply(resolved.getValue()), null);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public <R> Promise<R> flatMap(Function<? super T, Promise<? extends R>> 
mapper) {
+               return then(new FlatMap<T, R>(mapper));
+       }
+
+       /**
+        * A callback used by the {@link PromiseImpl#flatMap(Function)} method.
+        * 
+        * @Immutable
+        */
+       private static final class FlatMap<T, R> implements Success<T, R> {
+               private final Function<? super T, Promise<? extends R>> mapper;
+
+               FlatMap(Function<? super T, Promise<? extends R>> mapper) {
+                       this.mapper = requireNonNull(mapper);
+               }
+
+               @SuppressWarnings("unchecked")
+               public Promise<R> call(Promise<T> resolved) throws Exception {
+                       return (Promise<R>) mapper.apply(resolved.getValue());
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Promise<T> recover(Function<Promise<?>, ? extends T> recovery) {
+               PromiseImpl<T> chained = new PromiseImpl<T>();
+               Recover<T> recover = new Recover<T>(chained, recovery);
+               then(recover, recover);
+               return chained;
+       }
+
+       /**
+        * A callback used by the {@link PromiseImpl#recover(Function)} method.
+        * 
+        * @Immutable
+        */
+       private static final class Recover<T> implements Success<T, Void>, 
Failure {
+               private final PromiseImpl<T>                                    
chained;
+               private final Function<Promise<?>, ? extends T> recovery;
+
+               Recover(PromiseImpl<T> chained, Function<Promise<?>, ? extends 
T> recovery) {
+                       this.chained = chained;
+                       this.recovery = requireNonNull(recovery);
+               }
+
+               public Promise<Void> call(Promise<T> resolved) throws Exception 
{
+                       T value;
+                       try {
+                               value = resolved.getValue();
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return null;
+                       }
+                       chained.resolve(value, null);
+                       return null;
+               }
+
+               public void fail(Promise<?> resolved) throws Exception {
+                       T recovered;
+                       Throwable failure;
+                       try {
+                               recovered = recovery.apply(resolved);
+                               failure = resolved.getFailure();
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return;
+                       }
+                       if (recovered == null) {
+                               chained.resolve(null, failure);
+                       } else {
+                               chained.resolve(recovered, null);
+                       }
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Promise<T> recoverWith(Function<Promise<?>, Promise<? extends 
T>> recovery) {
+               PromiseImpl<T> chained = new PromiseImpl<T>();
+               RecoverWith<T> recoverWith = new RecoverWith<T>(chained, 
recovery);
+               then(recoverWith, recoverWith);
+               return chained;
+       }
+
+       /**
+        * A callback used by the {@link PromiseImpl#recoverWith(Function)} 
method.
+        * 
+        * @Immutable
+        */
+       private static final class RecoverWith<T> implements Success<T, Void>, 
Failure {
+               private final PromiseImpl<T>                                    
                        chained;
+               private final Function<Promise<?>, Promise<? extends T>>        
recovery;
+
+               RecoverWith(PromiseImpl<T> chained, Function<Promise<?>, 
Promise<? extends T>> recovery) {
+                       this.chained = chained;
+                       this.recovery = requireNonNull(recovery);
+               }
+
+               public Promise<Void> call(Promise<T> resolved) throws Exception 
{
+                       T value;
+                       try {
+                               value = resolved.getValue();
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return null;
+                       }
+                       chained.resolve(value, null);
+                       return null;
+               }
+
+               public void fail(Promise<?> resolved) throws Exception {
+                       Promise<? extends T> recovered;
+                       Throwable failure;
+                       try {
+                               recovered = recovery.apply(resolved);
+                               failure = resolved.getFailure();
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return;
+                       }
+                       if (recovered == null) {
+                               chained.resolve(null, failure);
+                       } else {
+                               recovered.onResolve(new Chain<T>(chained, 
recovered));
+                       }
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Promise<T> fallbackTo(Promise<? extends T> fallback) {
+               PromiseImpl<T> chained = new PromiseImpl<T>();
+               FallbackTo<T> fallbackTo = new FallbackTo<T>(chained, fallback);
+               then(fallbackTo, fallbackTo);
+               return chained;
+       }
+
+       /**
+        * A callback used by the {@link PromiseImpl#fallbackTo(Promise)} 
method.
+        * 
+        * @Immutable
+        */
+       private static final class FallbackTo<T> implements Success<T, Void>, 
Failure {
+               private final PromiseImpl<T>            chained;
+               private final Promise<? extends T>      fallback;
+
+               FallbackTo(PromiseImpl<T> chained, Promise<? extends T> 
fallback) {
+                       this.chained = chained;
+                       this.fallback = requireNonNull(fallback);
+               }
+
+               public Promise<Void> call(Promise<T> resolved) throws Exception 
{
+                       T value;
+                       try {
+                               value = resolved.getValue();
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return null;
+                       }
+                       chained.resolve(value, null);
+                       return null;
+               }
+
+               public void fail(Promise<?> resolved) throws Exception {
+                       Throwable failure;
+                       try {
+                               failure = resolved.getFailure();
+                       } catch (Throwable e) {
+                               chained.resolve(null, e);
+                               return;
+                       }
+                       fallback.onResolve(new Chain<T>(chained, fallback, 
failure));
+               }
+       }
+
+       static <V> V requireNonNull(V value) {
+               if (value != null) {
+                       return value;
+               }
+               throw new NullPointerException();
+       }
+
+       /**
+        * Use the lazy initialization holder class idiom to delay creating a 
Logger
+        * until we actually need it.
+        */
+       private static final class Logger {
+               private final static java.util.logging.Logger   LOGGER;
+               static {
+                       LOGGER = 
java.util.logging.Logger.getLogger(PromiseImpl.class.getName());
+               }
+
+               static void logCallbackException(Throwable t) {
+                       LOGGER.log(java.util.logging.Level.WARNING, "Exception 
from Promise callback", t);
+               }
+       }
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promises.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promises.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promises.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Promises.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.util.promise;
+
+import static org.osgi.util.promise.PromiseImpl.requireNonNull;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Static helper methods for {@link Promise}s.
+ * 
+ * @ThreadSafe
+ * @author $Id: 6ad9c7cca5a98dbddd87db8417df51bf6e008922 $
+ */
+public class Promises {
+       private Promises() {
+               // disallow object creation
+       }
+
+       /**
+        * Create a new Promise that has been resolved with the specified value.
+        * 
+        * @param <T> The value type associated with the returned Promise.
+        * @param value The value of the resolved Promise.
+        * @return A new Promise that has been resolved with the specified 
value.
+        */
+       public static <T> Promise<T> resolved(T value) {
+               return new PromiseImpl<T>(value, null);
+       }
+
+       /**
+        * Create a new Promise that has been resolved with the specified 
failure.
+        * 
+        * @param <T> The value type associated with the returned Promise.
+        * @param failure The failure of the resolved Promise. Must not be
+        *        {@code null}.
+        * @return A new Promise that has been resolved with the specified 
failure.
+        */
+       public static <T> Promise<T> failed(Throwable failure) {
+               return new PromiseImpl<T>(null, requireNonNull(failure));
+       }
+
+       /**
+        * Create a new Promise that is a latch on the resolution of the 
specified
+        * Promises.
+        * 
+        * <p>
+        * The new Promise acts as a gate and must be resolved after all of the
+        * specified Promises are resolved.
+        * 
+        * @param <T> The value type of the List value associated with the 
returned
+        *        Promise.
+        * @param <S> A subtype of the value type of the List value associated 
with
+        *        the returned Promise.
+        * @param promises The Promises which must be resolved before the 
returned
+        *        Promise must be resolved. Must not be {@code null} and all of 
the
+        *        elements in the collection must not be {@code null}.
+        * @return A Promise that is resolved only when all the specified 
Promises
+        *         are resolved. The returned Promise will be successfully 
resolved,
+        *         with a List of the values in the order of the specified 
Promises,
+        *         if all the specified Promises are successfully resolved. The 
List
+        *         in the returned Promise is the property of the caller and is
+        *         modifiable. The returned Promise will be resolved with a 
failure
+        *         of {@link FailedPromisesException} if any of the specified
+        *         Promises are resolved with a failure. The failure
+        *         {@link FailedPromisesException} must contain all of the 
specified
+        *         Promises which resolved with a failure.
+        */
+       public static <T, S extends T> Promise<List<T>> 
all(Collection<Promise<S>> promises) {
+               if (promises.isEmpty()) {
+                       List<T> result = new ArrayList<T>();
+                       return resolved(result);
+               }
+               /* make a copy and capture the ordering */
+               List<Promise<? extends T>> list = new ArrayList<Promise<? 
extends T>>(promises);
+               PromiseImpl<List<T>> chained = new PromiseImpl<List<T>>();
+               All<T> all = new All<T>(chained, list);
+               for (Promise<? extends T> promise : list) {
+                       promise.onResolve(all);
+               }
+               return chained;
+       }
+
+       /**
+        * Create a new Promise that is a latch on the resolution of the 
specified
+        * Promises.
+        * 
+        * <p>
+        * The new Promise acts as a gate and must be resolved after all of the
+        * specified Promises are resolved.
+        * 
+        * @param <T> The value type associated with the specified Promises.
+        * @param promises The Promises which must be resolved before the 
returned
+        *        Promise must be resolved. Must not be {@code null} and all of 
the
+        *        arguments must not be {@code null}.
+        * @return A Promise that is resolved only when all the specified 
Promises
+        *         are resolved. The returned Promise will be successfully 
resolved,
+        *         with a List of the values in the order of the specified 
Promises,
+        *         if all the specified Promises are successfully resolved. The 
List
+        *         in the returned Promise is the property of the caller and is
+        *         modifiable. The returned Promise will be resolved with a 
failure
+        *         of {@link FailedPromisesException} if any of the specified
+        *         Promises are resolved with a failure. The failure
+        *         {@link FailedPromisesException} must contain all of the 
specified
+        *         Promises which resolved with a failure.
+        */
+       public static <T> Promise<List<T>> all(Promise<? extends T>... 
promises) {
+               @SuppressWarnings("unchecked")
+               List<Promise<T>> list = Arrays.asList((Promise<T>[]) promises);
+               return all(list);
+       }
+
+       /**
+        * A callback used to resolve a Promise when the specified list of 
Promises
+        * are resolved for the {@link Promises#all(Collection)} method.
+        * 
+        * @ThreadSafe
+        */
+       private static final class All<T> implements Runnable {
+               private final PromiseImpl<List<T>>                      chained;
+               private final List<Promise<? extends T>>        promises;
+               private final AtomicInteger                                     
promiseCount;
+
+               All(PromiseImpl<List<T>> chained, List<Promise<? extends T>> 
promises) {
+                       this.chained = chained;
+                       this.promises = promises;
+                       this.promiseCount = new AtomicInteger(promises.size());
+               }
+
+               public void run() {
+                       if (promiseCount.decrementAndGet() != 0) {
+                               return;
+                       }
+                       List<T> result = new ArrayList<T>(promises.size());
+                       List<Promise<?>> failed = new 
ArrayList<Promise<?>>(promises.size());
+                       Throwable cause = null;
+                       for (Promise<? extends T> promise : promises) {
+                               Throwable failure;
+                               T value;
+                               try {
+                                       failure = promise.getFailure();
+                                       value = (failure != null) ? null : 
promise.getValue();
+                               } catch (Throwable e) {
+                                       chained.resolve(null, e);
+                                       return;
+                               }
+                               if (failure != null) {
+                                       failed.add(promise);
+                                       if (cause == null) {
+                                               cause = failure;
+                                       }
+                               } else {
+                                       result.add(value);
+                               }
+                       }
+                       if (failed.isEmpty()) {
+                               chained.resolve(result, null);
+                       } else {
+                               chained.resolve(null, new 
FailedPromisesException(failed, cause));
+                       }
+               }
+       }
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Success.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Success.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Success.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/Success.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.util.promise;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Success callback for a Promise.
+ * 
+ * <p>
+ * A Success callback is registered with a {@link Promise} using the
+ * {@link Promise#then(Success)} method and is called if the Promise is 
resolved
+ * successfully.
+ * 
+ * <p>
+ * This is a functional interface and can be used as the assignment target for 
a
+ * lambda expression or method reference.
+ * 
+ * @param <T> The value type of the resolved Promise passed as input to this
+ *        callback.
+ * @param <R> The value type of the returned Promise from this callback.
+ * 
+ * @ThreadSafe
+ * @author $Id: 58eef5ba732ef999d57a1feaaf1e5229356647e3 $
+ */
+@ConsumerType
+public interface Success<T, R> {
+       /**
+        * Success callback for a Promise.
+        * 
+        * <p>
+        * This method is called if the Promise with which it is registered 
resolves
+        * successfully.
+        * 
+        * <p>
+        * In the remainder of this description we will refer to the Promise
+        * returned by this method as the returned Promise and the Promise 
returned
+        * by {@link Promise#then(Success)} when this Success callback was
+        * registered as the chained Promise.
+        * 
+        * <p>
+        * If the returned Promise is {@code null} then the chained Promise will
+        * resolve immediately with a successful value of {@code null}. If the
+        * returned Promise is not {@code null} then the chained Promise will be
+        * resolved when the returned Promise is resolved.
+        * 
+        * @param resolved The successfully resolved {@link Promise}.
+        * @return The Promise to use to resolve the chained Promise, or
+        *         {@code null} if the chained Promise is to be resolved 
immediately
+        *         with the value {@code null}.
+        * @throws Exception The chained Promise will be failed with the thrown
+        *         exception.
+        */
+       Promise<R> call(Promise<T> resolved) throws Exception;
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/package-info.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/package-info.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/package-info.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/osgi/util/promise/package-info.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * Promise Package Version 1.0.
+ * 
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ * 
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code  Import-Package: org.osgi.util.promise; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code  Import-Package: org.osgi.util.promise; version="[1.0,1.1)"}
+ * 
+ * @author $Id: 5a3ec65d3b7e7ebdd2278d75675b8a808e6cb2bf $
+ */
+
+@Version("1.0")
+package org.osgi.util.promise;
+
+import org.osgi.annotation.versioning.Version;
+

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/.gitignore
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/.gitignore?rev=1689973&view=auto
==============================================================================
    (empty)

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/DefaultPackageClass.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/DefaultPackageClass.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/DefaultPackageClass.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/DefaultPackageClass.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ * The DefaultPackageClass is just present for the
+ * {@link org.apache.felix.scr.impl.ReflectionHelperTest} to be able to test
+ * the <code>ReflectionHelper.getPackageName</code> method.
+ */
+public class DefaultPackageClass
+{
+
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_activate_10.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_activate_10.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_activate_10.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_activate_11.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_activate_11.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_activate_11.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.properties
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.properties?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.properties
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.properties
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,20 @@
+# 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.
+#
+# Sample properties file for the metadate load test
+
+file.property = Property from File
\ No newline at end of file

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_all_elements_10.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_anonymous_10.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_anonymous_10.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_anonymous_10.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_anonymous_11.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_anonymous_11.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_anonymous_11.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_implementation_10.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_implementation_10.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_implementation_10.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_implementation_11.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_implementation_11.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_implementation_11.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_service_10.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_service_10.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_service_10.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_service_11.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_service_11.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_duplicate_service_11.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_no_namespace.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_no_namespace.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_no_namespace.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_properties_11.xml
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_properties_11.xml?rev=1689973&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/components_properties_11.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/BundleComponentActivatorTest.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/BundleComponentActivatorTest.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/BundleComponentActivatorTest.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/BundleComponentActivatorTest.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,187 @@
+/*
+ * 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;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
+
+public class BundleComponentActivatorTest extends TestCase
+{
+
+    /**
+     * Test that an empty array is returned for a null bundle.
+     */
+    public void test_findDescriptors_withNullBundle()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( null, 
"foo.xml" );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that an empty array is returned for a null location.
+     */
+    public void test_findDescriptors_withNullLocation()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( new 
MockBundle(), null );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that an empty array is returned for an empty location.
+     */
+    public void test_findDescriptors_withEmptyLocation()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( new 
MockBundle(), "" );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that an empty array is returned for a location containing only 
blanks.
+     */
+    public void test_findDescriptors_withBlankLocation()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( new 
MockBundle(), " " );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that when using a non wilcarded location, getResource() will be 
used (for legacy reasons) and the returned
+     * array is the one returned by bundle method call.
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withNonWildcardLocation() throws 
MalformedURLException
+    {
+        final URL[] descriptors = new URL[]
+            { new URL( "file:foo.xml" ) };
+        final Enumeration de = new Vector( Arrays.asList( descriptors ) 
).elements();
+        final Bundle bundle = ( Bundle ) EasyMock.createNiceMock( Bundle.class 
);
+        EasyMock.expect( bundle.findEntries( "/some/location", "foo.xml", 
false ) ).andReturn( de );
+
+        EasyMock.replay( new Object[]
+            { bundle } );
+        final URL[] urls = BundleComponentActivator.findDescriptors( bundle, 
"/some/location/foo.xml" );
+        EasyMock.verify( new Object[]
+            { bundle } );
+
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor length", 1, urls.length );
+        assertEquals( "Descriptor", descriptors[0], urls[0] );
+    }
+
+
+    public void findDescriptors_withWildcardLocation( final String location,
+                                                      final String path,
+                                                      final String filePattern 
)
+        throws MalformedURLException
+    {
+        final URL[] urls = new URL[]
+            {
+                new URL( "file:foo1.xml" ),
+                new URL( "file:foo2.xml" )
+            };
+        final Enumeration de = new Vector( Arrays.asList( urls ) ).elements();
+        final Bundle bundle = (Bundle) EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.findEntries( path, filePattern, false ) 
).andReturn( de );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] actualUrls = BundleComponentActivator.findDescriptors( 
bundle, location );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", actualUrls );
+        assertEquals( "Descriptor length", urls.length, actualUrls.length );
+        for( int i = 0; i < actualUrls.length; i++ )
+        {
+            assertEquals( "Descriptor", urls[ i ], actualUrls[ i ] );
+        }
+    }
+
+    /**
+     * Test that when using "*.xml", path will be root of bundle "/" and file 
pattern will be "*.xml".
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation01()
+        throws MalformedURLException
+    {
+        findDescriptors_withWildcardLocation( "*.xml", "/", "*.xml" );
+    }
+
+    /**
+     * Test that when using "/foo/*.xml", path will be "/foo/" and file 
pattern will be "*.xml".
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation02()
+        throws MalformedURLException
+    {
+        findDescriptors_withWildcardLocation( "/foo/*.xml", "/foo", "*.xml" );
+    }
+
+    /**
+     * Test that in case that no resources are found (bundle return null) an 
empty array is returned.
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation_nullEnum()
+        throws MalformedURLException
+    {
+        final Bundle bundle = (Bundle) EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.findEntries( "/", "*.xml", false ) 
).andReturn( null );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] actualUrls = BundleComponentActivator.findDescriptors( 
bundle, "*.xml" );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", actualUrls );
+        assertEquals( "Descriptor length", 0, actualUrls.length );
+    }
+
+    /**
+     * Test that in case that no resources are found (bundle return empty 
enum) an empty array is returned.
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation_emptyEnum()
+        throws MalformedURLException
+    {
+        final Bundle bundle = (Bundle) EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.findEntries( "/", "*.xml", false ) 
).andReturn( new Vector().elements() );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] actualUrls = BundleComponentActivator.findDescriptors( 
bundle, "*.xml" );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", actualUrls );
+        assertEquals( "Descriptor length", 0, actualUrls.length );
+    }
+
+}
\ No newline at end of file

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/ComponentRegistryKeyTest.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/ComponentRegistryKeyTest.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/ComponentRegistryKeyTest.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/ComponentRegistryKeyTest.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+
+import junit.framework.TestCase;
+
+
+public class ComponentRegistryKeyTest extends TestCase
+{
+
+    private final ComponentRegistryKey b1_a_0 = key( 1, "a" );
+    private final ComponentRegistryKey b2_a_0 = key( 2, "a" );
+
+    private final ComponentRegistryKey b1_a_1 = key( 1, "a" );
+    private final ComponentRegistryKey b2_a_1 = key( 2, "a" );
+
+    private final ComponentRegistryKey b1_b = key( 1, "b" );
+    private final ComponentRegistryKey b2_b = key( 2, "b" );
+
+
+    public void test_globally_unique_key()
+    {
+        // same
+        TestCase.assertEquals( b1_a_0, b1_a_0 );
+
+        // equals both ways
+        TestCase.assertEquals( b1_a_0, b1_a_1 );
+        TestCase.assertEquals( b1_a_1, b1_a_0 );
+
+        // not equals both ways
+        TestCase.assertFalse( b1_a_0.equals( b2_a_0 ) );
+        TestCase.assertFalse( b2_a_0.equals( b1_a_0 ) );
+
+        // not equals both ways
+        TestCase.assertFalse( b1_a_0.equals( b1_b ) );
+        TestCase.assertFalse( b1_b.equals( b1_a_0 ) );
+
+        // not equals both ways
+        TestCase.assertFalse( b1_a_0.equals( b2_b ) );
+        TestCase.assertFalse( b2_b.equals( b1_a_0 ) );
+    }
+
+
+    private static ComponentRegistryKey key( final long bundleId, final String 
name )
+    {
+        return new ComponentRegistryKey( new MockBundle()
+        {
+//            @Override
+            public long getBundleId()
+            {
+                return bundleId;
+            }
+        }, name );
+    }
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockBundle.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockBundle.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockBundle.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockBundle.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,207 @@
+/*
+ * 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;
+
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.cert.X509Certificate;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+
+
+public class MockBundle implements Bundle
+{
+
+    public Enumeration findEntries( String arg0, String arg1, boolean arg2 )
+    {
+        return null;
+    }
+
+
+    public BundleContext getBundleContext()
+    {
+        return null;
+    }
+
+    public Map<X509Certificate, List<X509Certificate>> getSignerCertificates( 
int i )
+    {
+        return null;
+    }
+
+    public Version getVersion()
+    {
+        return null;
+    }
+
+    public <A> A adapt( Class<A> aClass )
+    {
+        return null;
+    }
+
+    public File getDataFile( String s )
+    {
+        return null;
+    }
+
+
+    public long getBundleId()
+    {
+        return 0;
+    }
+
+
+    public URL getEntry( String name )
+    {
+        return getClass().getClassLoader().getResource( name );
+    }
+
+
+    public Enumeration getEntryPaths( String arg0 )
+    {
+        return null;
+    }
+
+
+    public Dictionary getHeaders()
+    {
+        return null;
+    }
+
+
+    public Dictionary getHeaders( String arg0 )
+    {
+        return null;
+    }
+
+
+    public long getLastModified()
+    {
+        return 0;
+    }
+
+
+    public String getLocation()
+    {
+        return "test:mockbundle";
+    }
+
+
+    public ServiceReference[] getRegisteredServices()
+    {
+        return null;
+    }
+
+
+    public URL getResource( String arg0 )
+    {
+        return null;
+    }
+
+
+    public Enumeration getResources( String arg0 )
+    {
+        return null;
+    }
+
+
+    public ServiceReference[] getServicesInUse()
+    {
+        return null;
+    }
+
+
+    public int getState()
+    {
+        return 0;
+    }
+
+
+    public String getSymbolicName()
+    {
+        return null;
+    }
+
+
+    public boolean hasPermission( Object arg0 )
+    {
+        return false;
+    }
+
+
+    public Class loadClass( String arg0 )
+    {
+        return null;
+    }
+
+
+    public void start()
+    {
+
+    }
+
+
+    public void start( int options )
+    {
+
+    }
+
+
+    public void stop()
+    {
+
+    }
+
+
+    public void stop( int options )
+    {
+
+    }
+
+
+    public void uninstall()
+    {
+
+    }
+
+
+    public void update()
+    {
+
+    }
+
+
+    public void update( InputStream arg0 )
+    {
+
+    }
+
+    public int compareTo( Bundle bundle )
+    {
+        return 0;
+    }
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockLogger.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockLogger.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockLogger.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/MockLogger.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+
+import java.text.MessageFormat;
+
+import org.apache.felix.scr.impl.helper.Logger;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+
+
+public class MockLogger implements Logger
+{
+    String lastMessage;
+
+
+    public boolean isLogEnabled( int level )
+    {
+        return true;
+    }
+
+
+    public void log( int level, String pattern, Object[] arguments, 
ComponentMetadata metadata, Long componentId, Throwable ex )
+    {
+        if ( isLogEnabled( level ) )
+        {
+            log( level, MessageFormat.format( pattern, arguments ), metadata, 
null, ex );
+        }
+    }
+
+
+    public void log( int level, String message, ComponentMetadata metadata, 
Long componentId, Throwable ex )
+    {
+        lastMessage = message;
+    }
+
+
+    public boolean messageContains( String value )
+    {
+        return lastMessage != null && lastMessage.indexOf( value ) >= 0;
+    }
+}
\ No newline at end of file

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/SCRCommandlTest.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/SCRCommandlTest.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/SCRCommandlTest.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/SCRCommandlTest.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+import junit.framework.TestCase;
+
+public class SCRCommandlTest extends TestCase
+{
+ 
+    
+    public void testPropertyInfo()
+    {
+        ScrCommand scr = new ScrCommand(null, null, null);
+         check(scr, String.format("  Properties:%n    key = [1, 2]%n"), new 
int[] {1, 2});
+         check(scr, String.format("  Properties:%n    key = [1, 2]%n"), new 
String[] {"1", "2"});
+         check(scr, String.format("  Properties:%n    key = [true, false]%n"), 
new Boolean[] {true, false});
+         check(scr, String.format("  Properties:%n    key = foo%n"), "foo");
+         check(scr, String.format("  Properties:%n    key = true%n"), true);
+    }
+
+    private PrintWriter check(ScrCommand scr, String expected, Object o)
+    {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        scr.propertyInfo(Collections.<String, Object>singletonMap("key", o), 
pw, "");
+        assertEquals(expected, sw.toString());
+        return pw;
+    }
+    
+}

Added: 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/config/ConfigurationSupportTest.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/config/ConfigurationSupportTest.java?rev=1689973&view=auto
==============================================================================
--- 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/config/ConfigurationSupportTest.java
 (added)
+++ 
felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/test/org/apache/felix/scr/impl/config/ConfigurationSupportTest.java
 Wed Jul  8 22:10:14 2015
@@ -0,0 +1,31 @@
+/*
+ * 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.config;
+
+import junit.framework.TestCase;
+
+public class ConfigurationSupportTest extends TestCase
+{
+
+    public void testEscape()
+    {
+        assertEquals("foo \\(&\\)", ConfigurationSupport.escape("foo (&)"));
+    }
+    
+}


Reply via email to