You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by zm...@apache.org on 2015/08/26 23:00:19 UTC

[29/51] [partial] aurora git commit: Move packages from com.twitter.common to org.apache.aurora.common

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/IsDirectoryFileVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/IsDirectoryFileVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/IsDirectoryFileVerifier.java
new file mode 100644
index 0000000..968a098
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/IsDirectoryFileVerifier.java
@@ -0,0 +1,40 @@
+/**
+ * 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.args.constraints;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Verifier to ensure that a file is a directory.
+ *
+ * @author William Farner
+ */
+@VerifierFor(IsDirectory.class)
+public class IsDirectoryFileVerifier implements Verifier<File> {
+  @Override
+  public void verify(File value, Annotation annotation) {
+    checkArgument(value.isDirectory(), "Must be a directory.");
+  }
+
+  @Override
+  public String toString(Class<? extends File> argType, Annotation annotation) {
+    return "file must be a directory";
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmpty.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmpty.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmpty.java
new file mode 100644
index 0000000..8ff96af
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmpty.java
@@ -0,0 +1,30 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation that indicates that an entity is non-empty.
+ *
+ * @author William Farner
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface NotEmpty {
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyIterableVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyIterableVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyIterableVerifier.java
new file mode 100644
index 0000000..222bdb2
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyIterableVerifier.java
@@ -0,0 +1,41 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Annotation;
+
+import com.google.common.collect.Iterables;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Verifies that an iterable is not empty.
+ *
+ * @author William Farner
+ */
+@VerifierFor(NotEmpty.class)
+public class NotEmptyIterableVerifier implements Verifier<Iterable<?>> {
+  @Override
+  public void verify(Iterable<?> value, Annotation annotation) {
+    checkArgument(!Iterables.isEmpty(value), "Value must not be empty.");
+  }
+
+  @Override
+  public String toString(Class<? extends Iterable<?>> argType, Annotation annotation) {
+    return "must have at least 1 item";
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyStringVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyStringVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyStringVerifier.java
new file mode 100644
index 0000000..4384a97
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotEmptyStringVerifier.java
@@ -0,0 +1,39 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Verifier to ensure that a string is not empty.
+ *
+ * @author William Farner
+ */
+@VerifierFor(NotEmpty.class)
+public class NotEmptyStringVerifier implements Verifier<String> {
+  @Override
+  public void verify(String s, Annotation annotation) {
+    checkArgument(!s.isEmpty(), "Value must not be empty.");
+  }
+
+  @Override
+  public String toString(Class<? extends String> argType, Annotation annotation) {
+    return "must be non-empty";
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegative.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegative.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegative.java
new file mode 100644
index 0000000..1c1573f
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegative.java
@@ -0,0 +1,30 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation that indicates that an entity is non-negative.
+ *
+ * @author William Farner
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface NotNegative {
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegativeNumberVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegativeNumberVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegativeNumberVerifier.java
new file mode 100644
index 0000000..9309224
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNegativeNumberVerifier.java
@@ -0,0 +1,39 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Verifier to ensure that a number is non-negative.
+ *
+ * @author William Farner
+ */
+@VerifierFor(NotNegative.class)
+public class NotNegativeNumberVerifier implements Verifier<Number> {
+  @Override
+  public void verify(Number number, Annotation annotation) {
+    checkArgument(number.doubleValue() >= 0, "Value must be non-negative.");
+  }
+
+  @Override
+  public String toString(Class<? extends Number> argType, Annotation annotation) {
+    return "must be >= 0";
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNull.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNull.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNull.java
new file mode 100644
index 0000000..57936be
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNull.java
@@ -0,0 +1,30 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation to indicate that an entity must be non-null.
+ *
+ * @author William Farner
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface NotNull {
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNullVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNullVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNullVerifier.java
new file mode 100644
index 0000000..5366986
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/NotNullVerifier.java
@@ -0,0 +1,39 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * A verifier that ensures a value is non-null.
+ *
+ * @author William Farner
+ */
+@VerifierFor(NotNull.class)
+public class NotNullVerifier implements Verifier<Object> {
+  @Override
+  public void verify(Object value, Annotation annotation) {
+    checkArgument(value != null, "Value must not be null.");
+  }
+
+  @Override
+  public String toString(Class<?> argType, Annotation annotation) {
+    return "not null";
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/Positive.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/Positive.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/Positive.java
new file mode 100644
index 0000000..2c91f4a
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/Positive.java
@@ -0,0 +1,30 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation that indicates an entity must be positive.
+ *
+ * @author William Farner
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface Positive {
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/PositiveNumberVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/PositiveNumberVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/PositiveNumberVerifier.java
new file mode 100644
index 0000000..95f8857
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/PositiveNumberVerifier.java
@@ -0,0 +1,39 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Verifier to ensure that a number is positive.
+ *
+ * @author William Farner
+ */
+@VerifierFor(Positive.class)
+public class PositiveNumberVerifier implements Verifier<Number> {
+  @Override
+  public void verify(Number number, Annotation annotation) {
+    checkArgument(number.doubleValue() > 0, "Value must be positive.");
+  }
+
+  @Override
+  public String toString(Class<? extends Number> argType, Annotation annotation) {
+    return "must be > 0";
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/Range.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/Range.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/Range.java
new file mode 100644
index 0000000..71ceb6a
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/Range.java
@@ -0,0 +1,40 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation that indicates a field must be within a given numeric range.
+ *
+ * @author William Farner
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface Range {
+
+  /**
+   * The lower bound on the acceptable range (inclusive).
+   */
+  double lower();
+
+  /**
+   * The upper bound on the acceptable range (inclusive).
+   */
+  double upper();
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/constraints/RangeNumberVerifier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/constraints/RangeNumberVerifier.java b/commons/src/main/java/org/apache/aurora/common/args/constraints/RangeNumberVerifier.java
new file mode 100644
index 0000000..2725094
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/constraints/RangeNumberVerifier.java
@@ -0,0 +1,74 @@
+/**
+ * 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.args.constraints;
+
+import java.lang.annotation.Annotation;
+import java.math.BigDecimal;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Verifies that a number (inclusively) lies within a range.
+ *
+ * @author William Farner
+ */
+@VerifierFor(Range.class)
+public class RangeNumberVerifier implements Verifier<Number> {
+  @Override
+  public void verify(Number value, Annotation annotation) {
+    Range range = getRange(annotation);
+
+    checkArgument(range.lower() < range.upper(),
+        "Range lower bound must be greater than upper bound.");
+
+    double dblValue = value.doubleValue();
+    checkArgument(dblValue >= range.lower() && dblValue <= range.upper(),
+        String.format("Value must be in range [%f, %f]", range.lower(), range.upper()));
+  }
+
+  @Override
+  public String toString(Class<? extends Number> argType, Annotation annotation) {
+    Range range = getRange(annotation);
+
+    Function<Number, Number> converter;
+    if (Float.class.isAssignableFrom(argType)
+        || Double.class.isAssignableFrom(argType)
+        || BigDecimal.class.isAssignableFrom(argType)) {
+
+      converter = Functions.identity();
+    } else {
+      converter = new Function<Number, Number>() {
+        @Override public Number apply(Number item) {
+          return item.longValue();
+        }
+      };
+    }
+
+    return String.format("must be >= %s and <= %s",
+                         converter.apply(range.lower()),
+                         converter.apply(range.upper()));
+  }
+
+  private Range getRange(Annotation annotation) {
+    checkArgument(annotation instanceof Range, "Annotation is not a range: " + annotation);
+
+    return (Range) annotation;
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/AmountParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/AmountParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/AmountParser.java
new file mode 100644
index 0000000..1eb42bb
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/AmountParser.java
@@ -0,0 +1,86 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.common.reflect.TypeToken;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.quantity.Amount;
+import org.apache.aurora.common.quantity.Unit;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Amount parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class AmountParser extends TypeParameterizedParser<Amount<?, ?>> {
+
+  private static final Pattern AMOUNT_PATTERN = Pattern.compile("(\\d+)([A-Za-z]+)");
+
+  public AmountParser() {
+    super(2);
+  }
+
+  @Override
+  Amount<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> typeParams) {
+    Type valueType = typeParams.get(0);
+    Parser<?> parser = parserOracle.get(TypeToken.of(valueType));
+
+    Matcher matcher = AMOUNT_PATTERN.matcher(raw);
+    checkArgument(matcher.matches(),
+        "Value '" + raw + "' must be of the format 1ns, 4mb, etc.");
+
+    Number number = (Number) parser.parse(parserOracle, valueType, matcher.group(1));
+    String unitRaw = matcher.group(2);
+
+    Type unitType = typeParams.get(1);
+    @SuppressWarnings("rawtypes")
+    Parser<Unit> unitParser = parserOracle.get(TypeToken.of(Unit.class));
+    @SuppressWarnings("rawtypes")
+    Unit unit = unitParser.parse(parserOracle, unitType, unitRaw);
+    checkArgument(unit.getClass() == unitType, String.format(
+        "Unit type (%s) does not match argument type (%s).",
+        unit.getClass(), unitType));
+
+    return create(valueType, number, unit);
+  }
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  private static Amount<?, ?> create(Type valueType, Number number, Unit unit) {
+    if (valueType == Integer.class) {
+      return Amount.of(number.intValue(), unit);
+    } else if (valueType == Double.class) {
+      return Amount.of(number.doubleValue(), unit);
+    } else if (valueType == Long.class) {
+      return Amount.of(number.longValue(), unit);
+    } else if (valueType == Byte.class) {
+      return Amount.of(number.byteValue(), unit);
+    } else if (valueType == Short.class) {
+      return Amount.of(number.shortValue(), unit);
+    } else if (valueType == Float.class) {
+      return Amount.of(number.floatValue(), unit);
+    }
+    throw new IllegalArgumentException("Unrecognized number class " + valueType);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/BooleanParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/BooleanParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/BooleanParser.java
new file mode 100644
index 0000000..9ceb148
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/BooleanParser.java
@@ -0,0 +1,30 @@
+/**
+ * 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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Boolean parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class BooleanParser extends NonParameterizedTypeParser<Boolean> {
+  @Override
+  public Boolean doParse(String raw) {
+    // Magic boolean syntax, no argument value means true.
+    return raw.isEmpty() || Boolean.parseBoolean(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/ByteParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/ByteParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/ByteParser.java
new file mode 100644
index 0000000..64ee998
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/ByteParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Byte parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ByteParser extends NumberParser<Byte> {
+  @Override
+  Byte parseNumber(String raw) {
+    return Byte.parseByte(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/CharacterParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/CharacterParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/CharacterParser.java
new file mode 100644
index 0000000..c236357
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/CharacterParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Character parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class CharacterParser extends NonParameterizedTypeParser<Character> {
+  @Override
+  public Character doParse(String raw) {
+    checkArgument(raw.length() == 1,
+        "String " + raw + " cannot be assigned to a character.");
+    return raw.charAt(0);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/ClassParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/ClassParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/ClassParser.java
new file mode 100644
index 0000000..27f71a8
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/ClassParser.java
@@ -0,0 +1,48 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.args.TypeUtil;
+
+/**
+ * Class parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ClassParser extends TypeParameterizedParser<Class<?>> {
+
+  public ClassParser() {
+    super(1);
+  }
+
+  @Override
+  public Class<?> doParse(ParserOracle parserOracle, String raw, final List<Type> typeParams) {
+    Class<?> rawClassType = TypeUtil.getRawType(typeParams.get(0));
+    try {
+      Class<?> actualClass = Class.forName(raw);
+      Preconditions.checkArgument(rawClassType.isAssignableFrom(actualClass));
+      return actualClass;
+    } catch (ClassNotFoundException e) {
+      throw new IllegalArgumentException("Could not find class " + raw);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/DateParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/DateParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/DateParser.java
new file mode 100644
index 0000000..a2ee8f9
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/DateParser.java
@@ -0,0 +1,41 @@
+/**
+ * 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.args.parsers;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Date parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class DateParser extends NonParameterizedTypeParser<Date> {
+
+  private static final String FORMAT = "MM/dd/yyyy HH:mm";
+  private static final SimpleDateFormat SIMPLE_FORMAT = new SimpleDateFormat(FORMAT);
+
+  @Override
+  public Date doParse(String raw) {
+    try {
+      return SIMPLE_FORMAT.parse(raw);
+    } catch (ParseException e) {
+      throw new IllegalArgumentException("Failed to parse " + raw + " in format " + FORMAT);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/DoubleParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/DoubleParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/DoubleParser.java
new file mode 100644
index 0000000..6232437
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/DoubleParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Double parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class DoubleParser extends NumberParser<Double> {
+  @Override
+  Double parseNumber(String raw) {
+    return Double.parseDouble(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/DurationParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/DurationParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/DurationParser.java
new file mode 100644
index 0000000..7bf5578
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/DurationParser.java
@@ -0,0 +1,80 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import com.google.common.base.Preconditions;
+
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.quantity.Amount;
+import org.apache.aurora.common.quantity.Time;
+
+/**
+ * Utility class for parsing durations of the form "1d23h59m59s" (as well as subvariants, i.e.
+ * "10h5s" would also work, as would "2d"). These values are useful representations in HTTP query
+ * parameters for durations.
+ *
+ */
+public class DurationParser extends TypeParameterizedParser<Amount<?, ?>> {
+
+  private static final String SUFFIXES = "dhms";
+  private static final Time[] TIME_UNITS = {Time.DAYS, Time.HOURS, Time.MINUTES, Time.SECONDS};
+
+  public DurationParser() {
+    super(2);
+  }
+
+  @Override
+  Amount<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> paramParsers)
+      throws IllegalArgumentException {
+    Type secondParamClass = paramParsers.get(1);
+    Preconditions.checkArgument(
+        secondParamClass == Time.class,
+        String.format("Expected %s for "
+            + "second type parameter, but got got %s", Time.class.getName(),
+            secondParamClass));
+    return parse(raw);
+  }
+
+  /**
+   * Parses a duration of the form "1d23h59m59s" (as well as subvariants, i.e. "10h5s" would also
+   * work, as would "2d").
+   *
+   * @param spec the textual duration specification
+   * @return the parsed form
+   * @throws IllegalArgumentException if the specification can not be parsed
+   */
+  public static Amount<Long, Time> parse(String spec) {
+    long time = 0L;
+    final List<Object> tokens = Collections.list(new StringTokenizer(spec, SUFFIXES, true));
+    Preconditions.checkArgument(tokens.size() > 1);
+    for (int i = 1; i < tokens.size(); i += 2) {
+      final String token = (String) tokens.get(i);
+      Preconditions.checkArgument(token.length() == 1, "Too long suffix '%s'", token);
+      final int suffixIndex = SUFFIXES.indexOf(token.charAt(0));
+      Preconditions.checkArgument(suffixIndex != -1, "Unrecognized suffix '%s'", token);
+      try {
+        final int value = Integer.parseInt((String) tokens.get(i - 1));
+        time += Amount.of(value, TIME_UNITS[suffixIndex]).as(Time.SECONDS);
+      } catch (NumberFormatException e) {
+        Preconditions.checkArgument(false, "Invalid number %s", tokens.get(i - 1));
+      }
+    }
+    return Amount.of(time, Time.SECONDS);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/EnumParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/EnumParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/EnumParser.java
new file mode 100644
index 0000000..9f6a3ff
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/EnumParser.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.args.parsers;
+
+import java.lang.reflect.Type;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+
+/**
+ * An {@link Enum} parser that matches enum values via {@link Enum#valueOf(Class, String)}.
+ *
+ * @author John Sirois
+ */
+@ArgParser
+public class EnumParser<T extends Enum<T>> implements Parser<T> {
+
+  @Override
+  public T parse(ParserOracle parserOracle, Type type, String raw) throws IllegalArgumentException {
+    @SuppressWarnings("unchecked")
+    Class<T> enumClass = (Class<T>) type;
+    return Enum.valueOf(enumClass, raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/FileParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/FileParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/FileParser.java
new file mode 100644
index 0000000..c8573f5
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/FileParser.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.args.parsers;
+
+import java.io.File;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * File parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class FileParser extends NonParameterizedTypeParser<File> {
+  @Override
+  public File doParse(String raw) {
+    return new File(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/FloatParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/FloatParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/FloatParser.java
new file mode 100644
index 0000000..7ceb110
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/FloatParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Float parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class FloatParser extends NumberParser<Float> {
+  @Override
+  Float parseNumber(String raw) {
+    return Float.parseFloat(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/InetSocketAddressParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/InetSocketAddressParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/InetSocketAddressParser.java
new file mode 100644
index 0000000..dfa441e
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/InetSocketAddressParser.java
@@ -0,0 +1,32 @@
+/**
+ * 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.args.parsers;
+
+import java.net.InetSocketAddress;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.net.InetSocketAddressHelper;
+
+/**
+ * InetSocketAddress parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class InetSocketAddressParser extends NonParameterizedTypeParser<InetSocketAddress> {
+  @Override
+  public InetSocketAddress doParse(String raw) {
+    return InetSocketAddressHelper.parse(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/IntegerParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/IntegerParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/IntegerParser.java
new file mode 100644
index 0000000..275d121
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/IntegerParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Integer parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class IntegerParser extends NumberParser<Integer> {
+  @Override
+  Integer parseNumber(String raw) {
+    return Integer.parseInt(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/ListParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/ListParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/ListParser.java
new file mode 100644
index 0000000..02c10ed
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/ListParser.java
@@ -0,0 +1,52 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.args.Parsers;
+
+/**
+ * List parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ListParser extends TypeParameterizedParser<List<?>> {
+
+  public ListParser() {
+    super(1);
+  }
+
+  @Override
+  List<?> doParse(final ParserOracle parserOracle, String raw, final List<Type> typeParams) {
+    final Type listType = typeParams.get(0);
+    final Parser<?> parser = parserOracle.get(TypeToken.of(listType));
+    return ImmutableList.copyOf(Iterables.transform(Parsers.MULTI_VALUE_SPLITTER.split(raw),
+        new Function<String, Object>() {
+          @Override public Object apply(String raw) {
+            return parser.parse(parserOracle, listType, raw);
+          }
+        }));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/LongParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/LongParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/LongParser.java
new file mode 100644
index 0000000..95f92b8
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/LongParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Long parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class LongParser extends NumberParser<Long> {
+  @Override
+  Long parseNumber(String raw) {
+    return Long.parseLong(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/MapParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/MapParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/MapParser.java
new file mode 100644
index 0000000..3e1c916
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/MapParser.java
@@ -0,0 +1,68 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.args.Parsers;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Map parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class MapParser extends TypeParameterizedParser<Map<?, ?>> {
+
+  private static final Splitter KEY_VALUE_SPLITTER =
+      Splitter.on("=").trimResults().omitEmptyStrings();
+
+  public MapParser() {
+    super(2);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  Map<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> typeParams) {
+    Type keyType = typeParams.get(0);
+    Parser<?> keyParser = parserOracle.get(TypeToken.of(keyType));
+
+    Type valueType = typeParams.get(1);
+    Parser<?> valueParser = parserOracle.get(TypeToken.of(valueType));
+
+    ImmutableMap.Builder<Object, Object> map = ImmutableMap.builder();
+    for (String keyAndValue : Parsers.MULTI_VALUE_SPLITTER.split(raw)) {
+      List<String> fields = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyAndValue));
+      checkArgument(fields.size() == 2,
+          "Failed to parse key/value pair " + keyAndValue);
+
+      map.put(keyParser.parse(parserOracle, keyType, fields.get(0)),
+              valueParser.parse(parserOracle, valueType, fields.get(1)));
+    }
+
+    return map.build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/NonParameterizedTypeParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/NonParameterizedTypeParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/NonParameterizedTypeParser.java
new file mode 100644
index 0000000..c77543c
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/NonParameterizedTypeParser.java
@@ -0,0 +1,41 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+
+/**
+ * Base class for parsers of types that are not parameterized.
+ *
+ * @author William Farner
+ */
+public abstract class NonParameterizedTypeParser<T> implements Parser<T> {
+
+  /**
+   * Performs the parsing of the raw string.
+   *
+   * @param raw Value to parse.
+   * @return The parsed value.
+   * @throws IllegalArgumentException If the value could not be parsed into the target type.
+   */
+  public abstract T doParse(String raw) throws IllegalArgumentException;
+
+  @Override
+  public T parse(ParserOracle parserOracle, Type type, String raw) throws IllegalArgumentException {
+    return doParse(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/NumberParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/NumberParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/NumberParser.java
new file mode 100644
index 0000000..a551fa9
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/NumberParser.java
@@ -0,0 +1,41 @@
+/**
+ * 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.args.parsers;
+
+/**
+ * Parser that handles common functionality for parsing numbers.
+ *
+ * @author William Farner
+ */
+public abstract class NumberParser<T extends Number> extends NonParameterizedTypeParser<T> {
+
+  /**
+   * Performs the actual parsing of the value into the target type.
+   *
+   * @param raw Raw value to parse.
+   * @return The parsed value.
+   * @throws NumberFormatException If the raw value does not represent a valid number of the target
+   *    type.
+   */
+  abstract T parseNumber(String raw) throws NumberFormatException;
+
+  @Override
+  public T doParse(String raw) throws IllegalArgumentException {
+    try {
+      return parseNumber(raw);
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException(String.format("Invalid value: " + e.getMessage()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/PairParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/PairParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/PairParser.java
new file mode 100644
index 0000000..3465260
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/PairParser.java
@@ -0,0 +1,57 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.args.Parsers;
+import org.apache.aurora.common.collections.Pair;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Pair parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class PairParser extends TypeParameterizedParser<Pair<?, ?>> {
+
+  public PairParser() {
+    super(2);
+  }
+
+  @Override
+  Pair<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> typeParams) {
+    Type leftType = typeParams.get(0);
+    Parser<?> leftParser = parserOracle.get(TypeToken.of(leftType));
+
+    Type rightType = typeParams.get(1);
+    Parser<?> rightParser = parserOracle.get(TypeToken.of(rightType));
+
+    List<String> parts = ImmutableList.copyOf(Parsers.MULTI_VALUE_SPLITTER.split(raw));
+    checkArgument(parts.size() == 2,
+        "Only two values may be specified for a pair, you gave " + parts.size());
+
+    return Pair.of(leftParser.parse(parserOracle, leftType, parts.get(0)),
+                   rightParser.parse(parserOracle, rightType, parts.get(1)));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/PatternParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/PatternParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/PatternParser.java
new file mode 100644
index 0000000..0b86a21
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/PatternParser.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.args.parsers;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * A regular expression parser.
+ */
+@ArgParser
+public class PatternParser extends NonParameterizedTypeParser<Pattern> {
+
+  @Override
+  public Pattern doParse(String raw) throws IllegalArgumentException {
+    try {
+      return Pattern.compile(raw);
+    } catch (PatternSyntaxException e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/RangeParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/RangeParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/RangeParser.java
new file mode 100644
index 0000000..e861681
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/RangeParser.java
@@ -0,0 +1,46 @@
+/**
+ * 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.args.parsers;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Range;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * A parser that handles closed ranges. For the input "4-6", it will capture [4, 5, 6].
+ */
+@ArgParser
+public class RangeParser extends NonParameterizedTypeParser<Range<Integer>> {
+  @Override
+  public Range<Integer> doParse(String raw) throws IllegalArgumentException {
+    ImmutableList<String> numbers =
+        ImmutableList.copyOf(Splitter.on('-').omitEmptyStrings().split(raw));
+    try {
+      int from = Integer.parseInt(numbers.get(0));
+      int to = Integer.parseInt(numbers.get(1));
+      if (numbers.size() != 2) {
+        throw new IllegalArgumentException("Failed to parse the range:" + raw);
+      }
+      if (to < from) {
+        return Range.closed(to, from);
+      } else {
+        return Range.closed(from, to);
+      }
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Failed to parse the range:" + raw, e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/SetParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/SetParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/SetParser.java
new file mode 100644
index 0000000..1e12b06
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/SetParser.java
@@ -0,0 +1,54 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.args.Parsers;
+
+/**
+ * Set parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class SetParser extends TypeParameterizedParser<Set<?>> {
+
+  public SetParser() {
+    super(1);
+  }
+
+  @Override
+  Set<?> doParse(final ParserOracle parserOracle, String raw, List<Type> typeParams) {
+    final Type setType = typeParams.get(0);
+    final Parser<?> parser = parserOracle.get(TypeToken.of(setType));
+
+    return ImmutableSet.copyOf(Iterables.transform(Parsers.MULTI_VALUE_SPLITTER.split(raw),
+        new Function<String, Object>() {
+          @Override public Object apply(String raw) {
+            return parser.parse(parserOracle, setType, raw);
+          }
+        }));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/ShortParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/ShortParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/ShortParser.java
new file mode 100644
index 0000000..1e1323d
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/ShortParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * Short parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ShortParser extends NumberParser<Short> {
+  @Override
+  Short parseNumber(String raw) {
+    return Short.parseShort(raw);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/StringParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/StringParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/StringParser.java
new file mode 100644
index 0000000..5283992
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/StringParser.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.args.parsers;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * String parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class StringParser extends NonParameterizedTypeParser<String> {
+  @Override
+  public String doParse(String raw) {
+    return raw;
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/TypeParameterizedParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/TypeParameterizedParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/TypeParameterizedParser.java
new file mode 100644
index 0000000..a8455f5
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/TypeParameterizedParser.java
@@ -0,0 +1,65 @@
+/**
+ * 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.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.ParserOracle;
+import org.apache.aurora.common.args.TypeUtil;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Parser that makes implementation of parsers for parameterized types simpler.
+ *
+ * @param <T> The raw type this parser can parse.
+ *
+ * @author William Farner
+ */
+public abstract class TypeParameterizedParser<T> implements Parser<T> {
+
+  private final int typeParamCount;
+
+  /**
+   * Creates a new type parameterized parser.
+   *
+   * @param typeParamCount Strict number of type parameters to allow on the assigned type.
+   */
+  TypeParameterizedParser(int typeParamCount) {
+    this.typeParamCount = typeParamCount;
+  }
+
+  /**
+   * Performs the actual parsing.
+   *
+   * @param parserOracle The registered parserOracle for delegation.
+   * @param raw The raw value to parse.
+   * @param typeParams The captured actual type parameters for {@code T}.
+   * @return The parsed value.
+   * @throws IllegalArgumentException If the value could not be parsed.
+   */
+  abstract T doParse(ParserOracle parserOracle, String raw, List<Type> typeParams)
+      throws IllegalArgumentException;
+
+  @Override public T parse(ParserOracle parserOracle, Type type, String raw) {
+    List<Type> typeParams = TypeUtil.getTypeParams(type);
+    checkArgument(typeParams.size() == typeParamCount, String.format(
+        "Expected %d type parameters for %s but got %d",
+        typeParamCount, type, typeParams.size()));
+
+    return doParse(parserOracle, raw, typeParams);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/URIParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/URIParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/URIParser.java
new file mode 100644
index 0000000..6026112
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/URIParser.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.args.parsers;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * URI parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class URIParser extends NonParameterizedTypeParser<URI> {
+  @Override
+  public URI doParse(String raw) {
+    try {
+      return new URI(raw);
+    } catch (URISyntaxException e) {
+      throw new IllegalArgumentException("Malformed URI " + raw + ", " + e.getMessage());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/URLParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/URLParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/URLParser.java
new file mode 100644
index 0000000..c2fd301
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/URLParser.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.args.parsers;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.aurora.common.args.ArgParser;
+
+/**
+ * URL parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class URLParser extends NonParameterizedTypeParser<URL> {
+  @Override
+  public URL doParse(String raw) {
+    try {
+      return new URL(raw);
+    } catch (MalformedURLException e) {
+      throw new IllegalArgumentException("Malformed URL " + raw + ", " + e.getMessage());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/args/parsers/UnitParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/args/parsers/UnitParser.java b/commons/src/main/java/org/apache/aurora/common/args/parsers/UnitParser.java
new file mode 100644
index 0000000..9109853
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/args/parsers/UnitParser.java
@@ -0,0 +1,54 @@
+/**
+ * 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.args.parsers;
+
+import java.util.EnumSet;
+import java.util.Map;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.quantity.Data;
+import org.apache.aurora.common.quantity.Time;
+import org.apache.aurora.common.quantity.Unit;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Unit parser.
+ * Units are matched (case sensitively) against the result of {@link Unit#toString()}.
+ */
+@ArgParser
+public class UnitParser extends NonParameterizedTypeParser<Unit<?>> {
+
+  private final Map<String, Unit<?>> unitValues;
+
+  public UnitParser() {
+    unitValues = Maps.uniqueIndex(
+        ImmutableList.<Unit<?>>builder().add(Time.values()).add(Data.values()).build(),
+        Functions.toStringFunction());
+  }
+
+  @Override
+  public Unit<?> doParse(String raw) {
+    Unit<?> unit = unitValues.get(raw);
+
+    checkArgument(unit != null, String.format(
+        "No Units found matching %s, options: (Time): %s, (Data): %s",
+        raw, EnumSet.allOf(Time.class), EnumSet.allOf(Data.class)));
+    return unit;
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/CachingSupplier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/CachingSupplier.java b/commons/src/main/java/org/apache/aurora/common/base/CachingSupplier.java
new file mode 100644
index 0000000..3a1511d
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/CachingSupplier.java
@@ -0,0 +1,68 @@
+/**
+ * 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.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+import org.apache.aurora.common.quantity.Amount;
+import org.apache.aurora.common.quantity.Time;
+import org.apache.aurora.common.util.Clock;
+
+/**
+ * A supplier that caches responses from an underling supplier, expiring the cached value after
+ * a fixed expiration time.
+ *
+ * @param <T> Supplied value type.
+ *
+ * @author William Farner
+ */
+public class CachingSupplier<T> implements Supplier<T> {
+
+  private final Supplier<T> wrapped;
+  private final long expirationNanos;
+  private final Clock clock;
+
+  private long lastFetchNanos = -1;
+  private T cachedValue;
+
+  /**
+   * Creates a new caching supplier.
+   *
+   * @param wrapped The supplier to delegate fetches to.
+   * @param expiration The maximum amount of time that a response from {@code supplier} will be
+   *   cached for.  The expiration must be positive.
+   */
+  public CachingSupplier(Supplier<T> wrapped, Amount<Long, Time> expiration) {
+    this(wrapped, expiration, Clock.SYSTEM_CLOCK);
+  }
+
+  @VisibleForTesting
+  CachingSupplier(Supplier<T> wrapped, Amount<Long, Time> expiration, Clock clock) {
+    this.wrapped = Preconditions.checkNotNull(wrapped);
+    this.expirationNanos = Preconditions.checkNotNull(expiration).as(Time.NANOSECONDS);
+    Preconditions.checkArgument(expiration.getValue() > 0, "Expiration must be positive.");
+    this.clock = Preconditions.checkNotNull(clock);
+  }
+
+  @Override
+  public synchronized T get() {
+    if ((lastFetchNanos == -1) || (clock.nowNanos() - lastFetchNanos > expirationNanos)) {
+      cachedValue = wrapped.get();
+      lastFetchNanos = clock.nowNanos();
+    }
+
+    return cachedValue;
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/CallableExceptionalSupplier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/CallableExceptionalSupplier.java b/commons/src/main/java/org/apache/aurora/common/base/CallableExceptionalSupplier.java
new file mode 100644
index 0000000..b4f2d53
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/CallableExceptionalSupplier.java
@@ -0,0 +1,32 @@
+/**
+ * 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.util.concurrent.Callable;
+
+/**
+ * A supplier that may also be called.
+ *
+ * @param <T> The supplier type.
+ * @param <E> Supplier exception type.
+ *
+ * @author John Sirois
+ */
+public abstract class CallableExceptionalSupplier<T, E extends Exception>
+    implements ExceptionalSupplier<T, E>, Callable<T> {
+
+  @Override public T call() throws Exception {
+    return get();
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Closure.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Closure.java b/commons/src/main/java/org/apache/aurora/common/base/Closure.java
new file mode 100644
index 0000000..9467255
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Closure.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 closure that does not throw any checked exceptions.
+ *
+ * @param <T> Closure value type.
+ *
+ * @author John Sirois
+ */
+public interface Closure<T> extends ExceptionalClosure<T, RuntimeException> {
+  // convenience typedef
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/org/apache/aurora/common/base/Closures.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/base/Closures.java b/commons/src/main/java/org/apache/aurora/common/base/Closures.java
new file mode 100644
index 0000000..d741e9c
--- /dev/null
+++ b/commons/src/main/java/org/apache/aurora/common/base/Closures.java
@@ -0,0 +1,133 @@
+/**
+ * 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;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utilities for dealing with Closures.
+ *
+ * @author John Sirois
+ */
+public final class Closures {
+
+  private static final Closure<?> NOOP = new Closure<Object>() {
+    @Override public void execute(Object item) {
+      // noop
+    }
+  };
+
+  private Closures() {
+    // utility
+  }
+
+  /**
+   * Converts a closure into a function returning {@code null}.
+   */
+  public static <T> Function<T, Void> asFunction(final ExceptionalClosure<T, ?> closure) {
+    checkNotNull(closure);
+
+    // CHECKSTYLE:OFF IllegalCatch
+    return new Function<T, Void>() {
+      @Override public Void apply(T item) {
+        try {
+          closure.execute(item);
+        } catch (Exception e) {
+          Throwables.propagate(e);
+        }
+        return null;
+      }
+    };
+    // CHECKSTYLE:ON IllegalCatch
+  }
+
+  /**
+   * Varargs equivalent of {@link #combine(Iterable)}.
+   *
+   * @param closures Closures to combine.
+   * @param <T> Type accepted by the closures.
+   * @return A single closure that will fan out all calls to {@link Closure#execute(Object)} to
+   *    the wrapped closures.
+   */
+  public static <T> Closure<T> combine(Closure<T>... closures) {
+    return combine(ImmutableList.copyOf(closures));
+  }
+
+  /**
+   * Combines multiple closures into a single closure, whose calls are replicated sequentially
+   * in the order that they were provided.
+   * If an exception is encountered from a closure it propagates to the top-level closure and the
+   * remaining closures are not executed.
+   *
+   * @param closures Closures to combine.
+   * @param <T> Type accepted by the closures.
+   * @return A single closure that will fan out all calls to {@link Closure#execute(Object)} to
+   *    the wrapped closures.
+   */
+  public static <T> Closure<T> combine(Iterable<Closure<T>> closures) {
+    checkNotNull(closures);
+    checkArgument(Iterables.all(closures, Predicates.notNull()));
+
+    final Iterable<Closure<T>> closuresCopy = ImmutableList.copyOf(closures);
+
+    return new Closure<T>() {
+      @Override public void execute(T item) {
+        for (Closure<T> closure : closuresCopy) {
+          closure.execute(item);
+        }
+      }
+    };
+  }
+
+  /**
+   * Applies a filter to a closure, such that the closure will only be called when the filter is
+   * satisfied (returns {@code true}}.
+   *
+   * @param filter Filter to determine when {@code closure} is called.
+   * @param closure Closure to filter.
+   * @param <T> Type handled by the filter and the closure.
+   * @return A filtered closure.
+   */
+  public static <T> Closure<T> filter(final Predicate<T> filter, final Closure<T> closure) {
+    checkNotNull(filter);
+    checkNotNull(closure);
+
+    return new Closure<T>() {
+      @Override public void execute(T item) {
+        if (filter.apply(item)) {
+          closure.execute(item);
+        }
+      }
+    };
+  }
+
+  /**
+   * Returns a closure that will do nothing.
+   *
+   * @param <T> The closure argument type.
+   * @return A closure that does nothing.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> Closure<T> noop() {
+    return (Closure<T>) NOOP;
+  }
+}