aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zma...@apache.org
Subject [49/51] [partial] aurora git commit: Move packages from com.twitter.common to org.apache.aurora.common
Date Wed, 26 Aug 2015 21:00:39 GMT
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));
-  }
-}


Mime
View raw message