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:39 UTC
[49/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-args/src/main/java/org/apache/aurora/common/args/apt/CmdLineProcessor.java
----------------------------------------------------------------------
diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/apt/CmdLineProcessor.java b/commons-args/src/main/java/org/apache/aurora/common/args/apt/CmdLineProcessor.java
new file mode 100644
index 0000000..5abb06b
--- /dev/null
+++ b/commons-args/src/main/java/org/apache/aurora/common/args/apt/CmdLineProcessor.java
@@ -0,0 +1,677 @@
+/**
+ * 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.apt;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleAnnotationValueVisitor6;
+import javax.lang.model.util.SimpleTypeVisitor6;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import org.apache.aurora.common.args.Arg;
+import org.apache.aurora.common.args.ArgParser;
+import org.apache.aurora.common.args.CmdLine;
+import org.apache.aurora.common.args.Parser;
+import org.apache.aurora.common.args.Positional;
+import org.apache.aurora.common.args.Verifier;
+import org.apache.aurora.common.args.VerifierFor;
+import org.apache.aurora.common.args.apt.Configuration.ParserInfo;
+
+import static org.apache.aurora.common.args.apt.Configuration.ArgInfo;
+import static org.apache.aurora.common.args.apt.Configuration.VerifierInfo;
+
+/**
+ * Processes {@literal @CmdLine} annotated fields and {@literal @ArgParser} and
+ * {@literal @VerifierFor} parser and verifier registrations and stores configuration data listing
+ * these fields, parsers and verifiers on the classpath for discovery via
+ * {@link Configuration#load()}.
+ *
+ * <p>Supports an apt option useful for some build setups that create monolithic jars aggregating
+ * many library jars, one or more of which have embedded arg definitions themselves. By adding the
+ * following flag to a javac invocation:
+ * <code>-Acom.twitter.common.args.apt.CmdLineProcessor.main</code>
+ * you signal this apt processor that the compilation target is a leaf target that will comprise one
+ * or more executable mains (as opposed to a library jar). As a result, the embedded arg
+ * definitions generated will occupy a special resource that is always checked for first during
+ * runtime arg parsing.
+ */
+@SupportedOptions({
+ CmdLineProcessor.MAIN_OPTION,
+ CmdLineProcessor.CHECK_LINKAGE_OPTION
+})
+public class CmdLineProcessor extends AbstractProcessor {
+ static final String MAIN_OPTION =
+ "com.twitter.common.args.apt.CmdLineProcessor.main";
+ static final String CHECK_LINKAGE_OPTION =
+ "com.twitter.common.args.apt.CmdLineProcessor.check_linkage";
+
+ private static final Function<Class<?>, String> GET_NAME = new Function<Class<?>, String>() {
+ @Override public String apply(Class<?> type) {
+ return type.getName();
+ }
+ };
+
+ private final Supplier<Configuration> configSupplier =
+ Suppliers.memoize(new Supplier<Configuration>() {
+ @Override public Configuration get() {
+ try {
+ Configuration configuration = Configuration.load();
+ for (ArgInfo argInfo : configuration.positionalInfo()) {
+ configBuilder.addPositionalInfo(argInfo);
+ }
+ for (ArgInfo argInfo : configuration.optionInfo()) {
+ configBuilder.addCmdLineArg(argInfo);
+ }
+ for (ParserInfo parserInfo : configuration.parserInfo()) {
+ configBuilder.addParser(parserInfo);
+ }
+ for (VerifierInfo verifierInfo : configuration.verifierInfo()) {
+ configBuilder.addVerifier(verifierInfo);
+ }
+ return configuration;
+ } catch (IOException e) {
+ error("Problem loading existing flags on compile time classpath: %s",
+ Throwables.getStackTraceAsString(e));
+ return null;
+ }
+ }
+ });
+
+ private final Configuration.Builder configBuilder = new Configuration.Builder();
+ private final ImmutableSet.Builder<String> contributingClassNamesBuilder = ImmutableSet.builder();
+
+ private Types typeUtils;
+ private Elements elementUtils;
+ private boolean isMain;
+ private boolean isCheckLinkage;
+
+ private static boolean getBooleanOption(Map<String, String> options, String name,
+ boolean defaultValue) {
+
+ if (!options.containsKey(name)) {
+ return defaultValue;
+ }
+
+ // We want to map the presence of a boolean option without a value to indicate true, giving the
+ // following accepted boolean option formats:
+ // -Afoo -> true
+ // -Afoo=false -> false
+ // -Afoo=true -> true
+
+ String isOption = options.get(name);
+ return (isOption == null) || Boolean.parseBoolean(isOption);
+ }
+
+ @Override
+ public void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+
+ typeUtils = processingEnv.getTypeUtils();
+ elementUtils = processingEnv.getElementUtils();
+
+ Map<String, String> options = processingEnv.getOptions();
+ isMain = getBooleanOption(options, MAIN_OPTION, false);
+ isCheckLinkage = getBooleanOption(options, CHECK_LINKAGE_OPTION, true);
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public Set<String> getSupportedAnnotationTypes() {
+ return ImmutableSet.copyOf(Iterables.transform(
+ ImmutableList.of(Positional.class, CmdLine.class, ArgParser.class, VerifierFor.class),
+ GET_NAME));
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ try {
+ @Nullable Configuration classpathConfiguration = configSupplier.get();
+
+ Set<? extends Element> parsers = getAnnotatedElements(roundEnv, ArgParser.class);
+ contributingClassNamesBuilder.addAll(extractClassNames(parsers));
+ @Nullable Set<String> parsedTypes = getParsedTypes(classpathConfiguration, parsers);
+
+ Set<? extends Element> cmdlineArgs = getAnnotatedElements(roundEnv, CmdLine.class);
+ contributingClassNamesBuilder.addAll(extractEnclosingClassNames(cmdlineArgs));
+ Set<? extends Element> positionalArgs = getAnnotatedElements(roundEnv, Positional.class);
+ contributingClassNamesBuilder.addAll(extractEnclosingClassNames(positionalArgs));
+
+ ImmutableSet<? extends Element> invalidArgs =
+ Sets.intersection(cmdlineArgs, positionalArgs).immutableCopy();
+ if (!invalidArgs.isEmpty()) {
+ error("An Arg cannot be annotated with both @CmdLine and @Positional, found bad Arg "
+ + "fields: %s", invalidArgs);
+ }
+
+ for (ArgInfo cmdLineInfo : processAnnotatedArgs(parsedTypes, cmdlineArgs, CmdLine.class)) {
+ configBuilder.addCmdLineArg(cmdLineInfo);
+ }
+
+ for (ArgInfo positionalInfo
+ : processAnnotatedArgs(parsedTypes, positionalArgs, Positional.class)) {
+
+ configBuilder.addPositionalInfo(positionalInfo);
+ }
+ checkPositionalArgsAreLists(roundEnv);
+
+ processParsers(parsers);
+
+ Set<? extends Element> verifiers = getAnnotatedElements(roundEnv, VerifierFor.class);
+ contributingClassNamesBuilder.addAll(extractClassNames(verifiers));
+ processVerifiers(verifiers);
+
+ if (roundEnv.processingOver()) {
+ if (classpathConfiguration != null
+ && (!classpathConfiguration.isEmpty() || !configBuilder.isEmpty())) {
+
+ @Nullable Resource cmdLinePropertiesResource =
+ openCmdLinePropertiesResource(classpathConfiguration);
+ if (cmdLinePropertiesResource != null) {
+ Writer writer = cmdLinePropertiesResource.getWriter();
+ try {
+ configBuilder.build(classpathConfiguration).store(writer,
+ "Generated via apt by " + getClass().getName());
+ } finally {
+ closeQuietly(writer);
+ }
+
+ writeResourceMapping(contributingClassNamesBuilder.build(),
+ cmdLinePropertiesResource.getResource());
+ }
+ }
+ }
+ // TODO(John Sirois): Investigate narrowing this catch - its not clear there is any need to be
+ // so general.
+ // SUPPRESS CHECKSTYLE RegexpSinglelineJava
+ } catch (RuntimeException e) {
+ // Catch internal errors - when these bubble more useful queued error messages are lost in
+ // some javac implementations.
+ error("Unexpected error completing annotation processing:\n%s",
+ Throwables.getStackTraceAsString(e));
+ }
+ return true;
+ }
+
+ private void writeResourceMapping(
+ Set<String> contributingClassNames,
+ FileObject cmdLinePropertiesResourcePath) {
+
+ // TODO(John Sirois): Lift the compiler resource-mappings writer to its own class/artifact to be
+ // re-used by other apt processors: https://github.com/twitter/commons/issues/319
+
+ // NB: javac rejects a package name with illegal package name characters like '-' so we just
+ // pass the empty package and the fully qualified resource file name.
+ @Nullable Resource resource = openResource("",
+ "META-INF/compiler/resource-mappings/" + getClass().getName());
+ if (resource != null) {
+ PrintWriter writer = new PrintWriter(resource.getWriter());
+ writer.printf("resources by class name:\n");
+ writer.printf("%d items\n", contributingClassNames.size());
+ try {
+ for (String className : contributingClassNames) {
+ writer.printf("%s -> %s\n", className, cmdLinePropertiesResourcePath.toUri().getPath());
+ }
+ } finally {
+ closeQuietly(writer);
+ }
+ }
+ }
+
+ private static final Function<Element, Element> EXTRACT_ENCLOSING_CLASS =
+ new Function<Element, Element>() {
+ @Override public Element apply(Element element) {
+ return element.getEnclosingElement();
+ }
+ };
+
+ private final Function<Element, String> extractClassName = new Function<Element, String>() {
+ @Override public String apply(Element element) {
+ return getBinaryName((TypeElement) element);
+ }
+ };
+
+ private final Function<Element, String> extractEnclosingClassName =
+ Functions.compose(extractClassName, EXTRACT_ENCLOSING_CLASS);
+
+ private Iterable<String> extractEnclosingClassNames(Iterable<? extends Element> elements) {
+ return Iterables.transform(elements, extractEnclosingClassName);
+ }
+
+ private Iterable<String> extractClassNames(Iterable<? extends Element> elements) {
+ return Iterables.transform(elements, extractClassName);
+ }
+
+ private void closeQuietly(Closeable closeable) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ log(Kind.MANDATORY_WARNING, "Failed to close %s: %s", closeable, e);
+ }
+ }
+
+ private void checkPositionalArgsAreLists(RoundEnvironment roundEnv) {
+ for (Element positionalArg : getAnnotatedElements(roundEnv, Positional.class)) {
+ @Nullable TypeMirror typeArgument =
+ getTypeArgument(positionalArg.asType(), typeElement(Arg.class));
+ if ((typeArgument == null)
+ || !typeUtils.isSubtype(typeElement(List.class).asType(), typeArgument)) {
+ error("Found @Positional %s %s.%s that is not a List",
+ positionalArg.asType(), positionalArg.getEnclosingElement(), positionalArg);
+ }
+ }
+ }
+
+ @Nullable
+ private Set<String> getParsedTypes(@Nullable Configuration configuration,
+ Set<? extends Element> parsers) {
+
+ if (!isCheckLinkage) {
+ return null;
+ }
+
+ Iterable<String> parsersFor = Optional.presentInstances(Iterables.transform(parsers,
+ new Function<Element, Optional<String>>() {
+ @Override public Optional<String> apply(Element parser) {
+ TypeMirror parsedType = getTypeArgument(parser.asType(), typeElement(Parser.class));
+ if (parsedType == null) {
+ error("failed to find a type argument for Parser: %s", parser);
+ return Optional.absent();
+ }
+ // Equals on TypeMirrors doesn't work - so we compare string representations :/
+ return Optional.of(typeUtils.erasure(parsedType).toString());
+ }
+ }));
+ if (configuration != null) {
+ parsersFor = Iterables.concat(parsersFor, Iterables.filter(
+ Iterables.transform(configuration.parserInfo(),
+ new Function<ParserInfo, String>() {
+ @Override @Nullable public String apply(ParserInfo parserInfo) {
+ TypeElement typeElement = elementUtils.getTypeElement(parserInfo.parsedType);
+ // We may not have a type on the classpath for a previous round - this is fine as
+ // long as the no Args in this round that are of the type.
+ return (typeElement == null)
+ ? null : typeUtils.erasure(typeElement.asType()).toString();
+ }
+ }), Predicates.notNull()));
+ }
+ return ImmutableSet.copyOf(parsersFor);
+ }
+
+ private Iterable<ArgInfo> processAnnotatedArgs(
+ @Nullable final Set<String> parsedTypes,
+ Set<? extends Element> args,
+ final Class<? extends Annotation> argAnnotation) {
+
+ return Optional.presentInstances(Iterables.transform(args,
+ new Function<Element, Optional<ArgInfo>>() {
+ @Override public Optional<ArgInfo> apply(Element arg) {
+ @Nullable TypeElement containingType = processArg(parsedTypes, arg, argAnnotation);
+ if (containingType == null) {
+ return Optional.absent();
+ } else {
+ return Optional.of(new ArgInfo(getBinaryName(containingType),
+ arg.getSimpleName().toString()));
+ }
+ }
+ }));
+ }
+
+ private Set<? extends Element> getAnnotatedElements(RoundEnvironment roundEnv,
+ Class<? extends Annotation> argAnnotation) {
+ return roundEnv.getElementsAnnotatedWith(typeElement(argAnnotation));
+ }
+
+ @Nullable
+ private TypeElement processArg(@Nullable Set<String> parsedTypes, Element annotationElement,
+ Class<? extends Annotation> annotationType) {
+
+ TypeElement parserType = typeElement(Parser.class);
+ if (annotationElement.getKind() != ElementKind.FIELD) {
+ error("Found a @%s annotation on a non-field %s",
+ annotationType.getSimpleName(), annotationElement);
+ return null;
+ } else {
+ // Only types contain fields so this cast is safe.
+ TypeElement containingType = (TypeElement) annotationElement.getEnclosingElement();
+
+ if (!isAssignable(annotationElement.asType(), Arg.class)) {
+ error("Found a @%s annotation on a non-Arg %s.%s",
+ annotationType.getSimpleName(), containingType, annotationElement);
+ return null;
+ }
+ if (!annotationElement.getModifiers().contains(Modifier.STATIC)) {
+ return null;
+ }
+
+ if (parsedTypes != null) {
+ // Check Parser<T> linkage for the Arg<T> type T.
+ TypeMirror typeArgument =
+ getTypeArgument(annotationElement.asType(), typeElement(Arg.class));
+ @Nullable AnnotationMirror cmdLine =
+ getAnnotationMirror(annotationElement, typeElement(annotationType));
+ if (cmdLine != null) {
+ TypeMirror customParserType = getClassType(cmdLine, "parser", parserType).asType();
+ if (typeUtils.isSameType(parserType.asType(), customParserType)) {
+ if (!checkTypePresent(parsedTypes, typeArgument)) {
+ error("No parser registered for %s, %s.%s is un-parseable",
+ typeArgument, containingType, annotationElement);
+ }
+ } else {
+ TypeMirror customParsedType = getTypeArgument(customParserType, parserType);
+ if (!isAssignable(typeArgument, customParsedType)) {
+ error("Custom parser %s parses %s but registered for %s.%s with Arg type %s",
+ customParserType, customParsedType, containingType, annotationElement,
+ typeArgument);
+ }
+ }
+ }
+ }
+
+ // TODO(John Sirois): Add additional compile-time @CmdLine verification for:
+ // 1.) for each @CmdLine Arg<T> annotated with @VerifierFor.annotation: T is a subtype of
+ // V where there is a Verifier<V>
+ // 2.) name checks, including dups
+
+ return containingType;
+ }
+ }
+
+ private boolean checkTypePresent(Set<String> types, TypeMirror type) {
+ Iterable<TypeMirror> allTypes = getAllTypes(type);
+ for (TypeMirror t : allTypes) {
+ if (types.contains(typeUtils.erasure(t).toString())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void processParsers(Set<? extends Element> elements) {
+ TypeElement parserType = typeElement(Parser.class);
+ for (Element element : elements) {
+ if (element.getKind() != ElementKind.CLASS) {
+ error("Found an @ArgParser annotation on a non-class %s", element);
+ } else {
+ TypeElement parser = (TypeElement) element;
+ if (!isAssignable(parser, Parser.class)) {
+ error("Found an @ArgParser annotation on a non-Parser %s", element);
+ return;
+ }
+
+ @Nullable String parsedType = getTypeArgument(parser, parserType);
+ if (parsedType != null) {
+ configBuilder.addParser(parsedType, getBinaryName(parser));
+ }
+ }
+ }
+ }
+
+ private void processVerifiers(Set<? extends Element> elements) {
+ TypeElement verifierType = typeElement(Verifier.class);
+ TypeElement verifierForType = typeElement(VerifierFor.class);
+ for (Element element : elements) {
+ if (element.getKind() != ElementKind.CLASS) {
+ error("Found a @VerifierFor annotation on a non-class %s", element);
+ } else {
+ TypeElement verifier = (TypeElement) element;
+ if (!isAssignable(verifier, Verifier.class)) {
+ error("Found a @Verifier annotation on a non-Verifier %s", element);
+ return;
+ }
+
+ @Nullable AnnotationMirror verifierFor = getAnnotationMirror(verifier, verifierForType);
+ if (verifierFor != null) {
+ @Nullable TypeElement verifyAnnotationType = getClassType(verifierFor, "value", null);
+ if (verifyAnnotationType != null) {
+ @Nullable String verifiedType = getTypeArgument(verifier, verifierType);
+ if (verifiedType != null) {
+ String verifyAnnotationClassName =
+ elementUtils.getBinaryName(verifyAnnotationType).toString();
+ configBuilder.addVerifier(verifiedType, verifyAnnotationClassName,
+ getBinaryName(verifier));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Nullable
+ private String getTypeArgument(TypeElement annotatedType, final TypeElement baseType) {
+ TypeMirror typeArgument = getTypeArgument(annotatedType.asType(), baseType);
+ return typeArgument == null
+ ? null
+ : getBinaryName((TypeElement) typeUtils.asElement(typeArgument));
+ }
+
+ private Iterable<TypeMirror> getAllTypes(TypeMirror type) {
+ return getAllTypes(new HashSet<String>(), Lists.<TypeMirror>newArrayList(), type);
+ }
+
+ private Iterable<TypeMirror> getAllTypes(Set<String> visitedTypes, List<TypeMirror> types,
+ TypeMirror type) {
+
+ String typeName = typeUtils.erasure(type).toString();
+ if (!visitedTypes.contains(typeName)) {
+ types.add(type);
+ visitedTypes.add(typeName);
+ for (TypeMirror superType : typeUtils.directSupertypes(type)) {
+ getAllTypes(visitedTypes, types, superType);
+ }
+ }
+ return types;
+ }
+
+ @Nullable
+ private TypeMirror getTypeArgument(TypeMirror annotatedType, final TypeElement baseType) {
+ for (TypeMirror type : getAllTypes(annotatedType)) {
+ TypeMirror typeArgument = type.accept(new SimpleTypeVisitor6<TypeMirror, Void>() {
+ @Override public TypeMirror visitDeclared(DeclaredType t, Void aVoid) {
+ if (isAssignable(t, baseType)) {
+ List<? extends TypeMirror> typeArguments = t.getTypeArguments();
+ if (!typeArguments.isEmpty()) {
+ return typeUtils.erasure(typeArguments.get(0));
+ }
+ }
+ return null;
+ }
+ }, null);
+
+ if (typeArgument != null) {
+ return typeArgument;
+ }
+ }
+ error("Failed to find a type argument for %s in %s", baseType, annotatedType);
+ return null;
+ }
+
+ @Nullable
+ private AnnotationMirror getAnnotationMirror(Element element, TypeElement annotationType) {
+ for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
+ if (typeUtils.isSameType(annotationMirror.getAnnotationType(), annotationType.asType())) {
+ return annotationMirror;
+ }
+ }
+ error("Failed to find an annotation of type %s on %s", annotationType, element);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private TypeElement getClassType(AnnotationMirror annotationMirror, String methodName,
+ TypeElement defaultClassType) {
+
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry
+ : annotationMirror.getElementValues().entrySet()) {
+ if (entry.getKey().getSimpleName().equals(elementUtils.getName(methodName))) {
+ TypeElement classType = entry.getValue().accept(
+ new SimpleAnnotationValueVisitor6<TypeElement, Void>() {
+ @Override public TypeElement visitType(TypeMirror t, Void unused) {
+ return (TypeElement) processingEnv.getTypeUtils().asElement(t);
+ }
+ }, null);
+
+ if (classType != null) {
+ return classType;
+ }
+ }
+ }
+ if (defaultClassType == null) {
+ error("Could not find a class type for %s.%s", annotationMirror, methodName);
+ }
+ return defaultClassType;
+ }
+
+ @Nullable
+ private FileObject createCommandLineDb(Configuration configuration) {
+ String name = isMain ? Configuration.mainResourceName() : configuration.nextResourceName();
+ return createResource(Configuration.DEFAULT_RESOURCE_PACKAGE, name);
+ }
+
+ @Nullable
+ private FileObject createResource(String packageName, String name) {
+ try {
+ return processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT,
+ packageName, name);
+ } catch (IOException e) {
+ error("Failed to create resource file to store %s/%s: %s",
+ packageName, name, Throwables.getStackTraceAsString(e));
+ return null;
+ }
+ }
+
+ private static final class Resource {
+ private final FileObject resource;
+ private final Writer writer;
+
+ Resource(FileObject resource, Writer writer) {
+ this.resource = resource;
+ this.writer = writer;
+ }
+
+ FileObject getResource() {
+ return resource;
+ }
+
+ Writer getWriter() {
+ return writer;
+ }
+ }
+
+ @Nullable
+ private Resource openCmdLinePropertiesResource(Configuration configuration) {
+ @Nullable FileObject resource = createCommandLineDb(configuration);
+ return openResource(resource);
+ }
+
+ @Nullable
+ private Resource openResource(String packageName, String name) {
+ @Nullable FileObject resource = createResource(packageName, name);
+ return openResource(resource);
+ }
+
+ @Nullable
+ private Resource openResource(@Nullable FileObject resource) {
+ if (resource == null) {
+ return null;
+ }
+ try {
+ log(Kind.NOTE, "Writing %s", resource.toUri());
+ return new Resource(resource, resource.openWriter());
+ } catch (IOException e) {
+ if (!resource.delete()) {
+ log(Kind.WARNING, "Failed to clean up %s after a failing to open it for writing",
+ resource.toUri());
+ }
+ error("Failed to open resource file to store %s: %s", resource.toUri(),
+ Throwables.getStackTraceAsString(e));
+ return null;
+ }
+ }
+
+ private TypeElement typeElement(Class<?> type) {
+ return elementUtils.getTypeElement(type.getName());
+ }
+
+ private String getBinaryName(TypeElement typeElement) {
+ return elementUtils.getBinaryName(typeElement).toString();
+ }
+
+ private boolean isAssignable(TypeElement subType, Class<?> baseType) {
+ return isAssignable(subType.asType(), baseType);
+ }
+
+ private boolean isAssignable(TypeMirror subType, Class<?> baseType) {
+ return isAssignable(subType, typeElement(baseType));
+ }
+
+ private boolean isAssignable(TypeMirror subType, TypeElement baseType) {
+ return isAssignable(subType, baseType.asType());
+ }
+
+ private boolean isAssignable(TypeMirror subType, TypeMirror baseType) {
+ return typeUtils.isAssignable(typeUtils.erasure(subType), typeUtils.erasure(baseType));
+ }
+
+ private void error(String message, Object ... args) {
+ log(Kind.ERROR, message, args);
+ }
+
+ private void log(Kind kind, String message, Object ... args) {
+ processingEnv.getMessager().printMessage(kind, String.format(message, args));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons-args/src/main/java/org/apache/aurora/common/args/apt/Configuration.java
----------------------------------------------------------------------
diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/apt/Configuration.java b/commons-args/src/main/java/org/apache/aurora/common/args/apt/Configuration.java
new file mode 100644
index 0000000..e8e6447
--- /dev/null
+++ b/commons-args/src/main/java/org/apache/aurora/common/args/apt/Configuration.java
@@ -0,0 +1,527 @@
+/**
+ * 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.apt;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URL;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.io.CharStreams;
+import com.google.common.io.InputSupplier;
+import com.google.common.io.LineProcessor;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ * Loads and stores {@literal @CmdLine} configuration data. By default, that data
+ * is contained in text files called cmdline.arg.info.txt.0, cmdline.arg.info.txt.1
+ * etc. Every time a new Configuration object is created, it consumes all existing
+ * files with the above names. Saving this Configuration results in creation of a
+ * file with index increased by one, e.g. cmdline.arg.info.txt.2 in the above
+ * example.
+ *
+ * @author John Sirois
+ */
+public final class Configuration {
+
+ /**
+ * Indicates a problem reading stored {@literal @CmdLine} arg configuration data.
+ */
+ public static class ConfigurationException extends RuntimeException {
+ public ConfigurationException(String message, Object... args) {
+ super(String.format(message, args));
+ }
+ public ConfigurationException(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ static final String DEFAULT_RESOURCE_PACKAGE = Configuration.class.getPackage().getName();
+
+ private static final Logger LOG = Logger.getLogger(Configuration.class.getName());
+
+ private static final CharMatcher IDENTIFIER_START =
+ CharMatcher.forPredicate(new Predicate<Character>() {
+ @Override public boolean apply(Character c) {
+ return Character.isJavaIdentifierStart(c);
+ }
+ });
+
+ private static final CharMatcher IDENTIFIER_REST =
+ CharMatcher.forPredicate(new Predicate<Character>() {
+ @Override public boolean apply(Character c) {
+ return Character.isJavaIdentifierPart(c);
+ }
+ });
+
+ private static final Function<URL, InputSupplier<? extends InputStream>> URL_TO_INPUT =
+ new Function<URL, InputSupplier<? extends InputStream>>() {
+ @Override public InputSupplier<? extends InputStream> apply(final URL resource) {
+ return new InputSupplier<InputStream>() {
+ @Override public InputStream getInput() throws IOException {
+ return resource.openStream();
+ }
+ };
+ }
+ };
+
+ private static final Function<InputSupplier<? extends InputStream>,
+ InputSupplier<? extends Reader>> INPUT_TO_READER =
+ new Function<InputSupplier<? extends InputStream>, InputSupplier<? extends Reader>>() {
+ @Override public InputSupplier<? extends Reader> apply(
+ final InputSupplier<? extends InputStream> input) {
+ return CharStreams.newReaderSupplier(input, Charsets.UTF_8);
+ }
+ };
+
+ private static final Function<URL, InputSupplier<? extends Reader>> URL_TO_READER =
+ Functions.compose(INPUT_TO_READER, URL_TO_INPUT);
+
+ private static final String DEFAULT_RESOURCE_NAME = "cmdline.arg.info.txt";
+
+ private int nextResourceIndex;
+ private final ImmutableSet<ArgInfo> positionalInfos;
+ private final ImmutableSet<ArgInfo> cmdLineInfos;
+ private final ImmutableSet<ParserInfo> parserInfos;
+ private final ImmutableSet<VerifierInfo> verifierInfos;
+
+ private Configuration(int nextResourceIndex,
+ Iterable<ArgInfo> positionalInfos, Iterable<ArgInfo> cmdLineInfos,
+ Iterable<ParserInfo> parserInfos, Iterable<VerifierInfo> verifierInfos) {
+ this.nextResourceIndex = nextResourceIndex;
+ this.positionalInfos = ImmutableSet.copyOf(positionalInfos);
+ this.cmdLineInfos = ImmutableSet.copyOf(cmdLineInfos);
+ this.parserInfos = ImmutableSet.copyOf(parserInfos);
+ this.verifierInfos = ImmutableSet.copyOf(verifierInfos);
+ }
+
+ private static String checkValidIdentifier(String identifier, boolean compound) {
+ Preconditions.checkNotNull(identifier);
+
+ String trimmed = identifier.trim();
+ Preconditions.checkArgument(!trimmed.isEmpty(), "Invalid identifier: '%s'", identifier);
+
+ String[] parts = compound ? trimmed.split("\\.") : new String[] {trimmed};
+ for (String part : parts) {
+ Preconditions.checkArgument(
+ IDENTIFIER_REST.matchesAllOf(IDENTIFIER_START.trimLeadingFrom(part)),
+ "Invalid identifier: '%s'", identifier);
+ }
+
+ return trimmed;
+ }
+
+ public static final class ArgInfo {
+ public final String className;
+ public final String fieldName;
+
+ public ArgInfo(String className, String fieldName) {
+ this.className = checkValidIdentifier(className, true);
+ this.fieldName = checkValidIdentifier(fieldName, false);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof ArgInfo)) {
+ return false;
+ }
+
+ ArgInfo other = (ArgInfo) obj;
+
+ return new EqualsBuilder()
+ .append(className, other.className)
+ .append(fieldName, other.fieldName)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(className)
+ .append(fieldName)
+ .toHashCode();
+ }
+
+ @Override public String toString() {
+ return new ToStringBuilder(this)
+ .append("className", className)
+ .append("fieldName", fieldName)
+ .toString();
+ }
+ }
+
+ public static final class ParserInfo {
+ public final String parsedType;
+ public final String parserClass;
+
+ public ParserInfo(String parsedType, String parserClass) {
+ this.parsedType = checkValidIdentifier(parsedType, true);
+ this.parserClass = checkValidIdentifier(parserClass, true);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof ParserInfo)) {
+ return false;
+ }
+
+ ParserInfo other = (ParserInfo) obj;
+
+ return new EqualsBuilder()
+ .append(parsedType, other.parsedType)
+ .append(parserClass, other.parserClass)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(parsedType)
+ .append(parserClass)
+ .toHashCode();
+ }
+
+ @Override public String toString() {
+ return new ToStringBuilder(this)
+ .append("parsedType", parsedType)
+ .append("parserClass", parserClass)
+ .toString();
+ }
+ }
+
+ public static final class VerifierInfo {
+ public final String verifiedType;
+ public final String verifyingAnnotation;
+ public final String verifierClass;
+
+ public VerifierInfo(String verifiedType, String verifyingAnnotation, String verifierClass) {
+ this.verifiedType = checkValidIdentifier(verifiedType, true);
+ this.verifyingAnnotation = checkValidIdentifier(verifyingAnnotation, true);
+ this.verifierClass = checkValidIdentifier(verifierClass, true);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof VerifierInfo)) {
+ return false;
+ }
+
+ VerifierInfo other = (VerifierInfo) obj;
+
+ return new EqualsBuilder()
+ .append(verifiedType, other.verifiedType)
+ .append(verifyingAnnotation, other.verifyingAnnotation)
+ .append(verifierClass, other.verifierClass)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(verifiedType)
+ .append(verifyingAnnotation)
+ .append(verifierClass)
+ .toHashCode();
+ }
+
+ @Override public String toString() {
+ return new ToStringBuilder(this)
+ .append("verifiedType", verifiedType)
+ .append("verifyingAnnotation", verifyingAnnotation)
+ .append("verifierClass", verifierClass)
+ .toString();
+ }
+ }
+
+ static class Builder {
+ private final Set<ArgInfo> positionalInfos = Sets.newHashSet();
+ private final Set<ArgInfo> argInfos = Sets.newHashSet();
+ private final Set<ParserInfo> parserInfos = Sets.newHashSet();
+ private final Set<VerifierInfo> verifierInfos = Sets.newHashSet();
+
+ public boolean isEmpty() {
+ return positionalInfos.isEmpty()
+ && argInfos.isEmpty()
+ && parserInfos.isEmpty()
+ && verifierInfos.isEmpty();
+ }
+
+ void addPositionalInfo(ArgInfo positionalInfo) {
+ positionalInfos.add(positionalInfo);
+ }
+
+ void addCmdLineArg(ArgInfo argInfo) {
+ argInfos.add(argInfo);
+ }
+
+ void addParser(ParserInfo parserInfo) {
+ parserInfos.add(parserInfo);
+ }
+
+ public void addParser(String parserForType, String parserType) {
+ addParser(new ParserInfo(parserForType, parserType));
+ }
+
+ void addVerifier(VerifierInfo verifierInfo) {
+ verifierInfos.add(verifierInfo);
+ }
+
+ public void addVerifier(String verifierForType, String annotationType, String verifierType) {
+ addVerifier(new VerifierInfo(verifierForType, annotationType, verifierType));
+ }
+
+ public Configuration build(Configuration configuration) {
+ return new Configuration(configuration.nextResourceIndex + 1,
+ positionalInfos, argInfos, parserInfos, verifierInfos);
+ }
+ }
+
+ private static String getResourceName(int index) {
+ return String.format("%s.%s", DEFAULT_RESOURCE_NAME, index);
+ }
+
+ private static String getResourcePath(int index) {
+ return String.format("%s/%s", DEFAULT_RESOURCE_PACKAGE.replace('.', '/'),
+ getResourceName(index));
+ }
+
+ static final class ConfigurationResources {
+ private final int nextResourceIndex;
+ private final Iterator<URL> resources;
+
+ private ConfigurationResources(int nextResourceIndex, Iterator<URL> resources) {
+ this.nextResourceIndex = nextResourceIndex;
+ this.resources = resources;
+ }
+ }
+
+ /**
+ * Loads the {@literal @CmdLine} argument configuration data stored in the classpath.
+ *
+ * @return The {@literal @CmdLine} argument configuration materialized from the classpath.
+ * @throws ConfigurationException if any configuration data is malformed.
+ * @throws IOException if the configuration data can not be read from the classpath.
+ */
+ public static Configuration load() throws ConfigurationException, IOException {
+ ConfigurationResources allResources = getAllResources();
+ List<URL> configs = ImmutableList.copyOf(allResources.resources);
+ if (configs.isEmpty()) {
+ LOG.info("No @CmdLine arg configs found on the classpath");
+ } else {
+ LOG.info("Loading @CmdLine config from: " + configs);
+ }
+ return load(allResources.nextResourceIndex, configs);
+ }
+
+ private static ConfigurationResources getAllResources() throws IOException {
+ int maxResourceIndex = 0;
+ Iterator<URL> allResources = getResources(0); // Try for a main
+ // Probe for resource files with index up to 10 (or more, while resources at the
+ // given index can be found)
+ for (int nextResourceIndex = 1; nextResourceIndex <= maxResourceIndex + 10;
+ nextResourceIndex++) {
+ Iterator<URL> resources = getResources(nextResourceIndex);
+ if (resources.hasNext()) {
+ allResources = Iterators.concat(allResources, resources);
+ maxResourceIndex = nextResourceIndex;
+ }
+ }
+ return new ConfigurationResources(maxResourceIndex + 1, allResources);
+ }
+
+ private static Iterator<URL> getResources(int index) throws IOException {
+ return Iterators.forEnumeration(
+ Configuration.class.getClassLoader().getResources(getResourcePath(index)));
+ }
+
+ private static final class ConfigurationParser implements LineProcessor<Configuration> {
+ private final int nextIndex;
+ private int lineNumber = 0;
+
+ private final ImmutableList.Builder<ArgInfo> positionalInfo = ImmutableList.builder();
+ private final ImmutableList.Builder<ArgInfo> fieldInfoBuilder = ImmutableList.builder();
+ private final ImmutableList.Builder<ParserInfo> parserInfoBuilder = ImmutableList.builder();
+ private final ImmutableList.Builder<VerifierInfo> verifierInfoBuilder = ImmutableList.builder();
+
+ private ConfigurationParser(int nextIndex) {
+ this.nextIndex = nextIndex;
+ }
+
+ @Override
+ public boolean processLine(String line) throws IOException {
+ ++lineNumber;
+ String trimmed = line.trim();
+ if (!trimmed.isEmpty() && !trimmed.startsWith("#")) {
+ List<String> parts = Lists.newArrayList(trimmed.split(" "));
+ if (parts.size() < 1) {
+ throw new ConfigurationException("Invalid line: %s @%d", trimmed, lineNumber);
+ }
+
+ String type = parts.remove(0);
+ if ("positional".equals(type)) {
+ if (parts.size() != 2) {
+ throw new ConfigurationException(
+ "Invalid positional line: %s @%d", trimmed, lineNumber);
+ }
+ positionalInfo.add(new ArgInfo(parts.get(0), parts.get(1)));
+ } else if ("field".equals(type)) {
+ if (parts.size() != 2) {
+ throw new ConfigurationException("Invalid field line: %s @%d", trimmed, lineNumber);
+ }
+ fieldInfoBuilder.add(new ArgInfo(parts.get(0), parts.get(1)));
+ } else if ("parser".equals(type)) {
+ if (parts.size() != 2) {
+ throw new ConfigurationException("Invalid parser line: %s @%d", trimmed, lineNumber);
+ }
+ parserInfoBuilder.add(new ParserInfo(parts.get(0), parts.get(1)));
+ } else if ("verifier".equals(type)) {
+ if (parts.size() != 3) {
+ throw new ConfigurationException("Invalid verifier line: %s @%d", trimmed, lineNumber);
+ }
+ verifierInfoBuilder.add(new VerifierInfo(parts.get(0), parts.get(1), parts.get(2)));
+ } else {
+ LOG.warning(String.format("Did not recognize entry type %s for line: %s @%d",
+ type, trimmed, lineNumber));
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public Configuration getResult() {
+ return new Configuration(nextIndex, positionalInfo.build(),
+ fieldInfoBuilder.build(), parserInfoBuilder.build(), verifierInfoBuilder.build());
+ }
+ }
+
+ private static Configuration load(int nextIndex, List<URL> configs)
+ throws ConfigurationException, IOException {
+ InputSupplier<Reader> input = CharStreams.join(Iterables.transform(configs, URL_TO_READER));
+ return CharStreams.readLines(input, new ConfigurationParser(nextIndex));
+ }
+
+ public boolean isEmpty() {
+ return positionalInfos.isEmpty()
+ && cmdLineInfos.isEmpty()
+ && parserInfos.isEmpty()
+ && verifierInfos.isEmpty();
+ }
+
+ /**
+ * Returns the field info for the sole {@literal @Positional} annotated field on the classpath,
+ * if any.
+ *
+ * @return The field info for the {@literal @Positional} annotated field if any.
+ */
+ public Iterable<ArgInfo> positionalInfo() {
+ return positionalInfos;
+ }
+
+ /**
+ * Returns the field info for all the {@literal @CmdLine} annotated fields on the classpath.
+ *
+ * @return The field info for all the {@literal @CmdLine} annotated fields.
+ */
+ public Iterable<ArgInfo> optionInfo() {
+ return cmdLineInfos;
+ }
+
+ /**
+ * Returns the parser info for all the {@literal @ArgParser} annotated parsers on the classpath.
+ *
+ * @return The parser info for all the {@literal @ArgParser} annotated parsers.
+ */
+ public Iterable<ParserInfo> parserInfo() {
+ return parserInfos;
+ }
+
+ /**
+ * Returns the verifier info for all the {@literal @VerifierFor} annotated verifiers on the
+ * classpath.
+ *
+ * @return The verifier info for all the {@literal @VerifierFor} annotated verifiers.
+ */
+ public Iterable<VerifierInfo> verifierInfo() {
+ return verifierInfos;
+ }
+
+ static String mainResourceName() {
+ return getResourceName(0);
+ }
+
+ String nextResourceName() {
+ return getResourceName(nextResourceIndex);
+ }
+
+ void store(Writer output, String message) {
+ PrintWriter writer = new PrintWriter(output);
+ writer.printf("# %s\n", new Date());
+ writer.printf("# %s\n ", message);
+
+ writer.println();
+ for (ArgInfo info : positionalInfos) {
+ writer.printf("positional %s %s\n", info.className, info.fieldName);
+ }
+
+ writer.println();
+ for (ArgInfo info : cmdLineInfos) {
+ writer.printf("field %s %s\n", info.className, info.fieldName);
+ }
+
+ writer.println();
+ for (ParserInfo info : parserInfos) {
+ writer.printf("parser %s %s\n", info.parsedType, info.parserClass);
+ }
+
+ writer.println();
+ for (VerifierInfo info : verifierInfos) {
+ writer.printf("verifier %s %s %s\n",
+ info.verifiedType, info.verifyingAnnotation, info.verifierClass);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons-args/src/main/resources/META-INF/services/javax.annotation.processing.Processor
----------------------------------------------------------------------
diff --git a/commons-args/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/commons-args/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index bc5a756..b548fcd 100644
--- a/commons-args/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/commons-args/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -1 +1 @@
-com.twitter.common.args.apt.CmdLineProcessor
+org.apache.aurora.common.args.apt.CmdLineProcessor
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/AbstractApplication.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/AbstractApplication.java b/commons/src/main/java/com/twitter/common/application/AbstractApplication.java
deleted file mode 100644
index 17514e3..0000000
--- a/commons/src/main/java/com/twitter/common/application/AbstractApplication.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.util.Collections;
-
-import com.google.inject.Module;
-
-/**
- * A base application class that provides empty implementations of all but the {@link #run()}
- * method.
- */
-public abstract class AbstractApplication implements Application {
- @Override
- public Iterable<? extends Module> getModules() {
- return Collections.emptyList();
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/AppLauncher.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/AppLauncher.java b/commons/src/main/java/com/twitter/common/application/AppLauncher.java
deleted file mode 100644
index 700454f..0000000
--- a/commons/src/main/java/com/twitter/common/application/AppLauncher.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.google.common.base.Preconditions;
-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.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-import com.google.inject.Stage;
-import com.google.inject.util.Modules;
-
-import com.twitter.common.application.modules.AppLauncherModule;
-import com.twitter.common.application.modules.LifecycleModule;
-import com.twitter.common.args.Arg;
-import com.twitter.common.args.ArgFilters;
-import com.twitter.common.args.ArgScanner;
-import com.twitter.common.args.ArgScanner.ArgScanException;
-import com.twitter.common.args.CmdLine;
-import com.twitter.common.args.constraints.NotNull;
-import com.twitter.common.base.ExceptionalCommand;
-
-/**
- * An application launcher that sets up a framework for pluggable binding modules. This class
- * should be called directly as the main class, with a command line argument {@code -app_class}
- * which is the canonical class name of the application to execute.
- *
- * If your application uses command line arguments all {@link Arg} fields annotated with
- * {@link CmdLine} will be discovered and command line arguments will be validated against this set,
- * parsed and applied.
- *
- * A bootstrap module will be automatically applied ({@link AppLauncherModule}), which provides
- * overridable default bindings for things like quit/abort hooks and a health check function.
- * A {@link LifecycleModule} is also automatically applied to perform startup and shutdown
- * actions.
- */
-public final class AppLauncher {
-
- private static final Logger LOG = Logger.getLogger(AppLauncher.class.getName());
-
- private static final String APP_CLASS_NAME = "app_class";
- @NotNull
- @CmdLine(name = APP_CLASS_NAME,
- help = "Fully-qualified name of the application class, which must implement Runnable.")
- private static final Arg<Class<? extends Application>> APP_CLASS = Arg.create();
-
- @CmdLine(name = "guice_stage",
- help = "Guice development stage to create injector with.")
- private static final Arg<Stage> GUICE_STAGE = Arg.create(Stage.DEVELOPMENT);
-
- private static final Predicate<Field> SELECT_APP_CLASS =
- ArgFilters.selectCmdLineArg(AppLauncher.class, APP_CLASS_NAME);
-
- @Inject @StartupStage private ExceptionalCommand startupCommand;
- @Inject private Lifecycle lifecycle;
-
- private AppLauncher() {
- // This should not be invoked directly.
- }
-
- private void run(Application application) {
- try {
- configureInjection(application);
-
- LOG.info("Executing startup actions.");
- // We're an app framework and this is the outer shell - it makes sense to handle all errors
- // before exiting.
- // SUPPRESS CHECKSTYLE:OFF IllegalCatch
- try {
- startupCommand.execute();
- } catch (Exception e) {
- LOG.log(Level.SEVERE, "Startup action failed, quitting.", e);
- throw Throwables.propagate(e);
- }
- // SUPPRESS CHECKSTYLE:ON IllegalCatch
-
- try {
- application.run();
- } finally {
- LOG.info("Application run() exited.");
- }
- } finally {
- if (lifecycle != null) {
- lifecycle.shutdown();
- }
- }
- }
-
- private void configureInjection(Application application) {
- Iterable<Module> modules = ImmutableList.<Module>builder()
- .add(new LifecycleModule())
- .add(new AppLauncherModule())
- .addAll(application.getModules())
- .build();
-
- Injector injector = Guice.createInjector(GUICE_STAGE.get(), Modules.combine(modules));
- injector.injectMembers(this);
- injector.injectMembers(application);
- }
-
- public static void main(String... args) throws IllegalAccessException, InstantiationException {
- // TODO(John Sirois): Support a META-INF/MANIFEST.MF App-Class attribute to allow java -jar
- parseArgs(ArgFilters.SELECT_ALL, Arrays.asList(args));
- new AppLauncher().run(APP_CLASS.get().newInstance());
- }
-
- /**
- * A convenience for main wrappers. Equivalent to:
- * <pre>
- * AppLauncher.launch(appClass, ArgFilters.SELECT_ALL, Arrays.asList(args));
- * </pre>
- *
- * @param appClass The application class to instantiate and launch.
- * @param args The command line arguments to parse.
- * @see ArgFilters
- */
- public static void launch(Class<? extends Application> appClass, String... args) {
- launch(appClass, ArgFilters.SELECT_ALL, Arrays.asList(args));
- }
-
- /**
- * A convenience for main wrappers. Equivalent to:
- * <pre>
- * AppLauncher.launch(appClass, argFilter, Arrays.asList(args));
- * </pre>
- *
- * @param appClass The application class to instantiate and launch.
- * @param argFilter A filter that selects the {@literal @CmdLine} {@link Arg}s to enable for
- * parsing.
- * @param args The command line arguments to parse.
- * @see ArgFilters
- */
- public static void launch(Class<? extends Application> appClass, Predicate<Field> argFilter,
- String... args) {
- launch(appClass, argFilter, Arrays.asList(args));
- }
-
- /**
- * Used to launch an application with a restricted set of {@literal @CmdLine} {@link Arg}s
- * considered for parsing. This is useful if the classpath includes annotated fields you do not
- * wish arguments to be parsed for.
- *
- * @param appClass The application class to instantiate and launch.
- * @param argFilter A filter that selects the {@literal @CmdLine} {@link Arg}s to enable for
- * parsing.
- * @param args The command line arguments to parse.
- * @see ArgFilters
- */
- public static void launch(Class<? extends Application> appClass, Predicate<Field> argFilter,
- List<String> args) {
- Preconditions.checkNotNull(appClass);
- Preconditions.checkNotNull(argFilter);
- Preconditions.checkNotNull(args);
-
- parseArgs(Predicates.<Field>and(Predicates.not(SELECT_APP_CLASS), argFilter), args);
- try {
- new AppLauncher().run(appClass.newInstance());
- } catch (InstantiationException e) {
- throw new IllegalStateException(e);
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private static void parseArgs(Predicate<Field> filter, List<String> args) {
- try {
- if (!new ArgScanner().parse(filter, args)) {
- System.exit(0);
- }
- } catch (ArgScanException e) {
- exit("Failed to scan arguments", e);
- } catch (IllegalArgumentException e) {
- exit("Failed to apply arguments", e);
- }
- }
-
- private static void exit(String message, Exception error) {
- LOG.log(Level.SEVERE, message + "\n" + error, error);
- System.exit(1);
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/Application.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/Application.java b/commons/src/main/java/com/twitter/common/application/Application.java
deleted file mode 100644
index 5a2a9b8..0000000
--- a/commons/src/main/java/com/twitter/common/application/Application.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import com.google.inject.Module;
-
-/**
- * An application that supports a limited lifecycle and optional binding of guice modules.
- */
-public interface Application extends Runnable {
-
- /**
- * Returns binding modules for the application.
- *
- * @return Application binding modules.
- */
- Iterable<? extends Module> getModules();
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/Lifecycle.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/Lifecycle.java b/commons/src/main/java/com/twitter/common/application/Lifecycle.java
deleted file mode 100644
index 5c7af1f..0000000
--- a/commons/src/main/java/com/twitter/common/application/Lifecycle.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.logging.Logger;
-
-import com.google.inject.Inject;
-
-import com.twitter.common.base.Command;
-
-/**
- * Application lifecycle manager, which coordinates orderly shutdown of an application. This class
- * is responsible for executing shutdown commands, and can also be used to allow threads to await
- * application shutdown.
- *
- * @author William Farner
- */
-public class Lifecycle {
-
- private static final Logger LOG = Logger.getLogger(Lifecycle.class.getName());
-
- // Monitor and state for suspending and terminating execution.
- private final Object waitMonitor = new Object();
- private boolean destroyed = false;
-
- private final Command shutdownRegistry;
-
- @Inject
- public Lifecycle(@ShutdownStage Command shutdownRegistry,
- UncaughtExceptionHandler exceptionHandler) {
-
- this.shutdownRegistry = shutdownRegistry;
- Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
- }
-
- /**
- * Checks whether this lifecycle is still considered alive. The lifecycle is still alive until
- * {@link #shutdown()} has been called and all of the actions registered with the shutdown
- * controller have completed.
- *
- * @return {@code true} if the lifecycle is alive, {@code false} otherwise.
- *
- */
- public final boolean isAlive() {
- synchronized (waitMonitor) {
- return !destroyed;
- }
- }
-
- /**
- * Allows a caller to wait forever; typically used when all work is done in daemon threads.
- * Will exit on interrupts.
- */
- public final void awaitShutdown() {
- LOG.info("Awaiting shutdown");
- synchronized (waitMonitor) {
- while (!destroyed) {
- try {
- waitMonitor.wait();
- } catch (InterruptedException e) {
- LOG.info("Exiting on interrupt");
- shutdown();
- return;
- }
- }
- }
- }
-
- /**
- * Initiates an orderly shutdown of the lifecycle's registered shutdown hooks.
- */
- public final void shutdown() {
- synchronized (waitMonitor) {
- if (!destroyed) {
- destroyed = true;
- LOG.info("Shutting down application");
- shutdownRegistry.execute();
- waitMonitor.notifyAll();
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/ShutdownRegistry.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/ShutdownRegistry.java b/commons/src/main/java/com/twitter/common/application/ShutdownRegistry.java
deleted file mode 100644
index dc20861..0000000
--- a/commons/src/main/java/com/twitter/common/application/ShutdownRegistry.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
-import com.twitter.common.base.Command;
-import com.twitter.common.base.ExceptionalCommand;
-
-/**
- * A shutdown action controller. It executes actions in the reverse order they were registered, and
- * logs a warning for every shutdown action that fails, but doesn't prevent completion of subsequent
- * actions or the normal completion of the {@code execute()} method.
- *
- * @author Attila Szegedi
- */
-public interface ShutdownRegistry {
-
- /**
- * Adds an action to the shutdown registry.
- *
- * @param action Action to register.
- * @param <E> Exception type thrown by the action.
- * @param <T> Type of command.
- */
- <E extends Exception, T extends ExceptionalCommand<E>> void addAction(T action);
-
- /**
- * Implementation of a shutdown registry.
- */
- public static class ShutdownRegistryImpl implements ShutdownRegistry, Command {
- private static final Logger LOG = Logger.getLogger(ShutdownRegistry.class.getName());
-
- private final List<ExceptionalCommand<? extends Exception>> actions = Lists.newLinkedList();
-
- private boolean completed = false;
-
- /**
- * Registers an action to execute during {@link #execute()}. It is an error to call this method
- * after calling {@link #execute()}.
- *
- * @param action the action to add to the list of actions to execute during execution
- */
- @Override
- public synchronized <E extends Exception, T extends ExceptionalCommand<E>> void addAction(
- T action) {
- Preconditions.checkState(!completed);
- actions.add(action);
- }
-
- /**
- * Executes an application shutdown stage by executing all registered actions. This method can
- * be called multiple times but will only execute the registered actions the first time.
- *
- * This sends output to System.out because logging is unreliable during JVM shutdown, which
- * this class may be used for.
- */
- @Override
- public synchronized void execute() {
- if (!completed) {
- LOG.info(String.format("Executing %d shutdown commands.", actions.size()));
- completed = true;
- try {
- for (ExceptionalCommand<? extends Exception> action : Lists.reverse(actions)) {
- // Part of our contract is ensuring each shutdown action executes so we must catch all
- // exceptions.
- // SUPPRESS CHECKSTYLE:OFF IllegalCatch
- try {
- action.execute();
- } catch (Exception e) {
- LOG.log(Level.WARNING, "Shutdown action failed.", e);
- }
- // SUPPRESS CHECKSTYLE:ON IllegalCatch
- }
- } finally {
- actions.clear();
- }
- } else {
- LOG.info("Action controller has already completed, subsequent calls ignored.");
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/ShutdownStage.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/ShutdownStage.java b/commons/src/main/java/com/twitter/common/application/ShutdownStage.java
deleted file mode 100644
index 09a7229..0000000
--- a/commons/src/main/java/com/twitter/common/application/ShutdownStage.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import com.google.inject.BindingAnnotation;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Binding annotation used for the shutdown registry.
- */
-@BindingAnnotation
-@Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
-public @interface ShutdownStage { }
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/StartupRegistry.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/StartupRegistry.java b/commons/src/main/java/com/twitter/common/application/StartupRegistry.java
deleted file mode 100644
index 943c7af..0000000
--- a/commons/src/main/java/com/twitter/common/application/StartupRegistry.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Logger;
-
-import com.google.common.base.Preconditions;
-import com.google.inject.Inject;
-
-import com.twitter.common.base.ExceptionalCommand;
-
-/**
- * A registry that executes a set of commands. The registry will synchronously execute commands
- * when {@link #execute()} is invoked, returning early if any action throws an exception.
- * Only one call to {@link #execute()} will have an effect, all subsequent calls will be ignored.
- */
-public class StartupRegistry implements ExceptionalCommand<Exception> {
-
- private static final Logger LOG = Logger.getLogger(StartupRegistry.class.getName());
-
- private final Set<ExceptionalCommand> startupActions;
- private final AtomicBoolean started = new AtomicBoolean(false);
-
- @Inject
- public StartupRegistry(@StartupStage Set<ExceptionalCommand> startupActions) {
- this.startupActions = Preconditions.checkNotNull(startupActions);
- }
-
- @Override
- public void execute() throws Exception {
- if (!started.compareAndSet(false, true)) {
- LOG.warning("Startup actions cannot be executed more than once, ignoring.");
- }
-
- for (ExceptionalCommand<?> startupAction : startupActions) {
- startupAction.execute();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/StartupStage.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/StartupStage.java b/commons/src/main/java/com/twitter/common/application/StartupStage.java
deleted file mode 100644
index 0938cee..0000000
--- a/commons/src/main/java/com/twitter/common/application/StartupStage.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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 com.twitter.common.application;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import com.google.inject.BindingAnnotation;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Binding annotation used for the startup registry.
- */
-@BindingAnnotation
-@Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
-public @interface StartupStage { }
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/http/DefaultQuitHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/http/DefaultQuitHandler.java b/commons/src/main/java/com/twitter/common/application/http/DefaultQuitHandler.java
deleted file mode 100644
index 544b4dc..0000000
--- a/commons/src/main/java/com/twitter/common/application/http/DefaultQuitHandler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * 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 com.twitter.common.application.http;
-
-import java.util.logging.Logger;
-
-import com.google.inject.Inject;
-
-import com.twitter.common.application.Lifecycle;
-
-/**
- * The default quit handler to use, which invokes {@link Lifecycle#shutdown()}.
- *
- * @author William Farner
- */
-public class DefaultQuitHandler implements Runnable {
-
- private static final Logger LOG = Logger.getLogger(DefaultQuitHandler.class.getName());
-
- private final Lifecycle lifecycle;
-
- @Inject
- public DefaultQuitHandler(Lifecycle lifecycle) {
- this.lifecycle = lifecycle;
- }
-
- @Override
- public void run() {
- LOG.info("Instructing lifecycle to destroy.");
- lifecycle.shutdown();
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/http/GraphViewer.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/http/GraphViewer.java b/commons/src/main/java/com/twitter/common/application/http/GraphViewer.java
deleted file mode 100644
index adb1ddc..0000000
--- a/commons/src/main/java/com/twitter/common/application/http/GraphViewer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * 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 com.twitter.common.application.http;
-
-import com.google.inject.Binder;
-
-/**
- * A utility class to register the file resources for the graph viewer.
- */
-public final class GraphViewer {
-
- private GraphViewer() {
- // Utility class.
- }
-
- private static void registerJs(Binder binder, String assetName) {
- Registration.registerHttpAsset(
- binder,
- "/graphview/" + assetName,
- GraphViewer.class,
- "graphview/" + assetName,
- "application/javascript",
- true);
- }
-
- /**
- * Registers required resources with the binder.
- *
- * @param binder Binder to register with.
- */
- public static void registerResources(Binder binder) {
- registerJs(binder, "dygraph-combined.js");
- registerJs(binder, "dygraph-extra.js");
- registerJs(binder, "grapher.js");
- registerJs(binder, "parser.js");
- Registration.registerHttpAsset(binder,
- "/graphview", GraphViewer.class, "graphview/graphview.html", "text/html", false);
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/http/HttpAssetConfig.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/http/HttpAssetConfig.java b/commons/src/main/java/com/twitter/common/application/http/HttpAssetConfig.java
deleted file mode 100644
index ed7a2bd..0000000
--- a/commons/src/main/java/com/twitter/common/application/http/HttpAssetConfig.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * 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 com.twitter.common.application.http;
-
-import java.net.URL;
-
-import com.google.common.io.Resources;
-
-import com.twitter.common.net.http.handlers.AssetHandler;
-import com.twitter.common.net.http.handlers.AssetHandler.StaticAsset;
-
-import static com.twitter.common.base.MorePreconditions.checkNotBlank;
-
-/**
- * Configuration for a static HTTP-served asset.
- *
- * TODO(William Farner): Move this to a more appropriate package after initial AppLauncher check-in.
- *
- * @author William Farner
- */
-public class HttpAssetConfig {
- public final String path;
- public final AssetHandler handler;
- public final boolean silent;
-
- /**
- * Creates a new asset configuration.
- *
- * @param path HTTP path the asset should be accessible from.
- * @param asset Asset resource URL.
- * @param contentType HTTP content-type to report for the asset.
- * @param silent Whether the asset should be visible on the default index page.
- */
- public HttpAssetConfig(String path, URL asset, String contentType, boolean silent) {
- this.path = checkNotBlank(path);
- this.handler = new AssetHandler(
- new StaticAsset(Resources.newInputStreamSupplier(asset), contentType, true));
- this.silent = silent;
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/http/HttpFilterConfig.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/http/HttpFilterConfig.java b/commons/src/main/java/com/twitter/common/application/http/HttpFilterConfig.java
deleted file mode 100644
index 59b746f..0000000
--- a/commons/src/main/java/com/twitter/common/application/http/HttpFilterConfig.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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 com.twitter.common.application.http;
-
-import javax.servlet.Filter;
-
-import com.twitter.common.base.MorePreconditions;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Configuration tuple for an HTTP filter.
- */
-public class HttpFilterConfig {
- public final Class<? extends Filter> filterClass;
- public final String pathSpec;
-
- /**
- * Creates a new filter configuration.
- *
- * @param filterClass Filter class.
- * @param pathSpec Path spec that the filter should match.
- */
- public HttpFilterConfig(Class<? extends Filter> filterClass, String pathSpec) {
- this.pathSpec = MorePreconditions.checkNotBlank(pathSpec);
- this.filterClass = checkNotNull(filterClass);
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/http/HttpServletConfig.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/http/HttpServletConfig.java b/commons/src/main/java/com/twitter/common/application/http/HttpServletConfig.java
deleted file mode 100644
index d3b8829..0000000
--- a/commons/src/main/java/com/twitter/common/application/http/HttpServletConfig.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * 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 com.twitter.common.application.http;
-
-import javax.servlet.http.HttpServlet;
-
-import com.google.common.collect.ImmutableMap;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import static com.twitter.common.base.MorePreconditions.checkNotBlank;
-
-/**
- * An {@link javax.servlet.http.HttpServlet} configuration used to mount HTTP handlers via
- * {@link Registration#registerServlet(com.google.inject.Binder, HttpServletConfig)}.
- *
- * TODO(William Farner): Move this to a more appropriate package after initial AppLauncher check-in.
- *
- */
-public class HttpServletConfig {
- public final String path;
- public final Class<? extends HttpServlet> handlerClass;
- public final ImmutableMap<String, String> params;
- public final boolean silent;
-
- /**
- * Creates a new servlet config.
- *
- * @param path the absolute path to mount the handler on
- * @param servletClass the type of servlet that will render pages at {@code path}
- * @param silent whether or not to display a link for this handler on the landing page
- */
- public HttpServletConfig(String path, Class<? extends HttpServlet> servletClass,
- boolean silent) {
- this(path, servletClass, ImmutableMap.<String, String>of(), silent);
- }
-
- /**
- * Registers a new servlet config with servlet initialization parameters.
- *
- * @param path the absolute path to mount the handler on
- * @param servletClass the type of servlet that will render pages at {@code path}
- * @param params a map of servlet init parameters to initialize the servlet with
- * @param silent whether or not to display a link for this handler on the landing page
- */
- public HttpServletConfig(String path, Class<? extends HttpServlet> servletClass,
- ImmutableMap<String, String> params, boolean silent) {
-
- this.path = checkNotBlank(path);
- this.handlerClass = checkNotNull(servletClass);
- this.params = checkNotNull(params);
- this.silent = silent;
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/application/http/Registration.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/application/http/Registration.java b/commons/src/main/java/com/twitter/common/application/http/Registration.java
deleted file mode 100644
index fef5d09..0000000
--- a/commons/src/main/java/com/twitter/common/application/http/Registration.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * 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 com.twitter.common.application.http;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import java.net.URL;
-
-import javax.servlet.Filter;
-import javax.servlet.http.HttpServlet;
-
-import com.google.common.io.Resources;
-import com.google.inject.Binder;
-import com.google.inject.BindingAnnotation;
-import com.google.inject.multibindings.Multibinder;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Utility class for registering HTTP servlets and assets.
- */
-public final class Registration {
-
- private Registration() {
- // Utility class.
- }
-
- /**
- * Equivalent to
- * {@code registerServlet(binder, new HttpServletConfig(path, servletClass, silent))}.
- */
- public static void registerServlet(Binder binder, String path,
- Class<? extends HttpServlet> servletClass, boolean silent) {
- registerServlet(binder, new HttpServletConfig(path, servletClass, silent));
- }
-
- /**
- * Registers a binding for an {@link javax.servlet.http.HttpServlet} to be exported at a specified
- * path.
- *
- * @param binder a guice binder to register the handler with
- * @param config a servlet mounting specification
- */
- public static void registerServlet(Binder binder, HttpServletConfig config) {
- Multibinder.newSetBinder(binder, HttpServletConfig.class).addBinding().toInstance(config);
- }
-
- /**
- * A binding annotation applied to the set of additional index page links bound via
- * {@link #Registration#registerEndpoint()}
- */
- @BindingAnnotation
- @Target({FIELD, PARAMETER, METHOD})
- @Retention(RUNTIME)
- public @interface IndexLink { }
-
- /**
- * Gets the multibinder used to bind links on the root servlet.
- * The resulting {@link java.util.Set} is bound with the {@link IndexLink} annotation.
- *
- * @param binder a guice binder to associate the multibinder with.
- * @return The multibinder to bind index links against.
- */
- public static Multibinder<String> getEndpointBinder(Binder binder) {
- return Multibinder.newSetBinder(binder, String.class, IndexLink.class);
- }
-
- /**
- * Registers a link to display on the root servlet.
- *
- * @param binder a guice binder to register the link with.
- * @param endpoint Endpoint URI to include.
- */
- public static void registerEndpoint(Binder binder, String endpoint) {
- getEndpointBinder(binder).addBinding().toInstance(endpoint);
- }
-
- /**
- * Registers a binding for a URL asset to be served by the HTTP server, with an optional
- * entity tag for cache control.
- *
- * @param binder a guice binder to register the handler with
- * @param servedPath Path to serve the resource from in the HTTP server.
- * @param asset Resource to be served.
- * @param assetType MIME-type for the asset.
- * @param silent Whether the server should hide this asset on the index page.
- */
- public static void registerHttpAsset(Binder binder, String servedPath, URL asset,
- String assetType, boolean silent) {
- Multibinder.newSetBinder(binder, HttpAssetConfig.class).addBinding().toInstance(
- new HttpAssetConfig(servedPath, asset, assetType, silent));
- }
-
- /**
- * Registers a binding for a classpath resource to be served by the HTTP server, using a resource
- * path relative to a class.
- *
- * @param binder a guice binder to register the handler with
- * @param servedPath Path to serve the asset from in the HTTP server.
- * @param contextClass Context class for defining the relative path to the asset.
- * @param assetRelativePath Path to the served asset, relative to {@code contextClass}.
- * @param assetType MIME-type for the asset.
- * @param silent Whether the server should hide this asset on the index page.
- */
- public static void registerHttpAsset(
- Binder binder,
- String servedPath,
- Class<?> contextClass,
- String assetRelativePath,
- String assetType,
- boolean silent) {
-
- registerHttpAsset(binder, servedPath, Resources.getResource(contextClass, assetRelativePath),
- assetType, silent);
- }
-
- /**
- * Gets the multibinder used to bind HTTP filters.
- *
- * @param binder a guice binder to associate the multibinder with.
- * @return The multibinder to bind HTTP filter configurations against.
- */
- public static Multibinder<HttpFilterConfig> getFilterBinder(Binder binder) {
- return Multibinder.newSetBinder(binder, HttpFilterConfig.class);
- }
-
- /**
- * Registers an HTTP servlet filter.
- *
- * @param binder a guice binder to register the filter with.
- * @param filterClass Filter class to register.
- * @param pathSpec Path spec that the filter should be activated on.
- */
- public static void registerServletFilter(
- Binder binder,
- Class<? extends Filter> filterClass,
- String pathSpec) {
-
- getFilterBinder(binder).addBinding().toInstance(new HttpFilterConfig(filterClass, pathSpec));
- }
-}