Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id C75DE200D27 for ; Wed, 11 Oct 2017 02:29:15 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id C5E17160BE0; Wed, 11 Oct 2017 00:29:15 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A5250160BE4 for ; Wed, 11 Oct 2017 02:29:13 +0200 (CEST) Received: (qmail 83611 invoked by uid 500); 11 Oct 2017 00:29:12 -0000 Mailing-List: contact commits-help@aurora.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aurora.apache.org Delivered-To: mailing list commits@aurora.apache.org Received: (qmail 83486 invoked by uid 99); 11 Oct 2017 00:29:12 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 11 Oct 2017 00:29:12 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 9C6A8E9688; Wed, 11 Oct 2017 00:29:10 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: wfarner@apache.org To: commits@aurora.apache.org Date: Wed, 11 Oct 2017 00:29:17 -0000 Message-Id: In-Reply-To: <267bd21f25a441cca38d85834ead8d5b@git.apache.org> References: <267bd21f25a441cca38d85834ead8d5b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [8/8] aurora git commit: Use a simpler command line argument system archived-at: Wed, 11 Oct 2017 00:29:15 -0000 Use a simpler command line argument system Reviewed at https://reviews.apache.org/r/62623/ Project: http://git-wip-us.apache.org/repos/asf/aurora/repo Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/519e3df7 Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/519e3df7 Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/519e3df7 Branch: refs/heads/master Commit: 519e3df732ea5d009d92685ee3c4823606eb2462 Parents: cb8e956 Author: Bill Farner Authored: Tue Oct 10 17:24:45 2017 -0700 Committer: Bill Farner Committed: Tue Oct 10 17:24:45 2017 -0700 ---------------------------------------------------------------------- build.gradle | 67 +- .../java/org/apache/aurora/common/args/Arg.java | 127 ---- .../apache/aurora/common/args/ArgParser.java | 28 - .../org/apache/aurora/common/args/CmdLine.java | 54 -- .../org/apache/aurora/common/args/NoParser.java | 23 - .../org/apache/aurora/common/args/Parser.java | 35 - .../apache/aurora/common/args/ParserOracle.java | 31 - .../org/apache/aurora/common/args/Verifier.java | 37 -- .../apache/aurora/common/args/VerifierFor.java | 34 - .../common/args/apt/CmdLineProcessor.java | 628 ------------------ .../aurora/common/args/apt/Configuration.java | 476 -------------- .../javax.annotation.processing.Processor | 1 - .../apache/aurora/common/args/ArgFilters.java | 109 ---- .../apache/aurora/common/args/ArgScanner.java | 473 -------------- .../org/apache/aurora/common/args/Args.java | 171 ----- .../apache/aurora/common/args/ArgumentInfo.java | 216 ------- .../apache/aurora/common/args/OptionInfo.java | 145 ----- .../org/apache/aurora/common/args/Parsers.java | 110 ---- .../org/apache/aurora/common/args/TypeUtil.java | 120 ---- .../apache/aurora/common/args/Verifiers.java | 89 --- .../common/args/constraints/CanExecute.java | 30 - .../constraints/CanExecuteFileVerifier.java | 40 -- .../aurora/common/args/constraints/CanRead.java | 30 - .../args/constraints/CanReadFileVerifier.java | 40 -- .../common/args/constraints/CanWrite.java | 30 - .../args/constraints/CanWriteFileVerifier.java | 40 -- .../aurora/common/args/constraints/Exists.java | 30 - .../args/constraints/ExistsFileVerifier.java | 40 -- .../common/args/constraints/IsDirectory.java | 30 - .../constraints/IsDirectoryFileVerifier.java | 40 -- .../common/args/constraints/NotEmpty.java | 30 - .../constraints/NotEmptyIterableVerifier.java | 41 -- .../constraints/NotEmptyStringVerifier.java | 39 -- .../common/args/constraints/NotNegative.java | 30 - .../constraints/NotNegativeNumberVerifier.java | 39 -- .../aurora/common/args/constraints/NotNull.java | 30 - .../args/constraints/NotNullVerifier.java | 39 -- .../common/args/constraints/Positive.java | 30 - .../constraints/PositiveNumberVerifier.java | 39 -- .../aurora/common/args/constraints/Range.java | 40 -- .../args/constraints/RangeNumberVerifier.java | 70 -- .../common/args/parsers/AmountParser.java | 86 --- .../common/args/parsers/BooleanParser.java | 30 - .../aurora/common/args/parsers/ByteParser.java | 29 - .../common/args/parsers/CharacterParser.java | 33 - .../aurora/common/args/parsers/ClassParser.java | 48 -- .../aurora/common/args/parsers/DateParser.java | 41 -- .../common/args/parsers/DoubleParser.java | 29 - .../common/args/parsers/DurationParser.java | 80 --- .../aurora/common/args/parsers/EnumParser.java | 37 -- .../aurora/common/args/parsers/FileParser.java | 31 - .../aurora/common/args/parsers/FloatParser.java | 29 - .../args/parsers/InetSocketAddressParser.java | 32 - .../common/args/parsers/IntegerParser.java | 29 - .../aurora/common/args/parsers/ListParser.java | 47 -- .../aurora/common/args/parsers/LongParser.java | 29 - .../aurora/common/args/parsers/MapParser.java | 68 -- .../common/args/parsers/MultimapParser.java | 65 -- .../parsers/NonParameterizedTypeParser.java | 41 -- .../common/args/parsers/NumberParser.java | 41 -- .../aurora/common/args/parsers/PairParser.java | 57 -- .../common/args/parsers/PatternParser.java | 35 - .../aurora/common/args/parsers/RangeParser.java | 46 -- .../aurora/common/args/parsers/SetParser.java | 49 -- .../aurora/common/args/parsers/ShortParser.java | 29 - .../common/args/parsers/StringParser.java | 29 - .../args/parsers/TypeParameterizedParser.java | 65 -- .../aurora/common/args/parsers/URIParser.java | 36 -- .../aurora/common/args/parsers/URLParser.java | 36 -- .../aurora/common/args/parsers/UnitParser.java | 54 -- .../apache/aurora/common/quantity/Amount.java | 2 +- .../aurora/common/args/ArgFiltersTest.java | 98 --- .../aurora/common/args/ArgScannerTest.java | 632 ------------------- .../org/apache/aurora/common/args/ArgTest.java | 34 - .../org/apache/aurora/common/args/ArgsTest.java | 67 -- .../aurora/common/args/OptionInfoTest.java | 62 -- .../apache/aurora/common/args/ParsersTest.java | 80 --- .../common/args/argfilterstest/ArgsRoot.java | 29 - .../args/argfilterstest/subpackageA/ArgsA.java | 29 - .../subpackageA/subsubpackage1/ArgsA1.java | 29 - .../args/argfilterstest/subpackageB/ArgsB.java | 29 - .../subpackageBwithSuffix/ArgsBWithSuffix.java | 29 - config/checkstyle/checkstyle.xml | 5 - config/checkstyle/suppressions.xml | 2 +- config/findbugs/excludeFilter.xml | 6 + .../aurora/benchmark/SchedulingBenchmarks.java | 14 +- .../benchmark/StateManagerBenchmarks.java | 4 +- .../aurora/benchmark/StatusUpdateBenchmark.java | 3 +- .../aurora/benchmark/TaskStoreBenchmarks.java | 4 +- .../aurora/benchmark/ThriftApiBenchmarks.java | 4 +- .../aurora/scheduler/SchedulerModule.java | 60 +- .../org/apache/aurora/scheduler/TierModule.java | 33 +- .../apache/aurora/scheduler/app/AppModule.java | 158 ++--- .../aurora/scheduler/app/MoreModules.java | 67 +- .../aurora/scheduler/app/SchedulerMain.java | 176 +++--- .../aurora/scheduler/app/VolumeConverter.java | 54 ++ .../aurora/scheduler/app/VolumeParser.java | 46 -- .../aurora/scheduler/async/AsyncModule.java | 21 +- .../aurora/scheduler/base/TaskTestUtil.java | 3 +- .../aurora/scheduler/config/CliOptions.java | 114 ++++ .../aurora/scheduler/config/CommandLine.java | 198 ++++++ .../config/converters/ClassConverter.java | 49 ++ .../config/converters/DataAmountConverter.java | 57 ++ .../converters/DockerParameterConverter.java | 36 ++ .../converters/InetSocketAddressConverter.java | 32 + .../config/converters/TimeAmountConverter.java | 57 ++ .../scheduler/config/types/DataAmount.java | 28 + .../scheduler/config/types/TimeAmount.java | 28 + .../config/validators/NotEmptyIterable.java | 28 + .../config/validators/NotEmptyString.java | 27 + .../config/validators/NotNegativeAmount.java | 29 + .../config/validators/PositiveAmount.java | 29 + .../config/validators/PositiveNumber.java | 27 + .../config/validators/ReadableFile.java | 29 + .../configuration/ConfigurationManager.java | 14 +- .../configuration/executor/ExecutorModule.java | 147 +++-- .../scheduler/cron/quartz/CronModule.java | 61 +- .../discovery/FlaggedZooKeeperConfig.java | 79 +-- .../scheduler/discovery/ZooKeeperConfig.java | 5 + .../aurora/scheduler/events/WebhookModule.java | 58 +- .../aurora/scheduler/http/H2ConsoleModule.java | 18 +- .../scheduler/http/JettyServerModule.java | 95 +-- .../aurora/scheduler/http/api/ApiModule.java | 31 +- .../http/api/security/HttpSecurityModule.java | 78 ++- .../http/api/security/IniShiroRealmModule.java | 31 +- .../api/security/Kerberos5ShiroRealmModule.java | 44 +- .../security/KerberosPrincipalConverter.java | 39 ++ .../api/security/KerberosPrincipalParser.java | 27 - .../http/api/security/ModuleParser.java | 54 -- .../http/api/security/ShiroIniConverter.java | 91 +++ .../http/api/security/ShiroIniParser.java | 84 --- .../log/mesos/MesosLogStreamModule.java | 154 +++-- .../mesos/CommandLineDriverSettingsModule.java | 160 ++--- .../scheduler/mesos/LibMesosLoadingModule.java | 6 +- .../scheduler/mesos/SchedulerDriverModule.java | 6 +- .../aurora/scheduler/offers/OffersModule.java | 123 ++-- .../offers/RandomJitterReturnDelay.java | 8 +- .../scheduler/preemptor/PreemptorModule.java | 140 ++-- .../aurora/scheduler/pruning/PruningModule.java | 68 +- .../reconciliation/ReconciliationModule.java | 128 ++-- .../scheduler/resources/ResourceSettings.java | 23 +- .../scheduler/resources/ResourceType.java | 13 +- .../scheduling/RescheduleCalculator.java | 10 +- .../scheduler/scheduling/SchedulingModule.java | 147 ++--- .../aurora/scheduler/sla/MetricCalculator.java | 4 +- .../apache/aurora/scheduler/sla/SlaModule.java | 66 +- .../aurora/scheduler/state/StateModule.java | 35 +- .../scheduler/stats/AsyncStatsModule.java | 43 +- .../aurora/scheduler/stats/StatsModule.java | 31 +- .../scheduler/storage/backup/BackupModule.java | 71 +-- .../aurora/scheduler/storage/db/DbModule.java | 117 ++-- .../scheduler/storage/log/LogStorageModule.java | 70 +- .../storage/log/SnapshotStoreImpl.java | 2 +- .../storage/mem/InMemStoresModule.java | 14 +- .../aurora/scheduler/thrift/ThriftModule.java | 2 - .../aurora/scheduler/thrift/aop/AopModule.java | 30 +- .../aurora/scheduler/updater/UpdaterModule.java | 40 +- .../org/apache/aurora/scheduler/webhook.json | 8 - .../apache/aurora/scheduler/TierModuleTest.java | 2 +- .../aurora/scheduler/app/MoreModulesTest.java | 39 +- .../aurora/scheduler/app/SchedulerIT.java | 17 +- .../scheduler/app/VolumeConverterTest.java | 55 ++ .../aurora/scheduler/app/VolumeParserTest.java | 53 -- .../scheduler/app/local/LocalSchedulerMain.java | 7 +- .../aurora/scheduler/async/AsyncModuleTest.java | 2 +- .../scheduler/config/CommandLineTest.java | 479 ++++++++++++++ .../aurora/scheduler/config/CustomModule.java | 48 ++ .../configuration/ConfigurationManagerTest.java | 9 +- .../aurora/scheduler/cron/quartz/CronIT.java | 2 +- .../aurora/scheduler/events/WebhookTest.java | 12 +- .../scheduler/http/AbstractJettyTest.java | 9 +- .../aurora/scheduler/http/api/ApiBetaTest.java | 2 +- .../apache/aurora/scheduler/http/api/ApiIT.java | 2 +- .../http/api/security/HttpSecurityIT.java | 2 +- .../KerberosPrincipalConverterTest.java | 37 ++ .../security/KerberosPrincipalParserTest.java | 35 - .../http/api/security/ModuleParserTest.java | 81 --- .../api/security/ShiroIniConverterTest.java | 74 +++ .../http/api/security/ShiroIniParserTest.java | 73 --- .../CommandLineDriverSettingsModuleTest.java | 8 +- .../mesos/MesosTaskFactoryImplTest.java | 2 + .../scheduler/offers/OfferManagerImplTest.java | 2 + .../preemptor/PreemptionVictimFilterTest.java | 1 + .../preemptor/PreemptorModuleTest.java | 33 +- .../scheduler/resources/AcceptedOfferTest.java | 6 + .../resources/ResourceManagerTest.java | 2 + .../RescheduleCalculatorImplTest.java | 6 +- .../aurora/scheduler/sla/SlaModuleTest.java | 12 +- .../scheduler/stats/AsyncStatsModuleTest.java | 8 + .../storage/db/RowGarbageCollectorTest.java | 2 +- .../storage/log/SnapshotStoreImplIT.java | 5 +- .../storage/mem/InMemTaskStoreTest.java | 4 +- .../storage/mem/MemCronJobStoreTest.java | 4 +- .../aurora/scheduler/thrift/ThriftIT.java | 21 +- .../aurora/scheduler/updater/JobUpdaterIT.java | 10 +- .../sh/org/apache/aurora/e2e/Dockerfile.python | 4 +- 196 files changed, 3264 insertions(+), 7941 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index d7a4287..fa3ed0d 100644 --- a/build.gradle +++ b/build.gradle @@ -171,25 +171,6 @@ project(':ui') { // building the Scheduler JAR, the JS bundle is built first. tasks.processResources.dependsOn(':ui:webpack') -/* This gradle project contains the annotation procesor from - * com.twitter.common.args and related dependencies. It needs to be outside of - * the commons project because gradle needs to compile the annotation processor - * first. - */ -project(':commons-args') { - dependencies { - compile "com.google.guava:guava:${guavaRev}" - compile "com.google.code.findbugs:jsr305:${jsrRev}" - compile "commons-lang:commons-lang:${commonsLangRev}" - } - - apply plugin: 'license' - license { - header rootProject.file('config/checkstyle/apache.header') - strictCheck true - } -} - project(':commons') { apply plugin: org.apache.aurora.build.ThriftPlugin thrift { @@ -391,10 +372,10 @@ dependencies { compile project(':api') compile project(':commons') - compile project(':commons-args') compile 'aopalliance:aopalliance:1.0' compile "ch.qos.logback:logback-classic:${logbackRev}" + compile "com.beust:jcommander:1.72" compile "com.google.code.findbugs:jsr305:${jsrRev}" compile "com.google.inject:guice:${guiceRev}" compile "com.google.inject.extensions:guice-assistedinject:${guiceRev}" @@ -492,15 +473,6 @@ tasks.withType(Test) { maxParallelForks = Runtime.runtime.availableProcessors() } -// Turn on annotation processors for commons (uses commons-args) and aurora -// (uses commons-args, forward, ...). The crux here is _not_ turning annotation processing on -// for commons-args (this leads to an attempt at self-processing before its processor is -// compiled); so the strategy taken is to white-list modules. -// -// NB: Unfortunately, most of the ipr/iml modeling we need is not exposed by the idea plugin DSL so -// we drop to xml manipulation here only out of necessity. -def apt_projects = ['commons', 'aurora'] - idea { project { vcs = 'Git' @@ -511,6 +483,9 @@ idea { withXml { def projectNode = it.asNode() + // TODO(wfarner): Does the below work? It still seems necessary to manually turn on + // annotation processing. + // Configure an annotation processor profile. def compilerConfiguration = projectNode.find { it.name() == 'component' && it.@name == 'CompilerConfiguration' @@ -524,9 +499,7 @@ idea { sourceOutputDir(name: 'generated') sourceTestOutputDir(name: 'generated') processorPath(useClasspath: 'true') - apt_projects.each { - module(name: it) - } + module(name: 'aurora') } } } @@ -534,11 +507,6 @@ idea { it.name() == 'component' && it.@name == 'ProjectRootManager' } projectRoot.remove(projectRoot.output) - - // Add parameter names to generated class file debug info. - projectNode - .appendNode('component', [name: 'JavacSettings']) - .appendNode('option', [name: 'ADDITIONAL_OPTIONS_STRING', value: '-parameters']) } } } @@ -548,21 +516,18 @@ idea { // generated code output dirs as source (and test) dirs. The key difficulty being worked around // here is the fact that excludes higher in a directory tree override includes deeper in the tree. allprojects { - def isApt = it.name in apt_projects def generatedSourceDir = file("${it.projectDir}/out/production/generated") def generatedTestDir = file("${it.projectDir}/out/test/generated") idea { module { - if (isApt) { - generatedSourceDir.exists() || generatedSourceDir.mkdirs() - sourceDirs += generatedSourceDir - generatedSourceDirs += generatedSourceDir - - generatedTestDir.exists() || generatedTestDir.mkdirs() - testSourceDirs += generatedTestDir - generatedSourceDirs += generatedTestDir - } + generatedSourceDir.exists() || generatedSourceDir.mkdirs() + sourceDirs += generatedSourceDir + generatedSourceDirs += generatedSourceDir + + generatedTestDir.exists() || generatedTestDir.mkdirs() + testSourceDirs += generatedTestDir + generatedSourceDirs += generatedTestDir iml { withXml { @@ -574,11 +539,9 @@ allprojects { moduleConfiguration.appendNode('output', [url: 'file://$MODULE_DIR$/out/production']) moduleConfiguration.appendNode('output-test', [url: 'file://$MODULE_DIR$/out/test']) - if (isApt) { - def excludeOutput = moduleConfiguration.find { it.name() == 'exclude-output' } - if (excludeOutput) { - moduleConfiguration.remove(excludeOutput) - } + def excludeOutput = moduleConfiguration.find { it.name() == 'exclude-output' } + if (excludeOutput) { + moduleConfiguration.remove(excludeOutput) } } } http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/Arg.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/Arg.java b/commons-args/src/main/java/org/apache/aurora/common/args/Arg.java deleted file mode 100644 index 4da9159..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/Arg.java +++ /dev/null @@ -1,127 +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 org.apache.aurora.common.args; - -import javax.annotation.Nullable; -import java.util.function.Supplier; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; - -/** - * Wrapper class for the value of an argument. For proper behavior, an {@code Arg} should always - * be annotated with {@link CmdLine}, which will define the command line interface to the argument. - */ -public class Arg implements Supplier { - - @Nullable private final T defaultValue; - @Nullable private T value; - private boolean hasDefault = true; - private boolean valueApplied = false; - private boolean valueObserved = false; - - /** - * Creates an arg that has no default value, meaning that its value can only ever be retrieved - * if it has been externally set. - */ - public Arg() { - this(null); - hasDefault = false; - } - - /** - * Creates an arg that has a default value, and may optionally be set. - * - * @param defaultValue The default value for the arg. - */ - public Arg(@Nullable T defaultValue) { - this.defaultValue = defaultValue; - value = defaultValue; - } - - synchronized void set(@Nullable T appliedValue) { - Preconditions.checkState(!valueApplied, "A value cannot be applied twice to an argument."); - Preconditions.checkState(!valueObserved, "A value cannot be changed after it was read."); - valueApplied = true; - value = appliedValue; - } - - @VisibleForTesting - synchronized void reset() { - valueApplied = false; - valueObserved = false; - value = hasDefault ? defaultValue : null; - } - - public boolean hasDefault() { - return hasDefault; - } - - /** - * Gets the value of the argument. If a value has not yet been applied to the argument, or the - * argument did not provide a default value, {@link IllegalStateException} will be thrown. - * - * @return The argument value. - */ - @Nullable - public synchronized T get() { - // TODO(William Farner): This has a tendency to break bad-arg reporting by ArgScanner. Fix. - Preconditions.checkState(valueApplied || hasDefault, - "A value may only be retrieved from a variable that has a default or has been set."); - valueObserved = true; - return uncheckedGet(); - } - - /** - * Checks whether a value has been applied to the argument (i.e., apart from the default). - * - * @return {@code true} if a value from the command line has been applied to this arg, - * {@code false} otherwise. - */ - public synchronized boolean hasAppliedValue() { - return valueApplied; - } - - /** - * Gets the value of the argument, without checking whether a default was available or if a - * value was applied. - * - * @return The argument value. - */ - @Nullable - synchronized T uncheckedGet() { - return value; - } - - /** - * Convenience factory method to create an arg that has no default value. - * - * @param Type of arg value. - * @return A new arg. - */ - public static Arg create() { - return new Arg(); - } - - /** - * Convenience factory method to create an arg with a default value. - * - * @param value Default argument value. - * @param Type of arg value. - * @return A new arg. - */ - public static Arg create(@Nullable T value) { - return new Arg(value); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/ArgParser.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/ArgParser.java b/commons-args/src/main/java/org/apache/aurora/common/args/ArgParser.java deleted file mode 100644 index 25ed250..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/ArgParser.java +++ /dev/null @@ -1,28 +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 org.apache.aurora.common.args; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Annotation to register a command line argument parser globally. - */ -@Target(TYPE) -@Retention(SOURCE) -public @interface ArgParser { -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/CmdLine.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/CmdLine.java b/commons-args/src/main/java/org/apache/aurora/common/args/CmdLine.java deleted file mode 100644 index a72ea7a..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/CmdLine.java +++ /dev/null @@ -1,54 +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 org.apache.aurora.common.args; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Annotation for a command line argument. - */ -@Target(FIELD) -@Retention(RUNTIME) -public @interface CmdLine { - /** - * The short name of the argument, as supplied on the command line. The argument can also be - * accessed by the canonical name, which is {@code com.foo.bar.MyArgClass.arg_name}. - * If the global scope contains more than one argument with the same name, all colliding arguments - * must be disambiguated with the canonical form. - * - * The argument name must match the format {@code [\w\-\.]+}. - */ - String name(); - - /** - * The help string to display on the command line in a usage message. - */ - String help(); - - /** - * The parser class to use for parsing this argument. The parser must return the same type as - * the field being annotated. - */ - Class> parser() default NoParser.class; - - /** - * The flag to indicate whether an argument file is accepted for this argument. - * - */ - boolean argFile() default false; -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/NoParser.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/NoParser.java b/commons-args/src/main/java/org/apache/aurora/common/args/NoParser.java deleted file mode 100644 index 3366531..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/NoParser.java +++ /dev/null @@ -1,23 +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 org.apache.aurora.common.args; - -/** - * A sentinel parser type for internal use indicating no parser has been selected yet. - */ -abstract class NoParser implements Parser { - private NoParser() { - throw new UnsupportedOperationException("Not intended for construction."); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/Parser.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/Parser.java b/commons-args/src/main/java/org/apache/aurora/common/args/Parser.java deleted file mode 100644 index 93c2323..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/Parser.java +++ /dev/null @@ -1,35 +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 org.apache.aurora.common.args; - -import java.lang.reflect.Type; - -/** - * An interface to a command line argument parser. - * - * @param The base class this parser can parse all subtypes of. - */ -public interface Parser { - /** - * Parses strings as arguments of a given subtype of {@code T}. - * - * @param parserOracle The registered parserOracle for delegation. - * @param type The target type of the parsed argument. - * @param raw The raw value of the argument. - * @return A value of the given type parsed from the raw value. - * @throws IllegalArgumentException if the raw value could not be parsed into a value of the - * given type. - */ - T parse(ParserOracle parserOracle, Type type, String raw) throws IllegalArgumentException; -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/ParserOracle.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/ParserOracle.java b/commons-args/src/main/java/org/apache/aurora/common/args/ParserOracle.java deleted file mode 100644 index e84d302..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/ParserOracle.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 org.apache.aurora.common.args; - -import com.google.common.reflect.TypeToken; - -/** - * A registry of Parsers for different supported argument types. - */ -public interface ParserOracle { - - /** - * Gets the parser associated with a class. - * - * @param type Type to get the parser for. - * @return The parser for {@code cls}. - * @throws IllegalArgumentException If no parser was found for {@code cls}. - */ - Parser get(TypeToken type) throws IllegalArgumentException; -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/Verifier.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/Verifier.java b/commons-args/src/main/java/org/apache/aurora/common/args/Verifier.java deleted file mode 100644 index 8f09a98..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/Verifier.java +++ /dev/null @@ -1,37 +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 org.apache.aurora.common.args; - -import java.lang.annotation.Annotation; - -/** - * Typedef for a constraint verifier. - */ -public interface Verifier { - /** - * Verifies the value against the annotation. - * - * @param value Value that is being applied. - * @throws IllegalArgumentException if the value is invalid. - */ - void verify(T value, Annotation annotation) throws IllegalArgumentException; - - /** - * Returns a representation of the constraint this verifier checks. - * - * @param argType The type of the {@link Arg} this annotation applies to. - * @return A representation of the constraint this verifier checks. - */ - String toString(Class argType, Annotation annotation); -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons-args/src/main/java/org/apache/aurora/common/args/VerifierFor.java ---------------------------------------------------------------------- diff --git a/commons-args/src/main/java/org/apache/aurora/common/args/VerifierFor.java b/commons-args/src/main/java/org/apache/aurora/common/args/VerifierFor.java deleted file mode 100644 index aad8807..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/VerifierFor.java +++ /dev/null @@ -1,34 +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 org.apache.aurora.common.args; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Annotation to register a command line argument verifier. - */ -@Target(TYPE) -@Retention(SOURCE) -public @interface VerifierFor { - /** - * Returns the annotation that marks a field for verification by the annotated - * {@link Verifier} class. - */ - Class value(); -} http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/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 deleted file mode 100644 index 5fda5dc..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/apt/CmdLineProcessor.java +++ /dev/null @@ -1,628 +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 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 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.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()}. - * - *

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: - * -Acom.twitter.common.args.apt.CmdLineProcessor.main - * 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, String> GET_NAME = Class::getName; - - private final Supplier configSupplier = - Suppliers.memoize(new Supplier() { - @Override public Configuration get() { - try { - Configuration configuration = Configuration.load(); - 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 contributingClassNamesBuilder = ImmutableSet.builder(); - - private Types typeUtils; - private Elements elementUtils; - private boolean isMain; - private boolean isCheckLinkage; - - private static boolean getBooleanOption(Map 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 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 getSupportedAnnotationTypes() { - return ImmutableSet.copyOf(Iterables.transform( - ImmutableList.of(CmdLine.class, ArgParser.class, VerifierFor.class), - GET_NAME)); - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - try { - @Nullable Configuration classpathConfiguration = configSupplier.get(); - - Set parsers = getAnnotatedElements(roundEnv, ArgParser.class); - contributingClassNamesBuilder.addAll(extractClassNames(parsers)); - @Nullable Set parsedTypes = getParsedTypes(classpathConfiguration, parsers); - - Set cmdlineArgs = getAnnotatedElements(roundEnv, CmdLine.class); - contributingClassNamesBuilder.addAll(extractEnclosingClassNames(cmdlineArgs)); - - for (ArgInfo cmdLineInfo : processAnnotatedArgs(parsedTypes, cmdlineArgs, CmdLine.class)) { - configBuilder.addCmdLineArg(cmdLineInfo); - } - - processParsers(parsers); - - Set 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 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 EXTRACT_ENCLOSING_CLASS = - Element::getEnclosingElement; - - private final Function extractClassName = element -> getBinaryName((TypeElement) element); - - private final Function extractEnclosingClassName = - Functions.compose(extractClassName, EXTRACT_ENCLOSING_CLASS); - - private Iterable extractEnclosingClassNames(Iterable elements) { - return Iterables.transform(elements, extractEnclosingClassName); - } - - private Iterable extractClassNames(Iterable 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); - } - } - - @Nullable - private Set getParsedTypes(@Nullable Configuration configuration, - Set parsers) { - - if (!isCheckLinkage) { - return null; - } - - Iterable parsersFor = Optional.presentInstances(Iterables.transform(parsers, - 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() { - @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 processAnnotatedArgs( - @Nullable final Set parsedTypes, - Set args, - final Class argAnnotation) { - - return Optional.presentInstances(Iterables.transform(args, - 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 getAnnotatedElements(RoundEnvironment roundEnv, - Class argAnnotation) { - return roundEnv.getElementsAnnotatedWith(typeElement(argAnnotation)); - } - - @Nullable - private TypeElement processArg(@Nullable Set parsedTypes, Element annotationElement, - Class 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 linkage for the Arg 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 annotated with @VerifierFor.annotation: T is a subtype of - // V where there is a Verifier - // 2.) name checks, including dups - - return containingType; - } - } - - private boolean checkTypePresent(Set types, TypeMirror type) { - Iterable allTypes = getAllTypes(type); - for (TypeMirror t : allTypes) { - if (types.contains(typeUtils.erasure(t).toString())) { - return true; - } - } - return false; - } - - private void processParsers(Set 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 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 getAllTypes(TypeMirror type) { - return getAllTypes(new HashSet(), Lists.newArrayList(), type); - } - - private Iterable getAllTypes(Set visitedTypes, List 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() { - @Override public TypeMirror visitDeclared(DeclaredType t, Void aVoid) { - if (isAssignable(t, baseType)) { - List 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 entry - : annotationMirror.getElementValues().entrySet()) { - if (entry.getKey().getSimpleName().equals(elementUtils.getName(methodName))) { - TypeElement classType = entry.getValue().accept( - new SimpleAnnotationValueVisitor6() { - @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/519e3df7/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 deleted file mode 100644 index 1832d41..0000000 --- a/commons-args/src/main/java/org/apache/aurora/common/args/apt/Configuration.java +++ /dev/null @@ -1,476 +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 org.apache.aurora.common.args.apt; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.Writer; -import java.net.URL; -import java.nio.charset.StandardCharsets; -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.Function; -import com.google.common.base.Preconditions; -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.CharSource; -import com.google.common.io.CharStreams; -import com.google.common.io.LineProcessor; -import com.google.common.io.Resources; - -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(Character::isJavaIdentifierStart); - - private static final CharMatcher IDENTIFIER_REST = - CharMatcher.forPredicate(Character::isJavaIdentifierPart); - - private static final Function URL_TO_SOURCE = input -> Resources.asCharSource(input, StandardCharsets.UTF_8); - - private static final String DEFAULT_RESOURCE_NAME = "cmdline.arg.info.txt"; - - private int nextResourceIndex; - private final ImmutableSet cmdLineInfos; - private final ImmutableSet parserInfos; - private final ImmutableSet verifierInfos; - - private Configuration( - int nextResourceIndex, - Iterable cmdLineInfos, - Iterable parserInfos, - Iterable verifierInfos) { - - this.nextResourceIndex = nextResourceIndex; - 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 argInfos = Sets.newHashSet(); - private final Set parserInfos = Sets.newHashSet(); - private final Set verifierInfos = Sets.newHashSet(); - - public boolean isEmpty() { - return argInfos.isEmpty() - && parserInfos.isEmpty() - && verifierInfos.isEmpty(); - } - - 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, - 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 resources; - - private ConfigurationResources(int nextResourceIndex, Iterator 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 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 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 resources = getResources(nextResourceIndex); - if (resources.hasNext()) { - allResources = Iterators.concat(allResources, resources); - maxResourceIndex = nextResourceIndex; - } - } - return new ConfigurationResources(maxResourceIndex + 1, allResources); - } - - private static Iterator getResources(int index) throws IOException { - return Iterators.forEnumeration( - Configuration.class.getClassLoader().getResources(getResourcePath(index))); - } - - private static final class ConfigurationParser implements LineProcessor { - private final int nextIndex; - private int lineNumber = 0; - - private final ImmutableList.Builder fieldInfoBuilder = ImmutableList.builder(); - private final ImmutableList.Builder parserInfoBuilder = ImmutableList.builder(); - private final ImmutableList.Builder 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 parts = Lists.newArrayList(trimmed.split(" ")); - if (parts.size() < 1) { - throw new ConfigurationException("Invalid line: %s @%d", trimmed, lineNumber); - } - - String type = parts.remove(0); - 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, - fieldInfoBuilder.build(), - parserInfoBuilder.build(), - verifierInfoBuilder.build()); - } - } - - private static Configuration load(int nextIndex, List configs) - throws ConfigurationException, IOException { - CharSource input = CharSource.concat(Iterables.transform(configs, URL_TO_SOURCE)); - try(Reader reader = input.openStream()) { - return CharStreams.readLines(reader, new ConfigurationParser(nextIndex)); - } - } - - public boolean isEmpty() { - return cmdLineInfos.isEmpty() - && parserInfos.isEmpty() - && verifierInfos.isEmpty(); - } - - /** - * 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 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() { - 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() { - 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 : 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/519e3df7/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 deleted file mode 100644 index b548fcd..0000000 --- a/commons-args/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -org.apache.aurora.common.args.apt.CmdLineProcessor http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/main/java/org/apache/aurora/common/args/ArgFilters.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/org/apache/aurora/common/args/ArgFilters.java b/commons/src/main/java/org/apache/aurora/common/args/ArgFilters.java deleted file mode 100644 index 9fd6eae..0000000 --- a/commons/src/main/java/org/apache/aurora/common/args/ArgFilters.java +++ /dev/null @@ -1,109 +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 org.apache.aurora.common.args; - -import java.lang.reflect.Field; -import java.util.Set; - -import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.ImmutableSet; - -import org.apache.aurora.common.base.MorePreconditions; - -/** - * Utilities for generating {@literal @CmdLine} {@link Arg} filters suitable for use with - * {@link ArgScanner#parse(Predicate, Iterable)}. These filters assume the - * fields parsed will all be annotated with {@link CmdLine}. - * - * @author John Sirois - */ -public final class ArgFilters { - - /** - * A filter that selects all {@literal @CmdLine} {@link Arg}s found on the classpath. - */ - public static final Predicate SELECT_ALL = Predicates.alwaysTrue(); - - private ArgFilters() { - // utility - } - - /** - * Creates a filter that selects all {@literal @CmdLine} {@link Arg}s found in classes that are - * members of the given package. Note that this will not select subpackages. - * - * @param pkg The exact package of classes whose command line args will be selected. - * @return A filter that selects only command line args declared in classes that are members of - * the given {@code pkg}. - */ - public static Predicate selectPackage(final Package pkg) { - Preconditions.checkNotNull(pkg); - return field -> field.getDeclaringClass().getPackage().equals(pkg); - } - - /** - * Creates a filter that selects all {@literal @CmdLine} {@link Arg}s found in classes that are - * members of the given package or its sub-packages. - * - * @param pkg The ancestor package of classes whose command line args will be selected. - * @return A filter that selects only command line args declared in classes that are members of - * the given {@code pkg} or its sub-packages. - */ - public static Predicate selectAllPackagesUnderHere(final Package pkg) { - Preconditions.checkNotNull(pkg); - final String prefix = pkg.getName() + '.'; - return Predicates.or(selectPackage(pkg), field -> { - return field.getDeclaringClass().getPackage().getName().startsWith(prefix); - }); - } - - /** - * Creates a filter that selects all {@literal @CmdLine} {@link Arg}s found in the given class. - * - * @param clazz The class whose command line args will be selected. - * @return A filter that selects only command line args declared in the given {@code clazz}. - */ - public static Predicate selectClass(final Class clazz) { - Preconditions.checkNotNull(clazz); - return field -> field.getDeclaringClass().equals(clazz); - } - - /** - * Creates a filter that selects all {@literal @CmdLine} {@link Arg}s found in the given classes. - * - * @param cls The classes whose command line args will be selected. - * @return A filter that selects only command line args declared in the given classes. - */ - public static Predicate selectClasses(final Class ... cls) { - Preconditions.checkNotNull(cls); - final Set> listOfClasses = ImmutableSet.copyOf(cls); - return field -> listOfClasses.contains(field.getDeclaringClass()); - } - - /** - * Creates a filter that selects a single {@literal @CmdLine} {@link Arg}. - * - * @param clazz The class that declares the command line arg to be selected. - * @param name The {@link CmdLine#name()} of the arg to select. - * @return A filter that selects a single specified command line arg. - */ - public static Predicate selectCmdLineArg(Class clazz, final String name) { - MorePreconditions.checkNotBlank(name); - return Predicates.and(selectClass(clazz), field -> { - return field.getAnnotation(CmdLine.class).name().equals(name); - }); - } -}