aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zma...@apache.org
Subject [28/51] [partial] aurora git commit: Move packages from com.twitter.common to org.apache.aurora.common
Date Wed, 26 Aug 2015 21:00:18 GMT
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Command.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Command.java b/commons/src/main/java/org/apache/aurora/common/base/Command.java
new file mode 100644
index 0000000..b33bee4
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Command.java
@@ -0,0 +1,23 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * A command that does not throw any checked exceptions.
+ *
+ * @author John Sirois
+ */
+public interface Command extends ExceptionalCommand<RuntimeException> {
+  // convenience typedef
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Commands.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Commands.java b/commons/src/main/java/org/apache/aurora/common/base/Commands.java
new file mode 100644
index 0000000..6d9fc4c
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Commands.java
@@ -0,0 +1,77 @@
+/**
+ * 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.apache.aurora.common.base;
+
+import com.google.common.collect.ImmutableList;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utility functions for working with commands.
+ *
+ * @author John Sirois
+ */
+public final class Commands {
+
+  /**
+   * A command that does nothing when executed.
+   */
+  public static final Command NOOP = new Command() {
+    @Override public void execute() {
+      // noop
+    }
+  };
+
+  private Commands() {
+    // utility
+  }
+
+  /**
+   * Converts a command into a supplier returning null.
+   *
+   * @return A supplier whose {@link Supplier#get()} will cause the given
+   *         {@code command} to be executed and {@code null} to be returned.
+   */
+  public static <E extends Exception> ExceptionalSupplier<Void, E> asSupplier(
+      final ExceptionalCommand<E> command) {
+    checkNotNull(command);
+
+    return new ExceptionalSupplier<Void, E>() {
+      @Override public Void get() throws E {
+        command.execute();
+        return null;
+      }
+    };
+  }
+
+  /**
+   * Combines multiple {@code commands} into a single command. A {@link RuntimeException} thrown
+   * during the execution of one of the commands will prevent the subsequent commands from being
+   * executed.
+   *
+   * @param commands Commands to compound.
+   * @return A command whose {@link Command#execute()} will cause the given {@code commands} to be
+   *         executed serially.
+   */
+  public static Command compound(Iterable<Command> commands) {
+    final ImmutableList<Command> executableCommands = ImmutableList.copyOf(commands);
+    return new Command() {
+      @Override public void execute() {
+        for (Command command : executableCommands) {
+          command.execute();
+        }
+      }
+    };
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Either.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Either.java b/commons/src/main/java/org/apache/aurora/common/base/Either.java
new file mode 100644
index 0000000..a746e72
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Either.java
@@ -0,0 +1,358 @@
+/**
+ * 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.apache.aurora.common.base;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * A value of one of two possible types.
+ *
+ * <p>Often Either processing is used as an alternative exception flow control.  In these uses the
+ * left type represents failure by convention and the right type the success path result.
+ *
+ * @param <L> The left type.
+ * @param <R> The right type.
+ */
+public final class Either<L, R> {
+  private final Optional<L> left;
+  private final Optional<R> right;
+
+  private Either(Optional<L> left, Optional<R> right) {
+    this.left = left;
+    this.right = right;
+  }
+
+  /**
+   * Turns a left into a right and vice-versa.
+   *
+   * @return A new swapped either instance.
+   */
+  public Either<R, L> swap() {
+    return new Either<R, L>(right, left);
+  }
+
+  /**
+   * Returns an optional the will be {@link Optional#isPresent() present} is this is a left
+   * instance.
+   *
+   * @return An optional value for the left.
+   */
+  public Optional<L> left() {
+    return left;
+  }
+
+  /**
+   * Returns an optional the will be {@link Optional#isPresent() present} is this is a right
+   * instance.
+   *
+   * @return An optional value for the right.
+   */
+  public Optional<R> right() {
+    return right;
+  }
+
+  /**
+   * Returns {@code true} if this is a left instance.
+   *
+   * @return {@code true} if this is a left.
+   */
+  public boolean isLeft() {
+    return left().isPresent();
+  }
+
+  /**
+   * Returns {@code true} if this is a right instance.
+   *
+   * @return {@code true} if this is a right.
+   */
+  public boolean isRight() {
+    return right().isPresent();
+  }
+
+  /**
+   * Returns the underlying value if this is a left; otherwise, throws.
+   *
+   * @return The underlying value.
+   * @throws IllegalStateException if this is a right instance.
+   */
+  public L getLeft() {
+    return left().get();
+  }
+
+  /**
+   * Returns the underlying value if this is a right; otherwise, throws.
+   *
+   * @return The underlying value.
+   * @throws IllegalStateException if this is a right instance.
+   */
+  public R getRight() {
+    return right().get();
+  }
+
+  /**
+   * If this is a left, maps its value into a new left; otherwise just returns this right.
+   *
+   * @param transformer The transformation to apply to the left value.
+   * @param <M> The type a left value will be mapped to.
+   * @return The mapped left or else the right.
+   */
+  public <M> Either<M, R> mapLeft(Function<? super L, M> transformer) {
+    if (isLeft()) {
+      return left(transformer.apply(getLeft()));
+    } else {
+      @SuppressWarnings("unchecked") // I am a right so my left is never accessible
+      Either<M, R> self = (Either<M, R>) this;
+      return self;
+    }
+  }
+
+  /**
+   * If this is a right, maps its value into a new right; otherwise just returns this left.
+   *
+   * @param transformer The transformation to apply to the left value.
+   * @param <M> The type a right value will be mapped to.
+   * @return The mapped right or else the left.
+   */
+  public <M> Either<L, M> mapRight(Function<? super R, M> transformer) {
+    if (isRight()) {
+      return right(transformer.apply(getRight()));
+    } else {
+      @SuppressWarnings("unchecked") // I am a left so my right is never accessible
+      Either<L, M> self = (Either<L, M>) this;
+      return self;
+    }
+  }
+
+  /**
+   * Can transform either a left or a right into a result.
+   *
+   * @param <L> The left type.
+   * @param <R> The right type.
+   * @param <T> The transformation result type.
+   */
+  public abstract static class Transformer<L, R, T> implements Function<Either<L, R>, T> {
+
+    /**
+     * Maps left values to a result.
+     *
+     * @param left the left value to map.
+     * @return The mapped value.
+     */
+    public abstract T mapLeft(L left);
+
+    /**
+     * Maps right values to a result.
+     *
+     * @param right the right value to map.
+     * @return The mapped value.
+     */
+    public abstract T mapRight(R right);
+
+    @Override
+    public final T apply(Either<L, R> either) {
+      return either.map(this);
+    }
+  }
+
+  /**
+   * Creates a transformer from left and right transformation functions.
+   *
+   * @param leftTransformer A transformer to process left values.
+   * @param rightTransformer A transformer to process right values.
+   * @param <L> The left type.
+   * @param <R> The right type.
+   * @param <T> The transformation result type.
+   * @return A new transformer composed of left and right transformer functions.
+   */
+  public static <L, R, T> Transformer<L, R, T> transformer(
+      final Function<? super L, T> leftTransformer,
+      final Function<? super R, T> rightTransformer) {
+
+    return new Transformer<L, R, T>() {
+      @Override public T mapLeft(L item) {
+        return leftTransformer.apply(item);
+      }
+      @Override public T mapRight(R item) {
+        return rightTransformer.apply(item);
+      }
+    };
+  }
+
+  /**
+   * Transforms this either instance to a value regardless of whether it is a left or a right.
+   *
+   * @param transformer The transformer to map this either instance.
+   * @param <T> The type the transformer produces.
+   * @return A value mapped by the transformer from this left or right instance.
+   */
+  public <T> T map(final Transformer<? super L, ? super R, T> transformer) {
+    if (isLeft()) {
+      return transformer.mapLeft(getLeft());
+    } else {
+      return transformer.mapRight(getRight());
+    }
+  }
+
+  @Override
+  public boolean equals(@Nullable Object o) {
+    if (!(o instanceof Either)) {
+      return false;
+    }
+    Either<?, ?> other = (Either<?, ?>) o;
+    return Objects.equal(left, other.left)
+        && Objects.equal(right, other.right);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(left, right);
+  }
+
+  @Override
+  public String toString() {
+    if (isLeft()) {
+      return String.format("Left(%s)", getLeft());
+    } else {
+      return String.format("Right(%s)", getRight());
+    }
+  }
+
+  /**
+   * Creates a left either instance.
+   *
+   * @param value The left value to wrap - may not be null.
+   * @param <L> The left type.
+   * @param <R> The right type.
+   * @return A left either instance wrapping {@code value}.
+   */
+  public static <L, R> Either<L, R> left(L value) {
+    return new Either<L, R>(Optional.of(value), Optional.<R>absent());
+  }
+
+  /**
+   * Creates a right either instance.
+   *
+   * @param value The right value to wrap - may not be null.
+   * @param <L> The left type.
+   * @param <R> The right type.
+   * @return A right either instance wrapping {@code value}.
+   */
+  public static <L, R> Either<L, R> right(R value) {
+    return new Either<L, R>(Optional.<L>absent(), Optional.of(value));
+  }
+
+  /**
+   * Extracts all the lefts from a sequence of eithers lazily.
+   *
+   * @param results A sequence of either's to process.
+   * @param <L> The left type.
+   * @param <R> The right type.
+   * @return A lazy iterable that will produce the lefts present in results in order.
+   */
+  public static <L, R> Iterable<L> lefts(Iterable<Either<L, R>> results) {
+    return Optional.presentInstances(Iterables.transform(results,
+        new Function<Either<L, R>, Optional<L>>() {
+          @Override public Optional<L> apply(Either<L, R> item) {
+            return item.left();
+          }
+        }));
+  }
+
+  /**
+   * Extracts all the rights from a sequence of eithers lazily.
+   *
+   * @param results A sequence of either's to process.
+   * @param <L> The left type.
+   * @param <R> The right type.
+   * @return A lazy iterable that will produce the rights present in results in order.
+   */
+  public static <L, R> Iterable<R> rights(Iterable<Either<L, R>> results) {
+    return Optional.presentInstances(Iterables.transform(results,
+        new Function<Either<L, R>, Optional<R>>() {
+          @Override public Optional<R> apply(Either<L, R> item) {
+            return item.right();
+          }
+        }));
+  }
+
+  /**
+   * A convenience method equivalent to calling {@code guard(work, exceptionType)}.
+   */
+  public static <X extends Exception, R> Either<X, R> guard(
+      Class<X> exceptionType,
+      ExceptionalSupplier<R, X> work) {
+
+    @SuppressWarnings("unchecked")
+    Either<X, R> either = guard(work, exceptionType);
+    return either;
+  }
+
+  /**
+   * A convenience method equivalent to calling
+   * {@code guard(Lists.asList(execpetionType, rest), work)}.
+   */
+  public static <X extends Exception, R> Either<X, R> guard(
+      ExceptionalSupplier<R, X> work,
+      Class<? extends X> exceptionType,
+      Class<? extends X>... rest) {
+
+    return guard(Lists.asList(exceptionType, rest), work);
+  }
+
+  /**
+   * Thrown when guarded work throws an unguarded exception.  The {@link #getCause() cause} will
+   * contain the original unguarded exception.
+   */
+  public static class UnguardedException extends RuntimeException {
+    public UnguardedException(Throwable cause) {
+      super(cause);
+    }
+  }
+
+  /**
+   * Converts work that can throw exceptions into an either with a left exception base type.  This
+   * can be useful to fold an exception throwing library call into an either processing style
+   * pipeline.
+   *
+   * @param exceptionTypes The expected exception types.
+   * @param work The work to perform to get a result produce an error.
+   * @param <X> The base error type.
+   * @param <R> The success type.
+   * @return An either wrapping the result of performing {@code work}.
+   * @throws UnguardedException if work throws an unguarded exception type.
+   */
+  public static <X extends Exception, R> Either<X, R> guard(
+      Iterable<Class<? extends X>> exceptionTypes,
+      ExceptionalSupplier<R, X> work) {
+
+    try {
+      return right(work.get());
+    // We're explicitly dealing with generic exception types here by design.
+    // SUPPRESS CHECKSTYLE RegexpSinglelineJava
+    } catch (Exception e) {
+      for (Class<? extends X> exceptionType : exceptionTypes) {
+        if (exceptionType.isInstance(e)) {
+          X exception = exceptionType.cast(e);
+          return left(exception);
+        }
+      }
+      throw new UnguardedException(e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/ExceptionTransporter.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/ExceptionTransporter.java b/commons/src/main/java/org/apache/aurora/common/base/ExceptionTransporter.java
new file mode 100644
index 0000000..e5cb60d
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/ExceptionTransporter.java
@@ -0,0 +1,84 @@
+/**
+ * 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.apache.aurora.common.base;
+
+import com.google.common.base.Function;
+
+/**
+ * A utility for transporting checked exceptions across boundaries that do not allow for checked
+ * exception propagation.
+ *
+ * @param <E> The type of checked exception the ExceptionTransported can transport
+ *
+ * @author John Sirois
+ */
+public class ExceptionTransporter<E extends Exception> {
+
+  /**
+   * An exception wrapper used to transport checked exceptions.  Never leaves an
+   * {@link ExceptionTransporter#guard(com.google.common.base.Function)} call.
+   */
+  private static final class TransportingException extends RuntimeException {
+    private TransportingException(Exception cause) {
+      super("It is a usage error to see this message!", cause);
+    }
+  }
+
+  /**
+   * Guards a unit of work that internally can generate checked exceptions.  Callers wrap up the
+   * work in a function that rethrows any checked exceptions using the supplied
+   * ExceptionTransporter.  Guard will ensure the original exception is unwrapped an re-thrown.
+   *
+   * @param work The unit of work that guards its checked exceptions.
+   * @param <T> The type returned by the unit of work when it successfully completes.
+   * @param <X> The type of checked exception that the unit of work wishes to guard.
+   * @return the result of the unit of work if no excpetions are thrown
+   * @throws X when the unit of work uses the ExceptionTransporter to throw a checked exception
+   */
+  public static <T, X extends Exception> T guard(Function<ExceptionTransporter<X>, T> work)
+    throws X {
+
+    try {
+      return work.apply(new ExceptionTransporter<X>());
+    } catch (TransportingException e) {
+      @SuppressWarnings("unchecked")
+      X cause = (X) e.getCause();
+      throw cause;
+    }
+  }
+
+  /**
+   * Throws the given {@code checked} exception across a boundary that does not allow checked
+   * exceptions.  Although a RuntimeException is returned by this method signature, the method never
+   * actually completes normally.  The return type does allow the following usage idiom however:
+   * <pre>
+   * public String apply(ExceptionTransporter transporter) {
+   *   try {
+   *     return doChecked();
+   *   } catch (CheckedException e) {
+   *     // Although transport internally throws and does not return, we satisfy the compiler that
+   *     // our method returns a value or throws by pretending to throw the RuntimeException that
+   *     // never actually gets returned by transporter.transport(...)
+   *     throw transporter.transport(e);
+   *   }
+   * }
+   * </pre>
+   *
+   * @param checked The checked exception to transport.
+   * @return A RuntimeException that can be thrown to satisfy the compiler at the call site
+   */
+  public RuntimeException transport(E checked) {
+    throw new TransportingException(checked);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/ExceptionalClosure.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/ExceptionalClosure.java b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalClosure.java
new file mode 100644
index 0000000..66b3314
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalClosure.java
@@ -0,0 +1,35 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * An interface that captures a unit of work against an item.
+ *
+ * @param <T> The closure type.
+ * @param <E> The exception type thrown by the closure.
+ *
+ * @author John Sirois
+ */
+public interface ExceptionalClosure<T, E extends Exception> {
+
+  /**
+   * Performs a unit of work on item, possibly throwing {@code E} in the process.
+   *
+   * <p>TODO(John Sirois): consider supporting @Nullable
+   *
+   * @param item the item to perform work against
+   * @throws E if there was a problem performing the work
+   */
+  void execute(T item) throws E;
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/ExceptionalCommand.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/ExceptionalCommand.java b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalCommand.java
new file mode 100644
index 0000000..8e38133
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalCommand.java
@@ -0,0 +1,31 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * An interface that captures a unit of work.
+ *
+ * @param <E> The type of exception that the command throws.
+ *
+ * @author John Sirois
+ */
+public interface ExceptionalCommand<E extends Exception> {
+
+  /**
+   * Performs a unit of work, possibly throwing {@code E} in the process.
+   *
+   * @throws E if there was a problem performing the work
+   */
+  void execute() throws E;
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunction.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunction.java b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunction.java
new file mode 100644
index 0000000..f867c35
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunction.java
@@ -0,0 +1,37 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * An interface that captures a unit of work against an item.
+ *
+ * @param <S> The argument type for the function.
+ * @param <T> The return type for the function.
+ * @param <E> The exception type that the function throws.
+ *
+ * @author John Sirois
+ */
+public interface ExceptionalFunction<S, T, E extends Exception> {
+
+  /**
+   * Performs a unit of work on item, possibly throwing {@code E} in the process.
+   *
+   * <p>TODO(John Sirois): consider supporting @Nullable
+   *
+   * @param item The item to perform work against.
+   * @return The result of the computation.
+   * @throws E if there was a problem performing the work.
+   */
+  T apply(S item) throws E;
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunctions.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunctions.java b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunctions.java
new file mode 100644
index 0000000..f06c66c
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalFunctions.java
@@ -0,0 +1,153 @@
+/**
+ * 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.apache.aurora.common.base;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Utility functions for working with exceptional functions.
+ *
+ * @author John Sirois
+ */
+public final class ExceptionalFunctions {
+
+  private ExceptionalFunctions() {
+    // utility
+  }
+
+  /**
+   * Returns an {@link ExceptionalSupplier}/{@link java.util.concurrent.Callable} object that will
+   * return the result of {@code function} applied to {@code argument}.  Evaluation is lazy and
+   * un-memoized.
+   */
+  public static <S, T, E extends Exception> CallableExceptionalSupplier<T, E> curry(
+      final ExceptionalFunction<S, T, E> function, final S argument) {
+
+    return new CallableExceptionalSupplier<T, E>() {
+      @Override
+      public T get() throws E {
+        return function.apply(argument);
+      }
+    };
+  }
+
+  /**
+   * Returns an ExceptionalFunction that is a composition of multiple ExceptionalFunctions.
+   */
+  public static <T, E extends Exception> ExceptionalFunction<T, T, E> compose(
+      final Iterable<ExceptionalFunction<T, T, E>> functions) {
+    return new ExceptionalFunction<T, T, E>() {
+      @Override
+      public T apply(T input) throws E {
+        T result = input;
+        for (ExceptionalFunction<T, T, E> f : functions) {
+          result = f.apply(result);
+        }
+        return result;
+      }
+    };
+  }
+
+  /**
+   * Returns a List of ExceptionalFunctions from variable number of ExceptionalFunctions.
+   */
+  public static <T, E extends Exception> ExceptionalFunction<T, T, E> compose(
+      ExceptionalFunction<T, T, E> function, ExceptionalFunction<T, T, E>... functions) {
+    return compose(ImmutableList.<ExceptionalFunction<T, T, E>>builder()
+        .add(function)
+        .add(functions)
+        .build());
+  }
+
+  /**
+   * Returns a new ExceptionalFunction which composes two ExceptionalFunctions of compatible types.
+   *
+   * @param second function to apply to result of first.
+   * @param first function to apply to input item.
+   * @param <A> input type of first.
+   * @param <B> input type of second.
+   * @param <C> output type of second.
+   * @param <E> exception type.
+   * @return new composed ExceptionalFunction.
+   */
+  public static <A, B, C, E extends Exception> ExceptionalFunction<A, C, E> compose(
+      final ExceptionalFunction<B, C, ? extends E> second,
+      final ExceptionalFunction<A, ? extends B, ? extends E> first) {
+    return new ExceptionalFunction<A, C, E>() {
+      @Override
+      public C apply(A item) throws E {
+        return second.apply(first.apply(item));
+      }
+    };
+  }
+
+  /**
+   * Builds an ExceptionalFunction from {@link com.google.common.base.Function}.
+   *
+   * @param function guava Function.
+   * @param <S> input type.
+   * @param <T> output type.
+   * @param <E> exception type.
+   * @return new ExceptionalFunction.
+   */
+  public static <S, T, E extends Exception> ExceptionalFunction<S, T, E> forFunction(
+      final com.google.common.base.Function<S, T> function) {
+    return new ExceptionalFunction<S, T, E>() {
+      @Override
+      public T apply(S item) {
+        return function.apply(item);
+      }
+    };
+  }
+
+  /**
+   * Builds an ExceptionalFunction from a return value. The returned ExceptionalFunction will always
+   * return the given value.
+   *
+   * @param value value to return.
+   * @param <S> input type.
+   * @param <T> output type.
+   * @param <E> exception type.
+   * @return new ExceptionalFunction.
+   */
+  public static <S, T, E extends Exception> ExceptionalFunction<S, T, E> constant(
+      final T value) {
+    return new ExceptionalFunction<S, T, E>() {
+      @Override
+      public T apply(S item) throws E {
+        return value;
+      }
+    };
+  }
+
+  /**
+   * Builds an ExceptionalFunction from an Exception. The returned ExceptionalFunction will always
+   * throw the given Exception.
+   *
+   * @param exception exception to throw.
+   * @param <S> input type.
+   * @param <T> output type.
+   * @param <E> exception type.
+   * @return new ExceptionalFunction.
+   */
+  public static <S, T, E extends Exception> ExceptionalFunction<S, T, E> forException(
+      final E exception) {
+    return new ExceptionalFunction<S, T, E>() {
+      @Override
+      public T apply(S item) throws E {
+        throw exception;
+      }
+    };
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/ExceptionalSupplier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/ExceptionalSupplier.java b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalSupplier.java
new file mode 100644
index 0000000..27a4be4
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/ExceptionalSupplier.java
@@ -0,0 +1,33 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * An interface that captures a source of data.
+ *
+ * @param <T> The supplied value type.
+ * @param <E> The type of exception that the supplier throws.
+ *
+ * @author John Sirois
+ */
+public interface ExceptionalSupplier<T, E extends Exception> {
+
+  /**
+   * Supplies an item, possibly throwing {@code E} in the process of obtaining the item.
+   *
+   * @return the result of the computation
+   * @throws E if there was a problem performing the work
+   */
+  T get() throws E;
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Function.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Function.java b/commons/src/main/java/org/apache/aurora/common/base/Function.java
new file mode 100644
index 0000000..d089eb8
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Function.java
@@ -0,0 +1,29 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * A convenience typedef that also ties into google's {@code Function}.
+ *
+ * @param <S> The argument type for the function.
+ * @param <T> The return type for the function.
+ *
+ * @author John Sirois
+ */
+public interface Function<S, T>
+    extends ExceptionalFunction<S, T, RuntimeException>, com.google.common.base.Function<S, T> {
+
+  @Override
+  T apply(S item);
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/MorePreconditions.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/MorePreconditions.java b/commons/src/main/java/org/apache/aurora/common/base/MorePreconditions.java
new file mode 100644
index 0000000..1fe19d4
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/MorePreconditions.java
@@ -0,0 +1,144 @@
+/**
+ * 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.apache.aurora.common.base;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * A utility helpful in concisely checking preconditions on arguments.  This utility is a complement
+ * to {@link com.google.common.base.Preconditions}.
+ *
+ * @author John Sirois
+ */
+public final class MorePreconditions {
+
+  private static final String ARG_NOT_BLANK_MSG = "Argument cannot be blank";
+
+  private MorePreconditions() {
+    // utility
+  }
+
+  /**
+   * Checks that a string is both non-null and non-empty.
+   *
+   * @see #checkNotBlank(String, String, Object...)
+   */
+  public static String checkNotBlank(String argument) {
+    return checkNotBlank(argument, ARG_NOT_BLANK_MSG);
+  }
+
+  /**
+   * Checks that a string is both non-null and non-empty.
+   *
+   * @param argument the argument to validate
+   * @param message the message template for validation exception messages where %s serves as the
+   *     sole argument placeholder
+   * @param args any arguments needed by the message template
+   * @return the argument if it is valid
+   * @throws NullPointerException if the argument is null
+   * @throws IllegalArgumentException if the argument is the empty string or a pure whitespace
+   *    string
+   */
+  public static String checkNotBlank(String argument, String message, Object... args) {
+    Preconditions.checkNotNull(argument, message, args);
+    Preconditions.checkArgument(!StringUtils.isBlank(argument), message, args);
+    return argument;
+  }
+
+  /**
+   * Checks that an Iterable is both non-null and non-empty.  This method does not check individual
+   * elements in the Iterable.
+   *
+   * @see #checkNotBlank(Iterable, String, Object...)
+   */
+  public static <S, T extends Iterable<S>> T checkNotBlank(T argument) {
+    return checkNotBlank(argument, ARG_NOT_BLANK_MSG);
+  }
+
+  /**
+   * Checks that an Iterable is both non-null and non-empty.  This method does not check individual
+   * elements in the Iterable, it just checks that the Iterable has at least one element.
+   *
+   * @param argument the argument to validate
+   * @param message the message template for validation exception messages where %s serves as the
+   *     sole argument placeholder
+   * @param args any arguments needed by the message template
+   * @return the argument if it is valid
+   * @throws NullPointerException if the argument is null
+   * @throws IllegalArgumentException if the argument has no iterable elements
+   */
+  public static <S, T extends Iterable<S>> T checkNotBlank(T argument, String message,
+      Object... args) {
+    Preconditions.checkNotNull(argument, message, args);
+    Preconditions.checkArgument(!Iterables.isEmpty(argument), message, args);
+    return argument;
+  }
+
+  /**
+   * Checks that a double falls within a specified range, inclusive
+   *
+   * @param argument argument to validate.
+   * @param minimum minimum possible valid value for the argument.
+   * @param maximum maximum possible valid value for the argument.
+   * @param message the message template for validation exception messages where %s serves as the
+   *                sole argument placeholder.
+   * @return the argument if it is valid.
+   * @throws IllegalArgumentException if the argument falls outside of the specified range.
+   */
+  public static double checkArgumentRange(double argument, double minimum, double maximum,
+      String message) {
+    Preconditions.checkArgument(minimum <= argument, message, argument);
+    Preconditions.checkArgument(argument <= maximum, message, argument);
+    return argument;
+  }
+
+  /**
+   * Checks that an int falls within a specified range, inclusive
+   *
+   * @param argument argument to validate.
+   * @param minimum minimum possible valid value for the argument.
+   * @param maximum maximum possible valid value for the argument.
+   * @param message the message template for validation exception messages where %s serves as the
+   *                sole argument placeholder.
+   * @return the argument if it is valid.
+   * @throws IllegalArgumentException if the argument falls outside of the specified range.
+   */
+  public static int checkArgumentRange(int argument, int minimum, int maximum,
+      String message) {
+    Preconditions.checkArgument(minimum <= argument, message, argument);
+    Preconditions.checkArgument(argument <= maximum, message, argument);
+    return argument;
+  }
+
+  /**
+   * Checks that at least one of the specified arguments is true.
+   *
+   * @param message the message for validation exception messages.
+   * @param arguments one or more arguments to check.
+   * @return true if at least one of the arguments is true.
+   * @throws IllegalArgumentException if none of the arguments are true.
+   */
+  public static boolean checkArguments(String message,
+      Boolean... arguments) {
+    for (Boolean argument : arguments) {
+      if (argument) {
+        return true;
+      }
+    }
+    throw new IllegalArgumentException(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/MoreSuppliers.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/MoreSuppliers.java b/commons/src/main/java/org/apache/aurora/common/base/MoreSuppliers.java
new file mode 100644
index 0000000..9ab877d
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/MoreSuppliers.java
@@ -0,0 +1,103 @@
+/**
+ * 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.apache.aurora.common.base;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Utility methods for working with Suppliers.
+ *
+ * @author John Sirois
+ */
+public final class MoreSuppliers {
+
+  private MoreSuppliers() {
+    // utility
+  }
+
+  /**
+   * Creates a Supplier that uses the no-argument constructor of {@code type} to supply new
+   * instances.
+   *
+   * @param type the type of object this supplier creates
+   * @param <T> the type of object this supplier creates
+   * @return a Supplier that created a new obeject of type T on each call to {@link Supplier#get()}
+   * @throws IllegalArgumentException if the given {@code type} does not have a no-arg constructor
+   */
+  public static <T> Supplier<T> of(final Class<? extends T> type) {
+    Preconditions.checkNotNull(type);
+
+    try {
+      final Constructor<? extends T> constructor = getNoArgConstructor(type);
+      return new Supplier<T>() {
+        @Override public T get() {
+          try {
+            return constructor.newInstance();
+          } catch (InstantiationException e) {
+            throw instantiationFailed(e, type);
+          } catch (IllegalAccessException e) {
+            throw instantiationFailed(e, type);
+          } catch (InvocationTargetException e) {
+            throw instantiationFailed(e, type);
+          }
+        }
+      };
+    } catch (NoSuchMethodException e) {
+      throw new IllegalArgumentException("No accessible no-arg constructor for " + type, e);
+    }
+  }
+
+  private static RuntimeException instantiationFailed(Exception cause, Object type) {
+    return new RuntimeException("Could not create a new instance of type: " + type, cause);
+  }
+
+  private static <T> Constructor<T> getNoArgConstructor(Class<T> type)
+    throws NoSuchMethodException {
+
+    try {
+      Constructor<T> constructor = type.getConstructor();
+      if (!MoreSuppliers.class.getPackage().equals(type.getPackage())
+          && !Modifier.isPublic(type.getModifiers())) {
+        // Handle a public no-args constructor in a non-public class
+        constructor.setAccessible(true);
+      }
+      return constructor;
+    } catch (NoSuchMethodException e) {
+      Constructor<T> declaredConstructor = type.getDeclaredConstructor();
+      declaredConstructor.setAccessible(true);
+      return declaredConstructor;
+    }
+  }
+
+  /**
+   * Returns an {@link ExceptionalSupplier} that always supplies {@code item} without error.
+   *
+   * @param item The item to supply.
+   * @param <T> The type of item being supplied.
+   * @return A supplier that will always supply {@code item}.
+   */
+  public static <T> Supplier<T> ofInstance(@Nullable final T item) {
+    return new Supplier<T>() {
+      @Override public T get() {
+        return item;
+      }
+    };
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Supplier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Supplier.java b/commons/src/main/java/org/apache/aurora/common/base/Supplier.java
new file mode 100644
index 0000000..cb6e86a
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Supplier.java
@@ -0,0 +1,28 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * A convenience typedef that also ties into google's {@code Supplier}.
+ *
+ * @param <T> The supplied type.
+ *
+ * @author John Sirois
+ */
+public interface Supplier<T>
+    extends ExceptionalSupplier<T, RuntimeException>, com.google.common.base.Supplier<T> {
+
+  @Override
+  T get();
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/SupplierE.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/SupplierE.java b/commons/src/main/java/org/apache/aurora/common/base/SupplierE.java
new file mode 100644
index 0000000..ecad43e
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/SupplierE.java
@@ -0,0 +1,25 @@
+/**
+ * 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.apache.aurora.common.base;
+
+/**
+ * A convenience typedef for suppliers that throw multiple exception types.
+ *
+ * @param <T> The supplied type.
+ *
+ * @author John Sirois
+ */
+public interface SupplierE<T> extends ExceptionalSupplier<T, Exception> {
+  // typedef
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/collections/Bits.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/collections/Bits.java b/commons/src/main/java/org/apache/aurora/common/collections/Bits.java
new file mode 100644
index 0000000..f07e04a
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/collections/Bits.java
@@ -0,0 +1,116 @@
+/**
+ * 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.apache.aurora.common.collections;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Convenience class for doing bit-level operations on ints and longs.
+ *
+ * @author William Farner
+ */
+public final class Bits {
+
+  private static final int LSB = 0;
+  private static final int INT_MSB = 31;
+  private static final int LONG_MSB = 63;
+
+  private Bits() {
+    // Utility.
+  }
+
+  /**
+   * Tests whether a bit is set in an int value.
+   *
+   * @param value The bit field to test.
+   * @param bit The index of the bit to test, where bit 0 is the LSB.
+   * @return {@code true} if the bit is set, {@code false} otherwise.
+   */
+  public static boolean isBitSet(int value, int bit) {
+    Preconditions.checkState(bit >= LSB);
+    Preconditions.checkState(bit <= INT_MSB);
+    int mask = 1 << bit;
+    return (value & mask) != 0;
+  }
+
+  /**
+   * Tests whether a bit is set in a long value.
+   *
+   * @param value The bit field to test.
+   * @param bit The index of the bit to test, where bit 0 is the LSB.
+   * @return {@code true} if the bit is set, {@code false} otherwise.
+   */
+  public static boolean isBitSet(long value, int bit) {
+    Preconditions.checkState(bit >= LSB);
+    Preconditions.checkState(bit <= LONG_MSB);
+    long mask = 1L << bit;
+    return (value & mask) != 0;
+  }
+
+  /**
+   * Sets a bit in an int value.
+   *
+   * @param value The bit field to modify.
+   * @param bit The index of the bit to set, where bit 0 is the LSB.
+   * @return The original value, with the indexed bit set.
+   */
+  public static int setBit(int value, int bit) {
+    Preconditions.checkState(bit >= LSB);
+    Preconditions.checkState(bit <= INT_MSB);
+    int mask = 1 << bit;
+    return value | mask;
+  }
+
+  /**
+   * Sets a bit in a long value.
+   *
+   * @param value The bit field to modify.
+   * @param bit The index of the bit to set, where bit 0 is the LSB.
+   * @return The original value, with the indexed bit set.
+   */
+  public static long setBit(long value, int bit) {
+    Preconditions.checkState(bit >= LSB);
+    Preconditions.checkState(bit <= LONG_MSB);
+    long mask = 1L << bit;
+    return value | mask;
+  }
+
+  /**
+   * Clears a bit in an int value.
+   *
+   * @param value The bit field to modify.
+   * @param bit The index of the bit to clear, where bit 0 is the LSB.
+   * @return The original value, with the indexed bit clear.
+   */
+  public static int clearBit(int value, int bit) {
+    Preconditions.checkState(bit >= LSB);
+    Preconditions.checkState(bit <= INT_MSB);
+    int mask = ~setBit(0, bit);
+    return value & mask;
+  }
+
+  /**
+   * Clears a bit in a long value.
+   *
+   * @param value The bit field to modify.
+   * @param bit The index of the bit to clear, where bit 0 is the LSB.
+   * @return The original value, with the indexed bit clear.
+   */
+  public static long clearBit(long value, int bit) {
+    Preconditions.checkState(bit >= LSB);
+    Preconditions.checkState(bit <= LONG_MSB);
+    long mask = ~setBit(0L, bit);
+    return value & mask;
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/collections/BoundedQueue.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/collections/BoundedQueue.java b/commons/src/main/java/org/apache/aurora/common/collections/BoundedQueue.java
new file mode 100644
index 0000000..3e2d5fa
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/collections/BoundedQueue.java
@@ -0,0 +1,76 @@
+/**
+ * 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.apache.aurora.common.collections;
+
+import java.util.Iterator;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * A limited implementation of a bounded queue.  Values can be added and iterated over, and will
+ * automatically expire when the queue exceeds capacity.
+ *
+ * @param <T> The type that this queue contains.
+ *
+ * @author William Farner
+*/
+public class BoundedQueue<T> implements Iterable<T> {
+  private final LinkedBlockingDeque<T> values;
+
+  /**
+   * Creates a new bounded queue.
+   *
+   * @param limit Maximum number of items that can be in the queue at any time.
+   */
+  public BoundedQueue(int limit) {
+    values = new LinkedBlockingDeque<T>(limit);
+  }
+
+  /**
+   * Adds a value to head of the queue, evicting the oldest item if the queue is at capacity.
+   *
+   * @param value Value to add.
+   */
+  public synchronized void add(T value) {
+    if (values.remainingCapacity() == 0) {
+      values.removeFirst();
+    }
+    values.addLast(value);
+  }
+
+  /**
+   * Removes all values from the queue.
+   */
+  public synchronized void clear() {
+    values.clear();
+  }
+
+  /**
+   * Returns the size of the queue.
+   *
+   * @return The current queue length.
+   */
+  public synchronized int size() {
+    return values.size();
+  }
+
+  @Override
+  public synchronized Iterator<T> iterator() {
+    return values.iterator();
+  }
+
+  @Override
+  public synchronized String toString() {
+    return values.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/collections/Iterables2.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/collections/Iterables2.java b/commons/src/main/java/org/apache/aurora/common/collections/Iterables2.java
new file mode 100644
index 0000000..072159e
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/collections/Iterables2.java
@@ -0,0 +1,148 @@
+/**
+ * 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.apache.aurora.common.collections;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import com.google.common.base.Function;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * Utility functions for dealing with iterables.
+ *
+ * @author William Farner
+ */
+public final class Iterables2 {
+
+  private Iterables2() {
+    // Utility class.
+  }
+
+  /**
+   * An iterator that zips multiple iterables into a single list iterator, filling missing values
+   * with a provided default.
+   *
+   * @param <T> The value type for the iterator.
+   */
+  private static class ZippingIterator<T> implements Iterator<List<T>> {
+
+    private final Iterable<Iterable<T>> iterables;
+    private final T defaultValue;
+
+    private List<Iterator<T>> iterators = null;
+    private final LoadingCache<Iterator<T>, Boolean> overflowing = CacheBuilder.newBuilder().build(
+        new CacheLoader<Iterator<T>, Boolean>() {
+          @Override public Boolean load(Iterator<T> iterator) {
+            return false;
+          }
+        });
+
+    ZippingIterator(Iterable<Iterable<T>> iterables, T defaultValue) {
+      this.iterables = iterables;
+      this.defaultValue = defaultValue;
+    }
+
+    private void init() {
+      if (iterators == null) {
+        // Iterables -> Iterators.
+        iterators = ImmutableList.copyOf(Iterables.transform(iterables,
+            new Function<Iterable<T>, Iterator<T>>() {
+              @Override public Iterator<T> apply(Iterable<T> it) { return it.iterator(); }
+            }));
+      }
+    }
+
+    @Override public boolean hasNext() {
+      init();
+      for (Iterator<T> it : iterators) {
+        if (it.hasNext()) {
+          return true;
+        }
+      }
+
+      return false;
+    }
+
+    @Override public List<T> next() {
+      init();
+      List<T> data = new ArrayList<T>(iterators.size());
+
+      for (Iterator<T> it : iterators) {
+        if (it.hasNext()) {
+          data.add(it.next());
+        } else {
+          overflowing.asMap().put(it, true);
+          data.add(defaultValue);
+        }
+      }
+
+      return data;
+    }
+
+    @Override public void remove() {
+      init();
+      for (Iterator<T> it : iterators) {
+        if (!overflowing.getUnchecked(it)) {
+          it.remove();
+        }
+      }
+    }
+
+    @Override public String toString() {
+      return Lists.newArrayList(iterables).toString();
+    }
+  }
+
+  /**
+   * Zips multiple iterables into one iterable that will return iterators to step over
+   * rows of the input iterators (columns).  The order of the returned values within each row will
+   * match the ordering of the input iterables. The iterators will iterate the length of the longest
+   * input iterable, filling other columns with {@code defaultValue}.
+   * The returned iterator is lazy, in that 'rows' are constructed as they are requested.
+   *
+   * @param iterables Columns to iterate over.
+   * @param defaultValue Default fill value when an input iterable is exhausted.
+   * @param <T> Type of value being iterated over.
+   * @return An iterator that iterates over rows of the input iterables.
+   */
+  public static <T> Iterable<List<T>> zip(final Iterable<Iterable<T>> iterables,
+      final T defaultValue) {
+
+    return new Iterable<List<T>>() {
+      @Override public Iterator<List<T>> iterator() {
+        return new ZippingIterator<T>(iterables, defaultValue);
+      }
+    };
+  }
+
+  /**
+   * Varargs convenience function to call {@link #zip(Iterable, Object)}.
+   *
+   * @param defaultValue Default fill value when an input iterable is exhausted.
+   * @param iterables Columns to iterate over.
+   * @param <T> Type of value being iterated over.
+   * @return An iterator that iterates over rows of the input iterables.
+   */
+  public static <T> Iterable<List<T>> zip(T defaultValue, Iterable<T>... iterables) {
+    return zip(Arrays.asList(iterables), defaultValue);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/collections/Multimaps.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/collections/Multimaps.java b/commons/src/main/java/org/apache/aurora/common/collections/Multimaps.java
new file mode 100644
index 0000000..7f94a8a
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/collections/Multimaps.java
@@ -0,0 +1,134 @@
+/**
+ * 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.apache.aurora.common.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.Sets;
+
+/**
+ * Utility class for functions related to Multimaps in the java collections library.
+ *
+ * @author William Farner
+ */
+public final class Multimaps {
+
+  private Multimaps() {
+    // Utility.
+  }
+
+  /**
+   * Prunes a multimap based on a predicate, returning the pruned values.  The input map will be
+   * modified.
+   *
+   * @param map The multimap to prune.
+   * @param filterRule The pruning rule.  When the predicate returns {@code false} for an entry, it
+   *    will be pruned, otherwise it will be retained.
+   * @param <K> The key type in the multimap.
+   * @param <V> The value type in the multimap.
+   * @return A new multimap, containing the pruned keys/values.
+   */
+  public static <K, V> Multimap<K, V> prune(Multimap<K, V> map,
+      Predicate<? super Collection<V>> filterRule) {
+    Preconditions.checkNotNull(map);
+    Preconditions.checkNotNull(filterRule);
+    Multimap<K, V> pruned = ArrayListMultimap.create();
+    Iterator<Map.Entry<K, Collection<V>>> asMapItr = map.asMap().entrySet().iterator();
+    while (asMapItr.hasNext()) {
+      Map.Entry<K, Collection<V>> asMapEntry = asMapItr.next();
+      if (!filterRule.apply(asMapEntry.getValue())) {
+        pruned.putAll(asMapEntry.getKey(), asMapEntry.getValue());
+        asMapItr.remove();
+      }
+    }
+
+    return pruned;
+  }
+
+  private static final class AtLeastSize implements Predicate<Collection<?>> {
+    private final int minSize;
+
+    AtLeastSize(int minSize) {
+      Preconditions.checkArgument(minSize >= 0);
+      this.minSize = minSize;
+    }
+
+    @Override
+    public boolean apply(Collection<?> c) {
+      return c.size() >= minSize;
+    }
+  }
+
+  /**
+   * Convenience method to prune key/values pairs where the size of the value collection is below a
+   * threshold.
+   *
+   * @param map The multimap to prune.
+   * @param minSize The minimum size for retained value collections.
+   * @param <K> The key type in the multimap.
+   * @param <V> The value type in the multimap.
+   * @return A new multimap, containing the pruned keys/values.
+   * @throws IllegalArgumentException if minSize < 0
+   */
+  public static <K, V> Multimap<K, V> prune(Multimap<K, V> map, int minSize) {
+    return prune(map, new AtLeastSize(minSize));
+  }
+
+  /**
+   * Returns the set of keys associated with groups of a size greater than or equal to a given size.
+   *
+   * @param map The multimap to search.
+   * @param minSize The minimum size to return associated keys for.
+   * @param <K> The key type for the multimap.
+   * @return The keys associated with groups of size greater than or equal to {@code minSize}.
+   * @throws IllegalArgumentException if minSize < 0
+   */
+  public static <K> Set<K> getLargeGroups(Multimap<K, ?> map, int minSize) {
+    return Sets.newHashSet(
+        Maps.filterValues(map.asMap(), new AtLeastSize(minSize)).keySet());
+  }
+
+  /**
+   * Returns the set of keys associated with the largest values in the multimap.
+   *
+   * @param map The multimap to search.
+   * @param topValues Number of groupings to find the keys for.
+   * @return The keys associated with the largest groups, of maximum size {@code topValues}.
+   */
+  public static <K> Set<K> getLargestGroups(Multimap<K, ?> map, int topValues) {
+    Ordering<Multiset.Entry<K>> groupOrdering = new Ordering<Multiset.Entry<K>>() {
+      @Override
+      public int compare(Multiset.Entry<K> entry1, Multiset.Entry<K> entry2) {
+        return entry1.getCount() - entry2.getCount();
+        // overflow-safe, since sizes are nonnegative
+      }
+    };
+    Set<K> topKeys = Sets.newHashSetWithExpectedSize(topValues);
+    for (Multiset.Entry<K> entry
+         : groupOrdering.greatestOf(map.keys().entrySet(), topValues)) {
+      topKeys.add(entry.getElement());
+    }
+    return topKeys;
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/collections/Pair.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/collections/Pair.java b/commons/src/main/java/org/apache/aurora/common/collections/Pair.java
new file mode 100644
index 0000000..b1f9b63
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/collections/Pair.java
@@ -0,0 +1,127 @@
+/**
+ * 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.apache.aurora.common.collections;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+
+/**
+ * An immutable 2-tuple with value-equals semantics.
+ *
+ * @param <A> The type of the 1st item in the pair.
+ * @param <B> The type of the 2nd item in the pair.
+ *
+ * @author William Farner
+ */
+public class Pair<A, B> {
+
+  @Nullable
+  private final A first;
+  @Nullable
+  private final B second;
+
+  /**
+   * Creates a new pair.
+   *
+   * @param first The first value.
+   * @param second The second value.
+   */
+  public Pair(@Nullable A first, @Nullable B second) {
+    this.first = first;
+    this.second = second;
+  }
+
+  @Nullable
+  public A getFirst() {
+    return first;
+  }
+
+  @Nullable
+  public B getSecond() {
+    return second;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) { return true; }
+    if (!(o instanceof Pair)) { return false; }
+
+    Pair<?, ?> that = (Pair<?, ?>) o;
+    return new EqualsBuilder()
+        .append(this.first, that.first)
+        .append(this.second, that.second)
+        .isEquals();
+  }
+
+  @Override
+  public String toString() {
+    return String.format("(%s, %s)", getFirst(), getSecond());
+  }
+
+  @Override
+  public int hashCode() {
+    return new HashCodeBuilder()
+        .append(first)
+        .append(second)
+        .toHashCode();
+  }
+
+  /**
+   * Creates a function that can extract the first item of pairs of the given type parametrization.
+   *
+   * @param <S> The type of the 1st item in the pair.
+   * @param <T> The type of the 2nd item in the pair.
+   * @return A function that will extract the 1st item in a pair.
+   */
+  public static <S, T> Function<Pair<S, T>, S> first() {
+    return new Function<Pair<S, T>, S>() {
+      @Override public S apply(Pair<S, T> pair) {
+        return pair.first;
+      }
+    };
+  }
+
+  /**
+   * Creates a function that can extract the second item of pairs of the given type parametrization.
+   *
+   * @param <S> The type of the 1st item in the pair.
+   * @param <T> The type of the 2nd item in the pair.
+   * @return A function that will extract the 2nd item in a pair.
+   */
+  public static <S, T> Function<Pair<S, T>, T> second() {
+    return new Function<Pair<S, T>, T>() {
+      @Override public T apply(Pair<S, T> pair) {
+        return pair.second;
+      }
+    };
+  }
+
+  /**
+   * Convenience method to create a pair.
+   *
+   * @param a The first value.
+   * @param b The second value.
+   * @param <A> The type of the 1st item in the pair.
+   * @param <B> The type of the 2nd item in the pair.
+   * @return A new pair of [a, b].
+   */
+  public static <A, B> Pair<A, B> of(@Nullable A a, @Nullable B b) {
+    return new Pair<A, B>(a, b);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/common/webassets/bootstrap/BootstrapModule.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/common/webassets/bootstrap/BootstrapModule.java b/commons/src/main/java/org/apache/aurora/common/common/webassets/bootstrap/BootstrapModule.java
new file mode 100644
index 0000000..9cb6f54
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/common/webassets/bootstrap/BootstrapModule.java
@@ -0,0 +1,90 @@
+/**
+ * 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.apache.aurora.common.common.webassets.bootstrap;
+
+import com.google.common.io.Resources;
+import com.google.common.net.MediaType;
+import com.google.inject.AbstractModule;
+
+import org.apache.aurora.common.application.http.Registration;
+
+/**
+ * A binding module to register bootstrap HTTP assets.
+ */
+public final class BootstrapModule extends AbstractModule {
+  /**
+   * Enum for available Bootstrap versions to choose from.
+   */
+  public enum BootstrapVersion {
+    VERSION_2_1_1 ("2.1.1"),
+    VERSION_2_3_2 ("2.3.2");
+
+    private final String version;
+
+    BootstrapVersion(String s) {
+      version = s;
+    }
+  }
+
+  private final String version;
+
+  /**
+   * Default constructor.
+   */
+  public BootstrapModule() {
+    this(BootstrapVersion.VERSION_2_1_1);
+  }
+
+  /**
+   * BootstrapModule Constructor.
+   *
+   * @param version supplies the bootstrap version to select.
+   */
+  public BootstrapModule(BootstrapVersion version) {
+    this.version = version.version;
+  }
+
+  private void register(String mountPath, String resourcePath, String contentType) {
+    Registration.registerHttpAsset(
+        binder(),
+        "/" + mountPath,
+        Resources.getResource(BootstrapModule.class, resourcePath),
+        contentType,
+        true);
+  }
+
+  @Override
+  protected void configure() {
+    register(
+        "css/bootstrap-responsive.min.css",
+        version + "/css/bootstrap-responsive.min.css",
+        MediaType.CSS_UTF_8.toString());
+    register(
+        "css/bootstrap.min.css",
+        version + "/css/bootstrap.min.css",
+        MediaType.CSS_UTF_8.toString());
+    register(
+        "img/glyphicons-halflings-white.png",
+        version + "/img/glyphicons-halflings-white.png",
+        MediaType.PNG.toString());
+    register(
+        "img/glyphicons-halflings.png",
+        version + "/img/glyphicons-halflings.png",
+        MediaType.PNG.toString());
+    register(
+        "js/bootstrap.min.js",
+        version + "/js/bootstrap.min.js",
+        MediaType.JAVASCRIPT_UTF_8.toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/common/webassets/jquery/JQueryModule.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/common/webassets/jquery/JQueryModule.java b/commons/src/main/java/org/apache/aurora/common/common/webassets/jquery/JQueryModule.java
new file mode 100644
index 0000000..a8e4524
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/common/webassets/jquery/JQueryModule.java
@@ -0,0 +1,36 @@
+/**
+ * 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.apache.aurora.common.common.webassets.jquery;
+
+import com.google.common.io.Resources;
+import com.google.common.net.MediaType;
+import com.google.inject.AbstractModule;
+
+import org.apache.aurora.common.application.http.Registration;
+
+/**
+ * A binding module to register jQuery HTTP assets.
+ */
+public final class JQueryModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    Registration.registerHttpAsset(
+        binder(),
+        "/js/jquery.min.js",
+        Resources.getResource(JQueryModule.class, "js/jquery-1.8.2.min.js"),
+        MediaType.JAVASCRIPT_UTF_8.toString(),
+        true);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/inject/Bindings.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/inject/Bindings.java b/commons/src/main/java/org/apache/aurora/common/inject/Bindings.java
new file mode 100644
index 0000000..f910f22
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/inject/Bindings.java
@@ -0,0 +1,316 @@
+/**
+ * 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.apache.aurora.common.inject;
+
+import java.lang.annotation.Annotation;
+
+import javax.inject.Qualifier;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.PrivateModule;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+
+/**
+ * A utility that helps with guice bindings.
+ *
+ * @author John Sirois
+ */
+public final class Bindings {
+
+
+  private Bindings() {
+    // utility
+  }
+
+  /**
+   * Equivalent to calling {@code requireBinding(binder, Key.get(required, Names.named(namedKey)))}.
+   */
+  public static void requireNamedBinding(Binder binder, Class<?> required, String namedKey) {
+    requireBinding(binder, Key.get(Preconditions.checkNotNull(required),
+        Names.named(Preconditions.checkNotNull(namedKey))));
+  }
+
+  /**
+   * Equivalent to calling {@code requireBinding(binder, Key.get(required))}.
+   */
+  public static void requireBinding(Binder binder, Class<?> required) {
+    requireBinding(binder, Key.get(Preconditions.checkNotNull(required)));
+  }
+
+  /**
+   * Registers {@code required} as non-optional dependency in the {@link com.google.inject.Injector}
+   * associated with {@code binder}.
+   *
+   * @param binder A binder to require bindings against.
+   * @param required The dependency that is required.
+   */
+  public static void requireBinding(Binder binder, final Key<?> required) {
+    Preconditions.checkNotNull(binder);
+    Preconditions.checkNotNull(required);
+
+    binder.install(new AbstractModule() {
+      @Override protected void configure() {
+        requireBinding(required);
+      }
+    });
+  }
+
+  /**
+   * A convenient version of {@link #exposing(Iterable, com.google.inject.Module)} when you just
+   * want to expose a single binding.
+   */
+  public static Module exposing(Key<?> key, Module module) {
+    return exposing(ImmutableList.of(key), module);
+  }
+
+  /**
+   * Creates a module that hides all the given module's bindings and only exposes bindings for
+   * the given key.
+   *
+   * @param keys The keys of the bindings to expose.
+   * @param module The module to hide most bindings for.
+   * @return A limited visibility module.
+   */
+  public static Module exposing(final Iterable<? extends Key<?>> keys, final Module module) {
+    Preconditions.checkNotNull(keys);
+    Preconditions.checkNotNull(module);
+
+    return new PrivateModule() {
+      @Override protected void configure() {
+        install(module);
+        for (Key<?> key : keys) {
+          expose(key);
+        }
+      }
+    };
+  }
+
+  /**
+   * A guice binding helper that allows for any combination of Class, TypeLiteral or Key binding
+   * without forcing guiced implementation to provide all the overloaded binding methods they would
+   * otherwise have to.
+   *
+   * @param <T> The type this helper can be used to bind implementations for.
+   */
+  public interface BindHelper<T> {
+
+    /**
+     * Associates this BindHelper with an Injector instance.
+     *
+     * @param binder The binder for the injector implementations will be bound in.
+     * @return A binding builder that can be used to bind an implementation with.
+     */
+    LinkedBindingBuilder<T> with(Binder binder);
+  }
+
+  /**
+   * Creates a BindHelper for the given binding key that can be used to bind a single instance.
+   *
+   * @param key The binding key the returned BindHelper can be use to bind implementations for.
+   * @param <T> The type the returned BindHelper can be used to bind implementations for.
+   * @return A BindHelper that can be used to bind an implementation with.
+   */
+  public static <T> BindHelper<T> binderFor(final Key<T> key) {
+    return new BindHelper<T>() {
+      public LinkedBindingBuilder<T> with(Binder binder) {
+        return binder.bind(key);
+      }
+    };
+  }
+
+  /**
+   * Creates a BindHelper for the given type that can be used to add a binding of to a set.
+   *
+   * @param type The type the returned BindHelper can be use to bind implementations for.
+   * @param <T> The type the returned BindHelper can be used to bind implementations for.
+   * @return A BindHelper that can be used to bind an implementation with.
+   */
+  public static <T> BindHelper<T> multiBinderFor(final Class<T> type) {
+    return new BindHelper<T>() {
+      public LinkedBindingBuilder<T> with(Binder binder) {
+        return Multibinder.newSetBinder(binder, type).addBinding();
+      }
+    };
+  }
+
+  /**
+   * Checks that the given annotation instance is a {@link BindingAnnotation @BindingAnnotation}.
+   *
+   * @param annotation The annotation instance to check.
+   * @param <T> The type of the binding annotation.
+   * @return The checked binding annotation.
+   * @throws NullPointerException If the given {@code annotation} is null.
+   * @throws IllegalArgumentException If the given {@code annotation} is not a
+   *     {@literal @BindingAnnotation}.
+   */
+  public static <T extends Annotation> T checkBindingAnnotation(T annotation) {
+    Preconditions.checkNotNull(annotation);
+    checkBindingAnnotation(annotation.annotationType());
+    return annotation;
+  }
+
+  /**
+   * Checks that the given annotation type is a {@link BindingAnnotation @BindingAnnotation}.
+   *
+   * @param annotationType The annotation type to check.
+   * @param <T> The type of the binding annotation.
+   * @return The checked binding annotation type.
+   * @throws NullPointerException If the given {@code annotationType} is null.
+   * @throws IllegalArgumentException If the given {@code annotationType} is not a
+   *     {@literal @BindingAnnotation}.
+   */
+  public static <T extends Annotation> Class<T> checkBindingAnnotation(Class<T> annotationType) {
+    Preconditions.checkNotNull(annotationType);
+    boolean bindingAnnotation = annotationType.isAnnotationPresent(BindingAnnotation.class);
+    boolean qualifier = annotationType.isAnnotationPresent(Qualifier.class);
+    Preconditions.checkArgument(bindingAnnotation || qualifier,
+        "%s is not a @BindingAnnotation or @Qualifier", annotationType);
+    return annotationType;
+  }
+
+  /**
+   * A factory for binding {@link Key keys}.
+   */
+  public interface KeyFactory {
+
+    /**
+     * Creates plain un-annotated keys.
+     */
+    KeyFactory PLAIN = new KeyFactory() {
+      @Override public <T> Key<T> create(Class<T> type) {
+        return Key.get(type);
+      }
+      @Override public <T> Key<T> create(TypeLiteral<T> type) {
+        return Key.get(type);
+      }
+    };
+
+    /**
+     * Creates a key for the given type.
+     *
+     * @param type The type to create a key for.
+     * @param <T> The keyed type.
+     * @return A key.
+     */
+    <T> Key<T> create(Class<T> type);
+
+    /**
+     * Creates a key for the given type.
+     *
+     * @param type The type to create a key for.
+     * @param <T> The keyed type.
+     * @return A key.
+     */
+    <T> Key<T> create(TypeLiteral<T> type);
+  }
+
+  /**
+   * Creates a key factory that produces keys for a given annotation instance.
+   *
+   * @param annotation The annotation instance to apply to all keys.
+   * @return A key factory that creates annotated keys.
+   */
+  public static KeyFactory annotatedKeyFactory(final Annotation annotation) {
+    checkBindingAnnotation(annotation);
+    return new KeyFactory() {
+      @Override public <T> Key<T> create(Class<T> type) {
+        return Key.get(type, annotation);
+      }
+      @Override public <T> Key<T> create(TypeLiteral<T> type) {
+        return Key.get(type, annotation);
+      }
+    };
+  }
+
+  /**
+   * Creates a key factory that produces keys for a given annotation type.
+   *
+   * @param annotationType The annotation type to apply to all keys.
+   * @return A key factory that creates annotated keys.
+   */
+  public static KeyFactory annotatedKeyFactory(final Class<? extends Annotation> annotationType) {
+    checkBindingAnnotation(annotationType);
+    return new KeyFactory() {
+      @Override public <T> Key<T> create(Class<T> type) {
+        return Key.get(type, annotationType);
+      }
+      @Override public <T> Key<T> create(TypeLiteral<T> type) {
+        return Key.get(type, annotationType);
+      }
+    };
+  }
+
+  /**
+   * A utility that helps rebind keys.
+   */
+  public static final class Rebinder {
+    private final Binder binder;
+    private final KeyFactory bindToFactory;
+
+    /**
+     * Creates a Rebinder that links bindings to keys from the given {@code bindToFactory}.
+     *
+     * @param binder A binder to rebind keys in.
+     * @param bindToFactory A factory for the rebinding key.
+     */
+    public Rebinder(Binder binder, KeyFactory bindToFactory) {
+      this.binder = Preconditions.checkNotNull(binder);
+      this.bindToFactory = Preconditions.checkNotNull(bindToFactory);
+    }
+
+    /**
+     * Rebinds the given key to another, linking bindings.
+     *
+     * @param fromKey The source key to rebind.
+     * @return The key that {@code key} was rebound to.
+     */
+    public <T> Key<T> rebind(Key<T> fromKey) {
+      Key<T> toKey = bindToFactory.create(fromKey.getTypeLiteral());
+      binder.bind(toKey).to(fromKey);
+      requireBinding(binder, fromKey);
+      return toKey;
+    }
+  }
+
+  /**
+   * Creates a Rebinder that rebinds keys to the given annotation instance.
+   *
+   * @param binder A binder to rebind keys in.
+   * @param annotation The annotation instance to rebind keys to.
+   * @return A Rebinder targeting the given {@code annotationType}.
+   */
+  public static Rebinder rebinder(Binder binder, Annotation annotation) {
+    return new Rebinder(binder, annotatedKeyFactory(annotation));
+  }
+
+  /**
+   * Creates a Rebinder that rebinds keys to the given annotation type.
+   *
+   * @param binder A binder to rebind keys in.
+   * @param annotationType The annotation type to rebind keys to.
+   * @return A Rebinder targeting the given {@code annotationType}.
+   */
+  public static Rebinder rebinder(Binder binder, Class<? extends Annotation> annotationType) {
+    return new Rebinder(binder, annotatedKeyFactory(annotationType));
+  }
+}


Mime
View raw message