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;
+ }
+}