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