aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/java
diff options
context:
space:
mode:
authorGravatar Lukacs T. Berki <lberki@google.com>2017-04-18 14:13:49 +0200
committerGravatar Lukacs T. Berki <lberki@google.com>2017-04-18 14:15:05 +0200
commitdf8d804acb5826a120cad9acfc78dd6f0071d864 (patch)
treec15ca9e28ea15f66395fa1f8b1a069336a6b11b6 /third_party/java
parent50d62ee7888856f935d09e5fd60ee23d24d02b44 (diff)
Vendor `jopt-simple 5.0.3` .
This is necessary for vendoring jarjar, which is in turn necessary to get Java coverage collection to work again. Yak shaving for #2820. Change-Id: Idfd45e7322e0763fd316a4f67b1a048c93bf54ba
Diffstat (limited to 'third_party/java')
-rw-r--r--third_party/java/jopt-simple/BUILD7
-rw-r--r--third_party/java/jopt-simple/LICENSE.txt24
-rw-r--r--third_party/java/jopt-simple/README.bazel.md6
-rw-r--r--third_party/java/jopt-simple/README.md7
-rw-r--r--third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml283
-rw-r--r--third_party/java/jopt-simple/jopt-simple.importorder8
-rw-r--r--third_party/java/jopt-simple/paste-examples.xml205
-rw-r--r--third_party/java/jopt-simple/pom.xml342
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java148
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java65
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java329
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java59
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java565
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java45
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java46
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java46
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java46
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java81
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java170
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java50
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java116
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java100
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java125
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java46
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java647
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java76
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java325
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java97
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java275
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java126
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java69
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java84
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java52
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java45
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java52
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java46
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java54
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java58
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java242
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java75
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java106
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java56
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java47
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java58
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java47
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java142
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java39
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java55
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java103
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java67
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java115
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java114
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java104
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java67
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java83
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java51
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java60
-rw-r--r--third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java95
-rw-r--r--third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties19
-rw-r--r--third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties11
-rw-r--r--third_party/java/jopt-simple/src/site/apt/acknowledgments.apt90
-rw-r--r--third_party/java/jopt-simple/src/site/apt/changes.apt385
-rw-r--r--third_party/java/jopt-simple/src/site/apt/developer.apt48
-rw-r--r--third_party/java/jopt-simple/src/site/apt/download.apt.vm26
-rw-r--r--third_party/java/jopt-simple/src/site/apt/examples.apt462
-rw-r--r--third_party/java/jopt-simple/src/site/apt/index.apt71
-rw-r--r--third_party/java/jopt-simple/src/site/resources/css/prettify.css49
-rw-r--r--third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.pngbin0 -> 7147 bytes
-rw-r--r--third_party/java/jopt-simple/src/site/resources/scripts/prettify.js1602
-rw-r--r--third_party/java/jopt-simple/src/site/site.xml20
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java59
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java58
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java53
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java52
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java43
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java58
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java50
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java136
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java56
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java75
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java82
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java143
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java82
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java84
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java122
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java122
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java183
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java484
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java51
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java45
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java753
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java87
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java83
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java183
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java140
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java71
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java53
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java82
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java72
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java103
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java36
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java53
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java56
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java108
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java84
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java91
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java59
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java61
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java82
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java290
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java78
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java67
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java318
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java54
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java49
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java50
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java59
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java56
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java53
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java57
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java55
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java38
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java58
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java205
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java49
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java88
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java71
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java80
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java51
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java82
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java36
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java53
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java58
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java35
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java82
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java75
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java69
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java46
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java72
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java74
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java73
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java61
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java41
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java36
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java58
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java86
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java112
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java78
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java110
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java108
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java103
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java130
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java68
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java73
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java317
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java60
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java63
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java39
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java64
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java63
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java65
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java116
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java22
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java58
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java11
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java61
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java69
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java35
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java7
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java21
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java26
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java34
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java29
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java49
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java27
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java30
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java37
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java14
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java49
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java14
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java21
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java24
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java21
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java28
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java31
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java31
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java31
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java31
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java19
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java45
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java23
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java80
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java361
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java148
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java37
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java37
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java51
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java109
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java37
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java49
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java83
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java93
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java37
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java152
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java95
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java60
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java88
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java43
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java43
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java104
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java54
-rw-r--r--third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java84
-rw-r--r--third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties10
213 files changed, 20914 insertions, 0 deletions
diff --git a/third_party/java/jopt-simple/BUILD b/third_party/java/jopt-simple/BUILD
new file mode 100644
index 0000000000..698edb34ff
--- /dev/null
+++ b/third_party/java/jopt-simple/BUILD
@@ -0,0 +1,7 @@
+licenses(["notice"]) # MIT
+
+java_library(
+ name = "jopt-simple",
+ srcs = glob(["src/main/**/*.java"]),
+ visibility = ["//visibility:public"],
+)
diff --git a/third_party/java/jopt-simple/LICENSE.txt b/third_party/java/jopt-simple/LICENSE.txt
new file mode 100644
index 0000000000..85f923a952
--- /dev/null
+++ b/third_party/java/jopt-simple/LICENSE.txt
@@ -0,0 +1,24 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
diff --git a/third_party/java/jopt-simple/README.bazel.md b/third_party/java/jopt-simple/README.bazel.md
new file mode 100644
index 0000000000..9985e82975
--- /dev/null
+++ b/third_party/java/jopt-simple/README.bazel.md
@@ -0,0 +1,6 @@
+This is jopt-simple 5.0.3. Reproduction:
+
+1. `git clone https://github.com/jopt-simple/jopt-simple`
+2. `git checkout jopt-simple-5.0.3` (commithash `b52b94611dba126a8236a10277d15676e31ab5f6`)
+3. Dump the contents of the `git` tree into `third_party/java/jopt-simple`
+4. Keep the existing, trivial `BUILD` file
diff --git a/third_party/java/jopt-simple/README.md b/third_party/java/jopt-simple/README.md
new file mode 100644
index 0000000000..ffe1ce208d
--- /dev/null
+++ b/third_party/java/jopt-simple/README.md
@@ -0,0 +1,7 @@
+[![Build Status](https://travis-ci.org/pholser/jopt-simple.svg?branch=master)](https://travis-ci.org/pholser/jopt-simple)
+
+Please see http://pholser.github.com/jopt-simple for more information.
+
+### Discussing
+
+There is [a Google group for JOpt Simple](https://groups.google.com/d/forum/jopt-simple).
diff --git a/third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml b/third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml
new file mode 100644
index 0000000000..e4b2eb8312
--- /dev/null
+++ b/third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="12">
+<profile kind="CodeFormatterProfile" name="jopt-simple" version="12">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+</profile>
+</profiles>
diff --git a/third_party/java/jopt-simple/jopt-simple.importorder b/third_party/java/jopt-simple/jopt-simple.importorder
new file mode 100644
index 0000000000..e94bb816a3
--- /dev/null
+++ b/third_party/java/jopt-simple/jopt-simple.importorder
@@ -0,0 +1,8 @@
+#Organize Import Order
+#Tue Oct 18 14:21:56 CDT 2011
+5=\#
+4=\#javax
+3=\#java
+2=
+1=javax
+0=java
diff --git a/third_party/java/jopt-simple/paste-examples.xml b/third_party/java/jopt-simple/paste-examples.xml
new file mode 100644
index 0000000000..e1b6254481
--- /dev/null
+++ b/third_party/java/jopt-simple/paste-examples.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <target name="-paste-examples">
+ <filterchain id="htmlFilter">
+ <filterreader
+ classname="joptsimple.examples.ant.filters.HTMLEntitifier"
+ classpath="${example.class.path}"/>
+ </filterchain>
+ <loadfile property="short.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="short.options.with.arguments.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsWithArgumentsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="short.options.with.argument.positioning.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="short.options.with.multiple.arguments.for.single.option.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="short.options.clustering.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsClusteringTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="short.options.clustering.with.argument.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="long.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/LongOptionsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="long.options.with.arguments.example"
+ srcfile="${example.src.dir}/joptsimple/examples/LongOptionsWithArgumentsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="long.options.with.argument.positioning.example"
+ srcfile="${example.src.dir}/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="alternative.long.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/AlternativeLongOptionsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="option.argument.value.type.example"
+ srcfile="${example.src.dir}/joptsimple/examples/OptionArgumentValueTypeTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="option.argument.converter.example"
+ srcfile="${example.src.dir}/joptsimple/examples/OptionArgumentConverterTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="typesafe.option.argument.retrieval.example"
+ srcfile="${example.src.dir}/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="typesafe.option.argument.retrieval.example"
+ srcfile="${example.src.dir}/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="export.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/ExportOptionsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="required.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/RequiredOptionsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="required.if.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/RequiredIfExample.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="required.unless.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/RequiredUnlessExample.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="default.values.for.option.arguments.example"
+ srcfile="${example.src.dir}/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="option.synonym.example"
+ srcfile="${example.src.dir}/joptsimple/examples/OptionSynonymTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="multiple.delimited.arguments.example"
+ srcfile="${example.src.dir}/joptsimple/examples/MultipleDelimitedArgumentsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="signalling.end.of.options.example"
+ srcfile="${example.src.dir}/joptsimple/examples/SignallingEndOfOptionsTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="posixly.correct.example"
+ srcfile="${example.src.dir}/joptsimple/examples/PosixlyCorrectTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="special.optional.argument.handling.example"
+ srcfile="${example.src.dir}/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="help.screen.example"
+ srcfile="${example.src.dir}/joptsimple/examples/HelpScreenExample.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <java classname="joptsimple.examples.HelpScreenExample"
+ fork="yes"
+ output="${java.io.tmpdir}/help-output.txt"
+ classpath="${example.class.path}">
+ </java>
+ <loadfile property="help.screen.example.help"
+ srcfile="${java.io.tmpdir}/help-output.txt">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="help.formatter.example"
+ srcfile="${example.src.dir}/joptsimple/examples/HelpFormatterExample.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <java classname="joptsimple.examples.HelpFormatterExample"
+ fork="yes"
+ output="${java.io.tmpdir}/help-formatter-output.txt"
+ classpath="${example.class.path}">
+ </java>
+ <loadfile property="help.formatter.example.output"
+ srcfile="${java.io.tmpdir}/help-formatter-output.txt">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <java classname="joptsimple.examples.ExceptionExample"
+ fork="yes"
+ output="${java.io.tmpdir}/stack-trace-output.txt"
+ classpath="${example.class.path}">
+ </java>
+ <loadfile property="example.stack.trace"
+ srcfile="${java.io.tmpdir}/stack-trace-output.txt">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <loadfile property="unrecognized.options.allowed.example"
+ srcfile="${example.src.dir}/joptsimple/examples/UnrecognizedOptionsAllowedTest.java">
+ <filterchain refid="htmlFilter"/>
+ </loadfile>
+ <replace dir="${website.staging.dir}" includes="examples.html">
+ <replacefilter token="@SHORT_OPTIONS_EXAMPLE@"
+ value="${short.options.example}"/>
+ <replacefilter token="@SHORT_OPTIONS_WITH_ARGUMENTS_EXAMPLE@"
+ value="${short.options.with.arguments.example}"/>
+ <replacefilter token="@SHORT_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@"
+ value="${short.options.with.argument.positioning.example}"/>
+ <replacefilter token="@SHORT_OPTIONS_WITH_MULTIPLE_ARGUMENTS_FOR_SINGLE_OPTION_EXAMPLE@"
+ value="${short.options.with.multiple.arguments.for.single.option.example}"/>
+ <replacefilter token="@SHORT_OPTIONS_CLUSTERING_EXAMPLE@"
+ value="${short.options.clustering.example}"/>
+ <replacefilter token="@SHORT_OPTIONS_CLUSTERING_WITH_ARGUMENT_EXAMPLE@"
+ value="${short.options.clustering.with.argument.example}" />
+ <replacefilter token="@LONG_OPTIONS_EXAMPLE@"
+ value="${long.options.example}"/>
+ <replacefilter token="@LONG_OPTIONS_WITH_ARGUMENTS_EXAMPLE@"
+ value="${long.options.with.arguments.example}"/>
+ <replacefilter token="@LONG_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@"
+ value="${long.options.with.argument.positioning.example}"/>
+ <replacefilter token="@ALTERNATIVE_LONG_OPTIONS_EXAMPLE@"
+ value="${alternative.long.options.example}"/>
+ <replacefilter token="@OPTION_ARGUMENT_VALUE_TYPE_EXAMPLE@"
+ value="${option.argument.value.type.example}"/>
+ <replacefilter token="@OPTION_ARGUMENT_CONVERTER_EXAMPLE@"
+ value="${option.argument.converter.example}"/>
+ <replacefilter token="@TYPESAFE_OPTION_ARGUMENT_RETRIEVAL_EXAMPLE@"
+ value="${typesafe.option.argument.retrieval.example}"/>
+ <replacefilter token="@EXPORTING_OPTIONS_AND_ARGUMENTS_EXAMPLE@"
+ value="${export.options.example}"/>
+ <replacefilter token="@DEFAULT_VALUES_FOR_OPTION_ARGUMENTS_EXAMPLE@"
+ value="${default.values.for.option.arguments.example}"/>
+ <replacefilter token="@REQUIRED_OPTIONS_EXAMPLE@"
+ value="${required.options.example}"/>
+ <replacefilter token="@REQUIRED_IF_OPTIONS_EXAMPLE@"
+ value="${required.if.options.example}"/>
+ <replacefilter token="@REQUIRED_UNLESS_OPTIONS_EXAMPLE@"
+ value="${required.unless.options.example}"/>
+ <replacefilter token="@OPTION_SYNONYM_EXAMPLE@"
+ value="${option.synonym.example}"/>
+ <replacefilter token="@MULTIPLE_DELIMITED_ARGUMENTS_EXAMPLE@"
+ value="${multiple.delimited.arguments.example}"/>
+ <replacefilter token="@SIGNALLING_END_OF_OPTIONS_EXAMPLE@"
+ value="${signalling.end.of.options.example}"/>
+ <replacefilter token="@POSIXLY_CORRECT_EXAMPLE@"
+ value="${posixly.correct.example}"/>
+ <replacefilter token="@SPECIAL_OPTIONAL_ARGUMENT_HANDLING_EXAMPLE@"
+ value="${special.optional.argument.handling.example}"/>
+ <replacefilter token="@HELP_SCREEN_EXAMPLE@"
+ value="${help.screen.example}"/>
+ <replacefilter token="@HELP_SCREEN_EXAMPLE_HELP@"
+ value="${help.screen.example.help}"/>
+ <replacefilter token="@HELP_FORMATTER_EXAMPLE@"
+ value="${help.formatter.example}"/>
+ <replacefilter token="@HELP_FORMATTER_EXAMPLE_OUTPUT@"
+ value="${help.formatter.example.output}"/>
+ <replacefilter token="@EXAMPLE_STACK_TRACE@"
+ value="${example.stack.trace}"/>
+ <replacefilter token="@UNRECOGNIZED_OPTIONS_ALLOWED_EXAMPLE@"
+ value="${unrecognized.options.allowed.example}"/>
+ </replace>
+ </target>
+</project>
diff --git a/third_party/java/jopt-simple/pom.xml b/third_party/java/jopt-simple/pom.xml
new file mode 100644
index 0000000000..c2fc280944
--- /dev/null
+++ b/third_party/java/jopt-simple/pom.xml
@@ -0,0 +1,342 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.sonatype.oss</groupId>
+ <artifactId>oss-parent</artifactId>
+ <version>7</version>
+ </parent>
+ <groupId>net.sf.jopt-simple</groupId>
+ <artifactId>jopt-simple</artifactId>
+ <version>5.0.3</version>
+ <packaging>jar</packaging>
+ <name>JOpt Simple</name>
+ <url>http://pholser.github.io/jopt-simple</url>
+ <description>A Java library for parsing command line options</description>
+ <licenses>
+ <license>
+ <name>The MIT License</name>
+ <url>http://www.opensource.org/licenses/mit-license.php</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:git:git://github.com/pholser/jopt-simple.git</connection>
+ <developerConnection>scm:git:ssh://git@github.com/pholser/jopt-simple.git</developerConnection>
+ <url>https://github.com/pholser/jopt-simple</url>
+ </scm>
+ <issueManagement>
+ <system>GitHub</system>
+ <url>https://github.com/pholser/jopt-simple/issues</url>
+ </issueManagement>
+ <developers>
+ <developer>
+ <id>pholser</id>
+ <name>Paul Holser</name>
+ <email>pholser@alumni.rice.edu</email>
+ <url>http://www.pholser.com</url>
+ </developer>
+ </developers>
+ <properties>
+ <project.build.outputEncoding>UTF-8</project.build.outputEncoding>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.project.outputEncoding>UTF-8</project.project.outputEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ <version>2.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.8.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.infinitest</groupId>
+ <artifactId>continuous-testing-toolkit</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.scm</groupId>
+ <artifactId>maven-scm-provider-gitexe</artifactId>
+ <version>1.9.2</version>
+ </extension>
+ <extension>
+ <groupId>org.apache.maven.scm</groupId>
+ <artifactId>maven-scm-manager-plexus</artifactId>
+ <version>1.9.2</version>
+ </extension>
+ <extension>
+ <groupId>org.kathrynhuxtable.maven.wagon</groupId>
+ <artifactId>wagon-gitsite</artifactId>
+ <version>0.3.1</version>
+ </extension>
+ </extensions>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.2</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <version>1.13</version>
+ <configuration>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java17</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ <executions>
+ <execution>
+ <id>check-signature</id>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ <!-- Needs updated version of animal sniffer plugin
+ <execution>
+ <id>check-test-signature</id>
+ <goals>
+ <goal>test-check</goal>
+ </goals>
+ </execution>
+ -->
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.7</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Name>${project.artifactId}</Bundle-Name>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Bundle-Vendor>${project.name}</Bundle-Vendor>
+ <Export-Package>joptsimple,joptsimple.util</Export-Package>
+ <Private-Package>joptsimple.internal</Private-Package>
+ </instructions>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <check>
+ <haltOnFailure>true</haltOnFailure>
+ <totalBranchRate>96</totalBranchRate>
+ <totalLineRate>99</totalLineRate>
+ </check>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>clean</goal>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.4</version>
+ <configuration>
+ <minimumTokens>40</minimumTokens>
+ <targetJdk>1.7</targetJdk>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>cpd-check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <id>paste-examples</id>
+ <phase>post-site</phase>
+ <configuration>
+ <target>
+ <property name="java.io.tmpdir" value="${java.io.tmpdir}" />
+ <property name="example.src.dir" value="src/test/java" />
+ <property name="example.class.path" refid="maven.test.classpath" />
+ <property name="website.staging.dir" value="${project.build.directory}/site" />
+ <ant antfile="paste-examples.xml" target="-paste-examples" />
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.3</version>
+ <configuration>
+ <outputEncoding>UTF-8</outputEncoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.pitest</groupId>
+ <artifactId>pitest-maven</artifactId>
+ <version>1.1.9</version>
+ <configuration>
+ <targetClasses>
+ <param>joptsimple*</param>
+ </targetClasses>
+ <targetTests>
+ <param>*Test</param>
+ </targetTests>
+ <excludedMethods>
+ <param>equals</param>
+ <param>hashCode</param>
+ </excludedMethods>
+ <excludedClasses>
+ <param>joptsimple.examples*</param>
+ <param>*EqualsHash*Test</param>
+ <param>*TestCase</param>
+ <param>*Fixture</param>
+ <param>*Harness</param>
+ <param>*Matchers</param>
+ <param>*Ctor</param>
+ <param>*Problematic</param>
+ <param>*ValueOfHaver</param>
+ </excludedClasses>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.8</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <configuration>
+ <source>1.7</source>
+ <show>public</show>
+ <excludePackageNames>joptsimple.examples:joptsimple.internal:joptsimple.internal.*</excludePackageNames>
+ <links>
+ <link>https://docs.oracle.com/javase/8/docs/api</link>
+ </links>
+ <bottom><![CDATA[<i>&copy; Copyright 2004-2015 Paul R. Holser, Jr. All rights reserved. Licensed under The MIT License. pholser@alumni.rice.edu</i>]]></bottom>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>javadoc</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <check>
+ <haltOnFailure>true</haltOnFailure>
+ <totalBranchRate>97</totalBranchRate>
+ <totalLineRate>99</totalLineRate>
+ </check>
+ <formats>
+ <format>xml</format>
+ <format>html</format>
+ </formats>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>3.0.0</version>
+ <configuration>
+ <threshold>Low</threshold>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.4</version>
+ <configuration>
+ <minimumTokens>40</minimumTokens>
+ <targetJdk>1.7</targetJdk>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <distributionManagement>
+ <site>
+ <id>github-project-site</id>
+ <url>gitsite:git@github.com/pholser/jopt-simple.git</url>
+ </site>
+ </distributionManagement>
+</project>
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java
new file mode 100644
index 0000000000..2c045bd500
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java
@@ -0,0 +1,148 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Collections.*;
+
+import joptsimple.internal.Reflection;
+import joptsimple.internal.ReflectionException;
+
+import static joptsimple.internal.Strings.*;
+
+/**
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class AbstractOptionSpec<V> implements OptionSpec<V>, OptionDescriptor {
+ private final List<String> options = new ArrayList<>();
+ private final String description;
+ private boolean forHelp;
+
+ AbstractOptionSpec( String option ) {
+ this( singletonList( option ), EMPTY );
+ }
+
+ AbstractOptionSpec( List<String> options, String description ) {
+ arrangeOptions( options );
+
+ this.description = description;
+ }
+
+ public final List<String> options() {
+ return unmodifiableList( options );
+ }
+
+ public final List<V> values( OptionSet detectedOptions ) {
+ return detectedOptions.valuesOf( this );
+ }
+
+ public final V value( OptionSet detectedOptions ) {
+ return detectedOptions.valueOf( this );
+ }
+
+ public String description() {
+ return description;
+ }
+
+ public final AbstractOptionSpec<V> forHelp() {
+ forHelp = true;
+ return this;
+ }
+
+ public final boolean isForHelp() {
+ return forHelp;
+ }
+
+ public boolean representsNonOptions() {
+ return false;
+ }
+
+ protected abstract V convert( String argument );
+
+ protected V convertWith( ValueConverter<V> converter, String argument ) {
+ try {
+ return Reflection.convertWith( converter, argument );
+ } catch ( ReflectionException | ValueConversionException ex ) {
+ throw new OptionArgumentConversionException( this, argument, ex );
+ }
+ }
+
+ protected String argumentTypeIndicatorFrom( ValueConverter<V> converter ) {
+ if ( converter == null )
+ return null;
+
+ String pattern = converter.valuePattern();
+ return pattern == null ? converter.valueType().getName() : pattern;
+ }
+
+ abstract void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+ String detectedArgument );
+
+ private void arrangeOptions( List<String> unarranged ) {
+ if ( unarranged.size() == 1 ) {
+ options.addAll( unarranged );
+ return;
+ }
+
+ List<String> shortOptions = new ArrayList<>();
+ List<String> longOptions = new ArrayList<>();
+
+ for ( String each : unarranged ) {
+ if ( each.length() == 1 )
+ shortOptions.add( each );
+ else
+ longOptions.add( each );
+ }
+
+ sort( shortOptions );
+ sort( longOptions );
+
+ options.addAll( shortOptions );
+ options.addAll( longOptions );
+ }
+
+ @Override
+ public boolean equals( Object that ) {
+ if ( !( that instanceof AbstractOptionSpec<?> ) )
+ return false;
+
+ AbstractOptionSpec<?> other = (AbstractOptionSpec<?>) that;
+ return options.equals( other.options );
+ }
+
+ @Override
+ public int hashCode() {
+ return options.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return options.toString();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java
new file mode 100644
index 0000000000..a3108c1da4
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java
@@ -0,0 +1,65 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import joptsimple.internal.Messages;
+
+import java.util.Locale;
+
+import static java.util.Collections.*;
+
+import static joptsimple.ParserRules.*;
+
+/**
+ * Represents the {@code "-W"} form of long option specification.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class AlternativeLongOptionSpec extends ArgumentAcceptingOptionSpec<String> {
+ AlternativeLongOptionSpec() {
+ super( singletonList( RESERVED_FOR_EXTENSIONS ),
+ true,
+ Messages.message(
+ Locale.getDefault(),
+ "joptsimple.HelpFormatterMessages",
+ AlternativeLongOptionSpec.class,
+ "description" ) );
+
+ describedAs( Messages.message(
+ Locale.getDefault(),
+ "joptsimple.HelpFormatterMessages",
+ AlternativeLongOptionSpec.class,
+ "arg.description" ) );
+ }
+
+ @Override
+ protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+ if ( !arguments.hasMore() )
+ throw new OptionMissingRequiredArgumentException( this );
+
+ arguments.treatNextAsLongOption();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java
new file mode 100644
index 0000000000..ca4c59f0b0
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java
@@ -0,0 +1,329 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import static java.util.Collections.*;
+import static java.util.Objects.*;
+
+import static joptsimple.internal.Reflection.*;
+import static joptsimple.internal.Strings.*;
+
+/**
+ * <p>Specification of an option that accepts an argument.</p>
+ *
+ * <p>Instances are returned from {@link OptionSpecBuilder} methods to allow the formation of parser directives as
+ * sentences in a "fluent interface" language. For example:</p>
+ *
+ * <pre>
+ * <code>
+ * OptionParser parser = new OptionParser();
+ * parser.accepts( "c" ).withRequiredArg().<strong>ofType( Integer.class )</strong>;
+ * </code>
+ * </pre>
+ *
+ * <p>If no methods are invoked on an instance of this class, then that instance's option will treat its argument as
+ * a {@link String}.</p>
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class ArgumentAcceptingOptionSpec<V> extends AbstractOptionSpec<V> {
+ private static final char NIL_VALUE_SEPARATOR = '\u0000';
+
+ private final boolean argumentRequired;
+ private final List<V> defaultValues = new ArrayList<>();
+
+ private boolean optionRequired;
+ private ValueConverter<V> converter;
+ private String argumentDescription = "";
+ private String valueSeparator = String.valueOf( NIL_VALUE_SEPARATOR );
+
+ ArgumentAcceptingOptionSpec( String option, boolean argumentRequired ) {
+ super( option );
+
+ this.argumentRequired = argumentRequired;
+ }
+
+ ArgumentAcceptingOptionSpec( List<String> options, boolean argumentRequired, String description ) {
+ super( options, description );
+
+ this.argumentRequired = argumentRequired;
+ }
+
+ /**
+ * <p>Specifies a type to which arguments of this spec's option are to be converted.</p>
+ *
+ * <p>JOpt Simple accepts types that have either:</p>
+ *
+ * <ol>
+ * <li>a public static method called {@code valueOf} which accepts a single argument of type {@link String}
+ * and whose return type is the same as the class on which the method is declared. The {@code java.lang}
+ * primitive wrapper classes have such methods.</li>
+ *
+ * <li>a public constructor which accepts a single argument of type {@link String}.</li>
+ * </ol>
+ *
+ * <p>This class converts arguments using those methods in that order; that is, {@code valueOf} would be invoked
+ * before a one-{@link String}-arg constructor would.</p>
+ *
+ * <p>Invoking this method will trump any previous calls to this method or to
+ * {@link #withValuesConvertedBy(ValueConverter)}.</p>
+ *
+ * @param <T> represents the runtime class of the desired option argument type
+ * @param argumentType desired type of arguments to this spec's option
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws NullPointerException if the type is {@code null}
+ * @throws IllegalArgumentException if the type does not have the standard conversion methods
+ */
+ public final <T> ArgumentAcceptingOptionSpec<T> ofType( Class<T> argumentType ) {
+ return withValuesConvertedBy( findConverter( argumentType ) );
+ }
+
+ /**
+ * <p>Specifies a converter to use to translate arguments of this spec's option into Java objects. This is useful
+ * when converting to types that do not have the requisite factory method or constructor for
+ * {@link #ofType(Class)}.</p>
+ *
+ * <p>Invoking this method will trump any previous calls to this method or to {@link #ofType(Class)}.
+ *
+ * @param <T> represents the runtime class of the desired option argument type
+ * @param aConverter the converter to use
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws NullPointerException if the converter is {@code null}
+ */
+ @SuppressWarnings( "unchecked" )
+ public final <T> ArgumentAcceptingOptionSpec<T> withValuesConvertedBy( ValueConverter<T> aConverter ) {
+ if ( aConverter == null )
+ throw new NullPointerException( "illegal null converter" );
+
+ converter = (ValueConverter<V>) aConverter;
+ return (ArgumentAcceptingOptionSpec<T>) this;
+ }
+
+ /**
+ * <p>Specifies a description for the argument of the option that this spec represents. This description is used
+ * when generating help information about the parser.</p>
+ *
+ * @param description describes the nature of the argument of this spec's option
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public final ArgumentAcceptingOptionSpec<V> describedAs( String description ) {
+ argumentDescription = description;
+ return this;
+ }
+
+ /**
+ * <p>Specifies a value separator for the argument of the option that this spec represents. This allows a single
+ * option argument to represent multiple values for the option. For example:</p>
+ *
+ * <pre>
+ * <code>
+ * parser.accepts( "z" ).withRequiredArg()
+ * .<strong>withValuesSeparatedBy( ',' )</strong>;
+ * OptionSet options = parser.parse( new String[] { "-z", "foo,bar,baz", "-z",
+ * "fizz", "-z", "buzz" } );
+ * </code>
+ * </pre>
+ *
+ * <p>Then <code>options.valuesOf( "z" )</code> would yield the list {@code [foo, bar, baz, fizz, buzz]}.</p>
+ *
+ * <p>You cannot use Unicode U+0000 as the separator.</p>
+ *
+ * @param separator a character separator
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws IllegalArgumentException if the separator is Unicode U+0000
+ */
+ public final ArgumentAcceptingOptionSpec<V> withValuesSeparatedBy( char separator ) {
+ if ( separator == NIL_VALUE_SEPARATOR )
+ throw new IllegalArgumentException( "cannot use U+0000 as separator" );
+
+ valueSeparator = String.valueOf( separator );
+ return this;
+ }
+
+ /**
+ * <p>Specifies a value separator for the argument of the option that this spec represents. This allows a single
+ * option argument to represent multiple values for the option. For example:</p>
+ *
+ * <pre>
+ * <code>
+ * parser.accepts( "z" ).withRequiredArg()
+ * .<strong>withValuesSeparatedBy( ":::" )</strong>;
+ * OptionSet options = parser.parse( new String[] { "-z", "foo:::bar:::baz", "-z",
+ * "fizz", "-z", "buzz" } );
+ * </code>
+ * </pre>
+ *
+ * <p>Then <code>options.valuesOf( "z" )</code> would yield the list {@code [foo, bar, baz, fizz, buzz]}.</p>
+ *
+ * <p>You cannot use Unicode U+0000 in the separator.</p>
+ *
+ * @param separator a string separator
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws IllegalArgumentException if the separator contains Unicode U+0000
+ */
+ public final ArgumentAcceptingOptionSpec<V> withValuesSeparatedBy( String separator ) {
+ if ( separator.indexOf( NIL_VALUE_SEPARATOR ) != -1 )
+ throw new IllegalArgumentException( "cannot use U+0000 in separator" );
+
+ valueSeparator = separator;
+ return this;
+ }
+
+ /**
+ * Specifies a set of default values for the argument of the option that this spec represents.
+ *
+ * @param value the first in the set of default argument values for this spec's option
+ * @param values the (optional) remainder of the set of default argument values for this spec's option
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws NullPointerException if {@code value}, {@code values}, or any elements of {@code values} are
+ * {@code null}
+ */
+ @SafeVarargs
+ public final ArgumentAcceptingOptionSpec<V> defaultsTo( V value, V... values ) {
+ addDefaultValue( value );
+ defaultsTo( values );
+
+ return this;
+ }
+
+ /**
+ * Specifies a set of default values for the argument of the option that this spec represents.
+ *
+ * @param values the set of default argument values for this spec's option
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws NullPointerException if {@code values} or any elements of {@code values} are {@code null}
+ */
+ public ArgumentAcceptingOptionSpec<V> defaultsTo( V[] values ) {
+ for ( V each : values )
+ addDefaultValue( each );
+
+ return this;
+ }
+
+ /**
+ * Marks this option as required. An {@link OptionException} will be thrown when
+ * {@link OptionParser#parse(java.lang.String...)} is called, if an option is marked as required and not specified
+ * on the command line.
+ *
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public ArgumentAcceptingOptionSpec<V> required() {
+ optionRequired = true;
+ return this;
+ }
+
+ public boolean isRequired() {
+ return optionRequired;
+ }
+
+ private void addDefaultValue( V value ) {
+ requireNonNull( value );
+ defaultValues.add( value );
+ }
+
+ @Override
+ final void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+ String detectedArgument ) {
+
+ if ( isNullOrEmpty( detectedArgument ) )
+ detectOptionArgument( parser, arguments, detectedOptions );
+ else
+ addArguments( detectedOptions, detectedArgument );
+ }
+
+ protected void addArguments( OptionSet detectedOptions, String detectedArgument ) {
+ StringTokenizer lexer = new StringTokenizer( detectedArgument, valueSeparator );
+ if ( !lexer.hasMoreTokens() )
+ detectedOptions.addWithArgument( this, detectedArgument );
+ else {
+ while ( lexer.hasMoreTokens() )
+ detectedOptions.addWithArgument( this, lexer.nextToken() );
+ }
+ }
+
+ protected abstract void detectOptionArgument( OptionParser parser, ArgumentList arguments,
+ OptionSet detectedOptions );
+
+ @Override
+ protected final V convert( String argument ) {
+ return convertWith( converter, argument );
+ }
+
+ protected boolean canConvertArgument( String argument ) {
+ StringTokenizer lexer = new StringTokenizer( argument, valueSeparator );
+
+ try {
+ while ( lexer.hasMoreTokens() )
+ convert( lexer.nextToken() );
+ return true;
+ } catch ( OptionException ignored ) {
+ return false;
+ }
+ }
+
+ protected boolean isArgumentOfNumberType() {
+ return converter != null && Number.class.isAssignableFrom( converter.valueType() );
+ }
+
+ public boolean acceptsArguments() {
+ return true;
+ }
+
+ public boolean requiresArgument() {
+ return argumentRequired;
+ }
+
+ public String argumentDescription() {
+ return argumentDescription;
+ }
+
+ public String argumentTypeIndicator() {
+ return argumentTypeIndicatorFrom( converter );
+ }
+
+ public List<V> defaultValues() {
+ return unmodifiableList( defaultValues );
+ }
+
+ @Override
+ public boolean equals( Object that ) {
+ if ( !super.equals( that ) )
+ return false;
+
+ ArgumentAcceptingOptionSpec<?> other = (ArgumentAcceptingOptionSpec<?>) that;
+ return requiresArgument() == other.requiresArgument();
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ ( argumentRequired ? 0 : 1 );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java
new file mode 100644
index 0000000000..744f31aa21
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java
@@ -0,0 +1,59 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static joptsimple.ParserRules.*;
+
+/**
+ * <p>Wrapper for an array of command line arguments.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class ArgumentList {
+ private final String[] arguments;
+ private int currentIndex;
+
+ ArgumentList( String... arguments ) {
+ this.arguments = arguments.clone();
+ }
+
+ boolean hasMore() {
+ return currentIndex < arguments.length;
+ }
+
+ String next() {
+ return arguments[ currentIndex++ ];
+ }
+
+ String peek() {
+ return arguments[ currentIndex ];
+ }
+
+ void treatNextAsLongOption() {
+ if ( HYPHEN_CHAR != arguments[ currentIndex ].charAt( 0 ) )
+ arguments[ currentIndex ] = DOUBLE_HYPHEN + arguments[ currentIndex ];
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java
new file mode 100644
index 0000000000..51ec603e6f
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java
@@ -0,0 +1,565 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.*;
+
+import joptsimple.internal.Messages;
+import joptsimple.internal.Rows;
+import joptsimple.internal.Strings;
+
+import static joptsimple.ParserRules.*;
+import static joptsimple.internal.Classes.*;
+import static joptsimple.internal.Strings.*;
+
+/**
+ * <p>A help formatter that allows configuration of overall row width and column separator width.</p>
+ *
+ * <p>The formatter produces output in two sections: one for the options, and one for non-option arguments.</p>
+ *
+ * <p>The options section has two columns: the left column for the options, and the right column for their
+ * descriptions. The formatter will allow as much space as possible for the descriptions, by minimizing the option
+ * column's width, no greater than slightly less than half the overall desired width.</p>
+ *
+ * <p>The non-option arguments section is one column, occupying as much width as it can.</p>
+ *
+ * <p>Subclasses are free to override bits of this implementation as they see fit. Inspect the code
+ * carefully to understand the flow of control that this implementation guarantees.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class BuiltinHelpFormatter implements HelpFormatter {
+ private final Rows nonOptionRows;
+ private final Rows optionRows;
+
+ /**
+ * Makes a formatter with a pre-configured overall row width and column separator width.
+ */
+ BuiltinHelpFormatter() {
+ this( 80, 2 );
+ }
+
+ /**
+ * Makes a formatter with a given overall row width and column separator width.
+ *
+ * @param desiredOverallWidth how many characters wide to make the overall help display
+ * @param desiredColumnSeparatorWidth how many characters wide to make the separation between option column and
+ * description column
+ */
+ public BuiltinHelpFormatter( int desiredOverallWidth, int desiredColumnSeparatorWidth ) {
+ nonOptionRows = new Rows( desiredOverallWidth * 2, 0 );
+ optionRows = new Rows( desiredOverallWidth, desiredColumnSeparatorWidth );
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation:</p>
+ * <ul>
+ * <li>Sorts the given descriptors by their first elements of {@link OptionDescriptor#options()}</li>
+ * <li>Passes the resulting sorted set to {@link #addRows(java.util.Collection)}</li>
+ * <li>Returns the result of {@link #formattedHelpOutput()}</li>
+ * </ul>
+ */
+ public String format( Map<String, ? extends OptionDescriptor> options ) {
+ optionRows.reset();
+ nonOptionRows.reset();
+
+ Comparator<OptionDescriptor> comparator =
+ new Comparator<OptionDescriptor>() {
+ public int compare( OptionDescriptor first, OptionDescriptor second ) {
+ return first.options().iterator().next().compareTo( second.options().iterator().next() );
+ }
+ };
+
+ Set<OptionDescriptor> sorted = new TreeSet<>( comparator );
+ sorted.addAll( options.values() );
+
+ addRows( sorted );
+
+ return formattedHelpOutput();
+ }
+
+ /**
+ * Adds a row of option help output in the left column, with empty space in the right column.
+ *
+ * @param single text to put in the left column
+ */
+ protected void addOptionRow( String single ) {
+ addOptionRow( single, "" );
+ }
+
+ /**
+ * Adds a row of option help output in the left and right columns.
+ *
+ * @param left text to put in the left column
+ * @param right text to put in the right column
+ */
+ protected void addOptionRow( String left, String right ) {
+ optionRows.add( left, right );
+ }
+
+ /**
+ * Adds a single row of non-option argument help.
+ *
+ * @param single single row of non-option argument help text
+ */
+ protected void addNonOptionRow( String single ) {
+ nonOptionRows.add( single, "" );
+ }
+
+ /**
+ * Resizes the columns of all the rows to be no wider than the widest element in that column.
+ */
+ protected void fitRowsToWidth() {
+ nonOptionRows.fitToWidth();
+ optionRows.fitToWidth();
+ }
+
+ /**
+ * Produces non-option argument help.
+ *
+ * @return non-option argument help
+ */
+ protected String nonOptionOutput() {
+ return nonOptionRows.render();
+ }
+
+ /**
+ * Produces help for options and their descriptions.
+ *
+ * @return option help
+ */
+ protected String optionOutput() {
+ return optionRows.render();
+ }
+
+ /**
+ * <p>Produces help output for an entire set of options and non-option arguments.</p>
+ *
+ * <p>This implementation concatenates:</p>
+ * <ul>
+ * <li>the result of {@link #nonOptionOutput()}</li>
+ * <li>if there is non-option output, a line separator</li>
+ * <li>the result of {@link #optionOutput()}</li>
+ * </ul>
+ *
+ * @return help output for entire set of options and non-option arguments
+ */
+ protected String formattedHelpOutput() {
+ StringBuilder formatted = new StringBuilder();
+ String nonOptionDisplay = nonOptionOutput();
+ if ( !Strings.isNullOrEmpty( nonOptionDisplay ) )
+ formatted.append( nonOptionDisplay ).append( LINE_SEPARATOR );
+ formatted.append( optionOutput() );
+
+ return formatted.toString();
+ }
+
+ /**
+ * <p>Adds rows of help output for the given options.</p>
+ *
+ * <p>This implementation:</p>
+ * <ul>
+ * <li>Calls {@link #addNonOptionsDescription(java.util.Collection)} with the options as the argument</li>
+ * <li>If there are no options, calls {@link #addOptionRow(String)} with an argument that indicates
+ * that no options are specified.</li>
+ * <li>Otherwise, calls {@link #addHeaders(java.util.Collection)} with the options as the argument,
+ * followed by {@link #addOptions(java.util.Collection)} with the options as the argument.</li>
+ * <li>Calls {@link #fitRowsToWidth()}.</li>
+ * </ul>
+ *
+ * @param options descriptors for the configured options of a parser
+ */
+ protected void addRows( Collection<? extends OptionDescriptor> options ) {
+ addNonOptionsDescription( options );
+
+ if ( options.isEmpty() )
+ addOptionRow( message( "no.options.specified" ) );
+ else {
+ addHeaders( options );
+ addOptions( options );
+ }
+
+ fitRowsToWidth();
+ }
+
+ /**
+ * <p>Adds non-option arguments descriptions to the help output.</p>
+ *
+ * <p>This implementation:</p>
+ * <ul>
+ * <li>{@linkplain #findAndRemoveNonOptionsSpec(java.util.Collection) Finds and removes the non-option
+ * arguments descriptor}</li>
+ * <li>{@linkplain #shouldShowNonOptionArgumentDisplay(OptionDescriptor) Decides whether there is
+ * anything to show for non-option arguments}</li>
+ * <li>If there is, {@linkplain #addNonOptionRow(String) adds a header row} and
+ * {@linkplain #addNonOptionRow(String) adds a}
+ * {@linkplain #createNonOptionArgumentsDisplay(OptionDescriptor) non-option arguments description} </li>
+ * </ul>
+ *
+ * @param options descriptors for the configured options of a parser
+ */
+ protected void addNonOptionsDescription( Collection<? extends OptionDescriptor> options ) {
+ OptionDescriptor nonOptions = findAndRemoveNonOptionsSpec( options );
+ if ( shouldShowNonOptionArgumentDisplay( nonOptions ) ) {
+ addNonOptionRow( message( "non.option.arguments.header" ) );
+ addNonOptionRow( createNonOptionArgumentsDisplay( nonOptions ) );
+ }
+ }
+
+ /**
+ * <p>Decides whether or not to show a non-option arguments help.</p>
+ *
+ * <p>This implementation responds with {@code true} if the non-option descriptor has a non-{@code null},
+ * non-empty value for any of {@link OptionDescriptor#description()},
+ * {@link OptionDescriptor#argumentTypeIndicator()}, or {@link OptionDescriptor#argumentDescription()}.</p>
+ *
+ * @param nonOptionDescriptor non-option argument descriptor
+ * @return {@code true} if non-options argument help should be shown
+ */
+ protected boolean shouldShowNonOptionArgumentDisplay( OptionDescriptor nonOptionDescriptor ) {
+ return !Strings.isNullOrEmpty( nonOptionDescriptor.description() )
+ || !Strings.isNullOrEmpty( nonOptionDescriptor.argumentTypeIndicator() )
+ || !Strings.isNullOrEmpty( nonOptionDescriptor.argumentDescription() );
+ }
+
+ /**
+ * <p>Creates a non-options argument help string.</p>
+ *
+ * <p>This implementation creates an empty string buffer and calls
+ * {@link #maybeAppendOptionInfo(StringBuilder, OptionDescriptor)}
+ * and {@link #maybeAppendNonOptionsDescription(StringBuilder, OptionDescriptor)}, passing them the
+ * buffer and the non-option arguments descriptor.</p>
+ *
+ * @param nonOptionDescriptor non-option argument descriptor
+ * @return help string for non-options
+ */
+ protected String createNonOptionArgumentsDisplay( OptionDescriptor nonOptionDescriptor ) {
+ StringBuilder buffer = new StringBuilder();
+ maybeAppendOptionInfo( buffer, nonOptionDescriptor );
+ maybeAppendNonOptionsDescription( buffer, nonOptionDescriptor );
+
+ return buffer.toString();
+ }
+
+ /**
+ * <p>Appends help for the given non-option arguments descriptor to the given buffer.</p>
+ *
+ * <p>This implementation appends {@code " -- "} if the buffer has text in it and the non-option arguments
+ * descriptor has a {@link OptionDescriptor#description()}; followed by the
+ * {@link OptionDescriptor#description()}.</p>
+ *
+ * @param buffer string buffer
+ * @param nonOptions non-option arguments descriptor
+ */
+ protected void maybeAppendNonOptionsDescription( StringBuilder buffer, OptionDescriptor nonOptions ) {
+ buffer.append( buffer.length() > 0 && !Strings.isNullOrEmpty( nonOptions.description() ) ? " -- " : "" )
+ .append( nonOptions.description() );
+ }
+
+ /**
+ * Finds the non-option arguments descriptor in the given collection, removes it, and returns it.
+ *
+ * @param options descriptors for the configured options of a parser
+ * @return the non-option arguments descriptor
+ */
+ protected OptionDescriptor findAndRemoveNonOptionsSpec( Collection<? extends OptionDescriptor> options ) {
+ for ( Iterator<? extends OptionDescriptor> it = options.iterator(); it.hasNext(); ) {
+ OptionDescriptor next = it.next();
+ if ( next.representsNonOptions() ) {
+ it.remove();
+ return next;
+ }
+ }
+
+ throw new AssertionError( "no non-options argument spec" );
+ }
+
+ /**
+ * <p>Adds help row headers for option help columns.</p>
+ *
+ * <p>This implementation uses the headers {@code "Option"} and {@code "Description"}. If the options contain
+ * a "required" option, the {@code "Option"} header looks like {@code "Option (* = required)}. Both headers
+ * are "underlined" using {@code "-"}.</p>
+ *
+ * @param options descriptors for the configured options of a parser
+ */
+ protected void addHeaders( Collection<? extends OptionDescriptor> options ) {
+ if ( hasRequiredOption( options ) ) {
+ addOptionRow( message( "option.header.with.required.indicator" ), message( "description.header" ) );
+ addOptionRow( message( "option.divider.with.required.indicator" ), message( "description.divider" ) );
+ } else {
+ addOptionRow( message( "option.header" ), message( "description.header" ) );
+ addOptionRow( message( "option.divider" ), message( "description.divider" ) );
+ }
+ }
+
+ /**
+ * Tells whether the given option descriptors contain a "required" option.
+ *
+ * @param options descriptors for the configured options of a parser
+ * @return {@code true} if at least one of the options is "required"
+ */
+ protected final boolean hasRequiredOption( Collection<? extends OptionDescriptor> options ) {
+ for ( OptionDescriptor each : options ) {
+ if ( each.isRequired() )
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * <p>Adds help rows for the given options.</p>
+ *
+ * <p>This implementation loops over the given options, and for each, calls {@link #addOptionRow(String, String)}
+ * using the results of {@link #createOptionDisplay(OptionDescriptor)} and
+ * {@link #createDescriptionDisplay(OptionDescriptor)}, respectively, as arguments.</p>
+ *
+ * @param options descriptors for the configured options of a parser
+ */
+ protected void addOptions( Collection<? extends OptionDescriptor> options ) {
+ for ( OptionDescriptor each : options ) {
+ if ( !each.representsNonOptions() )
+ addOptionRow( createOptionDisplay( each ), createDescriptionDisplay( each ) );
+ }
+ }
+
+ /**
+ * <p>Creates a string for how the given option descriptor is to be represented in help.</p>
+ *
+ * <p>This implementation gives a string consisting of the concatenation of:</p>
+ * <ul>
+ * <li>{@code "* "} for "required" options, otherwise {@code ""}</li>
+ * <li>For each of the {@link OptionDescriptor#options()} of the descriptor, separated by {@code ", "}:
+ * <ul>
+ * <li>{@link #optionLeader(String)} of the option</li>
+ * <li>the option</li>
+ * </ul>
+ * </li>
+ * <li>the result of {@link #maybeAppendOptionInfo(StringBuilder, OptionDescriptor)}</li>
+ * </ul>
+ *
+ * @param descriptor a descriptor for a configured option of a parser
+ * @return help string
+ */
+ protected String createOptionDisplay( OptionDescriptor descriptor ) {
+ StringBuilder buffer = new StringBuilder( descriptor.isRequired() ? "* " : "" );
+
+ for ( Iterator<String> i = descriptor.options().iterator(); i.hasNext(); ) {
+ String option = i.next();
+ buffer.append( optionLeader( option ) );
+ buffer.append( option );
+
+ if ( i.hasNext() )
+ buffer.append( ", " );
+ }
+
+ maybeAppendOptionInfo( buffer, descriptor );
+
+ return buffer.toString();
+ }
+
+ /**
+ * <p>Gives a string that represents the given option's "option leader" in help.</p>
+ *
+ * <p>This implementation answers with {@code "--"} for options of length greater than one; otherwise answers
+ * with {@code "-"}.</p>
+ *
+ * @param option a string option
+ * @return an "option leader" string
+ */
+ protected String optionLeader( String option ) {
+ return option.length() > 1 ? DOUBLE_HYPHEN : HYPHEN;
+ }
+
+ /**
+ * <p>Appends additional info about the given option to the given buffer.</p>
+ *
+ * <p>This implementation:</p>
+ * <ul>
+ * <li>calls {@link #extractTypeIndicator(OptionDescriptor)} for the descriptor</li>
+ * <li>calls {@link joptsimple.OptionDescriptor#argumentDescription()} for the descriptor</li>
+ * <li>if either of the above is present, calls
+ * {@link #appendOptionHelp(StringBuilder, String, String, boolean)}</li>
+ * </ul>
+ *
+ * @param buffer string buffer
+ * @param descriptor a descriptor for a configured option of a parser
+ */
+ protected void maybeAppendOptionInfo( StringBuilder buffer, OptionDescriptor descriptor ) {
+ String indicator = extractTypeIndicator( descriptor );
+ String description = descriptor.argumentDescription();
+ if ( descriptor.acceptsArguments()
+ || !isNullOrEmpty( description )
+ || descriptor.representsNonOptions() ) {
+
+ appendOptionHelp( buffer, indicator, description, descriptor.requiresArgument() );
+ }
+ }
+
+ /**
+ * <p>Gives an indicator of the type of arguments of the option described by the given descriptor,
+ * for use in help.</p>
+ *
+ * <p>This implementation asks for the {@link OptionDescriptor#argumentTypeIndicator()} of the given
+ * descriptor, and if it is present and not {@code "java.lang.String"}, parses it as a fully qualified
+ * class name and returns the base name of that class; otherwise returns {@code "String"}.</p>
+ *
+ * @param descriptor a descriptor for a configured option of a parser
+ * @return type indicator text
+ */
+ protected String extractTypeIndicator( OptionDescriptor descriptor ) {
+ String indicator = descriptor.argumentTypeIndicator();
+
+ if ( !isNullOrEmpty( indicator ) && !String.class.getName().equals( indicator ) )
+ return shortNameOf( indicator );
+
+ return "String";
+ }
+
+ /**
+ * <p>Appends info about an option's argument to the given buffer.</p>
+ *
+ * <p>This implementation calls {@link #appendTypeIndicator(StringBuilder, String, String, char, char)} with
+ * the surrounding characters {@code '<'} and {@code '>'} for options with {@code required} arguments, and
+ * with the surrounding characters {@code '['} and {@code ']'} for options with optional arguments.</p>
+ *
+ * @param buffer string buffer
+ * @param typeIndicator type indicator
+ * @param description type description
+ * @param required indicator of "required"-ness of the argument of the option
+ */
+ protected void appendOptionHelp( StringBuilder buffer, String typeIndicator, String description,
+ boolean required ) {
+ if ( required )
+ appendTypeIndicator( buffer, typeIndicator, description, '<', '>' );
+ else
+ appendTypeIndicator( buffer, typeIndicator, description, '[', ']' );
+ }
+
+ /**
+ * <p>Appends a type indicator for an option's argument to the given buffer.</p>
+ *
+ * <p>This implementation appends, in order:</p>
+ * <ul>
+ * <li>{@code ' '}</li>
+ * <li>{@code start}</li>
+ * <li>the type indicator, if not {@code null}</li>
+ * <li>if the description is present, then {@code ": "} plus the description if the type indicator is
+ * present; otherwise the description only</li>
+ * <li>{@code end}</li>
+ * </ul>
+ *
+ * @param buffer string buffer
+ * @param typeIndicator type indicator
+ * @param description type description
+ * @param start starting character
+ * @param end ending character
+ */
+ protected void appendTypeIndicator( StringBuilder buffer, String typeIndicator, String description,
+ char start, char end ) {
+ buffer.append( ' ' ).append( start );
+ if ( typeIndicator != null )
+ buffer.append( typeIndicator );
+
+ if ( !Strings.isNullOrEmpty( description ) ) {
+ if ( typeIndicator != null )
+ buffer.append( ": " );
+
+ buffer.append( description );
+ }
+
+ buffer.append( end );
+ }
+
+ /**
+ * <p>Gives a string representing a description of the option with the given descriptor.</p>
+ *
+ * <p>This implementation:</p>
+ * <ul>
+ * <li>Asks for the descriptor's {@link OptionDescriptor#defaultValues()}</li>
+ * <li>If they're not present, answers the descriptor's {@link OptionDescriptor#description()}.</li>
+ * <li>If they are present, concatenates and returns:
+ * <ul>
+ * <li>the descriptor's {@link OptionDescriptor#description()}</li>
+ * <li>{@code ' '}</li>
+ * <li>{@code "default: "} plus the result of {@link #createDefaultValuesDisplay(java.util.List)},
+ * surrounded by parentheses</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @param descriptor a descriptor for a configured option of a parser
+ * @return display text for the option's description
+ */
+ protected String createDescriptionDisplay( OptionDescriptor descriptor ) {
+ List<?> defaultValues = descriptor.defaultValues();
+ if ( defaultValues.isEmpty() )
+ return descriptor.description();
+
+ String defaultValuesDisplay = createDefaultValuesDisplay( defaultValues );
+ return ( descriptor.description()
+ + ' '
+ + surround( message( "default.value.header" ) + ' ' + defaultValuesDisplay, '(', ')' )
+ ).trim();
+ }
+
+ /**
+ * <p>Gives a display string for the default values of an option's argument.</p>
+ *
+ * <p>This implementation gives the {@link Object#toString()} of the first value if there is only one value,
+ * otherwise gives the {@link Object#toString()} of the whole list.</p>
+ *
+ * @param defaultValues some default values for a given option's argument
+ * @return a display string for those default values
+ */
+ protected String createDefaultValuesDisplay( List<?> defaultValues ) {
+ return defaultValues.size() == 1 ? defaultValues.get( 0 ).toString() : defaultValues.toString();
+ }
+
+ /**
+ * <p>Looks up and gives a resource bundle message.</p>
+ *
+ * <p>This implementation looks in the bundle {@code "joptsimple.HelpFormatterMessages"} in the default
+ * locale, using a key that is the concatenation of this class's fully qualified name, {@code '.'},
+ * and the given key suffix, formats the corresponding value using the given arguments, and returns
+ * the result.</p>
+ *
+ * @param keySuffix suffix to use when looking up the bundle message
+ * @param args arguments to fill in the message template with
+ * @return a formatted localized message
+ */
+ protected String message( String keySuffix, Object... args ) {
+ return Messages.message(
+ Locale.getDefault(),
+ "joptsimple.HelpFormatterMessages",
+ BuiltinHelpFormatter.class,
+ keySuffix,
+ args );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java
new file mode 100644
index 0000000000..d178d70c09
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java
@@ -0,0 +1,45 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Map;
+
+/**
+ * <p>Represents objects charged with taking a set of option descriptions and producing some help text from them.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface HelpFormatter {
+ /**
+ * Produces help text, given a set of option descriptors.
+ *
+ * @param options descriptors for the configured options of a parser
+ * @return text to be used as help
+ * @see OptionParser#printHelpOn(java.io.Writer)
+ * @see OptionParser#formatHelpWith(HelpFormatter)
+ */
+ String format( Map<String, ? extends OptionDescriptor> options );
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java
new file mode 100644
index 0000000000..214791544c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java
@@ -0,0 +1,46 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+/**
+ * Thrown when the option parser is asked to recognize an option with illegal characters in it.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class IllegalOptionSpecificationException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ IllegalOptionSpecificationException( String option ) {
+ super( singletonList( option ) );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { singleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java
new file mode 100644
index 0000000000..dcb829f342
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java
@@ -0,0 +1,46 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Thrown when options marked as required are not specified on the command line.
+ *
+ * @author <a href="https://github.com/TC1">Emils Solmanis</a>
+ */
+class MissingRequiredOptionsException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ protected MissingRequiredOptionsException( List<? extends OptionSpec<?>> missingRequiredOptions ) {
+ super( missingRequiredOptions );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { multipleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java
new file mode 100644
index 0000000000..12d1485a39
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java
@@ -0,0 +1,46 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+/**
+ * Thrown when asking an {@link OptionSet} for a single argument of an option when many have been specified.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class MultipleArgumentsForOptionException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ MultipleArgumentsForOptionException( OptionSpec<?> options ) {
+ super( singleton( options ) );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { singleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java
new file mode 100644
index 0000000000..82ac521772
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java
@@ -0,0 +1,81 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import static java.util.Collections.*;
+
+/**
+ * A specification for an option that does not accept arguments.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class NoArgumentOptionSpec extends AbstractOptionSpec<Void> {
+ NoArgumentOptionSpec( String option ) {
+ this( singletonList( option ), "" );
+ }
+
+ NoArgumentOptionSpec( List<String> options, String description ) {
+ super( options, description );
+ }
+
+ @Override
+ void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+ String detectedArgument ) {
+
+ detectedOptions.add( this );
+ }
+
+ public boolean acceptsArguments() {
+ return false;
+ }
+
+ public boolean requiresArgument() {
+ return false;
+ }
+
+ public boolean isRequired() {
+ return false;
+ }
+
+ public String argumentDescription() {
+ return "";
+ }
+
+ public String argumentTypeIndicator() {
+ return "";
+ }
+
+ @Override
+ protected Void convert( String argument ) {
+ return null;
+ }
+
+ public List<Void> defaultValues() {
+ return emptyList();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java
new file mode 100644
index 0000000000..7343d42c2a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java
@@ -0,0 +1,170 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+import static joptsimple.internal.Reflection.*;
+
+/**
+ * <p>Specification of a command line's non-option arguments.</p>
+ *
+ * <p>Instances are returned from {@link OptionParser} methods to allow the formation of parser directives as
+ * sentences in a "fluent interface" language. For example:</p>
+ *
+ * <pre>
+ * <code>
+ * OptionParser parser = new OptionParser();
+ * parser.nonOptions( "files to be processed" ).<strong>ofType( File.class )</strong>;
+ * </code>
+ * </pre>
+ *
+ * <p>If no methods are invoked on an instance of this class, then that instance's option will treat the non-option
+ * arguments as {@link String}s.</p>
+ *
+ * @param <V> represents the type of the non-option arguments
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class NonOptionArgumentSpec<V> extends AbstractOptionSpec<V> {
+ static final String NAME = "[arguments]";
+
+ private ValueConverter<V> converter;
+ private String argumentDescription = "";
+
+ NonOptionArgumentSpec() {
+ this( "" );
+ }
+
+ NonOptionArgumentSpec( String description ) {
+ super( asList( NAME ), description );
+ }
+
+ /**
+ * <p>Specifies a type to which the non-option arguments are to be converted.</p>
+ *
+ * <p>JOpt Simple accepts types that have either:</p>
+ *
+ * <ol>
+ * <li>a public static method called {@code valueOf} which accepts a single argument of type {@link String}
+ * and whose return type is the same as the class on which the method is declared. The {@code java.lang}
+ * primitive wrapper classes have such methods.</li>
+ *
+ * <li>a public constructor which accepts a single argument of type {@link String}.</li>
+ * </ol>
+ *
+ * <p>This class converts arguments using those methods in that order; that is, {@code valueOf} would be invoked
+ * before a one-{@link String}-arg constructor would.</p>
+ *
+ * <p>Invoking this method will trump any previous calls to this method or to
+ * {@link #withValuesConvertedBy(ValueConverter)}.</p>
+ *
+ * @param <T> represents the runtime class of the desired option argument type
+ * @param argumentType desired type of arguments to this spec's option
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws NullPointerException if the type is {@code null}
+ * @throws IllegalArgumentException if the type does not have the standard conversion methods
+ */
+ @SuppressWarnings( "unchecked" )
+ public <T> NonOptionArgumentSpec<T> ofType( Class<T> argumentType ) {
+ converter = (ValueConverter<V>) findConverter( argumentType );
+ return (NonOptionArgumentSpec<T>) this;
+ }
+
+ /**
+ * <p>Specifies a converter to use to translate non-option arguments into Java objects. This is useful
+ * when converting to types that do not have the requisite factory method or constructor for
+ * {@link #ofType(Class)}.</p>
+ *
+ * <p>Invoking this method will trump any previous calls to this method or to {@link #ofType(Class)}.
+ *
+ * @param <T> represents the runtime class of the desired non-option argument type
+ * @param aConverter the converter to use
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws NullPointerException if the converter is {@code null}
+ */
+ @SuppressWarnings( "unchecked" )
+ public final <T> NonOptionArgumentSpec<T> withValuesConvertedBy( ValueConverter<T> aConverter ) {
+ if ( aConverter == null )
+ throw new NullPointerException( "illegal null converter" );
+
+ converter = (ValueConverter<V>) aConverter;
+ return (NonOptionArgumentSpec<T>) this;
+ }
+
+ /**
+ * <p>Specifies a description for the non-option arguments that this spec represents. This description is used
+ * when generating help information about the parser.</p>
+ *
+ * @param description describes the nature of the argument of this spec's option
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public NonOptionArgumentSpec<V> describedAs( String description ) {
+ argumentDescription = description;
+ return this;
+ }
+
+ @Override
+ protected final V convert( String argument ) {
+ return convertWith( converter, argument );
+ }
+
+ @Override
+ void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+ String detectedArgument ) {
+
+ detectedOptions.addWithArgument( this, detectedArgument );
+ }
+
+ public List<?> defaultValues() {
+ return emptyList();
+ }
+
+ public boolean isRequired() {
+ return false;
+ }
+
+ public boolean acceptsArguments() {
+ return false;
+ }
+
+ public boolean requiresArgument() {
+ return false;
+ }
+
+ public String argumentDescription() {
+ return argumentDescription;
+ }
+
+ public String argumentTypeIndicator() {
+ return argumentTypeIndicatorFrom( converter );
+ }
+
+ public boolean representsNonOptions() {
+ return true;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java
new file mode 100644
index 0000000000..193557d8fa
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java
@@ -0,0 +1,50 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+/**
+ * Thrown when a problem occurs converting an argument of an option from {@link String} to another type.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionArgumentConversionException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ private final String argument;
+
+ OptionArgumentConversionException( OptionSpec<?> options, String argument, Throwable cause ) {
+ super( singleton( options ), cause );
+
+ this.argument = argument;
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { argument, singleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java
new file mode 100644
index 0000000000..7d54653443
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java
@@ -0,0 +1,116 @@
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Trains the option parser. This interface aids integration that disposes declaration of options but not actual
+ * command-line parsing.
+ *
+ * Typical use is for another class to implement {@code OptionDeclarer} as a facade, forwarding calls to an
+ * {@code OptionParser} instance.
+ *
+ * Note that although this is an interface, the returned values of calls are concrete jopt-simple classes.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ * @see OptionParser
+ * @since 4.6
+ */
+public interface OptionDeclarer {
+ /**
+ * Tells the parser to recognize the given option.
+ *
+ * <p>This method returns an instance of {@link OptionSpecBuilder} to allow the formation of parser directives
+ * as sentences in a fluent interface language. For example:</p>
+ *
+ * <pre><code>
+ * OptionDeclarer parser = new OptionParser();
+ * parser.<strong>accepts( "c" )</strong>.withRequiredArg().ofType( Integer.class );
+ * </code></pre>
+ *
+ * <p>If no methods are invoked on the returned {@link OptionSpecBuilder}, then the parser treats the option as
+ * accepting no argument.</p>
+ *
+ * @param option the option to recognize
+ * @return an object that can be used to flesh out more detail about the option
+ * @throws OptionException if the option contains illegal characters
+ * @throws NullPointerException if the option is {@code null}
+ */
+ OptionSpecBuilder accepts( String option );
+
+ /**
+ * Tells the parser to recognize the given option.
+ *
+ * @see #accepts(String)
+ * @param option the option to recognize
+ * @param description a string that describes the purpose of the option. This is used when generating help
+ * information about the parser.
+ * @return an object that can be used to flesh out more detail about the option
+ * @throws OptionException if the option contains illegal characters
+ * @throws NullPointerException if the option is {@code null}
+ */
+ OptionSpecBuilder accepts( String option, String description );
+
+ /**
+ * Tells the parser to recognize the given options, and treat them as synonymous.
+ *
+ * @see #accepts(String)
+ * @param options the options to recognize and treat as synonymous
+ * @return an object that can be used to flesh out more detail about the options
+ * @throws OptionException if any of the options contain illegal characters
+ * @throws NullPointerException if the option list or any of its elements are {@code null}
+ */
+ OptionSpecBuilder acceptsAll( List<String> options );
+
+ /**
+ * Tells the parser to recognize the given options, and treat them as synonymous.
+ *
+ * @see #acceptsAll(List)
+ * @param options the options to recognize and treat as synonymous
+ * @param description a string that describes the purpose of the option. This is used when generating help
+ * information about the parser.
+ * @return an object that can be used to flesh out more detail about the options
+ * @throws OptionException if any of the options contain illegal characters
+ * @throws NullPointerException if the option list or any of its elements are {@code null}
+ * @throws IllegalArgumentException if the option list is empty
+ */
+ OptionSpecBuilder acceptsAll( List<String> options, String description );
+
+ /**
+ * Gives an object that represents an access point for non-option arguments on a command line.
+ *
+ * @return an object that can be used to flesh out more detail about the non-option arguments
+ */
+ NonOptionArgumentSpec<String> nonOptions();
+
+ /**
+ * Gives an object that represents an access point for non-option arguments on a command line.
+ *
+ * @see #nonOptions()
+ * @param description a string that describes the purpose of the non-option arguments. This is used when generating
+ * help information about the parser.
+ * @return an object that can be used to flesh out more detail about the non-option arguments
+ */
+ NonOptionArgumentSpec<String> nonOptions( String description );
+
+ /**
+ * Tells the parser whether or not to behave "POSIX-ly correct"-ly.
+ *
+ * @param setting {@code true} if the parser should behave "POSIX-ly correct"-ly
+ */
+ void posixlyCorrect( boolean setting );
+
+ /**
+ * <p>Tells the parser to treat unrecognized options as non-option arguments.</p>
+ *
+ * <p>If not called, then the parser raises an {@link OptionException} when it encounters an unrecognized
+ * option.</p>
+ */
+ void allowsUnrecognizedOptions();
+
+ /**
+ * Tells the parser either to recognize or ignore {@code -W}-style long options.
+ *
+ * @param recognize {@code true} if the parser is to recognize the special style of long options
+ */
+ void recognizeAlternativeLongOptions( boolean recognize );
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java
new file mode 100644
index 0000000000..f77c775223
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java
@@ -0,0 +1,100 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Describes options that an option parser recognizes, in ways that might be useful to {@linkplain HelpFormatter
+ * help screens}.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface OptionDescriptor {
+ /**
+ * A set of options that are mutually synonymous.
+ *
+ * @return synonymous options
+ */
+ List<String> options();
+
+ /**
+ * Description of this option's purpose.
+ *
+ * @return a description for the option
+ */
+ String description();
+
+ /**
+ * What values will the option take if none are specified on the command line?
+ *
+ * @return any default values for the option
+ */
+ List<?> defaultValues();
+
+ /**
+ * Is this option {@linkplain ArgumentAcceptingOptionSpec#required() required} on a command line?
+ *
+ * @return whether the option is required
+ */
+ boolean isRequired();
+
+ /**
+ * Does this option {@linkplain ArgumentAcceptingOptionSpec accept arguments}?
+ *
+ * @return whether the option accepts arguments
+ */
+ boolean acceptsArguments();
+
+ /**
+ * Does this option {@linkplain OptionSpecBuilder#withRequiredArg() require an argument}?
+ *
+ * @return whether the option requires an argument
+ */
+ boolean requiresArgument();
+
+ /**
+ * Gives a short {@linkplain ArgumentAcceptingOptionSpec#describedAs(String) description} of the option's argument.
+ *
+ * @return a description for the option's argument
+ */
+ String argumentDescription();
+
+ /**
+ * Gives an indication of the {@linkplain ArgumentAcceptingOptionSpec#ofType(Class) expected type} of the option's
+ * argument.
+ *
+ * @return a description for the option's argument type
+ */
+ String argumentTypeIndicator();
+
+ /**
+ * Tells whether this object represents the non-option arguments of a command line.
+ *
+ * @return {@code true} if this represents non-option arguments
+ */
+ boolean representsNonOptions();
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java
new file mode 100644
index 0000000000..88e7e43f2e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java
@@ -0,0 +1,125 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import joptsimple.internal.Strings;
+
+import static java.util.Collections.*;
+import static joptsimple.internal.Messages.*;
+
+/**
+ * Thrown when a problem occurs during option parsing.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class OptionException extends RuntimeException {
+ private static final long serialVersionUID = -1L;
+
+ private final List<String> options = new ArrayList<>();
+
+ protected OptionException( List<String> options ) {
+ this.options.addAll( options );
+ }
+
+ protected OptionException( Collection<? extends OptionSpec<?>> options ) {
+ this.options.addAll( specsToStrings( options ) );
+ }
+
+ protected OptionException( Collection<? extends OptionSpec<?>> options, Throwable cause ) {
+ super( cause );
+ this.options.addAll( specsToStrings( options ) );
+ }
+
+ private List<String> specsToStrings( Collection<? extends OptionSpec<?>> options ) {
+ List<String> strings = new ArrayList<>();
+ for ( OptionSpec<?> each : options )
+ strings.add( specToString( each ) );
+ return strings;
+ }
+
+ private String specToString( OptionSpec<?> option ) {
+ return Strings.join( new ArrayList<>( option.options() ), "/" );
+ }
+
+ /**
+ * Gives the option being considered when the exception was created.
+ *
+ * @return the option being considered when the exception was created
+ */
+ public List<String> options() {
+ return unmodifiableList( options );
+ }
+
+ protected final String singleOptionString() {
+ return singleOptionString( options.get( 0 ) );
+ }
+
+ protected final String singleOptionString( String option ) {
+ return option;
+ }
+
+ protected final String multipleOptionString() {
+ StringBuilder buffer = new StringBuilder( "[" );
+
+ Set<String> asSet = new LinkedHashSet<String>( options );
+ for ( Iterator<String> iter = asSet.iterator(); iter.hasNext(); ) {
+ buffer.append( singleOptionString(iter.next()) );
+ if ( iter.hasNext() )
+ buffer.append( ", " );
+ }
+
+ buffer.append( ']' );
+
+ return buffer.toString();
+ }
+
+ static OptionException unrecognizedOption( String option ) {
+ return new UnrecognizedOptionException( option );
+ }
+
+ @Override
+ public final String getMessage() {
+ return localizedMessage( Locale.getDefault() );
+ }
+
+ final String localizedMessage( Locale locale ) {
+ return formattedMessage( locale );
+ }
+
+ private String formattedMessage( Locale locale ) {
+ return message( locale, "joptsimple.ExceptionMessages", getClass(), "message", messageArguments() );
+ }
+
+ abstract Object[] messageArguments();
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java
new file mode 100644
index 0000000000..9c69f12369
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java
@@ -0,0 +1,46 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+/**
+ * Thrown when the option parser discovers options that require an argument, but are missing an argument.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionMissingRequiredArgumentException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ OptionMissingRequiredArgumentException( OptionSpec<?> option ) {
+ super( asList( option ) );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { singleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java
new file mode 100644
index 0000000000..d141f623c0
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java
@@ -0,0 +1,647 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.*;
+
+import joptsimple.internal.AbbreviationMap;
+import joptsimple.internal.SimpleOptionNameMap;
+import joptsimple.internal.OptionNameMap;
+import joptsimple.util.KeyValuePair;
+
+import static java.util.Collections.*;
+import static joptsimple.OptionException.*;
+import static joptsimple.OptionParserState.*;
+import static joptsimple.ParserRules.*;
+
+/**
+ * <p>Parses command line arguments, using a syntax that attempts to take from the best of POSIX {@code getopt()}
+ * and GNU {@code getopt_long()}.</p>
+ *
+ * <p>This parser supports short options and long options.</p>
+ *
+ * <ul>
+ * <li><dfn>Short options</dfn> begin with a single hyphen ("{@code -}") followed by a single letter or digit,
+ * or question mark ("{@code ?}"), or dot ("{@code .}"), or underscore ("{@code _}").</li>
+ *
+ * <li>Short options can accept single arguments. The argument can be made required or optional. The option's
+ * argument can occur:
+ * <ul>
+ * <li>in the slot after the option, as in {@code -d /tmp}</li>
+ * <li>right up against the option, as in {@code -d/tmp}</li>
+ * <li>right up against the option separated by an equals sign ({@code "="}), as in {@code -d=/tmp}</li>
+ * </ul>
+ * To specify <em>n</em> arguments for an option, specify the option <em>n</em> times, once for each argument,
+ * as in {@code -d /tmp -d /var -d /opt}; or, when using the
+ * {@linkplain ArgumentAcceptingOptionSpec#withValuesSeparatedBy(char) "separated values"} clause of the "fluent
+ * interface" (see below), give multiple values separated by a given character as a single argument to the
+ * option.</li>
+ *
+ * <li>Short options can be clustered, so that {@code -abc} is treated as {@code -a -b -c}. If a short option
+ * in the cluster can accept an argument, the remaining characters are interpreted as the argument for that
+ * option.</li>
+ *
+ * <li>An argument consisting only of two hyphens ({@code "--"}) signals that the remaining arguments are to be
+ * treated as non-options.</li>
+ *
+ * <li>An argument consisting only of a single hyphen is considered a non-option argument (though it can be an
+ * argument of an option). Many Unix programs treat single hyphens as stand-ins for the standard input or standard
+ * output streams.</li>
+ *
+ * <li><dfn>Long options</dfn> begin with two hyphens ({@code "--"}), followed by multiple letters, digits,
+ * hyphens, question marks, or dots. A hyphen cannot be the first character of a long option specification when
+ * configuring the parser.</li>
+ *
+ * <li>You can abbreviate long options, so long as the abbreviation is unique. Suppress this behavior if
+ * you wish using {@linkplain OptionParser#OptionParser(boolean) this constructor}.</li>
+ *
+ * <li>Long options can accept single arguments. The argument can be made required or optional. The option's
+ * argument can occur:
+ * <ul>
+ * <li>in the slot after the option, as in {@code --directory /tmp}</li>
+ * <li>right up against the option separated by an equals sign ({@code "="}), as in
+ * {@code --directory=/tmp}
+ * </ul>
+ * Specify multiple arguments for a long option in the same manner as for short options (see above).</li>
+ *
+ * <li>You can use a single hyphen ({@code "-"}) instead of a double hyphen ({@code "--"}) for a long
+ * option.</li>
+ *
+ * <li>The option {@code -W} is reserved. If you tell the parser to {@linkplain
+ * #recognizeAlternativeLongOptions(boolean) recognize alternative long options}, then it will treat, for example,
+ * {@code -W foo=bar} as the long option {@code foo} with argument {@code bar}, as though you had written
+ * {@code --foo=bar}.</li>
+ *
+ * <li>You can specify {@code -W} as a valid short option, or use it as an abbreviation for a long option, but
+ * {@linkplain #recognizeAlternativeLongOptions(boolean) recognizing alternative long options} will always supersede
+ * this behavior.</li>
+ *
+ * <li>You can specify a given short or long option multiple times on a single command line. The parser collects
+ * any arguments specified for those options as a list.</li>
+ *
+ * <li>If the parser detects an option whose argument is optional, and the next argument "looks like" an option,
+ * that argument is not treated as the argument to the option, but as a potentially valid option. If, on the other
+ * hand, the optional argument is typed as a derivative of {@link Number}, then that argument is treated as the
+ * negative number argument of the option, even if the parser recognizes the corresponding numeric option.
+ * For example:
+ * <pre><code>
+ * OptionParser parser = new OptionParser();
+ * parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
+ * parser.accepts( "2" );
+ * OptionSet options = parser.parse( "-a", "-2" );
+ * </code></pre>
+ * In this case, the option set contains {@code "a"} with argument {@code -2}, not both {@code "a"} and
+ * {@code "2"}. Swapping the elements in the <em>args</em> array gives the latter.</li>
+ * </ul>
+ *
+ * <p>There are two ways to tell the parser what options to recognize:</p>
+ *
+ * <ol>
+ * <li>A "fluent interface"-style API for specifying options, available since version 2. Sentences in this fluent
+ * interface language begin with a call to {@link #accepts(String) accepts} or {@link #acceptsAll(List)
+ * acceptsAll} methods; calls on the ensuing chain of objects describe whether the options can take an argument,
+ * whether the argument is required or optional, to what type arguments of the options should be converted if any,
+ * etc. Since version 3, these calls return an instance of {@link OptionSpec}, which can subsequently be used to
+ * retrieve the arguments of the associated option in a type-safe manner.</li>
+ *
+ * <li>Since version 1, a more concise way of specifying short options has been to use the special {@linkplain
+ * #OptionParser(String) constructor}. Arguments of options specified in this manner will be of type {@link String}.
+ * Here are the rules for the format of the specification strings this constructor accepts:
+ *
+ * <ul>
+ * <li>Any letter or digit is treated as an option character.</li>
+ *
+ * <li>An option character can be immediately followed by an asterisk ({@code *)} to indicate that
+ * the option is a "help" option.</li>
+ *
+ * <li>If an option character (with possible trailing asterisk) is followed by a single colon ({@code ":"}),
+ * then the option requires an argument.</li>
+ *
+ * <li>If an option character (with possible trailing asterisk) is followed by two colons ({@code "::"}),
+ * then the option accepts an optional argument.</li>
+ *
+ * <li>Otherwise, the option character accepts no argument.</li>
+ *
+ * <li>If the option specification string begins with a plus sign ({@code "+" }), the parser will behave
+ * "POSIX-ly correct".</li>
+ *
+ * <li>If the option specification string contains the sequence {@code "W;"} (capital W followed by a
+ * semicolon), the parser will recognize the alternative form of long options.</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * <p>Each of the options in a list of options given to {@link #acceptsAll(List) acceptsAll} is treated as a
+ * synonym of the others. For example:</p>
+ * <pre>
+ * <code>
+ * OptionParser parser = new OptionParser();
+ * parser.acceptsAll( asList( "w", "interactive", "confirmation" ) );
+ * OptionSet options = parser.parse( "-w" );
+ * </code>
+ * </pre>
+ * <p>In this case, <code>options.{@link OptionSet#has(String) has}</code> would answer {@code true} when given arguments
+ * {@code "w"}, {@code "interactive"}, and {@code "confirmation"}. The {@link OptionSet} would give the same
+ * responses to these arguments for its other methods as well.</p>
+ *
+ * <p>By default, as with GNU {@code getopt()}, the parser allows intermixing of options and non-options. If, however,
+ * the parser has been created to be "POSIX-ly correct", then the first argument that does not look lexically like an
+ * option, and is not a required argument of a preceding option, signals the end of options. You can still bind
+ * optional arguments to their options using the abutting (for short options) or {@code =} syntax.</p>
+ *
+ * <p>Unlike GNU {@code getopt()}, this parser does not honor the environment variable {@code POSIXLY_CORRECT}.
+ * "POSIX-ly correct" parsers are configured by either:</p>
+ *
+ * <ol>
+ * <li>using the method {@link #posixlyCorrect(boolean)}, or</li>
+ *
+ * <li>using the {@linkplain #OptionParser(String) constructor} with an argument whose first character is a plus sign
+ * ({@code "+"})</li>
+ * </ol>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ * @see <a href="http://www.gnu.org/software/libc/manual">The GNU C Library</a>
+ */
+public class OptionParser implements OptionDeclarer {
+ private final OptionNameMap<AbstractOptionSpec<?>> recognizedOptions;
+ private final ArrayList<AbstractOptionSpec<?>> trainingOrder;
+ private final Map<List<String>, Set<OptionSpec<?>>> requiredIf;
+ private final Map<List<String>, Set<OptionSpec<?>>> requiredUnless;
+ private final Map<List<String>, Set<OptionSpec<?>>> availableIf;
+ private final Map<List<String>, Set<OptionSpec<?>>> availableUnless;
+
+ private OptionParserState state;
+ private boolean posixlyCorrect;
+ private boolean allowsUnrecognizedOptions;
+ private HelpFormatter helpFormatter = new BuiltinHelpFormatter();
+
+ /**
+ * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct"
+ * behavior.
+ */
+ public OptionParser() {
+ this(true);
+ }
+
+ /**
+ * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct"
+ * behavior.
+ *
+ * @param allowAbbreviations whether unambiguous abbreviations of long options should be recognized
+ * by the parser
+ */
+ public OptionParser( boolean allowAbbreviations ) {
+ trainingOrder = new ArrayList<>();
+ requiredIf = new HashMap<>();
+ requiredUnless = new HashMap<>();
+ availableIf = new HashMap<>();
+ availableUnless = new HashMap<>();
+ state = moreOptions( false );
+
+ recognizedOptions = allowAbbreviations
+ ? new AbbreviationMap<AbstractOptionSpec<?>>()
+ : new SimpleOptionNameMap<AbstractOptionSpec<?>>();
+
+ recognize( new NonOptionArgumentSpec<String>() );
+ }
+
+ /**
+ * Creates an option parser and configures it to recognize the short options specified in the given string.
+ *
+ * Arguments of options specified this way will be of type {@link String}.
+ *
+ * @param optionSpecification an option specification
+ * @throws NullPointerException if {@code optionSpecification} is {@code null}
+ * @throws OptionException if the option specification contains illegal characters or otherwise cannot be
+ * recognized
+ */
+ public OptionParser( String optionSpecification ) {
+ this();
+
+ new OptionSpecTokenizer( optionSpecification ).configure( this );
+ }
+
+ public OptionSpecBuilder accepts( String option ) {
+ return acceptsAll( singletonList( option ) );
+ }
+
+ public OptionSpecBuilder accepts( String option, String description ) {
+ return acceptsAll( singletonList( option ), description );
+ }
+
+ public OptionSpecBuilder acceptsAll( List<String> options ) {
+ return acceptsAll( options, "" );
+ }
+
+ public OptionSpecBuilder acceptsAll( List<String> options, String description ) {
+ if ( options.isEmpty() )
+ throw new IllegalArgumentException( "need at least one option" );
+
+ ensureLegalOptions( options );
+
+ return new OptionSpecBuilder( this, options, description );
+ }
+
+ public NonOptionArgumentSpec<String> nonOptions() {
+ NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<>();
+
+ recognize( spec );
+
+ return spec;
+ }
+
+ public NonOptionArgumentSpec<String> nonOptions( String description ) {
+ NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<>( description );
+
+ recognize( spec );
+
+ return spec;
+ }
+
+ public void posixlyCorrect( boolean setting ) {
+ posixlyCorrect = setting;
+ state = moreOptions( setting );
+ }
+
+ boolean posixlyCorrect() {
+ return posixlyCorrect;
+ }
+
+ public void allowsUnrecognizedOptions() {
+ allowsUnrecognizedOptions = true;
+ }
+
+ boolean doesAllowsUnrecognizedOptions() {
+ return allowsUnrecognizedOptions;
+ }
+
+ public void recognizeAlternativeLongOptions( boolean recognize ) {
+ if ( recognize )
+ recognize( new AlternativeLongOptionSpec() );
+ else
+ recognizedOptions.remove( String.valueOf( RESERVED_FOR_EXTENSIONS ) );
+ }
+
+ void recognize( AbstractOptionSpec<?> spec ) {
+ recognizedOptions.putAll( spec.options(), spec );
+ trainingOrder.add( spec );
+ }
+
+ /**
+ * Writes information about the options this parser recognizes to the given output sink.
+ *
+ * The output sink is flushed, but not closed.
+ *
+ * @param sink the sink to write information to
+ * @throws IOException if there is a problem writing to the sink
+ * @throws NullPointerException if {@code sink} is {@code null}
+ * @see #printHelpOn(Writer)
+ */
+ public void printHelpOn( OutputStream sink ) throws IOException {
+ printHelpOn( new OutputStreamWriter( sink ) );
+ }
+
+ /**
+ * Writes information about the options this parser recognizes to the given output sink.
+ *
+ * The output sink is flushed, but not closed.
+ *
+ * @param sink the sink to write information to
+ * @throws IOException if there is a problem writing to the sink
+ * @throws NullPointerException if {@code sink} is {@code null}
+ * @see #printHelpOn(OutputStream)
+ */
+ public void printHelpOn( Writer sink ) throws IOException {
+ sink.write( helpFormatter.format( _recognizedOptions() ) );
+ sink.flush();
+ }
+
+ /**
+ * Tells the parser to use the given formatter when asked to {@linkplain #printHelpOn(java.io.Writer) print help}.
+ *
+ * @param formatter the formatter to use for printing help
+ * @throws NullPointerException if the formatter is {@code null}
+ */
+ public void formatHelpWith( HelpFormatter formatter ) {
+ if ( formatter == null )
+ throw new NullPointerException();
+
+ helpFormatter = formatter;
+ }
+
+ /**
+ * Retrieves all options-spec pairings which have been configured for the parser in the same order as declared
+ * during training. Option flags for specs are alphabetized by {@link OptionSpec#options()}; only the order of the
+ * specs is preserved.
+ *
+ * (Note: prior to 4.7 the order was alphabetical across all options regardless of spec.)
+ *
+ * @return a map containing all the configured options and their corresponding {@link OptionSpec}
+ * @since 4.6
+ */
+ public Map<String, OptionSpec<?>> recognizedOptions() {
+ return new LinkedHashMap<String, OptionSpec<?>>( _recognizedOptions() );
+ }
+
+ private Map<String, AbstractOptionSpec<?>> _recognizedOptions() {
+ Map<String, AbstractOptionSpec<?>> options = new LinkedHashMap<>();
+ for ( AbstractOptionSpec<?> spec : trainingOrder ) {
+ for ( String option : spec.options() )
+ options.put( option, spec );
+ }
+ return options;
+ }
+
+ /**
+ * Parses the given command line arguments according to the option specifications given to the parser.
+ *
+ * @param arguments arguments to parse
+ * @return an {@link OptionSet} describing the parsed options, their arguments, and any non-option arguments found
+ * @throws OptionException if problems are detected while parsing
+ * @throws NullPointerException if the argument list is {@code null}
+ */
+ public OptionSet parse( String... arguments ) {
+ ArgumentList argumentList = new ArgumentList( arguments );
+ OptionSet detected = new OptionSet( recognizedOptions.toJavaUtilMap() );
+ detected.add( recognizedOptions.get( NonOptionArgumentSpec.NAME ) );
+
+ while ( argumentList.hasMore() )
+ state.handleArgument( this, argumentList, detected );
+
+ reset();
+
+ ensureRequiredOptions( detected );
+ ensureAllowedOptions( detected );
+
+ return detected;
+ }
+
+ /**
+ * Mandates mutual exclusiveness for the options built by the specified builders.
+ *
+ * @param specs descriptors for options that should be mutually exclusive on a command line.
+ * @throws NullPointerException if {@code specs} is {@code null}
+ */
+ public void mutuallyExclusive( OptionSpecBuilder... specs ) {
+ for ( int i = 0; i < specs.length; i++ ) {
+ for ( int j = 0; j < specs.length; j++ ) {
+ if ( i != j )
+ specs[i].availableUnless( specs[j] );
+ }
+ }
+ }
+
+ private void ensureRequiredOptions( OptionSet options ) {
+ List<AbstractOptionSpec<?>> missingRequiredOptions = missingRequiredOptions(options);
+ boolean helpOptionPresent = isHelpOptionPresent( options );
+
+ if ( !missingRequiredOptions.isEmpty() && !helpOptionPresent )
+ throw new MissingRequiredOptionsException( missingRequiredOptions );
+ }
+
+ private void ensureAllowedOptions( OptionSet options ) {
+ List<AbstractOptionSpec<?>> forbiddenOptions = unavailableOptions( options );
+ boolean helpOptionPresent = isHelpOptionPresent( options );
+
+ if ( !forbiddenOptions.isEmpty() && !helpOptionPresent )
+ throw new UnavailableOptionException( forbiddenOptions );
+ }
+
+ private List<AbstractOptionSpec<?>> missingRequiredOptions( OptionSet options ) {
+ List<AbstractOptionSpec<?>> missingRequiredOptions = new ArrayList<>();
+
+ for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) {
+ if ( each.isRequired() && !options.has( each ) )
+ missingRequiredOptions.add(each);
+ }
+
+ for ( Map.Entry<List<String>, Set<OptionSpec<?>>> each : requiredIf.entrySet() ) {
+ AbstractOptionSpec<?> required = specFor( each.getKey().iterator().next() );
+
+ if ( optionsHasAnyOf( options, each.getValue() ) && !options.has( required ) )
+ missingRequiredOptions.add( required );
+ }
+
+ for ( Map.Entry<List<String>, Set<OptionSpec<?>>> each : requiredUnless.entrySet() ) {
+ AbstractOptionSpec<?> required = specFor(each.getKey().iterator().next());
+
+ if ( !optionsHasAnyOf( options, each.getValue() ) && !options.has( required ) )
+ missingRequiredOptions.add( required );
+ }
+
+ return missingRequiredOptions;
+ }
+
+ private List<AbstractOptionSpec<?>> unavailableOptions(OptionSet options) {
+ List<AbstractOptionSpec<?>> unavailableOptions = new ArrayList<>();
+
+ for ( Map.Entry<List<String>, Set<OptionSpec<?>>> eachEntry : availableIf.entrySet() ) {
+ AbstractOptionSpec<?> forbidden = specFor( eachEntry.getKey().iterator().next() );
+
+ if ( !optionsHasAnyOf( options, eachEntry.getValue() ) && options.has( forbidden ) ) {
+ unavailableOptions.add(forbidden);
+ }
+ }
+
+ for ( Map.Entry<List<String>, Set<OptionSpec<?>>> eachEntry : availableUnless.entrySet() ) {
+ AbstractOptionSpec<?> forbidden = specFor( eachEntry.getKey().iterator().next() );
+
+ if ( optionsHasAnyOf( options, eachEntry.getValue() ) && options.has( forbidden ) ) {
+ unavailableOptions.add(forbidden);
+ }
+ }
+
+ return unavailableOptions;
+ }
+
+ private boolean optionsHasAnyOf( OptionSet options, Collection<OptionSpec<?>> specs ) {
+ for ( OptionSpec<?> each : specs ) {
+ if ( options.has( each ) )
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isHelpOptionPresent( OptionSet options ) {
+ boolean helpOptionPresent = false;
+
+ for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) {
+ if ( each.isForHelp() && options.has( each ) ) {
+ helpOptionPresent = true;
+ break;
+ }
+ }
+
+ return helpOptionPresent;
+ }
+
+ void handleLongOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
+ KeyValuePair optionAndArgument = parseLongOptionWithArgument( candidate );
+
+ if ( !isRecognized( optionAndArgument.key ) )
+ throw unrecognizedOption( optionAndArgument.key );
+
+ AbstractOptionSpec<?> optionSpec = specFor( optionAndArgument.key );
+ optionSpec.handleOption( this, arguments, detected, optionAndArgument.value );
+ }
+
+ void handleShortOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
+ KeyValuePair optionAndArgument = parseShortOptionWithArgument( candidate );
+
+ if ( isRecognized( optionAndArgument.key ) ) {
+ specFor( optionAndArgument.key ).handleOption( this, arguments, detected, optionAndArgument.value );
+ }
+ else
+ handleShortOptionCluster( candidate, arguments, detected );
+ }
+
+ private void handleShortOptionCluster( String candidate, ArgumentList arguments, OptionSet detected ) {
+ char[] options = extractShortOptionsFrom( candidate );
+ validateOptionCharacters( options );
+
+ for ( int i = 0; i < options.length; i++ ) {
+ AbstractOptionSpec<?> optionSpec = specFor( options[ i ] );
+
+ if ( optionSpec.acceptsArguments() && options.length > i + 1 ) {
+ String detectedArgument = String.valueOf( options, i + 1, options.length - 1 - i );
+ optionSpec.handleOption( this, arguments, detected, detectedArgument );
+ break;
+ }
+
+ optionSpec.handleOption( this, arguments, detected, null );
+ }
+ }
+
+ void handleNonOptionArgument( String candidate, ArgumentList arguments, OptionSet detectedOptions ) {
+ specFor( NonOptionArgumentSpec.NAME ).handleOption( this, arguments, detectedOptions, candidate );
+ }
+
+ void noMoreOptions() {
+ state = OptionParserState.noMoreOptions();
+ }
+
+ boolean looksLikeAnOption( String argument ) {
+ return isShortOptionToken( argument ) || isLongOptionToken( argument );
+ }
+
+ boolean isRecognized( String option ) {
+ return recognizedOptions.contains( option );
+ }
+
+ void requiredIf( List<String> precedentSynonyms, String required ) {
+ requiredIf( precedentSynonyms, specFor( required ) );
+ }
+
+ void requiredIf( List<String> precedentSynonyms, OptionSpec<?> required ) {
+ putDependentOption( precedentSynonyms, required, requiredIf );
+ }
+
+ void requiredUnless( List<String> precedentSynonyms, String required ) {
+ requiredUnless( precedentSynonyms, specFor( required ) );
+ }
+
+ void requiredUnless( List<String> precedentSynonyms, OptionSpec<?> required ) {
+ putDependentOption( precedentSynonyms, required, requiredUnless );
+ }
+
+ void availableIf( List<String> precedentSynonyms, String available ) {
+ availableIf( precedentSynonyms, specFor( available ) );
+ }
+
+ void availableIf( List<String> precedentSynonyms, OptionSpec<?> available) {
+ putDependentOption( precedentSynonyms, available, availableIf );
+ }
+
+ void availableUnless( List<String> precedentSynonyms, String available ) {
+ availableUnless( precedentSynonyms, specFor( available ) );
+ }
+
+ void availableUnless( List<String> precedentSynonyms, OptionSpec<?> available ) {
+ putDependentOption( precedentSynonyms, available, availableUnless );
+ }
+
+ private void putDependentOption( List<String> precedentSynonyms, OptionSpec<?> required,
+ Map<List<String>, Set<OptionSpec<?>>> target ) {
+
+ for ( String each : precedentSynonyms ) {
+ AbstractOptionSpec<?> spec = specFor( each );
+ if ( spec == null )
+ throw new UnconfiguredOptionException( precedentSynonyms );
+ }
+
+ Set<OptionSpec<?>> associated = target.get( precedentSynonyms );
+ if ( associated == null ) {
+ associated = new HashSet<>();
+ target.put( precedentSynonyms, associated );
+ }
+
+ associated.add( required );
+ }
+
+ private AbstractOptionSpec<?> specFor( char option ) {
+ return specFor( String.valueOf( option ) );
+ }
+
+ private AbstractOptionSpec<?> specFor( String option ) {
+ return recognizedOptions.get( option );
+ }
+
+ private void reset() {
+ state = moreOptions( posixlyCorrect );
+ }
+
+ private static char[] extractShortOptionsFrom( String argument ) {
+ char[] options = new char[ argument.length() - 1 ];
+ argument.getChars( 1, argument.length(), options, 0 );
+
+ return options;
+ }
+
+ private void validateOptionCharacters( char[] options ) {
+ for ( char each : options ) {
+ String option = String.valueOf( each );
+
+ if ( !isRecognized( option ) )
+ throw unrecognizedOption( option );
+
+ if ( specFor( option ).acceptsArguments() )
+ return;
+ }
+ }
+
+ private static KeyValuePair parseLongOptionWithArgument( String argument ) {
+ return KeyValuePair.valueOf( argument.substring( 2 ) );
+ }
+
+ private static KeyValuePair parseShortOptionWithArgument( String argument ) {
+ return KeyValuePair.valueOf( argument.substring( 1 ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java
new file mode 100644
index 0000000000..fe1000c263
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java
@@ -0,0 +1,76 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static joptsimple.ParserRules.*;
+
+/**
+ * Abstraction of parser state; mostly serves to model how a parser behaves depending on whether end-of-options
+ * has been detected.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+abstract class OptionParserState {
+ static OptionParserState noMoreOptions() {
+ return new OptionParserState() {
+ @Override
+ protected void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+ parser.handleNonOptionArgument( arguments.next(), arguments, detectedOptions );
+ }
+ };
+ }
+
+ static OptionParserState moreOptions( final boolean posixlyCorrect ) {
+ return new OptionParserState() {
+ @Override
+ protected void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+ String candidate = arguments.next();
+ try {
+ if ( isOptionTerminator( candidate ) ) {
+ parser.noMoreOptions();
+ return;
+ } else if ( isLongOptionToken( candidate ) ) {
+ parser.handleLongOptionToken( candidate, arguments, detectedOptions );
+ return;
+ } else if ( isShortOptionToken( candidate ) ) {
+ parser.handleShortOptionToken( candidate, arguments, detectedOptions );
+ return;
+ }
+ } catch ( UnrecognizedOptionException e ) {
+ if ( !parser.doesAllowsUnrecognizedOptions() )
+ throw e;
+ }
+
+ if ( posixlyCorrect )
+ parser.noMoreOptions();
+
+ parser.handleNonOptionArgument( candidate, arguments, detectedOptions );
+ }
+ };
+ }
+
+ protected abstract void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions );
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java
new file mode 100644
index 0000000000..e67363fd2e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java
@@ -0,0 +1,325 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.Collections.*;
+import static java.util.Objects.*;
+
+/**
+ * Representation of a group of detected command line options, their arguments, and non-option arguments.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSet {
+ private final List<OptionSpec<?>> detectedSpecs;
+ private final Map<String, AbstractOptionSpec<?>> detectedOptions;
+ private final Map<AbstractOptionSpec<?>, List<String>> optionsToArguments;
+ private final Map<String, AbstractOptionSpec<?>> recognizedSpecs;
+ private final Map<String, List<?>> defaultValues;
+
+ /*
+ * Package-private because clients don't create these.
+ */
+ OptionSet( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) {
+ detectedSpecs = new ArrayList<>();
+ detectedOptions = new HashMap<>();
+ optionsToArguments = new IdentityHashMap<>();
+ defaultValues = defaultValues( recognizedSpecs );
+ this.recognizedSpecs = recognizedSpecs;
+ }
+
+ /**
+ * Tells whether any options were detected.
+ *
+ * @return {@code true} if any options were detected
+ */
+ public boolean hasOptions() {
+ return !( detectedOptions.size() == 1 && detectedOptions.values().iterator().next().representsNonOptions() );
+ }
+
+ /**
+ * Tells whether the given option was detected.
+ *
+ * @param option the option to search for
+ * @return {@code true} if the option was detected
+ * @see #has(OptionSpec)
+ */
+ public boolean has( String option ) {
+ return detectedOptions.containsKey( option );
+ }
+
+ /**
+ * Tells whether the given option was detected.
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[])} default argument value}
+ * for an option does not cause this method to return {@code true} if the option was not detected on the command
+ * line.</p>
+ *
+ * @param option the option to search for
+ * @return {@code true} if the option was detected
+ * @see #has(String)
+ */
+ public boolean has( OptionSpec<?> option ) {
+ return optionsToArguments.containsKey( option );
+ }
+
+ /**
+ * Tells whether there are any arguments associated with the given option.
+ *
+ * @param option the option to search for
+ * @return {@code true} if the option was detected and at least one argument was detected for the option
+ * @see #hasArgument(OptionSpec)
+ */
+ public boolean hasArgument( String option ) {
+ AbstractOptionSpec<?> spec = detectedOptions.get( option );
+ return spec != null && hasArgument( spec );
+ }
+
+ /**
+ * Tells whether there are any arguments associated with the given option.
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+ * for an option does not cause this method to return {@code true} if the option was not detected on the command
+ * line, or if the option can take an optional argument but did not have one on the command line.</p>
+ *
+ * @param option the option to search for
+ * @return {@code true} if the option was detected and at least one argument was detected for the option
+ * @throws NullPointerException if {@code option} is {@code null}
+ * @see #hasArgument(String)
+ */
+ public boolean hasArgument( OptionSpec<?> option ) {
+ requireNonNull( option );
+
+ List<String> values = optionsToArguments.get( option );
+ return values != null && !values.isEmpty();
+ }
+
+ /**
+ * Gives the argument associated with the given option. If the option was given an argument type, the argument
+ * will take on that type; otherwise, it will be a {@link String}.
+ *
+ * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+ * for an option will cause this method to return that default value even if the option was not detected on the
+ * command line, or if the option can take an optional argument but did not have one on the command line.</p>
+ *
+ * @param option the option to search for
+ * @return the argument of the given option; {@code null} if no argument is present, or that option was not
+ * detected
+ * @throws NullPointerException if {@code option} is {@code null}
+ * @throws OptionException if more than one argument was detected for the option
+ */
+ public Object valueOf( String option ) {
+ requireNonNull( option );
+
+ AbstractOptionSpec<?> spec = detectedOptions.get( option );
+ if ( spec == null ) {
+ List<?> defaults = defaultValuesFor( option );
+ return defaults.isEmpty() ? null : defaults.get( 0 );
+ }
+
+ return valueOf( spec );
+ }
+
+ /**
+ * Gives the argument associated with the given option.
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * @param <V> represents the type of the arguments the given option accepts
+ * @param option the option to search for
+ * @return the argument of the given option; {@code null} if no argument is present, or that option was not
+ * detected
+ * @throws OptionException if more than one argument was detected for the option
+ * @throws NullPointerException if {@code option} is {@code null}
+ * @throws ClassCastException if the arguments of this option are not of the expected type
+ */
+ public <V> V valueOf( OptionSpec<V> option ) {
+ requireNonNull( option );
+
+ List<V> values = valuesOf( option );
+ switch ( values.size() ) {
+ case 0:
+ return null;
+ case 1:
+ return values.get( 0 );
+ default:
+ throw new MultipleArgumentsForOptionException( option );
+ }
+ }
+
+ /**
+ * <p>Gives any arguments associated with the given option. If the option was given an argument type, the
+ * arguments will take on that type; otherwise, they will be {@link String}s.</p>
+ *
+ * @param option the option to search for
+ * @return the arguments associated with the option, as a list of objects of the type given to the arguments; an
+ * empty list if no such arguments are present, or if the option was not detected
+ * @throws NullPointerException if {@code option} is {@code null}
+ */
+ public List<?> valuesOf( String option ) {
+ requireNonNull( option );
+
+ AbstractOptionSpec<?> spec = detectedOptions.get( option );
+ return spec == null ? defaultValuesFor( option ) : valuesOf( spec );
+ }
+
+ /**
+ * <p>Gives any arguments associated with the given option. If the option was given an argument type, the
+ * arguments will take on that type; otherwise, they will be {@link String}s.</p>
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * @param <V> represents the type of the arguments the given option accepts
+ * @param option the option to search for
+ * @return the arguments associated with the option; an empty list if no such arguments are present, or if the
+ * option was not detected
+ * @throws NullPointerException if {@code option} is {@code null}
+ * @throws OptionException if there is a problem converting the option's arguments to the desired type; for
+ * example, if the type does not implement a correct conversion constructor or method
+ */
+ public <V> List<V> valuesOf( OptionSpec<V> option ) {
+ requireNonNull( option );
+
+ List<String> values = optionsToArguments.get( option );
+ if ( values == null || values.isEmpty() )
+ return defaultValueFor( option );
+
+ AbstractOptionSpec<V> spec = (AbstractOptionSpec<V>) option;
+ List<V> convertedValues = new ArrayList<>();
+ for ( String each : values )
+ convertedValues.add( spec.convert( each ) );
+
+ return unmodifiableList( convertedValues );
+ }
+
+ /**
+ * Gives the set of options that were detected, in the form of {@linkplain OptionSpec}s, in the order in which the
+ * options were found on the command line.
+ *
+ * @return the set of detected command line options
+ */
+ public List<OptionSpec<?>> specs() {
+ List<OptionSpec<?>> specs = detectedSpecs;
+ specs.removeAll( singletonList( detectedOptions.get( NonOptionArgumentSpec.NAME ) ) );
+
+ return unmodifiableList( specs );
+ }
+
+ /**
+ * Gives all declared options as a map of string to {@linkplain OptionSpec}.
+ *
+ * @return the declared options as a map
+ */
+ public Map<OptionSpec<?>, List<?>> asMap() {
+ Map<OptionSpec<?>, List<?>> map = new HashMap<>();
+
+ for ( AbstractOptionSpec<?> spec : recognizedSpecs.values() ) {
+ if ( !spec.representsNonOptions() )
+ map.put( spec, valuesOf( spec ) );
+ }
+
+ return unmodifiableMap( map );
+ }
+
+ /**
+ * @return the detected non-option arguments
+ */
+ public List<?> nonOptionArguments() {
+ AbstractOptionSpec<?> spec = detectedOptions.get( NonOptionArgumentSpec.NAME );
+ return valuesOf( spec );
+ }
+
+ void add( AbstractOptionSpec<?> spec ) {
+ addWithArgument( spec, null );
+ }
+
+ void addWithArgument( AbstractOptionSpec<?> spec, String argument ) {
+ detectedSpecs.add( spec );
+
+ for ( String each : spec.options() )
+ detectedOptions.put( each, spec );
+
+ List<String> optionArguments = optionsToArguments.get( spec );
+
+ if ( optionArguments == null ) {
+ optionArguments = new ArrayList<>();
+ optionsToArguments.put( spec, optionArguments );
+ }
+
+ if ( argument != null )
+ optionArguments.add( argument );
+ }
+
+ @Override
+ public boolean equals( Object that ) {
+ if ( this == that )
+ return true;
+
+ if ( that == null || !getClass().equals( that.getClass() ) )
+ return false;
+
+ OptionSet other = (OptionSet) that;
+ Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments = new HashMap<>( optionsToArguments );
+ Map<AbstractOptionSpec<?>, List<String>> otherOptionsToArguments = new HashMap<>( other.optionsToArguments );
+ return detectedOptions.equals( other.detectedOptions )
+ && thisOptionsToArguments.equals( otherOptionsToArguments );
+ }
+
+ @Override
+ public int hashCode() {
+ Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments = new HashMap<>( optionsToArguments );
+ return detectedOptions.hashCode() ^ thisOptionsToArguments.hashCode();
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <V> List<V> defaultValuesFor( String option ) {
+ if ( defaultValues.containsKey( option ) )
+ return unmodifiableList( (List<V>) defaultValues.get( option ) );
+
+ return emptyList();
+ }
+
+ private <V> List<V> defaultValueFor( OptionSpec<V> option ) {
+ return defaultValuesFor( option.options().iterator().next() );
+ }
+
+ private static Map<String, List<?>> defaultValues( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) {
+ Map<String, List<?>> defaults = new HashMap<>();
+ for ( Map.Entry<String, AbstractOptionSpec<?>> each : recognizedSpecs.entrySet() )
+ defaults.put( each.getKey(), each.getValue().defaultValues() );
+ return defaults;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java
new file mode 100644
index 0000000000..70d2d43072
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java
@@ -0,0 +1,97 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Describes options that an option parser recognizes.
+ *
+ * <p>Instances of this interface are returned by the "fluent interface" methods to allow retrieval of option arguments
+ * in a type-safe manner. Here's an example:</p>
+ *
+ * <pre><code>
+ * OptionParser parser = new OptionParser();
+ * <strong>OptionSpec&lt;Integer&gt;</strong> count =
+ * parser.accepts( "count" ).withRequiredArg().ofType( Integer.class );
+ * OptionSet options = parser.parse( "--count", "2" );
+ * assert options.has( count );
+ * int countValue = options.valueOf( count );
+ * assert countValue == count.value( options );
+ * List&lt;Integer&gt; countValues = options.valuesOf( count );
+ * assert countValues.equals( count.values( options ) );
+ * </code></pre>
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface OptionSpec<V> {
+ /**
+ * Gives any arguments associated with the given option in the given set of detected options.
+ *
+ * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+ * for this option will cause this method to return that default value even if this option was not detected on the
+ * command line, or if this option can take an optional argument but did not have one on the command line.</p>
+ *
+ * @param detectedOptions the detected options to search in
+ * @return the arguments associated with this option; an empty list if no such arguments are present, or if this
+ * option was not detected
+ * @throws OptionException if there is a problem converting this option's arguments to the desired type; for
+ * example, if the type does not implement a correct conversion constructor or method
+ * @throws NullPointerException if {@code detectedOptions} is {@code null}
+ * @see OptionSet#valuesOf(OptionSpec)
+ */
+ List<V> values( OptionSet detectedOptions );
+
+ /**
+ * Gives the argument associated with the given option in the given set of detected options.
+ *
+ * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+ * for this option will cause this method to return that default value even if this option was not detected on the
+ * command line, or if this option can take an optional argument but did not have one on the command line.</p>
+ *
+ * @param detectedOptions the detected options to search in
+ * @return the argument of the this option; {@code null} if no argument is present, or that option was not detected
+ * @throws OptionException if more than one argument was detected for the option
+ * @throws NullPointerException if {@code detectedOptions} is {@code null}
+ * @throws ClassCastException if the arguments of this option are not of the expected type
+ * @see OptionSet#valueOf(OptionSpec)
+ */
+ V value( OptionSet detectedOptions );
+
+ /**
+ * @return the string representations of this option
+ */
+ List<String> options();
+
+ /**
+ * Tells whether this option is designated as a "help" option. The presence of a "help" option on a command line
+ * means that missing "required" options will not cause parsing to fail.
+ *
+ * @return whether this option is designated as a "help" option
+ */
+ boolean isForHelp();
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java
new file mode 100644
index 0000000000..fd5a15a1d6
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java
@@ -0,0 +1,275 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Allows callers to specify whether a given option accepts arguments (required or optional).
+ *
+ * <p>Instances are returned from {@link OptionParser#accepts(String)} to allow the formation of parser directives as
+ * sentences in a "fluent interface" language. For example:</p>
+ *
+ * <pre><code>
+ * OptionParser parser = new OptionParser();
+ * parser.accepts( "c" ).<strong>withRequiredArg()</strong>.ofType( Integer.class );
+ * </code></pre>
+ *
+ * <p>If no methods are invoked on an instance of this class, then that instance's option will accept no argument.</p>
+ *
+ * <p>Note that you should not use the fluent interface clauses in a way that would defeat the typing of option
+ * arguments:</p>
+ *
+ * <pre><code>
+ * OptionParser parser = new OptionParser();
+ * ArgumentAcceptingOptionSpec&lt;String&gt; optionC =
+ * parser.accepts( "c" ).withRequiredArg();
+ * <strong>optionC.ofType( Integer.class ); // DON'T THROW AWAY THE TYPE!</strong>
+ *
+ * String value = parser.parse( "-c", "2" ).valueOf( optionC ); // ClassCastException
+ * </code></pre>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSpecBuilder extends NoArgumentOptionSpec {
+ private final OptionParser parser;
+
+ OptionSpecBuilder( OptionParser parser, List<String> options, String description ) {
+ super( options, description );
+
+ this.parser = parser;
+ attachToParser();
+ }
+
+ private void attachToParser() {
+ parser.recognize( this );
+ }
+
+ /**
+ * Informs an option parser that this builder's option requires an argument.
+ *
+ * @return a specification for the option
+ */
+ public ArgumentAcceptingOptionSpec<String> withRequiredArg() {
+ ArgumentAcceptingOptionSpec<String> newSpec = new RequiredArgumentOptionSpec<>( options(), description() );
+ parser.recognize( newSpec );
+
+ return newSpec;
+ }
+
+ /**
+ * Informs an option parser that this builder's option accepts an optional argument.
+ *
+ * @return a specification for the option
+ */
+ public ArgumentAcceptingOptionSpec<String> withOptionalArg() {
+ ArgumentAcceptingOptionSpec<String> newSpec =
+ new OptionalArgumentOptionSpec<>( options(), description() );
+ parser.recognize( newSpec );
+
+ return newSpec;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is required if the given option is present on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #requiredUnless(String, String...)
+ * requiredUnless} to avoid conflicts.</p>
+ *
+ * @param dependent an option whose presence on a command line makes this builder's option required
+ * @param otherDependents other options whose presence on a command line makes this builder's option required
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws OptionException if any of the dependent options haven't been configured in the parser yet
+ */
+ public OptionSpecBuilder requiredIf( String dependent, String... otherDependents ) {
+ List<String> dependents = validatedDependents( dependent, otherDependents );
+ for ( String each : dependents )
+ parser.requiredIf( options(), each );
+
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is required if the given option is present on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #requiredUnless(OptionSpec, OptionSpec[])
+ * requiredUnless} to avoid conflicts.</p>
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * @param dependent the option whose presence on a command line makes this builder's option required
+ * @param otherDependents other options whose presence on a command line makes this builder's option required
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public OptionSpecBuilder requiredIf( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) {
+ parser.requiredIf( options(), dependent );
+ for ( OptionSpec<?> each : otherDependents )
+ parser.requiredIf( options(), each );
+
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is required if the given option is absent on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #requiredIf(OptionSpec, OptionSpec[])
+ * requiredIf} to avoid conflicts.</p>
+ *
+ * @param dependent an option whose absence on a command line makes this builder's option required
+ * @param otherDependents other options whose absence on a command line makes this builder's option required
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws OptionException if any of the dependent options haven't been configured in the parser yet
+ */
+ public OptionSpecBuilder requiredUnless( String dependent, String... otherDependents ) {
+ List<String> dependents = validatedDependents( dependent, otherDependents );
+ for ( String each : dependents ) {
+ parser.requiredUnless( options(), each );
+ }
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is required if the given option is absent on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #requiredIf(OptionSpec, OptionSpec[])
+ * requiredIf} to avoid conflicts.</p>
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * @param dependent the option whose absence on a command line makes this builder's option required
+ * @param otherDependents other options whose absence on a command line makes this builder's option required
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public OptionSpecBuilder requiredUnless( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) {
+ parser.requiredUnless( options(), dependent );
+ for ( OptionSpec<?> each : otherDependents )
+ parser.requiredUnless( options(), each );
+
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is allowed if the given option is present on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #availableUnless(String, String...)
+ * availableUnless} to avoid conflicts.</p>
+ *
+ * @param dependent an option whose presence on a command line makes this builder's option allowed
+ * @param otherDependents other options whose presence on a command line makes this builder's option allowed
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws OptionException if any of the dependent options haven't been configured in the parser yet
+ */
+ public OptionSpecBuilder availableIf( String dependent, String... otherDependents ) {
+ List<String> dependents = validatedDependents( dependent, otherDependents );
+ for ( String each : dependents )
+ parser.availableIf( options(), each );
+
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is allowed if the given option is present on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #availableUnless(OptionSpec, OptionSpec[])
+ * requiredUnless} to avoid conflicts.</p>
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * @param dependent the option whose presence on a command line makes this builder's option allowed
+ * @param otherDependents other options whose presence on a command line makes this builder's option allowed
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public OptionSpecBuilder availableIf( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) {
+ parser.availableIf( options(), dependent );
+
+ for ( OptionSpec<?> each : otherDependents )
+ parser.availableIf( options(), each );
+
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is allowed if the given option is absent on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #availableIf(OptionSpec, OptionSpec[])
+ * requiredIf} to avoid conflicts.</p>
+ *
+ * @param dependent an option whose absence on a command line makes this builder's option allowed
+ * @param otherDependents other options whose absence on a command line makes this builder's option allowed
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ * @throws OptionException if any of the dependent options haven't been configured in the parser yet
+ */
+ public OptionSpecBuilder availableUnless( String dependent, String... otherDependents ) {
+ List<String> dependents = validatedDependents( dependent, otherDependents );
+ for ( String each : dependents )
+ parser.availableUnless( options(), each );
+
+ return this;
+ }
+
+ /**
+ * <p>Informs an option parser that this builder's option is allowed if the given option is absent on the command
+ * line.</p>
+ *
+ * <p>For a given option, you <em>should not</em> mix this with {@link #availableIf(OptionSpec, OptionSpec[])
+ * requiredIf} to avoid conflicts.</p>
+ *
+ * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+ *
+ * @param dependent the option whose absence on a command line makes this builder's option allowed
+ * @param otherDependents other options whose absence on a command line makes this builder's option allowed
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public OptionSpecBuilder availableUnless( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) {
+ parser.availableUnless( options(), dependent );
+ for ( OptionSpec<?> each : otherDependents )
+ parser.availableUnless(options(), each);
+
+ return this;
+ }
+
+ private List<String> validatedDependents( String dependent, String... otherDependents ) {
+ List<String> dependents = new ArrayList<>();
+ dependents.add( dependent );
+ Collections.addAll( dependents, otherDependents );
+
+ for ( String each : dependents ) {
+ if ( !parser.isRecognized( each ) )
+ throw new UnconfiguredOptionException( each );
+ }
+
+ return dependents;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java
new file mode 100644
index 0000000000..f9e4606c0c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java
@@ -0,0 +1,126 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.NoSuchElementException;
+
+import static joptsimple.ParserRules.*;
+
+/**
+ * Tokenizes a short option specification string.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionSpecTokenizer {
+ private static final char POSIXLY_CORRECT_MARKER = '+';
+ private static final char HELP_MARKER = '*';
+
+ private String specification;
+ private int index;
+
+ OptionSpecTokenizer( String specification ) {
+ if ( specification == null )
+ throw new NullPointerException( "null option specification" );
+
+ this.specification = specification;
+ }
+
+ boolean hasMore() {
+ return index < specification.length();
+ }
+
+ AbstractOptionSpec<?> next() {
+ if ( !hasMore() )
+ throw new NoSuchElementException();
+
+
+ String optionCandidate = String.valueOf( specification.charAt( index ) );
+ index++;
+
+ AbstractOptionSpec<?> spec;
+ if ( RESERVED_FOR_EXTENSIONS.equals( optionCandidate ) ) {
+ spec = handleReservedForExtensionsToken();
+
+ if ( spec != null )
+ return spec;
+ }
+
+ ensureLegalOption( optionCandidate );
+
+ if ( hasMore() ) {
+ boolean forHelp = false;
+ if ( specification.charAt( index ) == HELP_MARKER ) {
+ forHelp = true;
+ ++index;
+ }
+ spec = hasMore() && specification.charAt( index ) == ':'
+ ? handleArgumentAcceptingOption( optionCandidate )
+ : new NoArgumentOptionSpec( optionCandidate );
+ if ( forHelp )
+ spec.forHelp();
+ } else
+ spec = new NoArgumentOptionSpec( optionCandidate );
+
+ return spec;
+ }
+
+ void configure( OptionParser parser ) {
+ adjustForPosixlyCorrect( parser );
+
+ while ( hasMore() )
+ parser.recognize( next() );
+ }
+
+ private void adjustForPosixlyCorrect( OptionParser parser ) {
+ if ( POSIXLY_CORRECT_MARKER == specification.charAt( 0 ) ) {
+ parser.posixlyCorrect( true );
+ specification = specification.substring( 1 );
+ }
+ }
+
+ private AbstractOptionSpec<?> handleReservedForExtensionsToken() {
+ if ( !hasMore() )
+ return new NoArgumentOptionSpec( RESERVED_FOR_EXTENSIONS );
+
+ if ( specification.charAt( index ) == ';' ) {
+ ++index;
+ return new AlternativeLongOptionSpec();
+ }
+
+ return null;
+ }
+
+ private AbstractOptionSpec<?> handleArgumentAcceptingOption( String candidate ) {
+ index++;
+
+ if ( hasMore() && specification.charAt( index ) == ':' ) {
+ index++;
+ return new OptionalArgumentOptionSpec<String>( candidate );
+ }
+
+ return new RequiredArgumentOptionSpec<String>( candidate );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java
new file mode 100644
index 0000000000..cd641ed580
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java
@@ -0,0 +1,69 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Specification of an option that accepts an optional argument.
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionalArgumentOptionSpec<V> extends ArgumentAcceptingOptionSpec<V> {
+ OptionalArgumentOptionSpec( String option ) {
+ super( option, false );
+ }
+
+ OptionalArgumentOptionSpec( List<String> options, String description ) {
+ super( options, false, description );
+ }
+
+ @Override
+ protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+ if ( arguments.hasMore() ) {
+ String nextArgument = arguments.peek();
+
+ if ( !parser.looksLikeAnOption( nextArgument ) && canConvertArgument( nextArgument ) )
+ handleOptionArgument( parser, detectedOptions, arguments );
+ else if ( isArgumentOfNumberType() && canConvertArgument( nextArgument ) )
+ addArguments( detectedOptions, arguments.next() );
+ else
+ detectedOptions.add( this );
+ }
+ else
+ detectedOptions.add( this );
+ }
+
+ private void handleOptionArgument( OptionParser parser, OptionSet detectedOptions, ArgumentList arguments ) {
+ if ( parser.posixlyCorrect() ) {
+ detectedOptions.add( this );
+ parser.noMoreOptions();
+ }
+ else
+ addArguments( detectedOptions, arguments.next() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java
new file mode 100644
index 0000000000..34ef7814d5
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java
@@ -0,0 +1,84 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import static java.lang.Character.*;
+
+/**
+ * Can tell whether or not options are well-formed.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+final class ParserRules {
+ static final char HYPHEN_CHAR = '-';
+ static final String HYPHEN = String.valueOf( HYPHEN_CHAR );
+ static final String DOUBLE_HYPHEN = "--";
+ static final String OPTION_TERMINATOR = DOUBLE_HYPHEN;
+ static final String RESERVED_FOR_EXTENSIONS = "W";
+
+ private ParserRules() {
+ throw new UnsupportedOperationException();
+ }
+
+ static boolean isShortOptionToken( String argument ) {
+ return argument.startsWith( HYPHEN )
+ && !HYPHEN.equals( argument )
+ && !isLongOptionToken( argument );
+ }
+
+ static boolean isLongOptionToken( String argument ) {
+ return argument.startsWith( DOUBLE_HYPHEN ) && !isOptionTerminator( argument );
+ }
+
+ static boolean isOptionTerminator( String argument ) {
+ return OPTION_TERMINATOR.equals( argument );
+ }
+
+ static void ensureLegalOption( String option ) {
+ if ( option.startsWith( HYPHEN ) )
+ throw new IllegalOptionSpecificationException( String.valueOf( option ) );
+
+ for ( int i = 0; i < option.length(); ++i )
+ ensureLegalOptionCharacter( option.charAt( i ) );
+ }
+
+ static void ensureLegalOptions( List<String> options ) {
+ for ( String each : options )
+ ensureLegalOption( each );
+ }
+
+ private static void ensureLegalOptionCharacter( char option ) {
+ if ( !( isLetterOrDigit( option ) || isAllowedPunctuation( option ) ) )
+ throw new IllegalOptionSpecificationException( String.valueOf( option ) );
+ }
+
+ private static boolean isAllowedPunctuation( char option ) {
+ String allowedPunctuation = "?._" + HYPHEN_CHAR;
+ return allowedPunctuation.indexOf( option ) != -1;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java
new file mode 100644
index 0000000000..4c7ab880c7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java
@@ -0,0 +1,52 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Specification of an option that accepts a required argument.
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class RequiredArgumentOptionSpec<V> extends ArgumentAcceptingOptionSpec<V> {
+ RequiredArgumentOptionSpec( String option ) {
+ super( option, true );
+ }
+
+ RequiredArgumentOptionSpec( List<String> options, String description ) {
+ super( options, true, description );
+ }
+
+ @Override
+ protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+ if ( !arguments.hasMore() )
+ throw new OptionMissingRequiredArgumentException( this );
+
+ addArguments( detectedOptions, arguments.next() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java
new file mode 100644
index 0000000000..b1fa0e3a1e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java
@@ -0,0 +1,45 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+/**
+ * Thrown when options marked as allowed are specified on the command line, but the options they depend upon are
+ * present/not present.
+ */
+class UnavailableOptionException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ UnavailableOptionException( List<? extends OptionSpec<?>> forbiddenOptions ) {
+ super( forbiddenOptions );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { multipleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java
new file mode 100644
index 0000000000..f62d88bd4a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java
@@ -0,0 +1,52 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import static java.util.Collections.*;
+
+/**
+ * Thrown when an option parser refers to an option that is not in fact configured already on the parser.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class UnconfiguredOptionException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ UnconfiguredOptionException( String option ) {
+ this( singletonList( option ) );
+ }
+
+ UnconfiguredOptionException( List<String> options ) {
+ super( options );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { multipleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java
new file mode 100644
index 0000000000..73e7d74a0b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java
@@ -0,0 +1,46 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+/**
+ * Thrown when the option parser encounters an unrecognized option.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class UnrecognizedOptionException extends OptionException {
+ private static final long serialVersionUID = -1L;
+
+ UnrecognizedOptionException( String option ) {
+ super( singletonList( option ) );
+ }
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[] { singleOptionString() };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java
new file mode 100644
index 0000000000..50d575d194
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java
@@ -0,0 +1,54 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * Thrown by {@link ValueConverter}s when problems occur in converting string values to other Java types.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ValueConversionException extends RuntimeException {
+ private static final long serialVersionUID = -1L;
+
+ /**
+ * Creates a new exception with the specified detail message.
+ *
+ * @param message the detail message
+ */
+ public ValueConversionException( String message ) {
+ this( message, null );
+ }
+
+ /**
+ * Creates a new exception with the specified detail message and cause.
+ *
+ * @param message the detail message
+ * @param cause the original exception
+ */
+ public ValueConversionException( String message, Throwable cause ) {
+ super( message, cause );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java
new file mode 100644
index 0000000000..bc968da2d8
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * Instances of this interface are used to convert arguments of options into specific Java types.
+ *
+ * @param <V> constraint on the type of values being converted to
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface ValueConverter<V> {
+ /**
+ * Converts the given string value into a Java type.
+ *
+ * @param value the string to convert
+ * @return the converted value
+ * @throws ValueConversionException if a problem occurs while converting the value
+ */
+ V convert( String value );
+
+ /**
+ * Gives the class of the type of values this converter converts to.
+ *
+ * @return the target class for conversion
+ */
+ Class<? extends V> valueType();
+
+ /**
+ * Gives a string that describes the pattern of the values this converter expects, if any. For example, a date
+ * converter can respond with a {@link java.text.SimpleDateFormat date format string}.
+ *
+ * @return a value pattern, or {@code null} if there's nothing interesting here
+ */
+ String valuePattern();
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java
new file mode 100644
index 0000000000..0d601839a5
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java
@@ -0,0 +1,242 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * <p>A map whose keys are strings; when a key/value pair is added to the map, the longest unique abbreviations of that
+ * key are added as well, and associated with the value. Thus:</p>
+ *
+ * <pre>
+ * <code>
+ * abbreviations.put( "good", "bye" );
+ * </code>
+ * </pre>
+ *
+ * <p>would make it such that you could retrieve the value {@code "bye"} from the map using the keys {@code "good"},
+ * {@code "goo"}, {@code "go"}, and {@code "g"}. A subsequent invocation of:</p>
+ * <pre>
+ * <code>
+ * abbreviations.put( "go", "fish" );
+ * </code>
+ * </pre>
+ *
+ * <p>would make it such that you could retrieve the value {@code "bye"} using the keys {@code "good"} and
+ * {@code "goo"}, and the value {@code "fish"} using the key {@code "go"}. The key {@code "g"} would yield
+ * {@code null}, since it would no longer be a unique abbreviation.</p>
+ *
+ * <p>The data structure is much like a "trie".</p>
+ *
+ * @param <V> a constraint on the types of the values in the map
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ * @see <a href="http://perldoc.perl.org/Text/Abbrev.html">Perl's Text::Abbrev module</a>
+ * @see <a href="https://en.wikipedia.org/wiki/Radix_tree">Radix tree</a>
+ */
+public class AbbreviationMap<V> implements OptionNameMap<V> {
+ private final Map<Character, AbbreviationMap<V>> children = new TreeMap<>();
+
+ private String key;
+ private V value;
+ private int keysBeyond;
+
+ /**
+ * <p>Tells whether the given key is in the map, or whether the given key is a unique
+ * abbreviation of a key that is in the map.</p>
+ *
+ * @param key key to look up
+ * @return {@code true} if {@code key} is present in the map
+ * @throws NullPointerException if {@code key} is {@code null}
+ */
+ @Override
+ public boolean contains(String key) {
+ return get(key) != null;
+ }
+
+ /**
+ * <p>Answers the value associated with the given key. The key can be a unique
+ * abbreviation of a key that is in the map. </p>
+ *
+ * @param key key to look up
+ * @return the value associated with {@code aKey}; or {@code null} if there is no
+ * such value or {@code aKey} is not a unique abbreviation of a key in the map
+ * @throws NullPointerException if {@code aKey} is {@code null}
+ */
+ @Override
+ public V get( String key ) {
+ char[] chars = charsOf( key );
+
+ AbbreviationMap<V> child = this;
+ for ( char each : chars ) {
+ child = child.children.get( each );
+ if ( child == null )
+ return null;
+ }
+
+ return child.value;
+ }
+
+ /**
+ * <p>Associates a given value with a given key. If there was a previous
+ * association, the old value is replaced with the new one.</p>
+ *
+ * @param key key to create in the map
+ * @param newValue value to associate with the key
+ * @throws NullPointerException if {@code aKey} or {@code newValue} is {@code null}
+ * @throws IllegalArgumentException if {@code aKey} is a zero-length string
+ */
+ @Override
+ public void put( String key, V newValue ) {
+ if ( newValue == null )
+ throw new NullPointerException();
+ if ( key.length() == 0 )
+ throw new IllegalArgumentException();
+
+ char[] chars = charsOf(key);
+ add( chars, newValue, 0, chars.length );
+ }
+
+ /**
+ * <p>Associates a given value with a given set of keys. If there was a previous
+ * association, the old value is replaced with the new one.</p>
+ *
+ * @param keys keys to create in the map
+ * @param newValue value to associate with the key
+ * @throws NullPointerException if {@code keys} or {@code newValue} is {@code null}
+ * @throws IllegalArgumentException if any of {@code keys} is a zero-length string
+ */
+ @Override
+ public void putAll( Iterable<String> keys, V newValue ) {
+ for ( String each : keys )
+ put( each, newValue );
+ }
+
+ private boolean add( char[] chars, V newValue, int offset, int length ) {
+ if ( offset == length ) {
+ value = newValue;
+ boolean wasAlreadyAKey = key != null;
+ key = new String( chars );
+ return !wasAlreadyAKey;
+ }
+
+ char nextChar = chars[ offset ];
+ AbbreviationMap<V> child = children.get( nextChar );
+ if ( child == null ) {
+ child = new AbbreviationMap<>();
+ children.put( nextChar, child );
+ }
+
+ boolean newKeyAdded = child.add( chars, newValue, offset + 1, length );
+
+ if ( newKeyAdded )
+ ++keysBeyond;
+
+ if ( key == null )
+ value = keysBeyond > 1 ? null : newValue;
+
+ return newKeyAdded;
+ }
+
+ /**
+ * <p>If the map contains the given key, dissociates the key from its value.</p>
+ *
+ * @param key key to remove
+ * @throws NullPointerException if {@code aKey} is {@code null}
+ * @throws IllegalArgumentException if {@code aKey} is a zero-length string
+ */
+ @Override
+ public void remove( String key ) {
+ if ( key.length() == 0 )
+ throw new IllegalArgumentException();
+
+ char[] keyChars = charsOf(key);
+ remove( keyChars, 0, keyChars.length );
+ }
+
+ private boolean remove( char[] aKey, int offset, int length ) {
+ if ( offset == length )
+ return removeAtEndOfKey();
+
+ char nextChar = aKey[ offset ];
+ AbbreviationMap<V> child = children.get( nextChar );
+ if ( child == null || !child.remove( aKey, offset + 1, length ) )
+ return false;
+
+ --keysBeyond;
+ if ( child.keysBeyond == 0 )
+ children.remove( nextChar );
+ if ( keysBeyond == 1 && key == null )
+ setValueToThatOfOnlyChild();
+
+ return true;
+ }
+
+ private void setValueToThatOfOnlyChild() {
+ Map.Entry<Character, AbbreviationMap<V>> entry = children.entrySet().iterator().next();
+ AbbreviationMap<V> onlyChild = entry.getValue();
+ value = onlyChild.value;
+ }
+
+ private boolean removeAtEndOfKey() {
+ if ( key == null )
+ return false;
+
+ key = null;
+ if ( keysBeyond == 1 )
+ setValueToThatOfOnlyChild();
+ else
+ value = null;
+
+ return true;
+ }
+
+ /**
+ * Gives a Java map representation of this abbreviation map.
+ *
+ * @return a Java map corresponding to this abbreviation map
+ */
+ @Override
+ public Map<String, V> toJavaUtilMap() {
+ Map<String, V> mappings = new TreeMap<>();
+ addToMappings( mappings );
+ return mappings;
+ }
+
+ private void addToMappings( Map<String, V> mappings ) {
+ if ( key != null )
+ mappings.put( key, value );
+
+ for ( AbbreviationMap<V> each : children.values() )
+ each.addToMappings( mappings );
+ }
+
+ private static char[] charsOf( String aKey ) {
+ char[] chars = new char[ aKey.length() ];
+ aKey.getChars( 0, aKey.length(), chars, 0 );
+ return chars;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java
new file mode 100644
index 0000000000..f7030f88cb
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java
@@ -0,0 +1,75 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public final class Classes {
+ private static final Map<Class<?>, Class<?>> WRAPPERS = new HashMap<>( 13 );
+
+ static {
+ WRAPPERS.put( boolean.class, Boolean.class );
+ WRAPPERS.put( byte.class, Byte.class );
+ WRAPPERS.put( char.class, Character.class );
+ WRAPPERS.put( double.class, Double.class );
+ WRAPPERS.put( float.class, Float.class );
+ WRAPPERS.put( int.class, Integer.class );
+ WRAPPERS.put( long.class, Long.class );
+ WRAPPERS.put( short.class, Short.class );
+ WRAPPERS.put( void.class, Void.class );
+ }
+
+ private Classes() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gives the "short version" of the given class name. Somewhat naive to inner classes.
+ *
+ * @param className class name to chew on
+ * @return the short name of the class
+ */
+ public static String shortNameOf( String className ) {
+ return className.substring( className.lastIndexOf( '.' ) + 1 );
+ }
+
+ /**
+ * Gives the primitive wrapper class for the given class. If the given class is not
+ * {@linkplain Class#isPrimitive() primitive}, returns the class itself.
+ *
+ * @param <T> generic class type
+ * @param clazz the class to check
+ * @return primitive wrapper type if {@code clazz} is primitive, otherwise {@code clazz}
+ */
+ @SuppressWarnings( "unchecked" )
+ public static <T> Class<T> wrapperOf( Class<T> clazz ) {
+ return clazz.isPrimitive() ? (Class<T>) WRAPPERS.get( clazz ) : clazz;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java
new file mode 100644
index 0000000000..a012b601f0
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java
@@ -0,0 +1,106 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.text.BreakIterator;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.text.BreakIterator.*;
+
+import static joptsimple.internal.Strings.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class Columns {
+ private static final int INDENT_WIDTH = 2;
+
+ private final int optionWidth;
+ private final int descriptionWidth;
+
+ Columns( int optionWidth, int descriptionWidth ) {
+ this.optionWidth = optionWidth;
+ this.descriptionWidth = descriptionWidth;
+ }
+
+ List<Row> fit( Row row ) {
+ List<String> options = piecesOf( row.option, optionWidth );
+ List<String> descriptions = piecesOf( row.description, descriptionWidth );
+
+ List<Row> rows = new ArrayList<>();
+ for ( int i = 0; i < Math.max( options.size(), descriptions.size() ); ++i )
+ rows.add( new Row( itemOrEmpty( options, i ), itemOrEmpty( descriptions, i ) ) );
+
+ return rows;
+ }
+
+ private static String itemOrEmpty( List<String> items, int index ) {
+ return index >= items.size() ? "" : items.get( index );
+ }
+
+ private List<String> piecesOf( String raw, int width ) {
+ List<String> pieces = new ArrayList<>();
+
+ for ( String each : raw.trim().split( LINE_SEPARATOR ) )
+ pieces.addAll( piecesOfEmbeddedLine( each, width ) );
+
+ return pieces;
+ }
+
+ private List<String> piecesOfEmbeddedLine( String line, int width ) {
+ List<String> pieces = new ArrayList<>();
+
+ BreakIterator words = BreakIterator.getLineInstance();
+ words.setText( line );
+
+ StringBuilder nextPiece = new StringBuilder();
+
+ int start = words.first();
+ for ( int end = words.next(); end != DONE; start = end, end = words.next() )
+ nextPiece = processNextWord( line, nextPiece, start, end, width, pieces );
+
+ if ( nextPiece.length() > 0 )
+ pieces.add( nextPiece.toString() );
+
+ return pieces;
+ }
+
+ private StringBuilder processNextWord( String source, StringBuilder nextPiece, int start, int end, int width,
+ List<String> pieces ) {
+ StringBuilder augmented = nextPiece;
+
+ String word = source.substring( start, end );
+ if ( augmented.length() + word.length() > width ) {
+ pieces.add( augmented.toString().replaceAll( "\\s+$", "" ) );
+ augmented = new StringBuilder( repeat( ' ', INDENT_WIDTH ) ).append( word );
+ }
+ else
+ augmented.append( word );
+
+ return augmented;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java
new file mode 100644
index 0000000000..d3a641b57d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java
@@ -0,0 +1,56 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.lang.reflect.Constructor;
+
+import joptsimple.ValueConverter;
+
+import static joptsimple.internal.Reflection.*;
+
+/**
+ * @param <V> constraint on the type of values being converted to
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class ConstructorInvokingValueConverter<V> implements ValueConverter<V> {
+ private final Constructor<V> ctor;
+
+ ConstructorInvokingValueConverter( Constructor<V> ctor ) {
+ this.ctor = ctor;
+ }
+
+ public V convert( String value ) {
+ return instantiate( ctor, value );
+ }
+
+ public Class<V> valueType() {
+ return ctor.getDeclaringClass();
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java
new file mode 100644
index 0000000000..5bb71fc727
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java
@@ -0,0 +1,47 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class Messages {
+ private Messages() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static String message( Locale locale, String bundleName, Class<?> type, String key, Object... args ) {
+ ResourceBundle bundle = ResourceBundle.getBundle( bundleName, locale );
+ String template = bundle.getString( type.getName() + '.' + key );
+ MessageFormat format = new MessageFormat( template );
+ format.setLocale( locale );
+ return format.format( args );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java
new file mode 100644
index 0000000000..503d6778d8
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.lang.reflect.Method;
+
+import joptsimple.ValueConverter;
+
+import static joptsimple.internal.Reflection.*;
+
+/**
+ * @param <V> constraint on the type of values being converted to
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class MethodInvokingValueConverter<V> implements ValueConverter<V> {
+ private final Method method;
+ private final Class<V> clazz;
+
+ MethodInvokingValueConverter( Method method, Class<V> clazz ) {
+ this.method = method;
+ this.clazz = clazz;
+ }
+
+ public V convert( String value ) {
+ return clazz.cast( invoke( method, value ) );
+ }
+
+ public Class<V> valueType() {
+ return clazz;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java
new file mode 100644
index 0000000000..1b9e49197b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java
@@ -0,0 +1,47 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.Map;
+
+/**
+ * Map-like interface for storing String-value pairs.
+ *
+ * @param <V> type of values stored in the map
+ */
+public interface OptionNameMap<V> {
+ boolean contains( String key );
+
+ V get( String key );
+
+ void put( String key, V newValue );
+
+ void putAll( Iterable<String> keys, V newValue );
+
+ void remove( String key );
+
+ Map<String, V> toJavaUtilMap();
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java
new file mode 100644
index 0000000000..5dad882787
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java
@@ -0,0 +1,142 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static java.lang.reflect.Modifier.*;
+
+import joptsimple.ValueConverter;
+
+import static joptsimple.internal.Classes.*;
+
+/**
+ * Helper methods for reflection.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public final class Reflection {
+ private Reflection() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Finds an appropriate value converter for the given class.
+ *
+ * @param <V> a constraint on the class object to introspect
+ * @param clazz class to introspect on
+ * @return a converter method or constructor
+ */
+ public static <V> ValueConverter<V> findConverter( Class<V> clazz ) {
+ Class<V> maybeWrapper = wrapperOf( clazz );
+
+ ValueConverter<V> valueOf = valueOfConverter( maybeWrapper );
+ if ( valueOf != null )
+ return valueOf;
+
+ ValueConverter<V> constructor = constructorConverter( maybeWrapper );
+ if ( constructor != null )
+ return constructor;
+
+ throw new IllegalArgumentException( clazz + " is not a value type" );
+ }
+
+ private static <V> ValueConverter<V> valueOfConverter( Class<V> clazz ) {
+ try {
+ Method valueOf = clazz.getMethod( "valueOf", String.class );
+ if ( meetsConverterRequirements( valueOf, clazz ) )
+ return new MethodInvokingValueConverter<>( valueOf, clazz );
+
+ return null;
+ } catch ( NoSuchMethodException ignored ) {
+ return null;
+ }
+ }
+
+ private static <V> ValueConverter<V> constructorConverter( Class<V> clazz ) {
+ try {
+ return new ConstructorInvokingValueConverter<>( clazz.getConstructor( String.class ) );
+ } catch ( NoSuchMethodException ignored ) {
+ return null;
+ }
+ }
+
+ /**
+ * Invokes the given constructor with the given arguments.
+ *
+ * @param <T> constraint on the type of the objects yielded by the constructor
+ * @param constructor constructor to invoke
+ * @param args arguments to hand to the constructor
+ * @return the result of invoking the constructor
+ * @throws ReflectionException in lieu of the gaggle of reflection-related exceptions
+ */
+ public static <T> T instantiate( Constructor<T> constructor, Object... args ) {
+ try {
+ return constructor.newInstance( args );
+ } catch ( Exception ex ) {
+ throw reflectionException( ex );
+ }
+ }
+
+ /**
+ * Invokes the given static method with the given arguments.
+ *
+ * @param method method to invoke
+ * @param args arguments to hand to the method
+ * @return the result of invoking the method
+ * @throws ReflectionException in lieu of the gaggle of reflection-related exceptions
+ */
+ public static Object invoke( Method method, Object... args ) {
+ try {
+ return method.invoke( null, args );
+ } catch ( Exception ex ) {
+ throw reflectionException( ex );
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public static <V> V convertWith( ValueConverter<V> converter, String raw ) {
+ return converter == null ? (V) raw : converter.convert( raw );
+ }
+
+ private static boolean meetsConverterRequirements( Method method, Class<?> expectedReturnType ) {
+ int modifiers = method.getModifiers();
+ return isPublic( modifiers ) && isStatic( modifiers ) && expectedReturnType.equals( method.getReturnType() );
+ }
+
+ private static RuntimeException reflectionException( Exception ex ) {
+ if ( ex instanceof IllegalArgumentException )
+ return new ReflectionException( ex );
+ if ( ex instanceof InvocationTargetException )
+ return new ReflectionException( ex.getCause() );
+ if ( ex instanceof RuntimeException )
+ return (RuntimeException) ex;
+
+ return new ReflectionException( ex );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java
new file mode 100644
index 0000000000..17cd4d6330
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java
@@ -0,0 +1,39 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+/**
+ * This unchecked exception wraps reflection-oriented exceptions.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ReflectionException extends RuntimeException {
+ private static final long serialVersionUID = -2L;
+
+ ReflectionException( Throwable cause ) {
+ super( cause );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java
new file mode 100644
index 0000000000..13d8e34905
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java
@@ -0,0 +1,55 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class Row {
+ final String option;
+ final String description;
+
+ Row( String option, String description ) {
+ this.option = option;
+ this.description = description;
+ }
+
+ @Override
+ public boolean equals( Object that ) {
+ if ( that == this )
+ return true;
+ if ( that == null || !getClass().equals( that.getClass() ) )
+ return false;
+
+ Row other = (Row) that;
+ return option.equals( other.option ) && description.equals( other.description );
+ }
+
+ @Override
+ public int hashCode() {
+ return option.hashCode() ^ description.hashCode();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java
new file mode 100644
index 0000000000..c2cae82ce4
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java
@@ -0,0 +1,103 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.lang.Math.*;
+
+import static joptsimple.internal.Strings.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class Rows {
+ private final int overallWidth;
+ private final int columnSeparatorWidth;
+ private final List<Row> rows = new ArrayList<>();
+
+ private int widthOfWidestOption;
+ private int widthOfWidestDescription;
+
+ public Rows( int overallWidth, int columnSeparatorWidth ) {
+ this.overallWidth = overallWidth;
+ this.columnSeparatorWidth = columnSeparatorWidth;
+ }
+
+ public void add( String option, String description ) {
+ add( new Row( option, description ) );
+ }
+
+ private void add( Row row ) {
+ rows.add( row );
+ widthOfWidestOption = max( widthOfWidestOption, row.option.length() );
+ widthOfWidestDescription = max( widthOfWidestDescription, row.description.length() );
+ }
+
+ public void reset() {
+ rows.clear();
+ widthOfWidestOption = 0;
+ widthOfWidestDescription = 0;
+ }
+
+ public void fitToWidth() {
+ Columns columns = new Columns( optionWidth(), descriptionWidth() );
+
+ List<Row> fitted = new ArrayList<>();
+ for ( Row each : rows )
+ fitted.addAll( columns.fit( each ) );
+
+ reset();
+
+ for ( Row each : fitted )
+ add( each );
+ }
+
+ public String render() {
+ StringBuilder buffer = new StringBuilder();
+
+ for ( Row each : rows ) {
+ pad( buffer, each.option, optionWidth() ).append( repeat( ' ', columnSeparatorWidth ) );
+ pad( buffer, each.description, descriptionWidth() ).append( LINE_SEPARATOR );
+ }
+
+ return buffer.toString();
+ }
+
+ private int optionWidth() {
+ return min( ( overallWidth - columnSeparatorWidth ) / 2, widthOfWidestOption );
+ }
+
+ private int descriptionWidth() {
+ return min( overallWidth - optionWidth() - columnSeparatorWidth, widthOfWidestDescription );
+ }
+
+ private StringBuilder pad( StringBuilder buffer, String s, int length ) {
+ buffer.append( s ).append( repeat( ' ', length - s.length() ) );
+ return buffer;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java
new file mode 100644
index 0000000000..69ad6b5c4c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java
@@ -0,0 +1,67 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>An {@code OptionNameMap} which wraps and behaves like {@code HashMap}.</p>
+ */
+public class SimpleOptionNameMap<V> implements OptionNameMap<V> {
+ private final Map<String, V> map = new HashMap<>();
+
+ @Override
+ public boolean contains( String key ) {
+ return map.containsKey( key );
+ }
+
+ @Override
+ public V get( String key ) {
+ return map.get( key );
+ }
+
+ @Override
+ public void put( String key, V newValue ) {
+ map.put( key, newValue );
+ }
+
+ @Override
+ public void putAll( Iterable<String> keys, V newValue ) {
+ for ( String each : keys )
+ map.put( each, newValue );
+ }
+
+ @Override
+ public void remove( String key ) {
+ map.remove( key );
+ }
+
+ @Override
+ public Map<String, V> toJavaUtilMap() {
+ return new HashMap<>( map );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java
new file mode 100644
index 0000000000..50ea3e49ea
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java
@@ -0,0 +1,115 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.Iterator;
+
+import static java.lang.System.*;
+import static java.util.Arrays.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public final class Strings {
+ public static final String EMPTY = "";
+ public static final String LINE_SEPARATOR = getProperty( "line.separator" );
+
+ private Strings() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gives a string consisting of the given character repeated the given number of times.
+ *
+ * @param ch the character to repeat
+ * @param count how many times to repeat the character
+ * @return the resultant string
+ */
+ public static String repeat( char ch, int count ) {
+ StringBuilder buffer = new StringBuilder();
+
+ for ( int i = 0; i < count; ++i )
+ buffer.append( ch );
+
+ return buffer.toString();
+ }
+
+ /**
+ * Tells whether the given string is either {@code} or consists solely of whitespace characters.
+ *
+ * @param target string to check
+ * @return {@code true} if the target string is null or empty
+ */
+ public static boolean isNullOrEmpty( String target ) {
+ return target == null || target.isEmpty();
+ }
+
+
+ /**
+ * Gives a string consisting of a given string prepended and appended with surrounding characters.
+ *
+ * @param target a string
+ * @param begin character to prepend
+ * @param end character to append
+ * @return the surrounded string
+ */
+ public static String surround( String target, char begin, char end ) {
+ return begin + target + end;
+ }
+
+ /**
+ * Gives a string consisting of the elements of a given array of strings, each separated by a given separator
+ * string.
+ *
+ * @param pieces the strings to join
+ * @param separator the separator
+ * @return the joined string
+ */
+ public static String join( String[] pieces, String separator ) {
+ return join( asList( pieces ), separator );
+ }
+
+ /**
+ * Gives a string consisting of the string representations of the elements of a given array of objects,
+ * each separated by a given separator string.
+ *
+ * @param pieces the elements whose string representations are to be joined
+ * @param separator the separator
+ * @return the joined string
+ */
+ public static String join( Iterable<String> pieces, String separator ) {
+ StringBuilder buffer = new StringBuilder();
+
+ for ( Iterator<String> iter = pieces.iterator(); iter.hasNext(); ) {
+ buffer.append( iter.next() );
+
+ if ( iter.hasNext() )
+ buffer.append( separator );
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java
new file mode 100644
index 0000000000..c3182ae2fd
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java
@@ -0,0 +1,114 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import java.text.DateFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+import joptsimple.internal.Messages;
+
+/**
+ * Converts values to {@link Date}s using a {@link DateFormat} object.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class DateConverter implements ValueConverter<Date> {
+ private final DateFormat formatter;
+
+ /**
+ * Creates a converter that uses the given date formatter/parser.
+ *
+ * @param formatter the formatter/parser to use
+ * @throws NullPointerException if {@code formatter} is {@code null}
+ */
+ public DateConverter( DateFormat formatter ) {
+ if ( formatter == null )
+ throw new NullPointerException( "illegal null formatter" );
+
+ this.formatter = formatter;
+ }
+
+ /**
+ * Creates a converter that uses a {@link SimpleDateFormat} with the given date/time pattern. The date formatter
+ * created is not {@link SimpleDateFormat#setLenient(boolean) lenient}.
+ *
+ * @param pattern expected date/time pattern
+ * @return the new converter
+ * @throws NullPointerException if {@code pattern} is {@code null}
+ * @throws IllegalArgumentException if {@code pattern} is invalid
+ */
+ public static DateConverter datePattern( String pattern ) {
+ SimpleDateFormat formatter = new SimpleDateFormat( pattern );
+ formatter.setLenient( false );
+
+ return new DateConverter( formatter );
+ }
+
+ public Date convert( String value ) {
+ ParsePosition position = new ParsePosition( 0 );
+
+ Date date = formatter.parse( value, position );
+ if ( position.getIndex() != value.length() )
+ throw new ValueConversionException( message( value ) );
+
+ return date;
+ }
+
+ public Class<Date> valueType() {
+ return Date.class;
+ }
+
+ public String valuePattern() {
+ return formatter instanceof SimpleDateFormat
+ ? ( (SimpleDateFormat) formatter ).toPattern()
+ : "";
+ }
+
+ private String message( String value ) {
+ String key;
+ Object[] arguments;
+
+ if ( formatter instanceof SimpleDateFormat ) {
+ key = "with.pattern.message";
+ arguments = new Object[] { value, ( (SimpleDateFormat) formatter ).toPattern() };
+ } else {
+ key = "without.pattern.message";
+ arguments = new Object[] { value };
+ }
+
+ return Messages.message(
+ Locale.getDefault(),
+ "joptsimple.ExceptionMessages",
+ DateConverter.class,
+ key,
+ arguments );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java
new file mode 100644
index 0000000000..c75b86607f
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java
@@ -0,0 +1,104 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2014 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import java.text.MessageFormat;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.ResourceBundle;
+
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+
+/**
+ * Converts values to {@link java.lang.Enum}s.
+ *
+ * @author <a href="mailto:christian.ohr@gmail.com">Christian Ohr</a>
+ */
+public abstract class EnumConverter<E extends Enum<E>> implements ValueConverter<E> {
+ private final Class<E> clazz;
+
+ private String delimiters = "[,]";
+
+ /**
+ * This constructor must be called by subclasses, providing the enum class as the parameter.
+ *
+ * @param clazz enum class
+ */
+ protected EnumConverter( Class<E> clazz ) {
+ this.clazz = clazz;
+ }
+
+ @Override
+ public E convert( String value ) {
+ for ( E each : valueType().getEnumConstants() ) {
+ if ( each.name().equalsIgnoreCase( value ) ) {
+ return each;
+ }
+ }
+
+ throw new ValueConversionException( message( value ) );
+ }
+
+ @Override
+ public Class<E> valueType() {
+ return clazz;
+ }
+
+ /**
+ * Sets the delimiters for the message string. Must be a 3-letter string,
+ * where the first character is the prefix, the second character is the
+ * delimiter between the values, and the 3rd character is the suffix.
+ *
+ * @param delimiters delimiters for message string. Default is [,]
+ */
+ public void setDelimiters( String delimiters ) {
+ this.delimiters = delimiters;
+ }
+
+ @Override
+ public String valuePattern() {
+ EnumSet<E> values = EnumSet.allOf( valueType() );
+
+ StringBuilder builder = new StringBuilder();
+ builder.append( delimiters.charAt(0) );
+ for ( Iterator<E> i = values.iterator(); i.hasNext(); ) {
+ builder.append( i.next().toString() );
+ if ( i.hasNext() )
+ builder.append( delimiters.charAt( 1 ) );
+ }
+ builder.append( delimiters.charAt( 2 ) );
+
+ return builder.toString();
+ }
+
+ private String message( String value ) {
+ ResourceBundle bundle = ResourceBundle.getBundle( "joptsimple.ExceptionMessages" );
+ Object[] arguments = new Object[] { value, valuePattern() };
+ String template = bundle.getString( EnumConverter.class.getName() + ".message" );
+ return new MessageFormat( template ).format( arguments );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java
new file mode 100644
index 0000000000..2f116f810d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java
@@ -0,0 +1,67 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Locale;
+
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+import joptsimple.internal.Messages;
+
+/**
+ * Converts values to {@link java.net.InetAddress} using {@link InetAddress#getByName(String) getByName}.
+ *
+ * @author <a href="mailto:r@ymund.de">Raymund F\u00FCl\u00F6p</a>
+ */
+public class InetAddressConverter implements ValueConverter<InetAddress> {
+ public InetAddress convert( String value ) {
+ try {
+ return InetAddress.getByName( value );
+ }
+ catch ( UnknownHostException e ) {
+ throw new ValueConversionException( message( value ) );
+ }
+ }
+
+ public Class<InetAddress> valueType() {
+ return InetAddress.class;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+
+ private String message( String value ) {
+ return Messages.message(
+ Locale.getDefault(),
+ "joptsimple.ExceptionMessages",
+ InetAddressConverter.class,
+ "message",
+ value );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java
new file mode 100644
index 0000000000..bdc2424190
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java
@@ -0,0 +1,83 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import static joptsimple.internal.Strings.*;
+
+/**
+ * <p>A simple string key/string value pair.</p>
+ *
+ * <p>This is useful as an argument type for options whose values take on the form {@code key=value}, such as JVM
+ * command line system properties.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public final class KeyValuePair {
+ public final String key;
+ public final String value;
+
+ private KeyValuePair( String key, String value ) {
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Parses a string assumed to be of the form {@code key=value} into its parts.
+ *
+ * @param asString key-value string
+ * @return a key-value pair
+ * @throws NullPointerException if {@code stringRepresentation} is {@code null}
+ */
+ public static KeyValuePair valueOf( String asString ) {
+ int equalsIndex = asString.indexOf( '=' );
+ if ( equalsIndex == -1 )
+ return new KeyValuePair( asString, EMPTY );
+
+ String aKey = asString.substring( 0, equalsIndex );
+ String aValue = equalsIndex == asString.length() - 1 ? EMPTY : asString.substring( equalsIndex + 1 );
+
+ return new KeyValuePair( aKey, aValue );
+ }
+
+ @Override
+ public boolean equals( Object that ) {
+ if ( !( that instanceof KeyValuePair ) )
+ return false;
+
+ KeyValuePair other = (KeyValuePair) that;
+ return key.equals( other.key ) && value.equals( other.value );
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode() ^ value.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return key + '=' + value;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java
new file mode 100644
index 0000000000..295bc00362
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java
@@ -0,0 +1,51 @@
+package joptsimple.util;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+
+/**
+ * Converts command line options to {@link Path} objects and checks the status of the underlying file.
+ */
+public class PathConverter implements ValueConverter<Path> {
+ private final PathProperties[] pathProperties;
+
+ public PathConverter( PathProperties... pathProperties ) {
+ this.pathProperties = pathProperties;
+ }
+
+ @Override
+ public Path convert( String value ) {
+ Path path = Paths.get(value);
+
+ if ( pathProperties != null ) {
+ for ( PathProperties each : pathProperties ) {
+ if ( !each.accept( path ) )
+ throw new ValueConversionException( message( each.getMessageKey(), path.toString() ) );
+ }
+ }
+
+ return path;
+ }
+
+ @Override
+ public Class<Path> valueType() {
+ return Path.class;
+ }
+
+ @Override
+ public String valuePattern() {
+ return null;
+ }
+
+ private String message( String errorKey, String value ) {
+ ResourceBundle bundle = ResourceBundle.getBundle( "joptsimple.ExceptionMessages" );
+ Object[] arguments = new Object[] { value, valuePattern() };
+ String template = bundle.getString( PathConverter.class.getName() + "." + errorKey + ".message" );
+ return new MessageFormat( template ).format( arguments );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java
new file mode 100644
index 0000000000..a7fb045025
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java
@@ -0,0 +1,60 @@
+package joptsimple.util;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Enum for checking common conditions of files and directories.
+ *
+ * @see joptsimple.util.PathConverter
+ */
+public enum PathProperties {
+ FILE_EXISTING( "file.existing" ) {
+ @Override
+ boolean accept( Path path ) {
+ return Files.isRegularFile( path );
+ }
+ },
+ DIRECTORY_EXISTING( "directory.existing" ) {
+ @Override
+ boolean accept( Path path ) {
+ return Files.isDirectory( path );
+ }
+ },
+ NOT_EXISTING( "file.not.existing" ) {
+ @Override
+ boolean accept( Path path ) {
+ return Files.notExists( path );
+ }
+ },
+ FILE_OVERWRITABLE( "file.overwritable" ) {
+ @Override
+ boolean accept( Path path ) {
+ return FILE_EXISTING.accept( path ) && WRITABLE.accept( path );
+ }
+ },
+ READABLE( "file.readable" ) {
+ @Override
+ boolean accept( Path path ) {
+ return Files.isReadable( path );
+ }
+ },
+ WRITABLE( "file.writable" ) {
+ @Override
+ boolean accept( Path path ) {
+ return Files.isWritable( path );
+ }
+ };
+
+ private final String messageKey;
+
+ private PathProperties( String messageKey ) {
+ this.messageKey = messageKey;
+ }
+
+ abstract boolean accept( Path path );
+
+ String getMessageKey() {
+ return messageKey;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java
new file mode 100644
index 0000000000..aca788c7ec
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java
@@ -0,0 +1,95 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+import static java.util.regex.Pattern.*;
+import static joptsimple.internal.Messages.message;
+
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+
+/**
+ * Ensures that values entirely match a regular expression.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RegexMatcher implements ValueConverter<String> {
+ private final Pattern pattern;
+
+ /**
+ * Creates a matcher that uses the given regular expression, modified by the given flags.
+ *
+ * @param pattern the regular expression pattern
+ * @param flags modifying regex flags
+ * @throws IllegalArgumentException if bit values other than those corresponding to the defined match flags are
+ * set in {@code flags}
+ * @throws java.util.regex.PatternSyntaxException if the expression's syntax is invalid
+ */
+ public RegexMatcher( String pattern, int flags ) {
+ this.pattern = compile( pattern, flags );
+ }
+
+ /**
+ * Gives a matcher that uses the given regular expression.
+ *
+ * @param pattern the regular expression pattern
+ * @return the new converter
+ * @throws java.util.regex.PatternSyntaxException if the expression's syntax is invalid
+ */
+ public static ValueConverter<String> regex( String pattern ) {
+ return new RegexMatcher( pattern, 0 );
+ }
+
+ public String convert( String value ) {
+ if ( !pattern.matcher( value ).matches() ) {
+ raiseValueConversionFailure( value );
+ }
+
+ return value;
+ }
+
+ public Class<String> valueType() {
+ return String.class;
+ }
+
+ public String valuePattern() {
+ return pattern.pattern();
+ }
+
+ private void raiseValueConversionFailure( String value ) {
+ String message = message(
+ Locale.getDefault(),
+ "joptsimple.ExceptionMessages",
+ RegexMatcher.class,
+ "message",
+ value,
+ pattern.pattern() );
+ throw new ValueConversionException( message );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties b/third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties
new file mode 100644
index 0000000000..e5ce44d8c3
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties
@@ -0,0 +1,19 @@
+joptsimple.IllegalOptionSpecificationException.message = {0} is not a legal option character
+joptsimple.MissingRequiredOptionsException.message = Missing required option(s) {0}
+joptsimple.MultipleArgumentsForOptionException.message = Found multiple arguments for option {0}, but you asked for only one
+joptsimple.OptionArgumentConversionException.message = Cannot parse argument ''{0}'' of option {1}
+joptsimple.OptionMissingRequiredArgumentException.message = Option {0} requires an argument
+joptsimple.UnavailableOptionException.message = Option(s) {0} are unavailable given other options on the command line
+joptsimple.UnconfiguredOptionException.message = Option(s) {0} not configured on this parser
+joptsimple.UnrecognizedOptionException.message = {0} is not a recognized option
+joptsimple.util.DateConverter.without.pattern.message = Value [{0}] does not match date/time pattern
+joptsimple.util.DateConverter.with.pattern.message = Value [{0}] does not match date/time pattern [{1}]
+joptsimple.util.RegexMatcher.message = Value [{0}] did not match regex [{1}]
+joptsimple.util.EnumConverter.message = Value [{0}] is not one of [{1}]
+joptsimple.util.PathConverter.file.existing.message = File [{0}] does not exist
+joptsimple.util.PathConverter.directory.existing.message = Directory [{0}] does not exist
+joptsimple.util.PathConverter.file.not.existing.message = File [{0}] does already exist
+joptsimple.util.PathConverter.file.overwritable.message = File [{0}] is not overwritable
+joptsimple.util.PathConverter.file.readable.message = File [{0}] is not readable
+joptsimple.util.PathConverter.file.writable.message = File [{0}] is not writable
+joptsimple.util.InetAddressConverter.message = Cannot convert value [{0}] into an InetAddress \ No newline at end of file
diff --git a/third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties b/third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties
new file mode 100644
index 0000000000..d0faea73e4
--- /dev/null
+++ b/third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties
@@ -0,0 +1,11 @@
+joptsimple.BuiltinHelpFormatter.no.options.specified = No options specified
+joptsimple.BuiltinHelpFormatter.non.option.arguments.header = Non-option arguments:
+joptsimple.BuiltinHelpFormatter.option.header.with.required.indicator = Option (* = required)
+joptsimple.BuiltinHelpFormatter.option.divider.with.required.indicator = ---------------------
+joptsimple.BuiltinHelpFormatter.option.header = Option
+joptsimple.BuiltinHelpFormatter.option.divider = ------
+joptsimple.BuiltinHelpFormatter.description.header = Description
+joptsimple.BuiltinHelpFormatter.description.divider = -----------
+joptsimple.BuiltinHelpFormatter.default.value.header = default:
+joptsimple.AlternativeLongOptionSpec.description = Alternative form of long options
+joptsimple.AlternativeLongOptionSpec.arg.description = opt=value
diff --git a/third_party/java/jopt-simple/src/site/apt/acknowledgments.apt b/third_party/java/jopt-simple/src/site/apt/acknowledgments.apt
new file mode 100644
index 0000000000..ec35ed7e19
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/apt/acknowledgments.apt
@@ -0,0 +1,90 @@
+ ---------------
+ Acknowledgments
+ ---------------
+
+ Thanks to the following people who have offered constructive feedback, support, contribution,
+ and/or praise for JOpt Simple:
+
+ * Paul Armstrong
+
+ * Guillaume Aubert
+
+ * David Beckingsale
+
+ * Jochen Bedersdorfer
+
+ * Louis Bergelson
+
+ * Ryan Breidenbach
+
+ * Erik Broes
+
+ * Carlos Cadete
+
+ * Laurent Caillette
+
+ * Matthew Daniel
+
+ * Hans Dockter
+
+ * Kevin C. Dorff
+
+ * Adam Fisk
+
+ * Raymund F\u00FCl\u00F6p
+
+ * Dave Jarvis
+
+ * Paul King
+
+ * El Kodus
+
+ * Alexander Kriegisch
+
+ * Zachary Kurmas
+
+ * Henning Luebbers
+
+ * Derek Mahar
+
+ * Bruno Mascret
+
+ * Antoine Neveux
+
+ * Christian Ohr
+
+ * Michael Osipov
+
+ * Brian Oxley (binkley)
+
+ * Andrew Parker
+
+ * Julien Ponge
+
+ * Rob Reed
+
+ * Mark Reinhold
+
+ * Alex Renger
+
+ * Andrew Robinson
+
+ * Jonathan Shook
+
+ * Jason Smith
+
+ * Emils Solmanis
+
+ * Leo Uzcategui
+
+ * Alan van Dam
+
+ * Douglas Wegscheid
+
+ * Chris K Wensel
+
+ * Ashley Williams
+
+ * Daniel Yokomizo
+
+ []
diff --git a/third_party/java/jopt-simple/src/site/apt/changes.apt b/third_party/java/jopt-simple/src/site/apt/changes.apt
new file mode 100644
index 0000000000..2bc0d7d9c6
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/apt/changes.apt
@@ -0,0 +1,385 @@
+ ----------
+ Change Log
+ ----------
+
+Changes in version 5.0.3
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/96} gh-96}} so that
+ options that take an argument but don't change the argument type from
+ <<<String>>> still show a <<<String>>> type indicator in the default
+ option help.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/104} gh-104}} so
+ that <<<EnumConverter>>> performs case-insensitive matching against arguments
+ of options. Thanks to Martin Paljak for this.
+
+Changes in version 5.0.2
+
+ * Made some package-private abstract classes become public classes
+ with package-private constructors. This makes it possible to call some methods
+ from Kotlin that were previously inaccessible. Thanks to Mirko Friedenhagen
+ for this.
+
+Changes in version 5.0.1
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/92} gh-92}} so that
+ in the event that <<<printHelpOn()>>> is called more than once, the output
+ is not duplicated.
+
+Changes in version 5.0
+
+ * Abandoning JDKs prior to 7. All source is Java 7-compatible, and bytecode is compiled to 1.7
+ version.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/51} gh-51}} by adding
+ <<<OptionSpecBuilder.availableIf()>>> and <<<OptionSpecBuilder.availableUnless()>>>. Thanks
+ to Christian Ohr for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/70} gh-70}} by adding
+ <<<EnumConverter>>> and <<<PathConverter>>>. Thanks to Christian Ohr for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/88} gh-88}} by adding
+ an <<<OptionParser>>> constructor to allow suppression of option abbreviations.
+ Thanks to Louis Bergelson for this.
+
+Changes in version 4.10
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/85} gh-85}}
+ by correcting the description column width consumption of the built-in
+ help formatter.
+
+Changes in version 4.9
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/79} gh-79}}
+ by correcting the behavior of <<<OptionException.multipleOptionString>>>
+ when handling options with synonyms.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/72} gh-72}}
+ by externalizing some of the literal strings in <<<BuiltinHelpFormatter>>>
+ into resource bundles.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/76} gh-76}}
+ by modifying the behavior of <<<OptionalArgumentOptionSpec>>> so that if
+ the argument following the option does not "look like" an option but can
+ be converted to the option argument's type, treat the argument as the argument
+ of the option.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/68} gh-68}}
+ by modifying <<<BuiltinHelpFormatter>>> to be more extensible and documenting
+ the behavior of the newly accessible methods.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/73} gh-73}}
+ by correcting the behavior of <<<OptionSet.specs()>>> to remove all instances
+ of the non-option argument spec.
+
+Changes in version 4.8
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/65} gh-65}}
+ by modifying the build file to create a JAR with OSGi metadata.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/63} gh-63}}
+ by externalizing exception messages into resource bundles.
+ Currently, we ship only with messages for locale "en_US".
+ Translations for other locales are more than welcome.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/58} gh-58}} by
+ rewriting exception messaging to clarify synonymous options.
+ Synonyms are be separated by slashes (/); lists of distinct options will
+ be separated by commas (,) in square brackets ([]).
+
+Changes in version 4.7
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/57} gh-57}} by admitting
+ the underscore as a legal option character.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/53} gh-53}} by correcting
+ <<<OptionSet.hasOptions()>>> to answer correctly for no switches.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/56} gh-56}} by correcting
+ the default help formatting not to use a <<<Set>>> for rows of output,
+ but <<<List>>>.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/59} gh-59}} by relaxing
+ the return type of <<<ValueConverter.valueType()>>>.
+
+Changes in version 4.6
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/31} gh-31}} by offering
+ <<<OptionSpecBuilder.requiredUnless()>>>. Thanks to Christian Ohr for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/38} gh-38}} by offering
+ <<<OptionParser.recognizedOptions()>>>. Thanks to Antoine Neveux for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/35} gh-35}} by offering
+ <<<OptionSet.asMap()>>>. Thanks to Brian Oxley for this.
+
+Changes in version 4.5
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/17} gh-17}} by offering
+ <<<OptionParser.nonOptions()>>> and <<<NonOptionArgumentSpec>>>.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/pull/27} gh-27}} by offering
+ <<<OptionParser.allowsUnrecognizedOptions()>>>. Thanks to Erik Broes for this.
+
+Changes in version 4.4
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/16} gh-16}} by offering
+ <<<BuiltinHelpFormatter>>> that allows configuration of overall row width and
+ column separator width. Thanks to Ryan Breidenbach for contributing code to this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/12} gh-12}} by offering
+ <<<OptionSpecBuilder.requiredIf()>>>.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/22} gh-22}}. Thanks to
+ El Kodus for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/19} gh-19}}. Thanks to
+ El Kodus for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/14} gh-14}} by offering
+ <<<AbstractOptionSpec.forHelp()>>>.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/13} gh-13}} by offering
+ <<<ArgumentAcceptingOptionSpec.withValuesSeparatedBy(String)>>>.
+
+ * Added <<<InetAddressValueConverter>>>. Thanks to Raymund F\u00FCl\u00F6p for this.
+
+Changes in version 4.3
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/9} gh-9}} by offering
+ <<<OptionSet.specs()>>>, which gives a list of the specs corresponding to the
+ options detected on a parse, in the order in which the options occurred on the
+ command line.
+
+Changes in version 4.2
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/8} gh-8}} by offering
+ <<<ArgumentAcceptingOptionSpec.defaultsTo(V[])>>> in addition to
+ <<<ArgumentAcceptingOptionSpec.defaultsTo(V, V...)>>>.
+
+ * Removing some internal unused classes and methods.
+
+Changes in version 4.1
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/7} gh-7}} by allowing short option
+ clusters to contain options which can accept arguments. When such an option is encountered,
+ the remaining characters in the cluster are treated as the argument to the option. Thanks to
+ Alan van Dam for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/6} gh-6}} with general improvements
+ to the project's site. Thanks to Michael Osipov for this.
+
+Changes in version 4.0
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/4} gh-4}} by adding method
+ <<<OptionParser.formatHelpWith(HelpFormatter)>>> to allow programmers to influence what
+ help is printed with <<<OptionParser.printHelpOn()>>>. A <<<HelpFormatter>>> is handed a
+ map, keyed by option text, whose values are <<<OptionDescriptor>>>s that describe the
+ options the parser has been configured with.
+
+ * Added method <<<OptionSet.hasOptions()>>>. Thanks to Michael Osipov for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/pull/3} gh-3}} by using
+ <<<SimpleDateFormat.toPattern()>>> rather than <<<SimpleDateFormat.toLocalizedPattern()>>>
+ in <<<DateConverter>>>. Thanks to Michael Osipov for this.
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/issues/5} gh-5}} by allowing primitive
+ <<<Class>>> objects whose wrapper types are considered "value types" for purposes of
+ <<<ArgumentAcceptingOptionSpec.ofType()>>> in place of the wrapper classes. Thanks to
+ Daniel Yokomizo for suggesting this.
+
+Changes in version 3.3
+
+ * Resolved {{{https://github.com/pholser/jopt-simple/pull/1} gh-1}} by adding method
+ <<<required()>>> to class <<<ArgumentAcceptingOptionSpec>>>, to allow callers to indicate
+ that a given option must be present on the command line. Thanks to Emils Solmanis for
+ adding this.
+
+Changes in version 3.2
+
+ * Added method <<<defaultsTo()>>> to class <<<ArgumentAcceptingOptionSpec>>>, to allow
+ callers to specify default values for arguments of options. These influence the return
+ values of <<<OptionSpec.value(s)()>>> and <<<OptionSet.value(s)Of()>>>. Default values
+ also show up in the help screen entries for their options. This serves to resolve
+ {{{https://sourceforge.net/tracker/?func=detail&aid=2484524&group_id=125731&atid=703508} feature
+ request 2484524}}.
+
+ * Fixed a problem whereby the empty string, a string consisting solely of whitespace, or a
+ string with embedded whitespace weren't being properly recognized as arguments of options
+ when they should have.
+
+ * Resolved {{{https://sourceforge.net/tracker/?func=detail&aid=2793762&group_id=125731&atid=703508} feature
+ request 2793762}}, having to do with improving the behavior of embedded newlines in option
+ descriptions in help screens.
+
+Changes in version 3.1
+
+ * Added method <<<withValuesConvertedBy()>>> to class <<<ArgumentAcceptingOptionSpec>>>,
+ to allow callers to specify converters or validators that transform arguments of
+ options into instances of specific Java types. This is useful for types which do not
+ meet the requirements of <<<ofType()>>>.
+
+ * Added classes <<<DateConverter>>> and <<<RegexMatcher>>> as examples of useful
+ argument converters.
+
+Changes in version 3.0.1
+
+ * Dependency on {{{http://ant.apache.org} Ant}} more appropriately test-scoped in the
+ {{{http://maven.apache.org} Maven}} POM. That way, if you use JOpt Simple with Maven,
+ you don't download Ant unnecessarily.
+
+Changes in version 3.0
+
+ * Version 3.0 supports Java 5 and greater only. If you need to use JOpt Simple in a
+ pre-Java-5 environment, use the latest 2.x release.
+
+ * Where appropriate, existing API calls have been updated to use Java generics.
+
+ * Extracted and surfaced interface <<<OptionSpec>>>. <<<OptionSpec>>>s returned by
+ the fluent interface methods can be used to retrieve arguments of the options they
+ represent in a type-safe manner.
+
+ * Removed all previously deprecated methods.
+
+ * Added methods to <<<OptionSet>>> to allow detection of options and retrieval of
+ option arguments using instances of <<<OptionSpec>>>.
+
+ * Converted tests to JUnit 4.
+
+ * Switched to MIT License.
+
+ * Relaxing some <<<List>>> parameter types and return types of methods to
+ <<<Collection>>>.
+
+ * <<<OptionArgumentConversionException>>> no longer drops the original cause on the
+ floor; hence <<<OptionException>>> can now be created with a cause.
+
+ * {{{http://maven.apache.org} Maven}}-ized the project web site.
+
+ * Overhauled the examples page.
+
+Changes in version 2.4.1
+
+ * Fixed {{{https://sourceforge.net/tracker/index.php?func=detail&aid=2018262&group_id=125731&atid=703505} bug 2018262}}.
+
+Changes in version 2.4
+
+ * Added the <<<acceptsAll()>>> method to class <<<OptionParser>>>. Options passed to
+ a given invocation of this method are treated as synonymous, so that each gives the
+ same answer when given as the argument to the methods <<<has()>>>, <<<valuesOf()>>>,
+ etc. on <<<OptionSet>>>.
+
+ * Surfaced the class <<<KeyValuePair>>>. This class can be very handy as a value
+ type for arguments whose values take on the form <<<key=value>>>, such as the <<<-D>>>
+ arguments to JVMs.
+
+ * Fixed {{{https://sourceforge.net/tracker/index.php?func=detail&aid=1932577&group_id=125731&atid=703505} bug 1932577}}.
+
+ * Added method <<<withValuesSeparatedBy()>>> to class <<<ArgumentAcceptingOptionSpec>>>,
+ to allow callers to specify multiple values for an option as a single argument with
+ values separated by a given character.
+
+ * Method <<<ofType()>>> on class <<<ArgumentAcceptingOptionSpec>>> now returns self
+ rather than <<<void>>>.
+
+ * Deprecated another "get for get's sake": <<<OptionParser.setPosixlyCorrect()>>>
+ It is replaced with a less Java-beany-looking method.
+
+ * Cleaned up the help screens produced by <<<OptionParser.printHelpOn()>>> so they are
+ rendered as two 40-character columns, with long space-broken values split across lines
+ as needed.
+
+ * Fixed {{{https://sourceforge.net/tracker/index.php?func=detail&aid=1956418&group_id=125731&atid=703505} bug 1956418}}.
+
+Changes in version 2.3.6
+
+ * No changes to code; just getting {{{http://maven.apache.org} Maven}} to do releases
+ with its plugins.
+
+Changes in version 2.3.3
+
+ * Deprecated method <<<OptionSet.wasDetected()>>> in favor of <<<OptionSet.has()>>> --
+ the new name seems to read better.
+
+ * <<<OptionException>>>s now override <<<getMessage()>>> sensibly, so that if a caller
+ wants to handle the exception by catching it and displaying a message from the
+ exception, she can do so and get satisfactory results.
+
+ * {{{http://maven.apache.org} Maven}}-ized project's build.
+
+ * Minor internal changes.
+
+Changes in version 2.3.2
+
+ * Minor internal changes.
+
+Changes in version 2.3.1
+
+ * Fixed a bug with POSIX-ly correct parsers. It was previously thought that POSIX-ly
+ correct parsers should signal end of options when they detect an argument that does
+ not lexically look like an option and could not be an argument of a previous option,
+ required or optional. Such parsers now signal end of options when they detect an
+ argument that does not lexically look like an option, and is not an argument of a
+ previous option with a required argument. If you want such an argument to be treated
+ as the argument of a preceding option whose argument is optional, you can still get
+ this behavior by appending the argument to the option, either with abutting syntax
+ (<<<-d/tmp>>>) or key-value syntax (<<<-d=/tmp>>>).
+
+Changes in version 2.3
+
+ * No feature changes in this release; but this release can now be used with JDK 1.3.
+ Previous releases could be used only with JDK 1.4 or newer.
+
+Changes in version 2.2
+
+ * Removed all previously deprecated methods.
+
+ * Re-clarified the contract of the one-arg <<<String>>> constructor of
+ <<<OptionParser>>>: the constructor now raises <<<NullPointerException>>> if its
+ argument is <<<null>>>. This is the convention for Java library methods which receive
+ illegal <<<null>>> parameters.
+
+Changes in version 2.1
+
+ * Introduced a facility for <<<OptionParser>>>s to print a help screen, which
+ describes the options they accept.
+
+ * Added the ability to provide descriptions of options and their arguments when
+ configuring an <<<OptionParser>>>. These descriptions are printed in the
+ aforementioned help screens.
+
+ * Clarified the contract of the one-arg <<<String>>> constructor of <<<OptionParser>>>:
+ the constructor raises <<<IllegalArgumentException>>> if its argument is <<<null>>>.
+
+ * Deprecated <<<OptionParser.noArg()>>>, <<<OptionParser.requiredArg()>>>, and
+ <<<OptionParser.optionalArg()>>>.
+
+ * Deprecated some "gets for gets' sake": <<<OptionException.getOption()>>>,
+ <<<OptionSet.getNonOptionArguments()>>>. They are replaced with less
+ Java-beany-looking methods.
+
+Changes in version 2.0
+
+ * Introduced a "fluent interface" API for specifying options for an <<<OptionParser>>>
+ to recognize. The old methods for option specification still work--you need not
+ convert to the new methods.
+
+ * Added the ability to specify that option arguments should be converted to specific
+ types. You can do this either with the old option specification methods or with the
+ new fluent interface API.
+
+ * Deprecated <<<OptionParser.requiresArg()>>> in favor of
+ <<<OptionParser.requiredArg()>>> -- the new name seems to read better.
+
+Version 1.0
+
+ * First major release.
+
+ * Includes concrete classes <<<OptionParser>>> and <<<OptionSet>>>.
+
+ * Supports POSIX <<<getopt()>>> and GNU <<<getopt_long()>>> command line syntax.
+
+ * No type conversion on option arguments, they are all treated as <<<String>>>s.
+
+ * Methods <<<noArg()>>>, <<<requiredArg()>>>, and <<<optionalArg()>>> tell an
+ <<<OptionParser>>> what options to recognize.
diff --git a/third_party/java/jopt-simple/src/site/apt/developer.apt b/third_party/java/jopt-simple/src/site/apt/developer.apt
new file mode 100644
index 0000000000..59d5d82d5a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/apt/developer.apt
@@ -0,0 +1,48 @@
+ --------------
+ Developer Docs
+ --------------
+
+Help for developing JOpt Simple
+
+ This page has notes and hints for contributing to JOpt Simple, mostly around getting started and style questions.
+
+* Code Style
+
+ Style is important. Why? Chiefly to aid merges. Reformatting code makes merging more difficult. When needing to reformat unchanged code, please do so on a separate commit with a clear commit message indicating a non-code change.
+
+ In general use the Eclipse formatter (there is a plugin for IntelliJ IDEA). See <<<jopt-simple-eclipse-formatting.xml>>> and <<<jopt-simple.importorder>>> in the project root.
+
+ The ultimate arbiter of good style is Paul Holser.
+
+** Braces
+
+ * Yes:
+
++----+
+for (int i = 0; i < 10; ++i) {
+ if (i < 5)
+ println(i);
+}
++----+
+
+ * No:
+
++----+
+for (int i = 0; i < 10; ++i)
+ if (i < 5)
+ println(i);
++----+
+
+* {{Building}}
+
+ There are no integration tests. Your typical command line is:
+
++----+
+$ mvn clean test
++----+
+
+ Before pushing commits, please check that the site fully builds:
+
++----+
+$ mvn clean post-site
++----+
diff --git a/third_party/java/jopt-simple/src/site/apt/download.apt.vm b/third_party/java/jopt-simple/src/site/apt/download.apt.vm
new file mode 100644
index 0000000000..dde9015f5e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/apt/download.apt.vm
@@ -0,0 +1,26 @@
+ --------
+ Download
+ --------
+
+ Releases of JOpt Simple are synced to the central Maven repository. Declare a
+ dependency element in your POM like so:
+
++---------------------------------------------
+...
+<dependencies>
+ ...
+ <dependency>
+ <groupId>net.sf.jopt-simple</groupId>
+ <artifactId>jopt-simple</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ ...
+</dependencies>
+...
++---------------------------------------------
+
+ If you're not using Maven, you can still download the newer releases from the Maven
+ repository manually, {{{http://repo1.maven.org/maven2/net/sf/jopt-simple/jopt-simple} here}}.
+
+ You can find older releases at
+ {{{http://sourceforge.net/project/showfiles.php?group_id=125731} SourceForge}}.
diff --git a/third_party/java/jopt-simple/src/site/apt/examples.apt b/third_party/java/jopt-simple/src/site/apt/examples.apt
new file mode 100644
index 0000000000..3b43dee995
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/apt/examples.apt
@@ -0,0 +1,462 @@
+ -----------------
+ Examples of Usage
+ -----------------
+
+Preamble
+
+ The simplicity in JOpt "Simple" arises from two guiding principles:
+
+ * Stick as often as possible to supporting conventional Unix option syntaxes.
+
+ * Keep the surface area of the published API as small and simple as possible.
+
+ []
+
+ To the first principle: You will not see support in JOpt Simple for option "groups",
+ alternative option prefixes (<<<+>>>, <<</>>>), enforced multiplicity of option
+ arguments, etc. JOpt Simple believes you can create a useful and understandable CLI
+ without all that stuff. If you feel as though you need any of those features, there
+ are lots of other choices out there. The author of JOpt Simple believes you'll want
+ to leverage its easy configuration, parsing, and option interrogation APIs instead of
+ using more feature-laden, but perhaps more confusing libraries.
+
+ To the second principle: JOpt Simple will make every attempt to keep the API free
+ of clutter. The API is well factored, making it intuitive to use, and the entire
+ library is well tested, making it more reliable and predictable. If you cannot look
+ at the Javadoc and quickly get a sense of what you need to do to use JOpt Simple,
+ then JOpt Simple has failed. So by all means, let the author know what needs
+ improved.
+
+ With that said, let's take a tour through JOpt Simple's features.
+
+Options
+
+ JOpt Simple supports short options and long options, using a syntax that attempts to
+ take from the best of POSIX <<<getopt()>>> and GNU <<<getopt_long()>>>.
+
+* Short Options
+
+ Short options begin with a single hyphen (<<<->>>) followed by a single letter or
+ digit, or question mark (<<<?>>>), or dot (<<<.>>>).
+
++----------------------------------------------------------------------------------------
+@SHORT_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ When you construct an <<<OptionParser>>> with a string of short option characters,
+ you configure that parser to recognize the options with those characters.
+
+** Arguments of Options
+
+ Short options can accept single arguments. The argument can be made required or
+ optional. When you construct an <<<OptionParser>>> with a string of short option
+ characters, append a single colon (<<<:>>>) to an option character to configure
+ that option to require an argument. Append two colons (<<<::>>>) to an option
+ character to configure that option to accept an optional argument. Append an
+ asterisk (<<<*>>>) to an option character, but before any "argument" indicators,
+ to configure that option as a "help" option.
+
+ The syntax of the option specification string given to the <<<OptionParser>>>
+ constructor should look familiar to you if you have used GNU's <<<getopt()>>>
+ before.
+
++----------------------------------------------------------------------------------------
+@SHORT_OPTIONS_WITH_ARGUMENTS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+*** Specifying Arguments for a Short Option on the Command Line
+
+ A short option's argument can occur:
+
+ * in the position on the command line after the option
+
+ * right up against the option
+
+ * right up against the option separated by an equals sign (<<<=>>>)
+
+ []
+
++----------------------------------------------------------------------------------------
+@SHORT_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+*** Multiple Arguments for a Single Option
+
+ To specify <n> arguments for a single option, specify the option <n> times on the
+ command line, once for each argument. JOpt Simple reports the arguments given to the
+ option in the order in which they were encountered on the command line.
+
++----------------------------------------------------------------------------------------
+@SHORT_OPTIONS_WITH_MULTIPLE_ARGUMENTS_FOR_SINGLE_OPTION_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Clustering Short Options
+
+ Short options can be <clustered> in a single argument.
+
++----------------------------------------------------------------------------------------
+@SHORT_OPTIONS_CLUSTERING_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ If one of the short options can accept an argument, the remaining characters are interpreted
+ as the argument for that option.
+
++----------------------------------------------------------------------------------------
+@SHORT_OPTIONS_CLUSTERING_WITH_ARGUMENT_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+* Long Options/Fluent Interface
+
+ Long options begin with two hyphens (<<<-->>>), followed by multiple letters,
+ digits, hyphens, question marks, or dots. A hyphen cannot be the first character of
+ a long option specification when configuring the parser.
+
+ Whereas short options can be configured using a constructor argument to
+ <<<OptionParser>>>, both long and short options can be configured using a "fluent
+ interface" API, that enables some very descriptive and powerful features.
+
++----------------------------------------------------------------------------------------
+@LONG_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Arguments of Options
+
+ Like short options, long options can accept single arguments. The argument can be
+ made required or optional. Use the methods <<<withRequiredArg()>>> and
+ <<<withOptionalArg()>>> on the return value of <<<OptionParser.accepts()>>> to signal
+ that an option takes a required or optional argument.
+
++----------------------------------------------------------------------------------------
+@LONG_OPTIONS_WITH_ARGUMENTS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Abbreviating Long Options
+
+ Notice in the example above that the command line uses abbreviations of command line
+ options. You can abbreviate options so long as the abbreviation is unambiguous.
+ Even though you can abbreviate the options on the command line, you cannot address
+ the <<<OptionSet>>> using those abbreviations. You can use a special constructor
+ for the <<<OptionParser>>> that turns off abbreviation matching.
+
+** Using Single Hyphen on Long Options
+
+ As demonstrated in the example above, you can use a single hyphen instead of a
+ double hyphen to specify a long option -- but be careful that doing so doesn't
+ introduce ambiguity.
+
+*** Specifying Arguments for a Long Option on the Command Line
+
+ A long option's argument can occur:
+
+ * in the position on the command line after the option
+
+ * right up against the option separated by an equals sign (<<<=>>>)
+
+ []
+
++----------------------------------------------------------------------------------------
+@LONG_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+*** Multiple Arguments for a Single Option
+
+ Specify multiple arguments for a long option in the same manner as for short options
+ (see above).
+
+** Alternative Form of Long Options
+
+ The option <<<-W>>> is reserved. If you tell the parser to recognize alternative
+ long options, then it will treat, for example, <<<-W foo=bar>>> as the long option
+ <<<foo>>> with argument bar, as though you had written <<<--foo=bar>>>.
+
+ You can specify <<<-W>>> as a valid short option, or use it as an abbreviation for a
+ long option, but recognizing alternative long options will always supersede this
+ behavior.
+
+ To recognize alternative long options, either construct an <<<OptionParser>>> with a
+ string of short option characters containing the sequence <<<W;>>> (a capital W
+ followed by a semicolon), or call the method
+ <<<OptionParser.recognizeAlternativeLongOptions()>>>.
+
++----------------------------------------------------------------------------------------
+@ALTERNATIVE_LONG_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+* Other Features
+
+** Converting Option Arguments to Other Types
+
+ Without action other than the <<<with*Arg()>>> methods, arguments of options are
+ returned as <<<String>>>s. For backwards compatibility,
+ <<<OptionSet.valueOf(String)>>> and <<<OptionSet.valuesOf(String)>>> return
+ <<<Object>>> and <<<List<?>>>>, respectively, so to get the values out as
+ <<<String>>>s, you will need to downcast the results of those methods.
+
+ You can tell JOpt Simple to convert the arguments of options to different Java types
+ via the <<<ofType()>>> method on the return value of <<<with*Arg()>>>. The
+ <<<Class>>> argument of <<<ofType()>>> must represent a Java class that has either:
+
+ * a <<<public static>>> method called <<<valueOf()>>> which accepts a single
+ <<<String>>> argument and whose return type is the type itself, or
+
+ * a <<<public>>> constructor which takes a single <<<String>>> argument.
+
+ []
+
+ If the class has both, the <<<valueOf()>>> method is used.
+
+ Note that <<<enum>>>s have a <<<valueOf()>>> method.
+
++----------------------------------------------------------------------------------------
+@OPTION_ARGUMENT_VALUE_TYPE_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ Another way to convert arguments of options is to specify a converter object via
+ <<<withValuesConvertedBy()>>>. This is useful when the desired type for the arguments
+ does not meet the requirements that <<<ofType()>>> sets forth. Such objects may not
+ perform any "conversion" at all, but rather can validate that arguments conform to
+ certain restrictions before passing through as-is.
+
+ You can also do this for the non-option arguments of your command line, if you desire
+ to treat them all as a single type.
+
++----------------------------------------------------------------------------------------
+@OPTION_ARGUMENT_CONVERTER_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Retrieving Arguments of Options in a Type-Safe Manner
+
+ In the previous examples, we have been discarding the return values of the methods
+ of JOpt Simple's fluent interface. If instead you retain them in variables of type
+ <<<OptionSpec>>>, you can use them to retrieve arguments of options in a type-safe
+ manner.
+
+ You can also do this for the non-option arguments of your command line, if you desire
+ to treat them all as a single type.
+
++----------------------------------------------------------------------------------------
+@TYPESAFE_OPTION_ARGUMENT_RETRIEVAL_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Exporting Options and Arguments to other Code
+
+ As an integration aid for other libraries, you can use <<<OptionSet.asMap()>>> to
+ obtain a mapping of <<<OptionSpec>>> to option values, for example to create a
+ properties map of options.
+
+ Here is sample code to create properties whose keys have a common prefix. The key is
+ choosen as the first non-short option:
+
++----------------------------------------------------------------------------------------
+@EXPORTING_OPTIONS_AND_ARGUMENTS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Default Values for Option Arguments
+
+ Often it is convenient to specify default values for the arguments of certain
+ command line options. To do this, call the <<<defaultsTo()>>> method.
+
++----------------------------------------------------------------------------------------
+@DEFAULT_VALUES_FOR_OPTION_ARGUMENTS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ You can see that <<<defaultsTo()>>> should relieve you of the burden of having to
+ check <<<has()>>> and/or <<<hasArgument()>>> on an <<<OptionSet>>> for a given option,
+ and has no bearing on the return values of those methods. Specifying a default value
+ for an option with a required argument does not mean that you can elide an argument for
+ the option on the command line.
+
+ The type of values <<<defaultsTo()>>> expects is dictated by the class given by a
+ previous call to <<<ofType()>>> or <<<withValuesConvertedBy()>>>; if no such call has
+ been made, the type is <<<String>>>.
+
+** "Required" Options
+
+ You can indicate that a given option must be present on the command line via the
+ <<<required()>>> method. Only options that accept arguments can be made "required".
+
+ An option designated as a "help" option via <<<forHelp()>>>, when present on the
+ command line, causes missing "required" options not to reject the command line.
+
++----------------------------------------------------------------------------------------
+@REQUIRED_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** "Required" Dependent Options
+
+ You can indicate that a given option must be present on the command line if some
+ other option is present on the command line via the <<<requiredIf()>>> method.
+ Any option can be made "required if".
+
+ An option designated as a "help" option via <<<forHelp()>>>, when present on the
+ command line, causes missing "required if" options not to reject the command line.
+
++----------------------------------------------------------------------------------------
+@REQUIRED_IF_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ You can also indicate that a given option must be present on the command line if some
+ other option is NOT present on the command line via the <<<requiredUnless()>>> method.
+ Any option can be made "required unless", but, to avoid potential conflicts, it should
+ not be "required if" at the same time.
+
++----------------------------------------------------------------------------------------
+@REQUIRED_UNLESS_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** "Available" Dependent Options
+
+ Similarly to <<<requiredIf()>>> and <<<requiredUnless()>>>, you can indicate that a
+ given option can be present on the command line only if/unless some other option is
+ present on the command line, via the <<<availableIf()>>> and <<<availableUnless()>>>
+ methods.
+
+
+** Synonyms of Options
+
+ Sometimes it is useful to allow many different options to share the same meaning in
+ the program that uses them. To specify that options are to be treated as synonymous,
+ use the <<<acceptsAll()>>> method of <<<OptionParser>>>.
+
++----------------------------------------------------------------------------------------
+@OPTION_SYNONYM_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Concise Specification of Multiple Arguments for an Option
+
+ Another way to specify multiple arguments for an option is to tell the parser to
+ treat a single argument containing multiple delimited values as multiple arguments
+ for the option using the <<<withValuesSeparatedBy()>>> method.
+
++----------------------------------------------------------------------------------------
+@MULTIPLE_DELIMITED_ARGUMENTS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Signalling End of Options
+
+ An argument consisting only of two hyphens (<<<-->>>) signals that the remaining
+ arguments are to be treated as non-options.
+
+ An argument consisting only of a single hyphen is considered a non-option argument
+ (though it can be an argument of an option). Many Unix programs treat single hyphens
+ as stand-ins for the standard input or standard output stream.
+
+*** Non-Option Arguments
+
+ Any arguments which are not options or arguments of options can be retrieved via
+ method <<<nonOptionArguments()>>> on <<<OptionSet>>>. If the double hyphen is an
+ argument, it is ignored and is not a non-option argument.
+
++----------------------------------------------------------------------------------------
+@SIGNALLING_END_OF_OPTIONS_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** "POSIX-ly Correct"-ness
+
+ By default, as with GNU <<<getopt()>>>, JOpt Simple allows intermixing of options and
+ non-options. If, however, the parser has been created to be "POSIX-ly correct", then
+ the first argument that does not look lexically like an option, and is not a required
+ argument of a preceding option, signals the end of options. You can still bind
+ optional arguments to their options using the abutting (for short options) or
+ <<<=>>> syntax.
+
+ Unlike GNU <<<getopt()>>>, JOptSimple does not honor the environment variable
+ <<<POSIXLY_CORRECT>>>. "POSIX-ly correct" parsers are configured by either:
+
+ * using the method <<<OptionParser.posixlyCorrect()>>>
+
+ * using the <<<OptionParser>>> constructor with an argument whose first character is
+ a plus sign (<<<+>>>)
+
+ []
+
++----------------------------------------------------------------------------------------
+@POSIXLY_CORRECT_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+** Special Optional Argument Handling
+
+ If the parser detects an option whose argument is optional, and the next argument
+ "looks like" an option, that argument is not treated as the argument to the option,
+ but as a potentially valid option. If, on the other hand, the optional argument is
+ typed as a derivative of <<<Number>>>, then that argument is treated as the negative
+ number argument of the option, even if the parser recognizes the corresponding numeric
+ option.
+
++----------------------------------------------------------------------------------------
+@SPECIAL_OPTIONAL_ARGUMENT_HANDLING_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+Generating Command Line Help
+
+ When you call method <<<OptionParser.printHelpOn()>>>, JOpt Simple will write a
+ help screen (80-column width) describing all the options it is configured with,
+ along with types of option arguments, whether the option is required (in angle
+ brackets) or optional (in square brackets), etc. To give an option a description,
+ use <<<OptionParser.accepts*()>>> with a description argument. To give an option
+ argument a description, use <<<describedAs()>>> on the return value of
+ <<<with*Arg()>>>.
+
++----------------------------------------------------------------------------------------
+@HELP_SCREEN_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ Here is what the help screen looks like for the example above:
+
++----------------------------------------------------------------------------------------
+@HELP_SCREEN_EXAMPLE_HELP@
++----------------------------------------------------------------------------------------
+
+ If you want to create your own help screen, give method
+ <<<OptionParser.formatHelpWith()>>> a <<<HelpFormatter>>> that builds the help screen
+ as a String. When you call <<<OptionParser.printHelpOn()>>>, JOpt Simple will use
+ your <<<HelpFormatter>>> to produce the help and write it to the given stream.
+
+ For example, this program:
+
++----------------------------------------------------------------------------------------
+@HELP_FORMATTER_EXAMPLE@
++----------------------------------------------------------------------------------------
+
+ yields the following output:
+
++----------------------------------------------------------------------------------------
+@HELP_FORMATTER_EXAMPLE_OUTPUT@
++----------------------------------------------------------------------------------------
+
+Handling Exceptions
+
+ JOpt Simple's classes raise some derivative of <<<OptionException>>> if they encounter
+ problems during parsing. These exceptions are unchecked, so you don't have to do
+ anything with such an exception if you don't want to. The rationale behind this
+ decision is that you will most likely be invoking JOpt Simple's functionality from a
+ <<<main()>>> method or very near to it, where a failure such as unrecognized arguments
+ can just stop down the JVM and yield a stack trace without much user or programmer
+ inconvenience. So, without any exception handling at all, a user would see something
+ like this:
+
++----------------------------------------------------------------------------------------
+@EXAMPLE_STACK_TRACE@
++----------------------------------------------------------------------------------------
+
+ If you want to handle the exception yourself, you can catch <<<OptionException>>> in
+ your code, and do whatever you please with the contents of the exception, perhaps
+ using the help generation facility.
+
+* Suppressing <<<UnrecognizedOptionException>>>
+
+ Sometimes you want to ignore unrecognized options on the command line.
+
+ For example, you might be interested in handling only a part of the arguments given.
+ Or you might want to pass on options to another program and not bother the user with
+ providing two hyphens (<<<-->>>) to indicate the end of known options. Or maybe
+ you want to provide future forwards/backwards compatibility when you foresee passing
+ in new options to old code (or old code invoking new code with "old" arguments).
+
+ You can achieve this by using the method <<<OptionParser.allowsUnrecognizedOptions()>>>.
+ When you call this method, then any unrecognized options handed to <<<parse()>>> are
+ treated as non-option arguments, rather than causing an exception to be raised.
+
++----------------------------------------------------------------------------------------
+@UNRECOGNIZED_OPTIONS_ALLOWED_EXAMPLE@
++----------------------------------------------------------------------------------------
diff --git a/third_party/java/jopt-simple/src/site/apt/index.apt b/third_party/java/jopt-simple/src/site/apt/index.apt
new file mode 100644
index 0000000000..88c2af858d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/apt/index.apt
@@ -0,0 +1,71 @@
+ -----------
+ JOpt Simple
+ -----------
+
+ JOpt Simple is a Java library for parsing command line options, such as those you
+ might pass to an invocation of <<<javac>>>.
+
+ In the interest of striving for simplicity, as closely as possible JOpt Simple
+ attempts to honor the command line option syntaxes of
+ {{{http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html} POSIX <<<getopt()>>>}}
+ and
+ GNU {{{http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html} <<<getopt_long()>>>}}.
+ It also aims to make option parser configuration and retrieval of options and their
+ arguments simple and expressive, without being overly clever.
+
+ Here are some libraries that perform the same duties as JOpt Simple:
+
+ * {{{http://jargs.sourceforge.net} JArgs}}
+
+ * {{{http://jakarta.apache.org/commons/cli/} Jakarta Commons CLI}}
+
+ * {{{http://te-code.sourceforge.net/} TE-Code}} has a command line parsing library.
+
+ * {{{http://www.cs.ubc.ca/spider/lloyd/java/argparser.html} argparser}}
+
+ * {{{http://www.urbanophile.com/arenn/hacking/download.html} Java port of GNU getopt}}
+
+ * {{{https://args4j.dev.java.net/} Args4J}}
+
+ * {{{http://www.martiansoftware.com/jsap/} JSAP}}
+
+ * {{{http://clajr.sourceforge.net} CLAJR}}
+
+ * {{{http://ostermiller.org/utils/CmdLn.html} CmdLn}}
+
+ * {{{http://jewelcli.sourceforge.net} JewelCli}}
+
+ * {{{http://jcommando.sourceforge.net} JCommando}}
+
+ * {{{http://code.google.com/p/parse-cmd/} parse-cmd}}
+
+ * {{{http://jcommander.org} JCommander}}
+
+ * {{{http://types.cs.washington.edu/plume-lib/api/plume/Options.html} plume-lib Options}}
+
+ []
+
+ I hope you'll agree that JOpt Simple tops them all in ease of use and cleanliness of
+ code (although I admire JewelCli quite a bit).
+
+ I'd love to hear your constructive {{{mailto:pholser@alumni.rice.edu} feedback}},
+ especially suggestions for improvements to the library or the site! If your project
+ is using JOpt Simple, do let me know.
+
+Projects Using JOpt Simple
+
+ Here are some we know of or have known of:
+
+ * {{{http://openjdk.java.net/} OpenJDK}}.
+ From {{{http://weblogs.java.net/blog/mreinhold/} Mark Reinhold}}: "I thought you might
+ be interested to know that we're using your jopt-simple library in the open-source
+ Java Development Kit. Thanks for writing such a nice little library! It's far
+ cleaner than any of the other alternatives out there."
+
+ * {{{http://www.gradle.org/} Gradle}}
+
+ * {{{http://natbraille.free.fr} NATBraille}}
+
+ * {{{https://minecraft.net} Minecraft}}
+
+ []
diff --git a/third_party/java/jopt-simple/src/site/resources/css/prettify.css b/third_party/java/jopt-simple/src/site/resources/css/prettify.css
new file mode 100644
index 0000000000..f8c7db2a96
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/resources/css/prettify.css
@@ -0,0 +1,49 @@
+/* Pretty printing styles. Used with prettify.js. */
+
+.str { color: #080; }
+.kwd { color: #008; }
+.com { color: #800; }
+.typ { color: #606; }
+.lit { color: #066; }
+.pun { color: #660; }
+.pln { color: #000; }
+.tag { color: #008; }
+.atn { color: #606; }
+.atv { color: #080; }
+.dec { color: #606; }
+
+pre.prettyprint {
+ padding: 2px;
+ border: 1px solid #888;
+}
+
+@media print {
+ .str { color: #060; }
+
+ .kwd {
+ color: #006;
+ font-weight: bold;
+ }
+
+ .com {
+ color: #600;
+ font-style: italic;
+ }
+
+ .typ {
+ color: #404;
+ font-weight: bold;
+ }
+
+ .lit { color: #044; }
+ .pun { color: #440; }
+ .pln { color: #000; }
+
+ .tag {
+ color: #006;
+ font-weight: bold;
+ }
+
+ .atn { color: #404; }
+ .atv { color: #060; }
+}
diff --git a/third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.png b/third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.png
new file mode 100644
index 0000000000..4a3f707d7a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.png
Binary files differ
diff --git a/third_party/java/jopt-simple/src/site/resources/scripts/prettify.js b/third_party/java/jopt-simple/src/site/resources/scripts/prettify.js
new file mode 100644
index 0000000000..de1e07ffd3
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/resources/scripts/prettify.js
@@ -0,0 +1,1602 @@
+// Copyright (C) 2006 Google Inc.
+//
+// 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.
+
+
+/**
+ * @fileoverview
+ * some functions for browser-side pretty printing of code contained in html.
+ *
+ * The lexer should work on a number of languages including C and friends,
+ * Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles.
+ * It works passably on Ruby, PHP and Awk and a decent subset of Perl, but,
+ * because of commenting conventions, doesn't work on Smalltalk, Lisp-like, or
+ * CAML-like languages.
+ *
+ * If there's a language not mentioned here, then I don't know it, and don't
+ * know whether it works. If it has a C-like, Bash-like, or XML-like syntax
+ * then it should work passably.
+ *
+ * Usage:
+ * 1) include this source file in an html page via
+ * <script type="text/javascript" src="/path/to/prettify.js"></script>
+ * 2) define style rules. See the example page for examples.
+ * 3) mark the <pre> and <code> tags in your source with class=prettyprint.
+ * You can also use the (html deprecated) <xmp> tag, but the pretty printer
+ * needs to do more substantial DOM manipulations to support that, so some
+ * css styles may not be preserved.
+ * That's it. I wanted to keep the API as simple as possible, so there's no
+ * need to specify which language the code is in.
+ *
+ * Change log:
+ * cbeust, 2006/08/22
+ * Java annotations (start with "@") are now captured as literals ("lit")
+ */
+
+var PR_keywords = {};
+/** initialize the keyword list for our target languages. */
+(function () {
+ var CPP_KEYWORDS = "abstract bool break case catch char class const " +
+ "const_cast continue default delete deprecated dllexport dllimport do " +
+ "double dynamic_cast else enum explicit extern false float for friend " +
+ "goto if inline int long mutable naked namespace new noinline noreturn " +
+ "nothrow novtable operator private property protected public register " +
+ "reinterpret_cast return selectany short signed sizeof static " +
+ "static_cast struct switch template this thread throw true try typedef " +
+ "typeid typename union unsigned using declaration, directive uuid " +
+ "virtual void volatile while typeof";
+ var CSHARP_KEYWORDS = "as base by byte checked decimal delegate descending " +
+ "event finally fixed foreach from group implicit in interface internal " +
+ "into is lock null object out override orderby params readonly ref sbyte " +
+ "sealed stackalloc string select uint ulong unchecked unsafe ushort var";
+ var JAVA_KEYWORDS = "package synchronized boolean implements import throws " +
+ "instanceof transient extends final strictfp native super";
+ var JSCRIPT_KEYWORDS = "debugger export function with NaN Infinity";
+ var PERL_KEYWORDS = "require sub unless until use elsif BEGIN END";
+ var PYTHON_KEYWORDS = "and assert def del elif except exec global lambda " +
+ "not or pass print raise yield False True None";
+ var RUBY_KEYWORDS = "then end begin rescue ensure module when undef next " +
+ "redo retry alias defined";
+ var SH_KEYWORDS = "done fi";
+
+ var KEYWORDS = [CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS,
+ JSCRIPT_KEYWORDS, PERL_KEYWORDS, PYTHON_KEYWORDS,
+ RUBY_KEYWORDS, SH_KEYWORDS];
+ for ( var k = 0; k < KEYWORDS.length; k++ ) {
+ var kw = KEYWORDS[k].split(' ');
+ for ( var i = 0; i < kw.length; i++ ) {
+ if ( kw[i] ) {
+ PR_keywords[kw[i]] = true;
+ }
+ }
+ }
+}).call(this);
+
+// token style names. correspond to css classes
+/** token style for a string literal */
+var PR_STRING = 'str';
+/** token style for a keyword */
+var PR_KEYWORD = 'kwd';
+/** token style for a comment */
+var PR_COMMENT = 'com';
+/** token style for a type */
+var PR_TYPE = 'typ';
+/** token style for a literal value. e.g. 1, null, true. */
+var PR_LITERAL = 'lit';
+/** token style for a punctuation string. */
+var PR_PUNCTUATION = 'pun';
+/** token style for a punctuation string. */
+var PR_PLAIN = 'pln';
+
+/** token style for an sgml tag. */
+var PR_TAG = 'tag';
+/** token style for a markup declaration such as a DOCTYPE. */
+var PR_DECLARATION = 'dec';
+/** token style for embedded source. */
+var PR_SOURCE = 'src';
+/** token style for an sgml attribute name. */
+var PR_ATTRIB_NAME = 'atn';
+/** token style for an sgml attribute value. */
+var PR_ATTRIB_VALUE = 'atv';
+
+/** the number of characters between tab columns */
+var PR_TAB_WIDTH = 8;
+
+/** the position of the end of a token during. A division of a string into
+ * n tokens can be represented as a series n - 1 token ends, as long as
+ * runs of whitespace warrant their own token.
+ * @private
+ */
+function PR_TokenEnd( end, style ) {
+ if ( undefined === style ) {
+ throw new Error('BAD');
+ }
+ if ( 'number' != typeof(end) ) {
+ throw new Error('BAD');
+ }
+ this.end = end;
+ this.style = style;
+}
+PR_TokenEnd.prototype.toString = function () {
+ return '[PR_TokenEnd ' + this.end +
+ (this.style ? ':' + this.style : '') + ']';
+};
+
+/** a chunk of text with a style. These are used to represent both the output
+ * from the lexing functions as well as intermediate results.
+ * @constructor
+ * @param token the token text
+ * @param style one of the token styles defined in designdoc-template, or null
+ * for a styleless token, such as an embedded html tag.
+ * @private
+ */
+function PR_Token( token, style ) {
+ if ( undefined === style ) {
+ throw new Error('BAD');
+ }
+ this.token = token;
+ this.style = style;
+}
+
+PR_Token.prototype.toString = function () {
+ return '[PR_Token ' + this.token + (this.style ? ':' + this.style : '') + ']';
+};
+
+/** a helper class that decodes common html entities used to escape special
+ * characters in source code.
+ * @constructor
+ * @private
+ */
+function PR_DecodeHelper() {
+ this.next = 0;
+ this.ch = '\0';
+}
+
+var PR_NAMED_ENTITIES = {
+ 'lt': '<',
+ 'gt': '>',
+ 'quot': '"',
+ 'apos': "'",
+ 'amp': '&' // reencoding requires that & always be decoded properly
+};
+
+PR_DecodeHelper.prototype.decode = function ( s, i ) {
+ var next = i + 1;
+ var ch = s.charAt(i);
+ if ( '&' === ch ) {
+ var semi = s.indexOf(';', next);
+ if ( semi >= 0 && semi < next + 4 ) {
+ var entityName = s.substring(next, semi);
+ var decoded = null;
+ if ( entityName.charAt(0) === '#' ) { // check for numeric entity
+ var ch1 = entityName.charAt(1);
+ var charCode;
+ if ( ch1 === 'x' || ch1 === 'X' ) { // like &#xA0;
+ charCode = parseInt(entityName.substring(2), 16);
+ }
+ else { // like &#160;
+ charCode = parseInt(entityName.substring(1), 10);
+ }
+ if ( !isNaN(charCode) ) {
+ decoded = String.fromCharCode(charCode);
+ }
+ }
+ if ( !decoded ) {
+ decoded = PR_NAMED_ENTITIES[entityName.toLowerCase()];
+ }
+ if ( decoded ) {
+ ch = decoded;
+ next = semi + 1;
+ }
+ else { // skip over unrecognized entity
+ next = i + 1;
+ ch = '\0';
+ }
+ }
+ }
+ this.next = next;
+ this.ch = ch;
+ return this.ch;
+};
+
+// some string utilities
+function PR_isWordChar( ch ) {
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
+}
+
+function PR_isIdentifierStart( ch ) {
+ return PR_isWordChar(ch) || ch == '_' || ch == '$' || ch == '@';
+}
+
+function PR_isIdentifierPart( ch ) {
+ return PR_isIdentifierStart(ch) || PR_isDigitChar(ch);
+}
+
+function PR_isSpaceChar( ch ) {
+ return "\t \r\n".indexOf(ch) >= 0;
+}
+
+function PR_isDigitChar( ch ) {
+ return ch >= '0' && ch <= '9';
+}
+
+function PR_trim( s ) {
+ var i = 0, j = s.length - 1;
+ while ( i <= j && PR_isSpaceChar(s.charAt(i)) ) {
+ ++i;
+ }
+ while ( j > i && PR_isSpaceChar(s.charAt(j)) ) {
+ --j;
+ }
+ return s.substring(i, j + 1);
+}
+
+function PR_startsWith( s, prefix ) {
+ return s.length >= prefix.length && prefix == s.substring(0, prefix.length);
+}
+
+function PR_endsWith( s, suffix ) {
+ return s.length >= suffix.length &&
+ suffix == s.substring(s.length - suffix.length, s.length);
+}
+
+/** true iff prefix matches the first prefix characters in chars[0:len].
+ * @private
+ */
+function PR_prefixMatch( chars, len, prefix ) {
+ if ( len < prefix.length ) {
+ return false;
+ }
+ for ( var i = 0, n = prefix.length; i < n; ++i ) {
+ if ( prefix.charAt(i) != chars[i] ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/** like textToHtml but escapes double quotes to be attribute safe. */
+function PR_attribToHtml( str ) {
+ return str.replace(/&/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/\"/g, '&quot;')
+ .replace(/\xa0/, '&nbsp;');
+}
+
+/** escapest html special characters to html. */
+function PR_textToHtml( str ) {
+ return str.replace(/&/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/\xa0/g, '&nbsp;');
+}
+
+/** is the given node's innerHTML normally unescaped? */
+function PR_isRawContent( node ) {
+ return 'XMP' == node.tagName;
+}
+
+var PR_innerHtmlWorks = null;
+function PR_getInnerHtml( node ) {
+ // inner html is hopelessly broken in Safari 2.0.4 when the content is
+ // an html description of well formed XML and the containing tag is a PRE
+ // tag, so we detect that case and emulate innerHTML.
+ if ( null == PR_innerHtmlWorks ) {
+ var testNode = document.createElement('PRE');
+ testNode.appendChild(
+ document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));
+ PR_innerHtmlWorks = !/</.test(testNode.innerHTML);
+ }
+
+ if ( PR_innerHtmlWorks ) {
+ var content = node.innerHTML;
+ // XMP tags contain unescaped entities so require special handling.
+ if ( PR_isRawContent(node) ) {
+ content = PR_textToHtml(content);
+ }
+ return content;
+ }
+
+ var out = [];
+ for ( var child = node.firstChild; child; child = child.nextSibling ) {
+ PR_normalizedHtml(child, out);
+ }
+ return out.join('');
+}
+
+/**
+ * walks the DOM returning a properly escaped version of innerHTML.
+ */
+function PR_normalizedHtml( node, out ) {
+ switch ( node.nodeType ) {
+ case 1: // an element
+ var name = node.tagName.toLowerCase();
+ out.push('\074', name);
+ for ( var i = 0; i < node.attributes.length; ++i ) {
+ var attr = node.attributes[i];
+ if ( !attr.specified ) {
+ continue;
+ }
+ out.push(' ');
+ PR_normalizedHtml(attr, out);
+ }
+ out.push('>');
+ for ( var child = node.firstChild; child; child = child.nextSibling ) {
+ PR_normalizedHtml(child, out);
+ }
+ if ( node.firstChild || !/^(?:br|link|img)$/.test(name) ) {
+ out.push('<\/', name, '>');
+ }
+ break;
+ case 2: // an attribute
+ out.push(node.name.toLowerCase(), '="', PR_attribToHtml(node.value), '"');
+ break;
+ case 3: case 4: // text
+ out.push(PR_textToHtml(node.nodeValue));
+ break;
+ }
+}
+
+/** expand tabs to spaces
+ * @param {Array} chunks PR_Tokens possibly containing tabs
+ * @param {Number} tabWidth number of spaces between tab columns
+ * @return {Array} chunks with tabs replaced with spaces
+ */
+function PR_expandTabs( chunks, tabWidth ) {
+ var SPACES = ' ';
+
+ var charInLine = 0;
+ var decodeHelper = new PR_DecodeHelper();
+
+ var chunksOut = []
+ for ( var chunkIndex = 0; chunkIndex < chunks.length; ++chunkIndex ) {
+ var chunk = chunks[chunkIndex];
+ if ( chunk.style == null ) {
+ chunksOut.push(chunk);
+ continue;
+ }
+
+ var s = chunk.token;
+ var pos = 0;
+ // index of last character output
+ var out = [];
+
+ // walk over each character looking for tabs and newlines.
+ // On tabs, expand them. On newlines, reset charInLine.
+ // Otherwise increment charInLine
+ for ( var charIndex = 0, n = s.length; charIndex < n;
+ charIndex = decodeHelper.next ) {
+ decodeHelper.decode(s, charIndex);
+ var ch = decodeHelper.ch;
+
+ switch ( ch ) {
+ case '\t':
+ out.push(s.substring(pos, charIndex));
+ // calculate how much space we need in front of this part
+ // nSpaces is the amount of padding -- the number of spaces needed to
+ // move us to the next column, where columns occur at factors of
+ // tabWidth.
+ var nSpaces = tabWidth - (charInLine % tabWidth);
+ charInLine += nSpaces;
+ for ( ; nSpaces >= 0; nSpaces -= SPACES.length ) {
+ out.push(SPACES.substring(0, nSpaces));
+ }
+ pos = decodeHelper.next;
+ break;
+ case '\n': case '\r':
+ charInLine = 0;
+ break;
+ default:
+ ++charInLine;
+ }
+ }
+ out.push(s.substring(pos));
+ chunksOut.push(new PR_Token(out.join(''), chunk.style));
+ }
+ return chunksOut
+}
+
+/** split markup into chunks of html tags (style null) and
+ * plain text (style {@link #PR_PLAIN}).
+ *
+ * @param {String} s html.
+ * @return {Array} of PR_Tokens of style PR_PLAIN, and null.
+ * @private
+ */
+function PR_chunkify( s ) {
+ // The below pattern matches one of the following
+ // (1) /[^<]+/ : A run of characters other than '<'
+ // (2) /<\/?[a-zA-Z][^>]*>/ : A probably tag that should not be highlighted
+ // (3) /</ : A '<' that does not begin a larger chunk. Treated as 1
+ var chunkPattern = /(?:[^<]+|<\/?[a-zA-Z][^>]*>|<)/g;
+ // since the pattern has the 'g' modifier and defines no capturing groups,
+ // this will return a list of all chunks which we then classify and wrap as
+ // PR_Tokens
+ var matches = s.match(chunkPattern);
+ var chunks = [];
+ if ( matches ) {
+ var lastChunk = null;
+ for ( var i = 0, n = matches.length; i < n; ++i ) {
+ var chunkText = matches[i];
+ var style;
+ if ( chunkText.length < 2 || chunkText.charAt(0) !== '<' ) {
+ if ( lastChunk && lastChunk.style === PR_PLAIN ) {
+ lastChunk.token += chunkText;
+ continue;
+ }
+ style = PR_PLAIN;
+ }
+ else { // a tag
+ style = null;
+ }
+ lastChunk = new PR_Token(chunkText, style);
+ chunks.push(lastChunk);
+ }
+ }
+ return chunks;
+}
+
+/** walk the tokenEnds list and the chunk list in parallel to generate a list
+ * of split tokens.
+ * @private
+ */
+function PR_splitChunks( chunks, tokenEnds ) {
+ var tokens = [];
+ // the output
+
+ var ci = 0;
+ // index into chunks
+ // position of beginning of amount written so far in absolute space.
+ var posAbs = 0;
+ // position of amount written so far in chunk space
+ var posChunk = 0;
+
+ // current chunk
+ var chunk = new PR_Token('', null);
+
+ for ( var ei = 0, ne = tokenEnds.length, lastEnd = 0; ei < ne; ++ei ) {
+ var tokenEnd = tokenEnds[ei];
+ var end = tokenEnd.end;
+ if ( end === lastEnd ) {
+ continue;
+ } // skip empty regions
+
+ var tokLen = end - posAbs;
+ var remainingInChunk = chunk.token.length - posChunk;
+ while ( remainingInChunk <= tokLen ) {
+ if ( remainingInChunk > 0 ) {
+ tokens.push(
+ new PR_Token(chunk.token.substring(posChunk, chunk.token.length),
+ null == chunk.style ? null : tokenEnd.style));
+ }
+ posAbs += remainingInChunk;
+ posChunk = 0;
+ if ( ci < chunks.length ) {
+ chunk = chunks[ci++];
+ }
+
+ tokLen = end - posAbs;
+ remainingInChunk = chunk.token.length - posChunk;
+ }
+
+ if ( tokLen ) {
+ tokens.push(
+ new PR_Token(chunk.token.substring(posChunk, posChunk + tokLen),
+ tokenEnd.style));
+ posAbs += tokLen;
+ posChunk += tokLen;
+ }
+ }
+
+ return tokens;
+}
+
+/** splits markup tokens into declarations, tags, and source chunks.
+ * @private
+ */
+function PR_splitMarkup( chunks ) {
+ // A state machine to split out declarations, tags, etc.
+ // This state machine deals with absolute space in the text, indexed by k,
+ // and position in the current chunk, indexed by pos and tokenStart to
+ // generate a list of the ends of tokens.
+ // Absolute space is calculated by considering the chunks as appended into
+ // one big string, as they were before being split.
+
+ // Known failure cases
+ // Server side scripting sections such as <?...?> in attributes.
+ // i.e. <span class="<? foo ?>">
+ // Handling this would require a stack, and we don't use PHP.
+
+ // The output: a list of pairs of PR_TokenEnd instances
+ var tokenEnds = [];
+
+ var state = 0;
+ // FSM state variable
+ var k = 0;
+ // position in absolute space of the start of the current chunk
+ var tokenStart = -1;
+ // the start of the current token
+
+ // Try to find a closing tag for any open <style> or <script> tags
+ // We can't do this at a later stage because then the following case
+ // would fail:
+ // <script>document.writeln('<!--');</script>
+
+ // We use tokenChars[:tokenCharsI] to accumulate the tag name so that we
+ // can check whether to enter into a no scripting section when the tag ends.
+ var tokenChars = new Array(12);
+ var tokenCharsI = 0;
+ // if non null, the tag prefix that we need to see to break out.
+ var endScriptTag = null;
+ var decodeHelper = new PR_DecodeHelper();
+
+ for ( var ci = 0, nc = chunks.length; ci < nc; ++ci ) {
+ var chunk = chunks[ci];
+ if ( PR_PLAIN != chunk.style ) {
+ k += chunk.token.length;
+ continue;
+ }
+
+ var s = chunk.token;
+ var pos = 0;
+ // the position past the last character processed so far in s
+
+ for ( var i = 0, n = s.length; i < n; /* i = next at bottom */ ) {
+ decodeHelper.decode(s, i);
+ var ch = decodeHelper.ch;
+ var next = decodeHelper.next;
+
+ var tokenStyle = null;
+ switch ( state ) {
+ case 0:
+ if ( '<' == ch ) {
+ state = 1;
+ }
+ break;
+ case 1:
+ tokenCharsI = 0;
+ if ( '/' == ch ) { // only consider close tags if we're in script/style
+ state = 7;
+ }
+ else if ( null == endScriptTag ) {
+ if ( '!' == ch ) {
+ state = 2;
+ }
+ else if ( PR_isWordChar(ch) ) {
+ state = 8;
+ }
+ else if ( '?' == ch ) {
+ state = 9;
+ }
+ else if ( '%' == ch ) {
+ state = 11;
+ }
+ else if ( '<' != ch ) {
+ state = 0;
+ }
+ }
+ else if ( '<' != ch ) {
+ state = 0;
+ }
+ break;
+ case 2:
+ if ( '-' == ch ) {
+ state = 4;
+ }
+ else if ( PR_isWordChar(ch) ) {
+ state = 3;
+ }
+ else if ( '<' == ch ) {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 3:
+ if ( '>' == ch ) {
+ state = 0;
+ tokenStyle = PR_DECLARATION;
+ }
+ break;
+ case 4:
+ if ( '-' == ch ) {
+ state = 5;
+ }
+ break;
+ case 5:
+ if ( '-' == ch ) {
+ state = 6;
+ }
+ break;
+ case 6:
+ if ( '>' == ch ) {
+ state = 0;
+ tokenStyle = PR_COMMENT;
+ }
+ else if ( '-' == ch ) {
+ state = 6;
+ }
+ else {
+ state = 4;
+ }
+ break;
+ case 7:
+ if ( PR_isWordChar(ch) ) {
+ state = 8;
+ }
+ else if ( '<' == ch ) {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 8:
+ if ( '>' == ch ) {
+ state = 0;
+ tokenStyle = PR_TAG;
+ }
+ break;
+ case 9:
+ if ( '?' == ch ) {
+ state = 10;
+ }
+ break;
+ case 10:
+ if ( '>' == ch ) {
+ state = 0;
+ tokenStyle = PR_SOURCE;
+ }
+ else if ( '?' != ch ) {
+ state = 9;
+ }
+ break;
+ case 11:
+ if ( '%' == ch ) {
+ state = 12;
+ }
+ break;
+ case 12:
+ if ( '>' == ch ) {
+ state = 0;
+ tokenStyle = PR_SOURCE;
+ }
+ else if ( '%' != ch ) {
+ state = 11;
+ }
+ break;
+ }
+
+ if ( tokenCharsI < tokenChars.length ) {
+ tokenChars[tokenCharsI++] = ch.toLowerCase();
+ }
+ if ( 1 == state ) {
+ tokenStart = k + i;
+ }
+ i = next;
+ if ( tokenStyle != null ) {
+ if ( null != tokenStyle ) {
+ if ( endScriptTag ) {
+ if ( PR_prefixMatch(tokenChars, tokenCharsI, endScriptTag) ) {
+ endScriptTag = null;
+ }
+ }
+ else {
+ if ( PR_prefixMatch(tokenChars, tokenCharsI, 'script') ) {
+ endScriptTag = '/script';
+ }
+ else if ( PR_prefixMatch(tokenChars, tokenCharsI, 'style') ) {
+ endScriptTag = '/style';
+ }
+ else if ( PR_prefixMatch(tokenChars, tokenCharsI, 'xmp') ) {
+ endScriptTag = '/xmp';
+ }
+ }
+ // disallow the tag if endScriptTag is set and this was not an open
+ // tag.
+ if ( endScriptTag && tokenCharsI && '/' == tokenChars[0] ) {
+ tokenStyle = null;
+ }
+ }
+ if ( null != tokenStyle ) {
+ tokenEnds.push(new PR_TokenEnd(tokenStart, PR_PLAIN));
+ tokenEnds.push(new PR_TokenEnd(k + next, tokenStyle));
+ }
+ }
+ }
+ k += chunk.token.length;
+ }
+ tokenEnds.push(new PR_TokenEnd(k, PR_PLAIN));
+
+ return tokenEnds;
+}
+
+/** splits the given string into comment, string, and "other" tokens.
+ * @return {Array} of PR_Tokens with style in
+ * (PR_STRING, PR_COMMENT, PR_PLAIN, null)
+ * The result array may contain spurious zero length tokens. Ignore them.
+ *
+ * @private
+ */
+function PR_splitStringAndCommentTokens( chunks ) {
+ // a state machine to split out comments, strings, and other stuff
+ var tokenEnds = [];
+ // positions of ends of tokens in absolute space
+ var state = 0;
+ // FSM state variable
+ var delim = -1;
+ // string delimiter
+ var k = 0;
+ // absolute position of beginning of current chunk
+
+ for ( var ci = 0, nc = chunks.length; ci < nc; ++ci ) {
+ var chunk = chunks[ci];
+ var s = chunk.token;
+ if ( PR_PLAIN == chunk.style ) {
+ var decodeHelper = new PR_DecodeHelper();
+ var last = -1;
+ var next;
+ for ( var i = 0, n = s.length; i < n; last = i,i = next ) {
+ decodeHelper.decode(s, i);
+ var ch = decodeHelper.ch;
+ next = decodeHelper.next;
+ if ( 0 == state ) {
+ if ( ch == '"' || ch == '\'' || ch == '`' ) {
+ tokenEnds.push(new PR_TokenEnd(k + i, PR_PLAIN));
+ state = 1;
+ delim = ch;
+ }
+ else if ( ch == '/' ) {
+ state = 3;
+ }
+ else if ( ch == '#' ) {
+ tokenEnds.push(new PR_TokenEnd(k + i, PR_PLAIN));
+ state = 4;
+ }
+ }
+ else if ( 1 == state ) {
+ if ( ch == delim ) {
+ state = 0;
+ tokenEnds.push(new PR_TokenEnd(k + next, PR_STRING));
+ }
+ else if ( ch == '\\' ) {
+ state = 2;
+ }
+ }
+ else if ( 2 == state ) {
+ state = 1;
+ }
+ else if ( 3 == state ) {
+ if ( ch == '/' ) {
+ state = 4;
+ tokenEnds.push(new PR_TokenEnd(k + last, PR_PLAIN));
+ }
+ else if ( ch == '*' ) {
+ state = 5;
+ tokenEnds.push(new PR_TokenEnd(k + last, PR_PLAIN));
+ }
+ else {
+ state = 0;
+ // next loop will reenter state 0 without same value of i, so
+ // ch will be reconsidered as start of new token.
+ next = i;
+ }
+ }
+ else if ( 4 == state ) {
+ if ( ch == '\r' || ch == '\n' ) {
+ state = 0;
+ tokenEnds.push(new PR_TokenEnd(k + i, PR_COMMENT));
+ }
+ }
+ else if ( 5 == state ) {
+ if ( ch == '*' ) {
+ state = 6;
+ }
+ }
+ else if ( 6 == state ) {
+ if ( ch == '/' ) {
+ state = 0;
+ tokenEnds.push(new PR_TokenEnd(k + next, PR_COMMENT));
+ }
+ else if ( ch != '*' ) {
+ state = 5;
+ }
+ }
+ }
+ }
+ k += s.length;
+ }
+ var endTokenType;
+ switch ( state ) {
+ case 1: case 2:
+ endTokenType = PR_STRING;
+ break;
+ case 4: case 5: case 6:
+ endTokenType = PR_COMMENT;
+ break;
+ default:
+ endTokenType = PR_PLAIN;
+ break;
+ }
+ // handle unclosed token which can legally happen for line comments (state 4)
+ tokenEnds.push(new PR_TokenEnd(k, endTokenType));
+ // a token ends at the end
+
+ return PR_splitChunks(chunks, tokenEnds);
+}
+
+/** used by lexSource to split a non string, non comment token.
+ * @private
+ */
+function PR_splitNonStringNonCommentToken( s, outlist ) {
+ var pos = 0;
+ var state = 0;
+
+ var decodeHelper = new PR_DecodeHelper();
+ var next;
+ for ( var i = 0; i <= s.length; i = next ) {
+ if ( i == s.length ) {
+ // nstate will not be equal to state, so it will append the token
+ nstate = -2;
+ next = i + 1;
+ }
+ else {
+ decodeHelper.decode(s, i);
+ next = decodeHelper.next;
+ var ch = decodeHelper.ch;
+
+ // the next state.
+ // if set to -1 then it will cause a reentry to state 0 without consuming
+ // another character.
+ var nstate = state;
+
+ switch ( state ) {
+ case 0: // whitespace state
+ if ( PR_isIdentifierStart(ch) ) {
+ nstate = 1;
+ }
+ else if ( PR_isDigitChar(ch) ) {
+ nstate = 2;
+ }
+ else if ( !PR_isSpaceChar(ch) ) {
+ nstate = 3;
+ }
+ if ( nstate && pos < i ) {
+ var t = s.substring(pos, i);
+ outlist.push(new PR_Token(t, PR_PLAIN));
+ pos = i;
+ }
+ break;
+ case 1: // identifier state
+ if ( !PR_isIdentifierPart(ch) ) {
+ nstate = -1;
+ }
+ break;
+ case 2: // number literal state
+ // handle numeric literals like
+ // 0x7f 300UL 100_000
+
+ // this does not treat floating point values as a single literal
+ // 0.1 and 3e-6
+ // are each split into multiple tokens
+ if ( !(PR_isDigitChar(ch) || PR_isWordChar(ch) || ch == '_') ) {
+ nstate = -1;
+ }
+ break;
+ case 3: // punctuation state
+ if ( PR_isIdentifierStart(ch) || PR_isDigitChar(ch) ||
+ PR_isSpaceChar(ch) ) {
+ nstate = -1;
+ }
+ break;
+ }
+ }
+
+ if ( nstate != state ) {
+ if ( nstate < 0 ) {
+ if ( i > pos ) {
+ var t = s.substring(pos, i);
+ var wordDecodeHelper = new PR_DecodeHelper();
+ wordDecodeHelper.decode(t, 0);
+ var ch0 = wordDecodeHelper.ch;
+ var isSingleCharacter = wordDecodeHelper.next == t.length;
+ var style;
+ if ( PR_isIdentifierStart(ch0) ) {
+ if ( PR_keywords[t] ) {
+ style = PR_KEYWORD;
+ }
+ else if ( ch0 === '@' ) {
+ style = PR_LITERAL;
+ }
+ else {
+ // Treat any word that starts with an uppercase character and
+ // contains at least one lowercase character as a type, or
+ // ends with _t.
+ // This works perfectly for Java, pretty well for C++, and
+ // passably for Python. The _t catches C structs.
+ var isType = false;
+ if ( ch0 >= 'A' && ch0 <= 'Z' ) {
+ for ( var j = wordDecodeHelper.next;
+ j < t.length; j = wordDecodeHelper.next ) {
+ wordDecodeHelper.decode(t, j);
+ var ch1 = wordDecodeHelper.ch;
+ if ( ch1 >= 'a' && ch1 <= 'z' ) {
+ isType = true;
+ break;
+ }
+ }
+ if ( !isType && !isSingleCharacter &&
+ t.substring(t.length - 2) == '_t' ) {
+ isType = true;
+ }
+ }
+ style = isType ? PR_TYPE : PR_PLAIN;
+ }
+ }
+ else if ( PR_isDigitChar(ch0) ) {
+ style = PR_LITERAL;
+ }
+ else if ( !PR_isSpaceChar(ch0) ) {
+ style = PR_PUNCTUATION;
+ }
+ else {
+ style = PR_PLAIN;
+ }
+ pos = i;
+ outlist.push(new PR_Token(t, style));
+ }
+
+ state = 0;
+ if ( nstate == -1 ) {
+ // don't increment. This allows us to use state 0 to redispatch based
+ // on the current character.
+ next = i;
+ continue;
+ }
+ }
+ state = nstate;
+ }
+ }
+
+}
+
+/** split a group of chunks of markup.
+ * @private
+ */
+function PR_tokenizeMarkup( chunks ) {
+ if ( !(chunks && chunks.length) ) {
+ return chunks;
+ }
+
+ var tokenEnds = PR_splitMarkup(chunks);
+ return PR_splitChunks(chunks, tokenEnds);
+}
+
+/** split tags attributes and their values out from the tag name, and
+ * recursively lex source chunks.
+ * @private
+ */
+function PR_splitTagAttributes( tokens ) {
+ var tokensOut = [];
+ var state = 0;
+ var stateStyle = PR_TAG;
+ var delim = null;
+ // attribute delimiter for quoted value state.
+ var decodeHelper = new PR_DecodeHelper();
+ for ( var ci = 0; ci < tokens.length; ++ci ) {
+ var tok = tokens[ci];
+ if ( PR_TAG == tok.style ) {
+ var s = tok.token;
+ var start = 0;
+ for ( var i = 0; i < s.length; /* i = next at bottom */ ) {
+ decodeHelper.decode(s, i);
+ var ch = decodeHelper.ch;
+ var next = decodeHelper.next;
+
+ var emitEnd = null;
+ // null or position of end of chunk to emit.
+ var nextStyle = null;
+ // null or next value of stateStyle
+ if ( ch == '>' ) {
+ if ( PR_TAG != stateStyle ) {
+ emitEnd = i;
+ nextStyle = PR_TAG;
+ }
+ }
+ else {
+ switch ( state ) {
+ case 0:
+ if ( '<' == ch ) {
+ state = 1;
+ }
+ break;
+ case 1:
+ if ( PR_isSpaceChar(ch) ) {
+ state = 2;
+ }
+ break;
+ case 2:
+ if ( !PR_isSpaceChar(ch) ) {
+ nextStyle = PR_ATTRIB_NAME;
+ emitEnd = i;
+ state = 3;
+ }
+ break;
+ case 3:
+ if ( '=' == ch ) {
+ emitEnd = i;
+ nextStyle = PR_TAG;
+ state = 5;
+ }
+ else if ( PR_isSpaceChar(ch) ) {
+ emitEnd = i;
+ nextStyle = PR_TAG;
+ state = 4;
+ }
+ break;
+ case 4:
+ if ( '=' == ch ) {
+ state = 5;
+ }
+ else if ( !PR_isSpaceChar(ch) ) {
+ emitEnd = i;
+ nextStyle = PR_ATTRIB_NAME;
+ state = 3;
+ }
+ break;
+ case 5:
+ if ( '"' == ch || '\'' == ch ) {
+ emitEnd = i;
+ nextStyle = PR_ATTRIB_VALUE;
+ state = 6;
+ delim = ch;
+ }
+ else if ( !PR_isSpaceChar(ch) ) {
+ emitEnd = i;
+ nextStyle = PR_ATTRIB_VALUE;
+ state = 7;
+ }
+ break;
+ case 6:
+ if ( ch == delim ) {
+ emitEnd = next;
+ nextStyle = PR_TAG;
+ state = 2;
+ }
+ break;
+ case 7:
+ if ( PR_isSpaceChar(ch) ) {
+ emitEnd = i;
+ nextStyle = PR_TAG;
+ state = 2;
+ }
+ break;
+ }
+ }
+ if ( emitEnd ) {
+ if ( emitEnd > start ) {
+ tokensOut.push(
+ new PR_Token(s.substring(start, emitEnd), stateStyle));
+ start = emitEnd;
+ }
+ stateStyle = nextStyle;
+ }
+ i = next;
+ }
+ if ( s.length > start ) {
+ tokensOut.push(new PR_Token(s.substring(start, s.length), stateStyle));
+ }
+ }
+ else {
+ if ( tok.style ) {
+ state = 0;
+ stateStyle = PR_TAG;
+ }
+ tokensOut.push(tok);
+ }
+ }
+ return tokensOut;
+}
+
+/** identify regions of markup that are really source code, and recursivley
+ * lex them.
+ * @private
+ */
+function PR_splitSourceNodes( tokens ) {
+ var tokensOut = [];
+ // when we see a <script> tag, store '/' here so that we know to end the
+ // source processing
+ var endScriptTag = null;
+ var decodeHelper = new PR_DecodeHelper();
+
+ var sourceChunks = null;
+
+ for ( var ci = 0, nc = tokens.length; /* break below */; ++ci ) {
+ var tok;
+
+ if ( ci < nc ) {
+ tok = tokens[ci];
+ if ( null == tok.style ) {
+ tokens.push(tok);
+ continue;
+ }
+ }
+ else if ( !endScriptTag ) {
+ break;
+ }
+ else {
+ // else pretend there's an end tag so we can gracefully handle
+ // unclosed source blocks
+ tok = new PR_Token('', null);
+ }
+
+ var s = tok.token;
+
+ if ( null == endScriptTag ) {
+ if ( PR_SOURCE == tok.style ) {
+ // split off any starting and trailing <?, <%
+ if ( '<' == decodeHelper.decode(s, 0) ) {
+ decodeHelper.decode(s, decodeHelper.next);
+ if ( '%' == decodeHelper.ch || '?' == decodeHelper.ch ) {
+ endScriptTag = decodeHelper.ch;
+ tokensOut.push(new PR_Token(s.substring(0, decodeHelper.next),
+ PR_TAG));
+ s = s.substring(decodeHelper.next, s.length);
+ }
+ }
+ }
+ else if ( PR_TAG == tok.style ) {
+ if ( '<' == decodeHelper.decode(s, 0) &&
+ '/' != s.charAt(decodeHelper.next) ) {
+ var tagContent = s.substring(decodeHelper.next).toLowerCase();
+ // FIXME(msamuel): this does not mirror exactly the code in
+ // in PR_splitMarkup that defers splitting tags inside script and
+ // style blocks.
+ if ( PR_startsWith(tagContent, 'script') ||
+ PR_startsWith(tagContent, 'style') ||
+ PR_startsWith(tagContent, 'xmp') ) {
+ endScriptTag = '/';
+ }
+ }
+ }
+ }
+
+ if ( null != endScriptTag ) {
+ var endTok = null;
+ if ( PR_SOURCE == tok.style ) {
+ if ( endScriptTag == '%' || endScriptTag == '?' ) {
+ var pos = s.lastIndexOf(endScriptTag);
+ if ( pos >= 0 && '>' == decodeHelper.decode(s, pos + 1) &&
+ s.length == decodeHelper.next ) {
+ endTok = new PR_Token(s.substring(pos, s.length), PR_TAG);
+ s = s.substring(0, pos);
+ }
+ }
+ if ( null == sourceChunks ) {
+ sourceChunks = [];
+ }
+ sourceChunks.push(new PR_Token(s, PR_PLAIN));
+ }
+ else if ( PR_PLAIN == tok.style ) {
+ if ( null == sourceChunks ) {
+ sourceChunks = [];
+ }
+ sourceChunks.push(tok);
+ }
+ else if ( PR_TAG == tok.style ) {
+ // if it starts with </ then it must be the end tag.
+ if ( '<' == decodeHelper.decode(tok.token, 0) &&
+ tok.token.length > decodeHelper.next &&
+ '/' == decodeHelper.decode(tok.token, decodeHelper.next) ) {
+ endTok = tok;
+ }
+ else {
+ tokensOut.push(tok);
+ }
+ }
+ else if ( ci >= nc ) {
+ // force the token to close
+ endTok = tok;
+ }
+ else {
+ if ( sourceChunks ) {
+ sourceChunks.push(tok);
+ }
+ else {
+ // push remaining tag and attribute tokens from the opening tag
+ tokensOut.push(tok);
+ }
+ }
+ if ( endTok ) {
+ if ( sourceChunks ) {
+ var sourceTokens = PR_lexSource(sourceChunks);
+ tokensOut.push(new PR_Token('<span class=embsrc>', null));
+ for ( var si = 0, ns = sourceTokens.length; si < ns; ++si ) {
+ tokensOut.push(sourceTokens[si]);
+ }
+ tokensOut.push(new PR_Token('</span>', null));
+ sourceChunks = null;
+ }
+ if ( endTok.token ) {
+ tokensOut.push(endTok);
+ }
+ endScriptTag = null;
+ }
+ }
+ else {
+ tokensOut.push(tok);
+ }
+ }
+ return tokensOut;
+}
+
+/** splits the quotes from an attribute value.
+ * ['"foo"'] -> ['"', 'foo', '"']
+ * @private
+ */
+function PR_splitAttributeQuotes( tokens ) {
+ var firstPlain = null, lastPlain = null;
+ for ( var i = 0; i < tokens.length; ++i ) {
+ if ( PR_PLAIN == tokens[i].style ) {
+ firstPlain = i;
+ break;
+ }
+ }
+ for ( var i = tokens.length; --i >= 0; ) {
+ if ( PR_PLAIN == tokens[i].style ) {
+ lastPlain = i;
+ break;
+ }
+ }
+ if ( null == firstPlain ) {
+ return tokens;
+ }
+
+ var decodeHelper = new PR_DecodeHelper();
+ var fs = tokens[firstPlain].token;
+ var fc = decodeHelper.decode(fs, 0);
+ if ( '"' != fc && '\'' != fc ) {
+ return tokens;
+ }
+ var fpos = decodeHelper.next;
+
+ var ls = tokens[lastPlain].token;
+ var lpos = ls.lastIndexOf('&');
+ if ( lpos < 0 ) {
+ lpos = ls.length - 1;
+ }
+ var lc = decodeHelper.decode(ls, lpos);
+ if ( lc != fc || decodeHelper.next != ls.length ) {
+ lc = null;
+ lpos = ls.length;
+ }
+
+ var tokensOut = [];
+ for ( var i = 0; i < firstPlain; ++i ) {
+ tokensOut.push(tokens[i]);
+ }
+ tokensOut.push(new PR_Token(fs.substring(0, fpos), PR_ATTRIB_VALUE));
+ if ( lastPlain == firstPlain ) {
+ tokensOut.push(new PR_Token(fs.substring(fpos, lpos), PR_PLAIN));
+ }
+ else {
+ tokensOut.push(new PR_Token(fs.substring(fpos, fs.length), PR_PLAIN));
+ for ( var i = firstPlain + 1; i < lastPlain; ++i ) {
+ tokensOut.push(tokens[i]);
+ }
+ if ( lc ) {
+ tokens.push(new PR_Token(ls.substring(0, lpos), PR_PLAIN));
+ }
+ else {
+ tokens.push(tokens[lastPlain]);
+ }
+ }
+ if ( lc ) {
+ tokensOut.push(new PR_Token(ls.substring(lpos, ls.length), PR_PLAIN));
+ }
+ for ( var i = lastPlain + 1; i < tokens.length; ++i ) {
+ tokensOut.push(tokens[i]);
+ }
+ return tokensOut;
+}
+
+/** identify attribute values that really contain source code and recursively
+ * lex them.
+ * @private
+ */
+function PR_splitSourceAttributes( tokens ) {
+ var tokensOut = [];
+
+ var sourceChunks = null;
+ var inSource = false;
+ var name = '';
+
+ for ( var ci = 0, nc = tokens.length; ci < nc; ++ci ) {
+ var tok = tokens[ci];
+ var outList = tokensOut;
+ if ( PR_TAG == tok.style ) {
+ if ( inSource ) {
+ inSource = false;
+ name = '';
+ if ( sourceChunks ) {
+ tokensOut.push(new PR_Token('<span class=embsrc>', null));
+ var sourceTokens =
+ PR_lexSource(PR_splitAttributeQuotes(sourceChunks));
+ for ( var si = 0, ns = sourceTokens.length; si < ns; ++si ) {
+ tokensOut.push(sourceTokens[si]);
+ }
+ tokensOut.push(new PR_Token('</span>', null));
+ sourceChunks = null;
+ }
+ }
+ else if ( name && tok.token.indexOf('=') >= 0 ) {
+ var nameLower = name.toLowerCase();
+ if ( PR_startsWith(nameLower, 'on') || 'style' == nameLower ) {
+ inSource = true;
+ }
+ }
+ else {
+ name = '';
+ }
+ }
+ else if ( PR_ATTRIB_NAME == tok.style ) {
+ name += tok.token;
+ }
+ else if ( PR_ATTRIB_VALUE == tok.style ) {
+ if ( inSource ) {
+ if ( null == sourceChunks ) {
+ sourceChunks = [];
+ }
+ outList = sourceChunks;
+ tok = new PR_Token(tok.token, PR_PLAIN);
+ }
+ }
+ else {
+ if ( sourceChunks ) {
+ outList = sourceChunks;
+ }
+ }
+ outList.push(tok);
+ }
+ return tokensOut;
+}
+
+/** returns a list of PR_Token objects given chunks of source code.
+ *
+ * This code treats ", ', and ` as string delimiters, and \ as a string escape.
+ * It does not recognize perl's qq() style strings. It has no special handling
+ * for double delimiter escapes as in basic, or tje tripled delimiters used in
+ * python, but should work on those regardless although in those cases a single
+ * string literal may be broken up into multiple adjacent string literals.
+ *
+ * It recognizes C, C++, and shell style comments.
+ *
+ * @param chunks PR_Tokens with style in (null, PR_PLAIN)
+ */
+function PR_lexSource( chunks ) {
+ // split into strings, comments, and other.
+ // We do this because strings and comments are easily recognizable and can
+ // contain stuff that looks like other tokens, so we want to mark those early
+ // so we don't recurse into them.
+ var tokens = PR_splitStringAndCommentTokens(chunks);
+
+ // split non comment|string tokens on whitespace and word boundaries
+ var tokensOut = [];
+ for ( var i = 0; i < tokens.length; ++i ) {
+ var tok = tokens[i];
+ if ( PR_PLAIN === tok.style ) {
+ PR_splitNonStringNonCommentToken(tok.token, tokensOut);
+ continue;
+ }
+ tokensOut.push(tok);
+ }
+
+ return tokensOut;
+}
+
+/** returns a list of PR_Token objects given a string of markup.
+ *
+ * This code assumes that < tokens are html escaped, but " are not.
+ * It will do a resonable job with <, but will not recognize an &quot;
+ * as starting a string.
+ *
+ * This code recognizes a number of constructs.
+ * <!-- ... --> comment
+ * <!\w ... > declaration
+ * <\w ... > tag
+ * </\w ... > tag
+ * <?...?> embedded source
+ * &[#\w]...; entity
+ *
+ * It does not recognizes %foo; entities.
+ *
+ * It will recurse into any <style>, <script>, and on* attributes using
+ * PR_lexSource.
+ */
+function PR_lexMarkup( chunks ) {
+ // This function works as follows:
+ // 1) Start by splitting the markup into text and tag chunks
+ // Input: String s
+ // Output: List<PR_Token> where style in (PR_PLAIN, null)
+ // 2) Then split the text chunks further into comments, declarations,
+ // tags, etc.
+ // After each split, consider whether the token is the start of an
+ // embedded source section, i.e. is an open <script> tag. If it is,
+ // find the corresponding close token, and don't bother to lex in between.
+ // Input: List<String>
+ // Output: List<PR_Token> with style in (PR_TAG, PR_PLAIN, PR_SOURCE, null)
+ // 3) Finally go over each tag token and split out attribute names and values.
+ // Input: List<PR_Token>
+ // Output: List<PR_Token> where style in
+ // (PR_TAG, PR_PLAIN, PR_SOURCE, NAME, VALUE, null)
+ var tokensOut = PR_tokenizeMarkup(chunks);
+ tokensOut = PR_splitTagAttributes(tokensOut);
+ tokensOut = PR_splitSourceNodes(tokensOut);
+ tokensOut = PR_splitSourceAttributes(tokensOut);
+ return tokensOut;
+}
+
+/**
+ * classify the string as either source or markup and lex appropriately.
+ * @param {String} html
+ */
+function PR_lexOne( html ) {
+ var chunks = PR_expandTabs(PR_chunkify(html), PR_TAB_WIDTH);
+
+ // treat it as markup if the first non whitespace character is a < and the
+ // last non-whitespace character is a >
+ var isMarkup = false;
+ for ( var i = 0; i < chunks.length; ++i ) {
+ if ( PR_PLAIN == chunks[i].style ) {
+ if ( PR_startsWith(PR_trim(chunks[i].token), '&lt;') ) {
+ for ( var j = chunks.length; --j >= 0; ) {
+ if ( PR_PLAIN == chunks[j].style ) {
+ isMarkup = PR_endsWith(PR_trim(chunks[j].token), '&gt;');
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ return isMarkup ? PR_lexMarkup(chunks) : PR_lexSource(chunks);
+}
+
+/** pretty print a chunk of code.
+ *
+ * @param s code as html
+ * @return code as html, but prettier
+ */
+function prettyPrintOne( s ) {
+ try {
+ var tokens = PR_lexOne(s);
+ var out = [];
+ var lastStyle = null;
+ for ( var i = 0; i < tokens.length; i++ ) {
+ var t = tokens[i];
+ if ( t.style != lastStyle ) {
+ if ( lastStyle != null ) {
+ out.push('</span>');
+ }
+ if ( t.style != null ) {
+ out.push('<span class=', t.style, '>');
+ }
+ lastStyle = t.style;
+ }
+ var html = t.token;
+ if ( null != t.style ) {
+ // This interacts badly with some wikis which introduces paragraph tags
+ // into pre blocks for some strange reason.
+ // It's necessary for IE though which seems to lose the preformattedness
+ // of <pre> tags when their innerHTML is assigned.
+ // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
+ html = html
+ .replace(/(\r\n?|\n| ) /g, '$1&nbsp;')
+ .replace(/\r\n?|\n/g, '<br>');
+ }
+ out.push(html);
+ }
+ if ( lastStyle != null ) {
+ out.push('</span>');
+ }
+ return out.join('');
+ }
+ catch ( e ) {
+ if ( 'console' in window ) {
+ console.log(e);
+ console.trace();
+ }
+ return s;
+ }
+}
+
+/** find all the < pre > and < code > tags in the DOM with class=prettyprint and
+ * prettify them.
+ */
+function prettyPrint() {
+ // fetch a list of nodes to rewrite
+ var codeSegments = [
+ document.getElementsByTagName('pre'),
+ document.getElementsByTagName('code'),
+ document.getElementsByTagName('xmp') ];
+ var elements = [];
+ for ( var i = 0; i < codeSegments.length; ++i ) {
+ for ( var j = 0; j < codeSegments[i].length; ++j ) {
+ elements.push(codeSegments[i][j]);
+ }
+ }
+ codeSegments = null;
+
+ // the loop is broken into a series of continuations to make sure that we
+ // don't make the browser unresponsive when rewriting a large page.
+ var k = 0;
+
+ function doWork() {
+ var endTime = new Date().getTime() + 250;
+ for ( ; k < elements.length && new Date().getTime() < endTime; k++ ) {
+ var cs = elements[k];
+ if ( cs.className && cs.className.indexOf('prettyprint') >= 0 ) {
+
+ // make sure this is not nested in an already prettified element
+ var nested = false;
+ for ( var p = cs.parentNode; p != null; p = p.parentNode ) {
+ if ( (p.tagName == 'pre' || p.tagName == 'code' ||
+ p.tagName == 'xmp') &&
+ p.className && p.className.indexOf('prettyprint') >= 0 ) {
+ nested = true;
+ break;
+ }
+ }
+ if ( !nested ) {
+ // fetch the content as a snippet of properly escaped HTML.
+ // Firefox adds newlines at the end.
+ var content = PR_getInnerHtml(cs);
+ content = content.replace(/(?:\r\n?|\n)$/, '');
+
+ // do the pretty printing
+ var newContent = prettyPrintOne(content);
+
+ // push the prettified html back into the tag.
+ if ( !PR_isRawContent(cs) ) {
+ // just replace the old html with the new
+ cs.innerHTML = newContent;
+ }
+ else {
+ // we need to change the tag to a <pre> since <xmp>s do not allow
+ // embedded tags such as the span tags used to attach styles to
+ // sections of source code.
+ var pre = document.createElement('PRE');
+ for ( var i = 0; i < cs.attributes.length; ++i ) {
+ var a = cs.attributes[i];
+ if ( a.specified ) {
+ pre.setAttribute(a.name, a.value);
+ }
+ }
+ pre.innerHTML = newContent;
+ // remove the old
+ cs.parentNode.replaceChild(pre, cs);
+ }
+ }
+ }
+ }
+ if ( k < elements.length ) {
+ // finish up in a continuation
+ setTimeout(doWork, 250);
+ }
+ }
+
+ doWork();
+}
diff --git a/third_party/java/jopt-simple/src/site/site.xml b/third_party/java/jopt-simple/src/site/site.xml
new file mode 100644
index 0000000000..8dafe09e18
--- /dev/null
+++ b/third_party/java/jopt-simple/src/site/site.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="JOpt Simple - a Java command line parsing library">
+ <bannerLeft>
+ <name>JOpt Simple</name>
+ <src>images/jopt-simple-logo.png</src>
+ <href>http://pholser.github.com/jopt-simple/</href>
+ </bannerLeft>
+ <body>
+ <menu name="JOpt Simple">
+ <item name="Overview" href="index.html"/>
+ <item name="Download" href="download.html"/>
+ <item name="Examples" href="examples.html"/>
+ <item name="Change Log" href="changes.html"/>
+ <item name="Javadoc" href="apidocs/index.html"/>
+ <item name="Developer Docs" href="developer.html"/>
+ <item name="Acknowledgements" href="acknowledgments.html"/>
+ </menu>
+ <menu ref="reports"/>
+ </body>
+</project>
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java
new file mode 100644
index 0000000000..3385c51249
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java
@@ -0,0 +1,59 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class AbstractOptionParserFixture {
+ @Rule public final ExpectedException thrown = none();
+
+ protected OptionParser parser;
+
+ @Before
+ public final void createNewParser() {
+ parser = new OptionParser();
+ }
+
+ static void assertOptionDetected( OptionSet detectedOptions, String option ) {
+ assertTrue( "option '" + option + "' not detected?", detectedOptions.has( option ) );
+ }
+
+ static void assertOptionNotDetected( OptionSet detectedOptions, String option ) {
+ assertOptionNotDetected( "option '" + option + "' detected?", detectedOptions, option );
+ }
+
+ static void assertOptionNotDetected( String message, OptionSet detectedOptions, String option ) {
+ assertFalse( message, detectedOptions.has( option ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java
new file mode 100644
index 0000000000..91901c9bd4
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.infinitest.toolkit.EqualsHashCodeTestSupport;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class AbstractOptionSpecFixture extends EqualsHashCodeTestSupport {
+ @Override
+ protected AbstractOptionSpec<?> equal() {
+ return createEqualOptionSpecInstance();
+ }
+
+ @Override
+ protected AbstractOptionSpec<?> notEqual() {
+ return createNotEqualOptionSpecInstance();
+ }
+
+ protected abstract AbstractOptionSpec<?> createEqualOptionSpecInstance();
+
+ protected abstract AbstractOptionSpec<?> createNotEqualOptionSpecInstance();
+
+ @Test( expected = NullPointerException.class )
+ public final void testValuesWithNullOptionSet() {
+ createEqualOptionSpecInstance().values( null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public final void testValueWithNullOptionSet() {
+ createNotEqualOptionSpecInstance().value( null );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java
new file mode 100644
index 0000000000..0660640efa
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java
@@ -0,0 +1,53 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class AbstractOptionSpecOptionsImmutabilityTestCase extends UnmodifiableListTestSupport<String> {
+ @Override
+ protected List<String> newList() {
+ AbstractOptionSpec<?> spec = newOptionSpec( containedItem() );
+ return spec.options();
+ }
+
+ @Override
+ protected final String newItem() {
+ return "not";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "in";
+ }
+
+ protected abstract AbstractOptionSpec<?> newOptionSpec( String option );
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java
new file mode 100644
index 0000000000..9e41ef8fc3
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java
@@ -0,0 +1,52 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class AbstractOptionSpecValuesImmutabilityTestCase<T> extends UnmodifiableListTestSupport<T> {
+ @Override
+ protected List<T> newList() {
+ AbstractOptionSpec<T> spec = newOptionSpec();
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ options.addWithArgument( spec, firstArg() );
+ options.addWithArgument( spec, secondArg() );
+
+ return spec.values( options );
+ }
+
+ protected abstract AbstractOptionSpec<T> newOptionSpec();
+
+ protected abstract String firstArg();
+
+ protected abstract String secondArg();
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java
new file mode 100644
index 0000000000..529557d6ab
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java
@@ -0,0 +1,43 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static joptsimple.ParserRules.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class AlternativeLongOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase {
+ @Override
+ protected AbstractOptionSpec<?> newOptionSpec( String option ) {
+ return new AlternativeLongOptionSpec();
+ }
+
+ @Override
+ protected String containedItem() {
+ return RESERVED_FOR_EXTENSIONS;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java
new file mode 100644
index 0000000000..933c171865
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class AlternativeLongOptionSpecValuesImmutabilityTest
+ extends AbstractOptionSpecValuesImmutabilityTestCase<String> {
+
+ @Override
+ protected AbstractOptionSpec<String> newOptionSpec() {
+ return new AlternativeLongOptionSpec();
+ }
+
+ @Override
+ protected String firstArg() {
+ return "x=y";
+ }
+
+ @Override
+ protected String secondArg() {
+ return "z=w";
+ }
+
+ @Override
+ protected String newItem() {
+ return "a=b";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "x=y";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java
new file mode 100644
index 0000000000..d20c48cb9f
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java
@@ -0,0 +1,50 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest extends UnmodifiableListTestSupport<String> {
+ @Override
+ protected List<String> newList() {
+ return new RequiredArgumentOptionSpec<String>( "option" ).defaultsTo( "a", "b" ).defaultValues();
+ }
+
+ @Override
+ protected String containedItem() {
+ return "a";
+ }
+
+ @Override
+ protected String newItem() {
+ return "c";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java
new file mode 100644
index 0000000000..32ef589fec
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java
@@ -0,0 +1,136 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.infinitest.toolkit.Block;
+import org.junit.Test;
+
+import static org.infinitest.toolkit.Assertions.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ArgumentAcceptingOptionSpecTest {
+ @Test( expected = NullPointerException.class )
+ public void requiredArgOfNullType() {
+ new RequiredArgumentOptionSpec<Void>( "a" ).ofType( null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void optionalArgOfNullType() {
+ new OptionalArgumentOptionSpec<Void>( "verbose" ).ofType( null );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void requiredArgOfNonValueType() {
+ new RequiredArgumentOptionSpec<Void>( "threshold" ).ofType( Object.class );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void optionalArgOfNonValueType() {
+ new OptionalArgumentOptionSpec<Void>( "max" ).ofType( Object.class );
+ }
+
+ @Test
+ public void requiredArgOfValueTypeBasedOnValueOf() {
+ assertNoException( new Block() {
+ public void execute() {
+ new RequiredArgumentOptionSpec<Void>( "threshold" ).ofType( ValueOfHaver.class );
+ }
+ } );
+ }
+
+ @Test
+ public void optionalArgOfValueTypeBasedOnValueOf() {
+ assertNoException( new Block() {
+ public void execute() {
+ new OptionalArgumentOptionSpec<Void>( "abc" ).ofType( ValueOfHaver.class );
+ }
+ } );
+ }
+
+ @Test
+ public void requiredArgOfValueTypeBasedOnCtor() {
+ assertNoException( new Block() {
+ public void execute() {
+ new RequiredArgumentOptionSpec<Void>( "threshold" ).ofType( Ctor.class );
+ }
+ } );
+ }
+
+ @Test
+ public void optionalArgOfValueTypeBasedOnCtor() {
+ final OptionalArgumentOptionSpec<Ctor> spec = new OptionalArgumentOptionSpec<>( "abc" );
+
+ assertNoException( new Block() {
+ public void execute() {
+ spec.ofType( Ctor.class );
+ assertEquals( "foo", spec.convert( "foo" ).getS() );
+ }
+ } );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void rejectsUnicodeZeroAsCharValueSeparatorForRequiredArgument() {
+ new RequiredArgumentOptionSpec<Void>( "a" ).withValuesSeparatedBy( '\u0000' );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void rejectsUnicodeZeroAsCharValueSeparatorForOptionalArgument() {
+ new OptionalArgumentOptionSpec<Void>( "b" ).withValuesSeparatedBy( '\u0000' );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void rejectsUnicodeZeroInStringValueSeparatorForRequiredArgument() {
+ new RequiredArgumentOptionSpec<Void>( "c" ).withValuesSeparatedBy( "::\u0000::" );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void rejectsUnicodeZeroInStringValueSeparatorForOptionalArgument() {
+ new OptionalArgumentOptionSpec<Void>( "d" ).withValuesSeparatedBy( "::::\u0000" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void rejectsNullConverter() {
+ new RequiredArgumentOptionSpec<Void>( "c" ).withValuesConvertedBy( null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void rejectsNullDefaultValue() {
+ new RequiredArgumentOptionSpec<Integer>( "d" ).defaultsTo( null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void rejectsNullDefaultValueRemainder() {
+ new RequiredArgumentOptionSpec<Integer>( "d" ).defaultsTo( 2, (Integer[]) null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void rejectsNullInDefaultValueRemainder() {
+ new RequiredArgumentOptionSpec<Integer>( "d" ).defaultsTo( 2, 3, null );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java
new file mode 100644
index 0000000000..1ae50755cd
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java
@@ -0,0 +1,56 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ArgumentListHasNoMoreArgsTest {
+ private ArgumentList noMore;
+
+ @Before
+ public void setUp() {
+ noMore = new ArgumentList();
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void peek() {
+ noMore.peek();
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void next() {
+ noMore.next();
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void treatNextAsLongOption() {
+ noMore.treatNextAsLongOption();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java
new file mode 100644
index 0000000000..425a41a97d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java
@@ -0,0 +1,75 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ArgumentListTest {
+ private ArgumentList args;
+
+ @Before
+ public void setUp() {
+ args = new ArgumentList( "-a", "b", "c" );
+ }
+
+ @Test
+ public void nextAndPeek() {
+ assertNextArgumentIs( "-a" );
+ assertNextArgumentIs( "b" );
+ assertNextArgumentIs( "c" );
+ assertNoMoreArguments();
+ }
+
+ @Test
+ public void treatNextAsLongOption() {
+ args.treatNextAsLongOption();
+ assertNextArgumentIs( "-a" );
+
+ args.treatNextAsLongOption();
+ assertNextArgumentIs( "--b" );
+
+ args.treatNextAsLongOption();
+ assertNextArgumentIs( "--c" );
+
+ assertNoMoreArguments();
+ }
+
+ private void assertNextArgumentIs( String expectedArg ) {
+ assertTrue( "no more arguments?", args.hasMore() );
+ assertEquals( "peek?", expectedArg, args.peek() );
+ assertEquals( "next?", expectedArg, args.next() );
+ }
+
+ private void assertNoMoreArguments() {
+ assertFalse( "more arguments?", args.hasMore() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java
new file mode 100644
index 0000000000..c3e4e592f6
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java
@@ -0,0 +1,82 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2014 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.Collections.emptyList;
+
+import static org.junit.Assert.assertEquals;
+
+public class AvailableIfAnyTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ OptionSpec<Void> a = parser.accepts( "a" );
+ parser.accepts( "b" );
+ OptionSpec<Void> c = parser.accepts( "c" );
+ parser.accepts( "d" );
+ parser.accepts( "n" ).availableIf( a, c );
+ }
+
+ @Test
+ public void rejectsCommandLineExistingForbiddenOption() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-b", "-n" );
+ }
+
+ @Test
+ public void rejectsCommandLineExistingOtherForbiddenOption() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-d", "-n" );
+ }
+
+ @Test
+ public void rejectsCommandLineOnlyForbiddenOption() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-n" );
+ }
+
+ @Test
+ public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-b", "-d", "-n" );
+ }
+
+ @Test
+ public void acceptsCommandLineWithAllowedOptionsPresent() {
+ OptionSet options = parser.parse( "-a", "-c", "-n" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "c" );
+ assertOptionDetected( options, "n" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java
new file mode 100644
index 0000000000..6f394b8311
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java
@@ -0,0 +1,143 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2014 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
+import static org.junit.Assert.assertEquals;
+
+public class AvailableIfUnlessTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ parser.mutuallyExclusive(
+ parser.acceptsAll( asList( "ftp", "file-transfer" ) ),
+ parser.accepts( "file" ),
+ parser.accepts( "http" )
+ );
+
+ parser.acceptsAll( asList( "username", "userid" ) ).availableIf( "file-transfer" ).withRequiredArg();
+ parser.acceptsAll( asList( "password", "pwd" ) ).availableIf( "ftp" ).withRequiredArg();
+ parser.acceptsAll( asList( "directory", "dir" ) ).availableIf( "file" ).withRequiredArg();
+ parser.accepts( "?" ).forHelp();
+ }
+
+ @Test
+ public void rejectsEmptyMutualExclusiveness() {
+ thrown.expect( NullPointerException.class );
+
+ parser.mutuallyExclusive( (OptionSpecBuilder[]) null );
+ }
+
+ @Test
+ public void rejectsConflictingCommandLineOptions1() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "--ftp", "--file" );
+ }
+
+ @Test
+ public void rejectsConflictingCommandLineOptions2() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "--ftp", "--http" );
+ }
+
+ @Test
+ public void rejectsIncompatibleOptions1() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "--file", "--username", "joe" );
+ }
+
+ @Test
+ public void rejectsIncompatibleOptions2() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "--ftp", "--directory", "/tmp" );
+ }
+
+
+ @Test
+ public void acceptsCommandLineWithConditionallyAllowedOptionsPresent1() {
+ OptionSet options = parser.parse( "--ftp", "--userid", "joe", "--password=secret" );
+
+ assertOptionDetected( options, "ftp" );
+ assertOptionDetected( options, "username" );
+ assertOptionDetected( options, "password" );
+ assertEquals( singletonList( "joe" ), options.valuesOf( "username" ) );
+ assertEquals( singletonList( "secret" ), options.valuesOf( "password" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void acceptsCommandLineWithConditionallyAllowedOptionsPresent2() {
+ OptionSet options = parser.parse( "--file", "--dir", "/tmp");
+
+ assertOptionDetected( options, "file" );
+ assertOptionDetected( options, "dir" );
+ assertEquals( singletonList( "/tmp" ), options.valuesOf( "dir" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void rejectsCommandLineOnlyContainingForbiddenOptionSynonym() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "--pwd", "secret" );
+ }
+
+ @Test
+ public void rejectsOptionNotAlreadyConfigured() {
+ thrown.expect( UnconfiguredOptionException.class );
+
+ parser.accepts( "foo" ).availableIf( "bar" );
+ parser.accepts( "foo" ).availableUnless( "bar" );
+ }
+
+ @Test
+ public void presenceOfHelpOptionNegatesAllowedIfness() {
+ OptionSet options = parser.parse( "--file", "--userid", "joe", "-?" );
+
+ assertOptionDetected( options, "file" );
+ assertOptionDetected( options, "?" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void presenceOfHelpOptionNegatesAllowedUnlessness() {
+ OptionSet options = parser.parse( "--file", "--ftp", "-?" );
+
+ assertOptionDetected( options, "file" );
+ assertOptionDetected( options, "file-transfer" );
+ assertOptionDetected( options, "?" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java
new file mode 100644
index 0000000000..c55191654b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java
@@ -0,0 +1,82 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2014 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.Collections.emptyList;
+
+import static org.junit.Assert.assertEquals;
+
+public class AvailableUnlessAnyTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ parser.accepts( "a" );
+ parser.accepts( "b" );
+ OptionSpec<Void> c = parser.accepts( "c" );
+ parser.accepts( "d" );
+ parser.accepts( "n" ).availableUnless( "a" ).availableUnless( c );
+ }
+
+ @Test
+ public void rejectsCommandLineExistingForbiddenOption() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-a", "-n" );
+ }
+
+ @Test
+ public void rejectsCommandLineExistingOtherForbiddenOption() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-c", "-n" );
+ }
+
+ @Test
+ public void rejectsCommandLineOnlyForbiddenOption() {
+ OptionSet options = parser.parse( "-n" );
+
+ assertOptionDetected( options, "n" );
+ }
+
+ @Test
+ public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() {
+ thrown.expect( UnavailableOptionException.class );
+
+ parser.parse( "-a", "-c", "-n" );
+ }
+
+ @Test
+ public void acceptsCommandLineWithAllowedOptionsPresent() {
+ OptionSet options = parser.parse( "-d", "-b", "-n" );
+
+ assertOptionDetected( options, "b" );
+ assertOptionDetected( options, "d" );
+ assertOptionDetected( options, "n" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java
new file mode 100644
index 0000000000..be71a1eb2c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java
@@ -0,0 +1,84 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ClusterVersusLongOptionTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "fox" );
+ parser.accepts( "f" );
+ parser.accepts( "o" );
+ parser.accepts( "x" );
+ }
+
+ @Test
+ public void resolvesToLongOptionEvenWithMatchingShortOptions() {
+ OptionSet options = parser.parse( "--fox" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ }
+
+ @Test
+ public void resolvesToLongOptionWithSingleDashEvenWithMatchingShortOptions() {
+ OptionSet options = parser.parse( "-fox" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ }
+
+ @Test
+ public void resolvesAbbreviationToLongOption() {
+ OptionSet options = parser.parse( "-fo" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ }
+
+ @Test
+ public void resolvesShortOptionToShortOption() {
+ OptionSet options = parser.parse( "-f" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ }
+
+ @Test
+ public void resolvesShortOptionToShortOptionEvenWithDoubleHyphen() {
+ OptionSet options = parser.parse( "--f" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java
new file mode 100644
index 0000000000..4e917648bb
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java
@@ -0,0 +1,122 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ClusterVersusLongOptionWithOptionalArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "fox" );
+ parser.accepts( "f" );
+ parser.accepts( "o" );
+ parser.accepts( "x" ).withOptionalArg();
+ }
+
+ @Test
+ public void resolvesToLongOptionEvenWithMatchingShortOptions() {
+ OptionSet options = parser.parse( "--fox" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ }
+
+ @Test
+ public void resolvesToLongOptionWithSingleDashEvenWithMatchingShortOptions() {
+ OptionSet options = parser.parse( "-fox" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ }
+
+ @Test
+ public void resolvesAbbreviationToLongOption() {
+ OptionSet options = parser.parse( "-fo" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ }
+
+ @Test
+ public void resolvesShortOptionToShortOption() {
+ OptionSet options = parser.parse( "-f" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ }
+
+ @Test
+ public void resolvesShortOptionToShortOptionEvenWithDoubleHyphen() {
+ OptionSet options = parser.parse( "--f" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ }
+
+ @Test
+ public void resolvesToShortOptionsWithArgumentFollowingX() {
+ OptionSet options = parser.parse( "-foxbar" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+ assertEquals( singletonList( "bar" ), options.valuesOf( "x" ) );
+ }
+
+ @Test
+ public void shortOptionsInDifferentOrder() {
+ OptionSet options = parser.parse( "-fxo" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+ assertEquals( singletonList( "o" ), options.valuesOf( "x" ) );
+ }
+
+ @Test( expected = UnrecognizedOptionException.class )
+ public void longOptionWithMessedUpOrder() {
+ parser.parse( "--fxo" );
+ }
+
+ @Test
+ public void withArgumentComingAfterCluster() {
+ OptionSet options = parser.parse( "-fox", "bar" );
+
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java
new file mode 100644
index 0000000000..b20fe67d92
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java
@@ -0,0 +1,122 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ClusterVersusLongOptionWithRequiredArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "fox" );
+ parser.accepts( "f" );
+ parser.accepts( "o" );
+ parser.accepts( "x" ).withRequiredArg();
+ }
+
+ @Test
+ public void resolvesToLongOptionEvenWithMatchingShortOptions() {
+ OptionSet options = parser.parse( "--fox" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ }
+
+ @Test
+ public void resolvesToLongOptionWithSingleDashEvenWithMatchingShortOptions() {
+ OptionSet options = parser.parse( "-fox" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ }
+
+ @Test
+ public void resolvesAbbreviationToLongOption() {
+ OptionSet options = parser.parse( "-fo" );
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ }
+
+ @Test
+ public void resolvesShortOptionToShortOption() {
+ OptionSet options = parser.parse( "-f" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ }
+
+ @Test
+ public void resolvesShortOptionToShortOptionEvenWithDoubleHyphen() {
+ OptionSet options = parser.parse( "--f" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ }
+
+ @Test
+ public void resolvesToShortOptionsWithArgumentFollowingX() {
+ OptionSet options = parser.parse( "-foxbar" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+ assertEquals( singletonList( "bar" ), options.valuesOf( "x" ) );
+ }
+
+ @Test
+ public void shortOptionsInDifferentOrder() {
+ OptionSet options = parser.parse( "-fxo" );
+ assertFalse( options.has( "fox" ) );
+ assertTrue( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+ assertEquals( singletonList( "o" ), options.valuesOf( "x" ) );
+ }
+
+ @Test( expected = UnrecognizedOptionException.class )
+ public void longOptionWithMessedUpOrder() {
+ parser.parse( "--fxo" );
+ }
+
+ @Test
+ public void withArgumentComingAfterCluster() {
+ OptionSet options = parser.parse( "-fox", "bar" );
+
+ assertTrue( options.has( "fox" ) );
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java
new file mode 100644
index 0000000000..ae82f27662
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java
@@ -0,0 +1,183 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ClusterWhereManyOptionsAcceptArgumentsTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "f" );
+ parser.accepts( "o" ).withOptionalArg();
+ parser.accepts( "x" ).withRequiredArg();
+ }
+
+ @Test
+ public void foxPermutation() {
+ OptionSet options = parser.parse( "-fox" );
+
+ assertTrue( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+
+ assertEquals( singletonList( "x" ), options.valuesOf( "o" ) );
+ }
+
+ @Test
+ public void fxoPermutation() {
+ OptionSet options = parser.parse( "-fxo" );
+
+ assertTrue( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+
+ assertEquals( singletonList( "o" ), options.valuesOf( "x" ) );
+ }
+
+ @Test
+ public void ofxPermutation() {
+ OptionSet options = parser.parse( "-ofx" );
+
+ assertFalse( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+
+ assertEquals( singletonList( "fx" ), options.valuesOf( "o" ) );
+ }
+
+ @Test
+ public void oxfPermutation() {
+ OptionSet options = parser.parse( "-oxf" );
+
+ assertFalse( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+
+ assertEquals( singletonList( "xf" ), options.valuesOf( "o" ) );
+ }
+
+ @Test
+ public void xofPermutation() {
+ OptionSet options = parser.parse( "-xof" );
+
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+
+ assertEquals( singletonList( "of" ), options.valuesOf( "x" ) );
+ }
+
+ @Test
+ public void xfoPermutation() {
+ OptionSet options = parser.parse( "-xfo" );
+
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+
+ assertEquals( singletonList( "fo" ), options.valuesOf( "x" ) );
+ }
+
+ @Test
+ public void foxPermutationWithFollowingArg() {
+ OptionSet options = parser.parse( "-fox", "bar" );
+
+ assertTrue( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+
+ assertEquals( singletonList( "x" ), options.valuesOf( "o" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void fxoPermutationWithFollowingArg() {
+ OptionSet options = parser.parse( "-fxo", "bar" );
+
+ assertTrue( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+
+ assertEquals( singletonList( "o" ), options.valuesOf( "x" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void ofxPermutationWithFollowingArg() {
+ OptionSet options = parser.parse( "-ofx", "bar" );
+
+ assertFalse( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+
+ assertEquals( singletonList( "fx" ), options.valuesOf( "o" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void oxfPermutationWithFollowingArg() {
+ OptionSet options = parser.parse( "-oxf", "bar" );
+
+ assertFalse( options.has( "f" ) );
+ assertTrue( options.has( "o" ) );
+ assertFalse( options.has( "x" ) );
+
+ assertEquals( singletonList( "xf" ), options.valuesOf( "o" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void xofPermutationWithFollowingArg() {
+ OptionSet options = parser.parse( "-xof", "bar" );
+
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+
+ assertEquals( singletonList( "of" ), options.valuesOf( "x" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void xfoPermutationWithFollowingArg() {
+ OptionSet options = parser.parse( "-xfo", "bar" );
+
+ assertFalse( options.has( "f" ) );
+ assertFalse( options.has( "o" ) );
+ assertTrue( options.has( "x" ) );
+
+ assertEquals( singletonList( "fo" ), options.valuesOf( "x" ) );
+ assertEquals( singletonList( "bar" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java
new file mode 100644
index 0000000000..066ca28a1d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java
@@ -0,0 +1,484 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import static java.math.BigDecimal.*;
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.internal.Strings.*;
+import static joptsimple.util.DateConverter.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ConfigurableOptionParserHelpTest extends AbstractOptionParserFixture {
+ private StringWriter sink;
+
+ @Before
+ public final void createSink() {
+ parser.formatHelpWith( new BuiltinHelpFormatter( 120, 3 ) );
+ sink = new StringWriter();
+ }
+
+ @Test
+ public void unconfiguredParser() throws Exception {
+ parser.printHelpOn( sink );
+
+ assertHelpLines( "No options specified ", EMPTY );
+ }
+
+ @Test
+ public void oneOptionNoArgNoDescription() throws Exception {
+ parser.accepts( "apple" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--apple ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionNoArgWithDescription() throws Exception {
+ parser.accepts( "a", "some description" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a some description",
+ EMPTY );
+ }
+
+ @Test
+ public void twoOptionsNoArgWithDescription() throws Exception {
+ parser.accepts( "a", "some description" );
+ parser.accepts( "verbose", "even more description" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a some description ",
+ "--verbose even more description",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgNoDescription() throws Exception {
+ parser.accepts( "a" ).withRequiredArg();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-a <String> ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgNoDescriptionWithType() throws Exception {
+ parser.accepts( "a" ).withRequiredArg().ofType( Integer.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-a <Integer> ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgWithDescription() throws Exception {
+ parser.accepts( "a", "some value you need" ).withRequiredArg().describedAs( "numerical" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a <String: numerical> some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgWithDescriptionAndType() throws Exception {
+ parser.accepts( "a", "some value you need" ).withRequiredArg().describedAs( "numerical" )
+ .ofType( Integer.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a <Integer: numerical> some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgNoDescription() throws Exception {
+ parser.accepts( "threshold" ).withOptionalArg();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--threshold [String] ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgNoDescriptionWithType() throws Exception {
+ parser.accepts( "a" ).withOptionalArg().ofType( Float.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-a [Float] ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgWithDescription() throws Exception {
+ parser.accepts( "threshold", "some value you need" ).withOptionalArg().describedAs( "positive integer" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--threshold [String: positive integer] some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgWithDescriptionAndType() throws Exception {
+ parser.accepts( "threshold", "some value you need" ).withOptionalArg().describedAs( "positive decimal" )
+ .ofType( Double.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--threshold [Double: positive decimal] some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void alternativeLongOptions() throws Exception {
+ parser.recognizeAlternativeLongOptions( true );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-W <String: opt=value> Alternative form of long options",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsWithoutArguments() throws Exception {
+ parser.acceptsAll( asList( "v", "chatty" ), "be verbose" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-v, --chatty be verbose ",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsWithRequiredArgument() throws Exception {
+ parser.acceptsAll( asList( "L", "index" ), "set level" ).withRequiredArg().ofType( Integer.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-L, --index <Integer> set level ",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsWithOptionalArgument() throws Exception {
+ parser.acceptsAll( asList( "d", "since" ), "date filter" ).withOptionalArg().describedAs( "yyyyMMdd" )
+ .ofType( Date.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-d, --since [Date: yyyyMMdd] date filter",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsSortedByShortOptionThenLexicographical() throws Exception {
+ parser.acceptsAll( asList( "v", "prolix", "chatty" ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-v, --chatty, --prolix ",
+ EMPTY );
+ }
+
+ @Test
+ public void bothColumnsExceedingAllocatedWidths() throws Exception {
+ parser.acceptsAll( asList( "t", "threshold", "cutoff" ),
+ "a threshold value beyond which a certain level of the application should cease to write logs" )
+ .withRequiredArg()
+ .describedAs( "a positive decimal number that will represent the threshold that has been outlined" )
+ .ofType( Double.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-t, --cutoff, --threshold <Double: a positive decimal a threshold value beyond which a certain level of the",
+ " number that will represent the threshold that has been application should cease to write logs ",
+ " outlined> ",
+ EMPTY );
+ }
+
+ // Bug 2018262
+ @Test
+ public void gradleHelp() throws Exception {
+ parser.acceptsAll( asList( "n", "non-recursive" ), "Do not execute primary tasks of child projects." );
+ parser.acceptsAll( singletonList( "S" ),
+ "Don't trigger a System.exit(0) for normal termination. Used for Gradle's internal testing." );
+ parser.acceptsAll( asList( "I", "no-imports" ), "Disable usage of default imports for build script files." );
+ parser.acceptsAll( asList( "u", "no-search-upward" ),
+ "Don't search in parent folders for a settings.gradle file." );
+ parser.acceptsAll( asList( "x", "cache-off" ), "No caching of compiled build scripts." );
+ parser.acceptsAll( asList( "r", "rebuild-cache" ), "Rebuild the cache of compiled build scripts." );
+ parser.acceptsAll( asList( "v", "version" ), "Print version info." );
+ parser.acceptsAll( asList( "d", "debug" ), "Log in debug mode (includes normal stacktrace)." );
+ parser.acceptsAll( asList( "q", "quiet" ), "Log errors only." );
+ parser.acceptsAll( asList( "j", "ivy-debug" ), "Set Ivy log level to debug (very verbose)." );
+ parser.acceptsAll( asList( "i", "ivy-quiet" ), "Set Ivy log level to quiet." );
+ parser.acceptsAll( asList( "s", "stacktrace" ),
+ "Print out the stacktrace also for user exceptions (e.g. compile error)." );
+ parser.acceptsAll( asList( "f", "full-stacktrace" ),
+ "Print out the full (very verbose) stacktrace for any exceptions." );
+ parser.acceptsAll( asList( "t", "tasks" ), "Show list of all available tasks and their dependencies." );
+ parser.acceptsAll( asList( "p", "project-dir" ),
+ "Specifies the start dir for Gradle. Defaults to current dir." ).withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "g", "gradle-user-home" ), "Specifies the gradle user home dir." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "l", "plugin-properties-file" ), "Specifies the plugin.properties file." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "b", "buildfile" ),
+ "Specifies the build file name (also for subprojects). Defaults to build.gradle." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "D", "systemprop" ), "Set system property of the JVM (e.g. -Dmyprop=myvalue)." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "P", "projectprop" ),
+ "Set project property for the build script (e.g. -Pmyprop=myvalue)." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "e", "embedded" ), "Specify an embedded build script." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "B", "bootstrap-debug" ),
+ "Specify a text to be logged at the beginning (e.g. used by Gradle's bootstrap class)." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "h", "?" ), "Shows this help message." ).forHelp();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-?, -h Shows this help message. ",
+ "-B, --bootstrap-debug <String> Specify a text to be logged at the beginning (e.g. used by Gradle's bootstrap ",
+ " class). ",
+ "-D, --systemprop <String> Set system property of the JVM (e.g. -Dmyprop=myvalue). ",
+ "-I, --no-imports Disable usage of default imports for build script files. ",
+ "-P, --projectprop <String> Set project property for the build script (e.g. -Pmyprop=myvalue). ",
+ "-S Don't trigger a System.exit(0) for normal termination. Used for Gradle's ",
+ " internal testing. ",
+ "-b, --buildfile <String> Specifies the build file name (also for subprojects). Defaults to build.gradle.",
+ "-d, --debug Log in debug mode (includes normal stacktrace). ",
+ "-e, --embedded <String> Specify an embedded build script. ",
+ "-f, --full-stacktrace Print out the full (very verbose) stacktrace for any exceptions. ",
+ "-g, --gradle-user-home <String> Specifies the gradle user home dir. ",
+ "-i, --ivy-quiet Set Ivy log level to quiet. ",
+ "-j, --ivy-debug Set Ivy log level to debug (very verbose). ",
+ "-l, --plugin-properties-file <String> Specifies the plugin.properties file. ",
+ "-n, --non-recursive Do not execute primary tasks of child projects. ",
+ "-p, --project-dir <String> Specifies the start dir for Gradle. Defaults to current dir. ",
+ "-q, --quiet Log errors only. ",
+ "-r, --rebuild-cache Rebuild the cache of compiled build scripts. ",
+ "-s, --stacktrace Print out the stacktrace also for user exceptions (e.g. compile error). ",
+ "-t, --tasks Show list of all available tasks and their dependencies. ",
+ "-u, --no-search-upward Don't search in parent folders for a settings.gradle file. ",
+ "-v, --version Print version info. ",
+ "-x, --cache-off No caching of compiled build scripts. ",
+ EMPTY );
+ }
+
+ @Test
+ public void dateConverterShowsDatePattern() throws Exception {
+ parser.accepts( "date", "a date" ).withRequiredArg().withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--date <MM/dd/yy> a date ",
+ EMPTY );
+ }
+
+ @Test
+ public void dateConverterShowsDatePatternInCombinationWithDescription() throws Exception {
+ parser.accepts( "date", "a date" ).withOptionalArg().describedAs( "your basic date pattern" )
+ .withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--date [MM/dd/yy: your basic date pattern] a date ",
+ EMPTY );
+ }
+
+ @Test
+ public void leavesEmbeddedNewlinesInDescriptionsAlone() throws Exception {
+ List<String> descriptionPieces =
+ asList( "Specify the output type.", "'raw' = raw data.", "'java' = java class" );
+ parser.accepts( "type", join( descriptionPieces, LINE_SEPARATOR ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--type Specify the output type.",
+ " 'raw' = raw data. ",
+ " 'java' = java class ",
+ EMPTY );
+ }
+
+ @Test
+ public void includesDefaultValueForRequiredOptionArgument() throws Exception {
+ parser.accepts( "a" ).withRequiredArg().defaultsTo( "boo" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a <String> (default: boo)",
+ EMPTY );
+ }
+
+ @Test
+ public void includesDefaultValueForOptionalOptionArgument() throws Exception {
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 5 );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-b [Integer] (default: 5)",
+ EMPTY );
+ }
+
+ @Test
+ public void includesDefaultValueForArgumentWithDescription() throws Exception {
+ parser.accepts( "c", "a quantity" ).withOptionalArg().ofType( BigDecimal.class )
+ .describedAs( "quantity" ).defaultsTo( TEN );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-c [BigDecimal: quantity] a quantity (default: 10)",
+ EMPTY );
+ }
+
+ @Test
+ public void includesListOfDefaultsForArgumentWithDescription() throws Exception {
+ parser.accepts( "d", "dizzle" ).withOptionalArg().ofType( Integer.class )
+ .describedAs( "double dizzle" ).defaultsTo( 2, 3, 5, 7 );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-d [Integer: double dizzle] dizzle (default: [2, 3, 5, 7])",
+ EMPTY );
+ }
+
+ @Test
+ public void marksRequiredOptionsSpecially() throws Exception {
+ parser.accepts( "e" ).withRequiredArg().required();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option (* = required) Description",
+ "--------------------- -----------",
+ "* -e <String> ",
+ EMPTY );
+ }
+
+ private void assertHelpLines( String... expectedLines ) {
+ assertEquals( join( expectedLines, LINE_SEPARATOR ), sink.toString() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java
new file mode 100644
index 0000000000..545676ad12
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java
@@ -0,0 +1,51 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class CreateWithOptionSpecificationStringTest {
+ @Test
+ public void createsParserWithOptionSpecificationString() {
+ OptionParser first = new OptionParser() {
+ {
+ accepts( "i" ).withOptionalArg();
+ accepts( "j" ).withRequiredArg();
+ accepts( "k" );
+ }
+ };
+
+ OptionParser second = new OptionParser( "i::j:k" );
+
+ String[] args = { "-k", "-ifoo", "-jbar" };
+ assertEquals( first.parse( args ), second.parse( args ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java b/third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java
new file mode 100644
index 0000000000..ad26a4de37
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java
@@ -0,0 +1,45 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class Ctor {
+ private String s;
+
+ public Ctor( String s ) {
+ this.s = s;
+ }
+
+ public String getS() {
+ return s;
+ }
+
+ static Ctor valueOf( String s ) {
+ return new Ctor( s );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java
new file mode 100644
index 0000000000..e9fd215b32
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java
@@ -0,0 +1,753 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import joptsimple.util.InetAddressConverter;
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.math.BigDecimal.*;
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+import static joptsimple.internal.Strings.*;
+import static joptsimple.util.DateConverter.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class DefaultSettingsOptionParserHelpTest extends AbstractOptionParserFixture {
+ private StringWriter sink;
+
+ @Before
+ public final void createSink() {
+ sink = new StringWriter();
+ }
+
+ @Test
+ public void unconfiguredParser() throws Exception {
+ parser.printHelpOn( sink );
+
+ assertHelpLines( "No options specified ", EMPTY );
+ }
+
+ @Test
+ public void repeatedCalls() throws Exception {
+ parser.accepts( "apple" );
+
+ parser.printHelpOn( sink );
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--apple ",
+ "Option Description",
+ "------ -----------",
+ "--apple ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionNoArgNoDescription() throws Exception {
+ parser.accepts( "apple" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--apple ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionNoArgWithDescription() throws Exception {
+ parser.accepts( "a", "some description" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a some description",
+ EMPTY );
+ }
+
+ @Test
+ public void twoOptionsNoArgWithDescription() throws Exception {
+ parser.accepts( "a", "some description" );
+ parser.accepts( "verbose", "even more description" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a some description ",
+ "--verbose even more description",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgNoDescription() throws Exception {
+ parser.accepts( "a" ).withRequiredArg();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-a <String> ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgNoDescriptionWithType() throws Exception {
+ parser.accepts( "a" ).withRequiredArg().ofType( Integer.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-a <Integer> ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgWithDescription() throws Exception {
+ parser.accepts( "a", "some value you need" ).withRequiredArg().describedAs( "numerical" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a <String: numerical> some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionRequiredArgWithDescriptionAndType() throws Exception {
+ parser.accepts( "a", "some value you need" )
+ .withRequiredArg().describedAs( "numerical" ).ofType( Integer.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a <Integer: numerical> some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgNoDescription() throws Exception {
+ parser.accepts( "threshold" ).withOptionalArg();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--threshold [String] ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgNoDescriptionWithType() throws Exception {
+ parser.accepts( "a" ).withOptionalArg().ofType( Float.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-a [Float] ",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgWithDescription() throws Exception {
+ parser.accepts( "threshold", "some value you need" ).withOptionalArg().describedAs( "positive integer" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--threshold [String: positive integer] some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void oneOptionOptionalArgWithDescriptionAndType() throws Exception {
+ parser.accepts( "threshold", "some value you need" )
+ .withOptionalArg().describedAs( "positive decimal" ).ofType( Double.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--threshold [Double: positive decimal] some value you need",
+ EMPTY );
+ }
+
+ @Test
+ public void alternativeLongOptions() throws Exception {
+ parser.recognizeAlternativeLongOptions( true );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-W <String: opt=value> Alternative form of long options",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsWithoutArguments() throws Exception {
+ parser.acceptsAll( asList( "v", "chatty" ), "be verbose" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-v, --chatty be verbose ",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsWithRequiredArgument() throws Exception {
+ parser.acceptsAll( asList( "L", "index" ), "set level" ).withRequiredArg().ofType( Integer.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-L, --index <Integer> set level ",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsWithOptionalArgument() throws Exception {
+ parser.acceptsAll( asList( "d", "since" ), "date filter" )
+ .withOptionalArg().describedAs( "yyyyMMdd" ).ofType( Date.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-d, --since [Date: yyyyMMdd] date filter",
+ EMPTY );
+ }
+
+ @Test
+ public void optionSynonymsSortedByShortOptionThenLexicographical() throws Exception {
+ parser.acceptsAll( asList( "v", "prolix", "chatty" ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "-v, --chatty, --prolix ",
+ EMPTY );
+ }
+
+ @Test
+ public void writingToOutputStream() throws Exception {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+
+ parser.printHelpOn( bytesOut );
+
+ assertEquals( "No options specified " + LINE_SEPARATOR, bytesOut.toString() );
+ }
+
+ // Bug 1956418
+ @Test
+ public void outputStreamFlushedButNotClosedWhenPrintingHelp() throws Exception {
+ FakeOutputStream fake = new FakeOutputStream();
+
+ parser.printHelpOn( fake );
+
+ assertTrue( fake.flushed );
+ assertFalse( fake.closed );
+ }
+
+ @Test
+ public void bothColumnsExceedingAllocatedWidths() throws Exception {
+ parser.acceptsAll( asList( "t", "threshold", "cutoff" ),
+ "a threshold value beyond which a certain level of the application should cease to write logs" )
+ .withRequiredArg()
+ .describedAs( "a positive decimal number that will represent the threshold that has been outlined" )
+ .ofType( Double.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-t, --cutoff, --threshold <Double: a a threshold value beyond which a ",
+ " positive decimal number that will certain level of the application",
+ " represent the threshold that has should cease to write logs ",
+ " been outlined> ",
+ EMPTY );
+ }
+
+ // Bug 2018262
+ @Test
+ public void gradleHelp() throws Exception {
+ parser.acceptsAll( asList( "n", "non-recursive" ),
+ "Do not execute primary tasks of child projects." );
+ parser.acceptsAll( singletonList( "S" ),
+ "Don't trigger a System.exit(0) for normal termination. Used for Gradle's internal testing." );
+ parser.acceptsAll( asList( "I", "no-imports" ),
+ "Disable usage of default imports for build script files." );
+ parser.acceptsAll( asList( "u", "no-search-upward" ),
+ "Don't search in parent folders for a settings.gradle file." );
+ parser.acceptsAll( asList( "x", "cache-off" ),
+ "No caching of compiled build scripts." );
+ parser.acceptsAll( asList( "r", "rebuild-cache" ),
+ "Rebuild the cache of compiled build scripts." );
+ parser.acceptsAll( asList( "v", "version" ), "Print version info." );
+ parser.acceptsAll( asList( "d", "debug" ),
+ "Log in debug mode (includes normal stacktrace)." );
+ parser.acceptsAll( asList( "q", "quiet" ), "Log errors only." );
+ parser.acceptsAll( asList( "j", "ivy-debug" ),
+ "Set Ivy log level to debug (very verbose)." );
+ parser.acceptsAll( asList( "i", "ivy-quiet" ), "Set Ivy log level to quiet." );
+ parser.acceptsAll( asList( "s", "stacktrace" ),
+ "Print out the stacktrace also for user exceptions (e.g. compile error)." );
+ parser.acceptsAll( asList( "f", "full-stacktrace" ),
+ "Print out the full (very verbose) stacktrace for any exceptions." );
+ parser.acceptsAll( asList( "t", "tasks" ),
+ "Show list of all available tasks and their dependencies." );
+ parser.acceptsAll( asList( "p", "project-dir" ),
+ "Specifies the start dir for Gradle. Defaults to current dir." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "g", "gradle-user-home" ),
+ "Specifies the gradle user home dir." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "l", "plugin-properties-file" ),
+ "Specifies the plugin.properties file." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "b", "buildfile" ),
+ "Specifies the build file name (also for subprojects). Defaults to build.gradle." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "D", "systemprop" ),
+ "Set system property of the JVM (e.g. -Dmyprop=myvalue)." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "P", "projectprop" ),
+ "Set project property for the build script (e.g. -Pmyprop=myvalue)." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "e", "embedded" ),
+ "Specify an embedded build script." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "B", "bootstrap-debug" ),
+ "Specify a text to be logged at the beginning (e.g. used by Gradle's bootstrap class)." )
+ .withRequiredArg().ofType( String.class );
+ parser.acceptsAll( asList( "h", "?" ), "Shows this help message" ).forHelp();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-?, -h Shows this help message ",
+ "-B, --bootstrap-debug <String> Specify a text to be logged at the ",
+ " beginning (e.g. used by Gradle's ",
+ " bootstrap class). ",
+ "-D, --systemprop <String> Set system property of the JVM (e.g. - ",
+ " Dmyprop=myvalue). ",
+ "-I, --no-imports Disable usage of default imports for ",
+ " build script files. ",
+ "-P, --projectprop <String> Set project property for the build ",
+ " script (e.g. -Pmyprop=myvalue). ",
+ "-S Don't trigger a System.exit(0) for ",
+ " normal termination. Used for Gradle's ",
+ " internal testing. ",
+ "-b, --buildfile <String> Specifies the build file name (also for ",
+ " subprojects). Defaults to build.gradle.",
+ "-d, --debug Log in debug mode (includes normal ",
+ " stacktrace). ",
+ "-e, --embedded <String> Specify an embedded build script. ",
+ "-f, --full-stacktrace Print out the full (very verbose) ",
+ " stacktrace for any exceptions. ",
+ "-g, --gradle-user-home <String> Specifies the gradle user home dir. ",
+ "-i, --ivy-quiet Set Ivy log level to quiet. ",
+ "-j, --ivy-debug Set Ivy log level to debug (very ",
+ " verbose). ",
+ "-l, --plugin-properties-file <String> Specifies the plugin.properties file. ",
+ "-n, --non-recursive Do not execute primary tasks of child ",
+ " projects. ",
+ "-p, --project-dir <String> Specifies the start dir for Gradle. ",
+ " Defaults to current dir. ",
+ "-q, --quiet Log errors only. ",
+ "-r, --rebuild-cache Rebuild the cache of compiled build ",
+ " scripts. ",
+ "-s, --stacktrace Print out the stacktrace also for user ",
+ " exceptions (e.g. compile error). ",
+ "-t, --tasks Show list of all available tasks and ",
+ " their dependencies. ",
+ "-u, --no-search-upward Don't search in parent folders for a ",
+ " settings.gradle file. ",
+ "-v, --version Print version info. ",
+ "-x, --cache-off No caching of compiled build scripts. ",
+ EMPTY );
+ }
+
+ @Test
+ public void dateConverterShowsDatePattern() throws Exception {
+ parser.accepts( "date", "a date" )
+ .withRequiredArg()
+ .withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--date <MM/dd/yy> a date ",
+ EMPTY );
+ }
+
+ @Test
+ public void dateConverterShowsDatePatternInCombinationWithDescription() throws Exception {
+ parser.accepts( "date", "a date" ).withOptionalArg()
+ .describedAs( "your basic date pattern" )
+ .withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description",
+ "------ -----------",
+ "--date [MM/dd/yy: your basic date a date ",
+ " pattern] ",
+ EMPTY );
+ }
+
+ @Test
+ public void inetAddressConverterShowsType() throws Exception {
+ parser.accepts( "addr", "an internet address" )
+ .withRequiredArg()
+ .withValuesConvertedBy( new InetAddressConverter() );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--addr <InetAddress> an internet address",
+ EMPTY );
+ }
+
+ @Test
+ public void leavesEmbeddedNewlinesInDescriptionsAlone() throws Exception {
+ List<String> descriptionPieces =
+ asList( "Specify the output type.", "'raw' = raw data.", "'java' = java class" );
+ parser.accepts( "type", join( descriptionPieces, LINE_SEPARATOR ) );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "--type Specify the output type.",
+ " 'raw' = raw data. ",
+ " 'java' = java class ",
+ EMPTY );
+ }
+
+ @Test
+ public void includesDefaultValueForRequiredOptionArgument() throws Exception {
+ parser.accepts( "a" ).withRequiredArg().defaultsTo( "boo" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-a <String> (default: boo)",
+ EMPTY );
+ }
+
+ @Test
+ public void includesDefaultValueForOptionalOptionArgument() throws Exception {
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 5 );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-b [Integer] (default: 5)",
+ EMPTY );
+ }
+
+ @Test
+ public void includesDefaultValueForArgumentWithDescription() throws Exception {
+ parser.accepts( "c", "a quantity" ).withOptionalArg().ofType( BigDecimal.class )
+ .describedAs( "quantity" ).defaultsTo( TEN );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-c [BigDecimal: quantity] a quantity (default: 10)",
+ EMPTY );
+ }
+
+ @Test
+ public void includesListOfDefaultsForArgumentWithDescription() throws Exception {
+ parser.accepts( "d", "dizzle" ).withOptionalArg().ofType( Integer.class )
+ .describedAs( "double dizzle" ).defaultsTo( 2, 3, 5, 7 );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-d [Integer: double dizzle] dizzle (default: [2, 3, 5, 7])",
+ EMPTY );
+ }
+
+ @Test
+ public void marksRequiredOptionsSpecially() throws Exception {
+ parser.accepts( "e" ).withRequiredArg().required();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option (* = required) Description",
+ "--------------------- -----------",
+ "* -e <String> ",
+ EMPTY );
+ }
+
+ @Test
+ public void showsNonOptionArgumentDescription() throws Exception {
+ parser.nonOptions( "stuff" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Non-option arguments:",
+ "[String] -- stuff ",
+ EMPTY,
+ "No options specified ",
+ EMPTY );
+ }
+
+ @Test
+ public void showsNonOptionArgumentType() throws Exception {
+ parser.nonOptions().ofType( File.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Non-option arguments:",
+ "[File] ",
+ EMPTY,
+ "No options specified ",
+ EMPTY );
+ }
+
+ @Test
+ public void showsNonOptionArgumentTypeDescribedAs() throws Exception {
+ parser.nonOptions().describedAs( "files" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Non-option arguments:",
+ "[String: files] ",
+ EMPTY,
+ "No options specified ",
+ EMPTY );
+ }
+
+ @Test
+ public void showsNonOptionArgumentTypeAndArgumentDescription() throws Exception {
+ parser.nonOptions().ofType( File.class ).describedAs( "files" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Non-option arguments:",
+ "[File: files] ",
+ EMPTY,
+ "No options specified ",
+ EMPTY );
+ }
+
+ @Test
+ public void showsNonOptionArgumentTypeAndDescription() throws Exception {
+ parser.nonOptions( "some files to operate on" ).ofType( File.class );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Non-option arguments: ",
+ "[File] -- some files to operate on",
+ EMPTY,
+ "No options specified ",
+ EMPTY );
+ }
+
+ @Test
+ public void showsNonOptionArgumentTypeAndDescriptionAndArgumentDescription() throws Exception {
+ parser.nonOptions( "some files to operate on" ).ofType( File.class ).describedAs( "files" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Non-option arguments: ",
+ "[File: files] -- some files to operate on",
+ EMPTY,
+ "No options specified ",
+ EMPTY );
+ }
+
+ @Test
+ public void canUseCustomHelpFormatter() {
+ parser.accepts( "f" );
+
+ parser.formatHelpWith( new HelpFormatter() {
+ public String format( Map<String, ? extends OptionDescriptor> options ) {
+ assertEquals( 1, options.size() );
+ OptionDescriptor only = options.get( "f" );
+ assertEquals( asList( "f" ), new ArrayList<>( only.options() ) );
+ assertFalse( only.acceptsArguments() );
+ assertEquals( "", only.argumentDescription() );
+ assertEquals( "", only.argumentTypeIndicator() );
+ assertEquals( emptyList(), only.defaultValues() );
+ assertEquals( "", only.description() );
+ assertFalse( only.isRequired() );
+ assertFalse( only.requiresArgument() );
+ return null;
+ }
+ } );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void rejectsNullHelpFormatter() {
+ parser.formatHelpWith( null );
+ }
+
+ @Test
+ public void fixForIssue56() throws Exception {
+ parser.accepts( "password", "Server Password" ).withRequiredArg().ofType( String.class );
+ parser.accepts( "F", "Forward port mapping (ie: localhost:5900:localhost:5900)" ).withRequiredArg();
+ parser.accepts( "R", "Reverse port mapping (ie: localhost:5900:localhost:5900)" ).withRequiredArg();
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-F <String> Forward port mapping (ie: localhost:5900:localhost:5900)",
+ "-R <String> Reverse port mapping (ie: localhost:5900:localhost:5900)",
+ "--password <String> Server Password ",
+ EMPTY );
+ }
+
+ @Test
+ public void fixForIssue85() throws Exception {
+ parser.acceptsAll( asList( "?", "help" ), "Display this help text" ).forHelp();
+ parser.acceptsAll( asList( "c", "check-avail" ),
+ "Check Galileo homepage for available books, compare with known ones" );
+ parser.acceptsAll( asList( "d", "download-dir" ),
+ "Download directory for openbooks; must exist" )
+ .withRequiredArg().ofType( File.class ).defaultsTo( new File( "." ) );
+ parser.acceptsAll( asList( "l", "log-level" ),
+ "Log level (0=normal, 1=verbose, 2=debug, 3=trace" )
+ .withRequiredArg().ofType( int.class ).defaultsTo( 0 );
+ parser.acceptsAll( asList( "m", "check-md5" ),
+ "Download all known books without storing them, verifying their MD5 checksum (slow! >1 Gb download)" );
+ parser.acceptsAll( asList( "t", "threading" ),
+ "Threading mode (0=single, 1=multi); single is slower, but better for diagnostics)" )
+ .withRequiredArg().ofType( int.class ).defaultsTo( 1 );
+ parser.acceptsAll( asList( "w", "write-config" ),
+ "Write editable book list to config.xml, enabling you to update MD5 checksums or add new books" );
+
+ parser.printHelpOn( sink );
+
+ assertHelpLines(
+ "Option Description ",
+ "------ ----------- ",
+ "-?, --help Display this help text ",
+ "-c, --check-avail Check Galileo homepage for available books, compare ",
+ " with known ones ",
+ "-d, --download-dir <File> Download directory for openbooks; must exist ",
+ " (default: .) ",
+ "-l, --log-level <Integer> Log level (0=normal, 1=verbose, 2=debug, 3=trace ",
+ " (default: 0) ",
+ "-m, --check-md5 Download all known books without storing them, ",
+ " verifying their MD5 checksum (slow! >1 Gb download)",
+ "-t, --threading <Integer> Threading mode (0=single, 1=multi); single is ",
+ " slower, but better for diagnostics) (default: 1) ",
+ "-w, --write-config Write editable book list to config.xml, enabling you ",
+ " to update MD5 checksums or add new books ",
+ EMPTY );
+ }
+
+ private void assertHelpLines( String... expectedLines ) {
+ assertEquals( join( expectedLines, LINE_SEPARATOR ), sink.toString() );
+ }
+
+ static class FakeOutputStream extends ByteArrayOutputStream {
+ boolean closed;
+ boolean flushed;
+
+ @Override
+ public void close() {
+ this.closed = true;
+ }
+
+ @Override
+ public void flush() {
+ this.flushed = true;
+ }
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java
new file mode 100644
index 0000000000..640f0ff90f
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java
@@ -0,0 +1,87 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class EmptyOptionSetTest {
+ private OptionSet empty;
+
+ @Before
+ public void setUp() {
+ empty = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ empty.add( new NonOptionArgumentSpec<>() );
+ }
+
+ @Test
+ public void valueOf() {
+ assertNull( empty.valueOf( "a" ) );
+ }
+
+ @Test
+ public void valuesOf() {
+ assertEquals( emptyList(), empty.valuesOf( "a" ) );
+ }
+
+ @Test
+ public void hasArgument() {
+ assertFalse( empty.hasArgument( "a" ) );
+ }
+
+ @Test
+ public void hasOptions() {
+ assertFalse( empty.hasOptions() );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void valueOfWithNullString() {
+ empty.valueOf( (String) null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void valueOfWithNullOptionSpec() {
+ empty.valueOf( (OptionSpec<?>) null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void valuesOfWithNullString() {
+ empty.valuesOf( (String) null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void valuesOfWithNullOptionSpec() {
+ empty.valuesOf( (OptionSpec<?>) null );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java
new file mode 100644
index 0000000000..5299fef2b9
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java
@@ -0,0 +1,83 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ExceptionMatchers {
+ private ExceptionMatchers() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static Matcher<OptionException> withOption( final String option ) {
+ return new TypeSafeMatcher<OptionException>() {
+ @Override
+ public boolean matchesSafely( OptionException target ) {
+ return target.options().contains( option );
+ }
+
+ public void describeTo( Description description ) {
+ description.appendText( "an OptionException indicating the option ");
+ description.appendValue( option );
+ }
+ };
+ }
+
+ public static Matcher<Throwable> withCauseOfType( final Class<? extends Throwable> type ) {
+ return new TypeSafeMatcher<Throwable>() {
+ @Override
+ public boolean matchesSafely( Throwable target ) {
+ return type.isInstance( target.getCause() );
+ }
+
+ public void describeTo( Description description ) {
+ description.appendText( "an exception with cause of type " );
+ description.appendValue( type );
+ }
+ };
+ }
+
+ public static Matcher<InvocationTargetException> withTargetOfType( final Class<? extends Throwable> type ) {
+ return new TypeSafeMatcher<InvocationTargetException>() {
+ @Override
+ public boolean matchesSafely( InvocationTargetException target ) {
+ return type.isInstance( target.getTargetException() );
+ }
+
+ public void describeTo( Description description ) {
+ description.appendText( "an InvocationTargetException with target of type " );
+ description.appendValue( type );
+ }
+ };
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java
new file mode 100644
index 0000000000..5ed3141b97
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java
@@ -0,0 +1,183 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import static java.math.BigDecimal.*;
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class HandlingDefaultValuesForOptionArgumentsTest extends AbstractOptionParserFixture {
+ @Test
+ public void requiredArgOptionWithDefaultGivesArgIfArgSpecifiedOnCommandLine() {
+ OptionSpec<Integer> optionA =
+ parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ).defaultsTo( 2 );
+
+ OptionSet options = parser.parse( "-a", "1" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( optionA ) );
+ assertTrue( options.hasArgument( "a" ) );
+ assertTrue( options.hasArgument( optionA ) );
+ Integer expectedArgument = 1;
+ assertEquals( expectedArgument, options.valueOf( "a" ) );
+ assertEquals( expectedArgument, options.valueOf( optionA ) );
+ assertEquals( expectedArgument, optionA.value( options ) );
+ assertEquals( asList( expectedArgument ), options.valuesOf( "a" ) );
+ assertEquals( asList( expectedArgument ), options.valuesOf( optionA ) );
+ assertEquals( asList( expectedArgument ), optionA.values( options ) );
+ }
+
+ @Test( expected = OptionMissingRequiredArgumentException.class )
+ public void requiredArgOptionWithDefaultStillsFailToParseIfArgNotSpecifiedOnCommandLine() {
+ parser.accepts( "a" ).withRequiredArg().defaultsTo( "boo" );
+
+ parser.parse( "-a" );
+ }
+
+ @Test
+ public void optionalArgOptionWithDefaultGivesDefaultIfArgNotSpecifiedOnCommandLine() {
+ OptionSpec<Long> optionA =
+ parser.accepts( "a" ).withOptionalArg().ofType( Long.class ).defaultsTo( -1L );
+
+ OptionSet options = parser.parse( "-a" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( optionA ) );
+ assertFalse( options.hasArgument( "a" ) );
+ assertFalse( options.hasArgument( optionA ) );
+ Long expectedArgument = -1L;
+ assertEquals( expectedArgument, options.valueOf( "a" ) );
+ assertEquals( expectedArgument, options.valueOf( optionA ) );
+ assertEquals( expectedArgument, optionA.value( options ) );
+ assertEquals( asList( expectedArgument ), options.valuesOf( "a" ) );
+ assertEquals( asList( expectedArgument ), options.valuesOf( optionA ) );
+ assertEquals( asList( expectedArgument ), optionA.values( options ) );
+ }
+
+ @Test
+ public void optionalArgOptionWithDefaultGivesArgIfSpecifiedOnCommandLine() {
+ OptionSpec<Long> optionA =
+ parser.accepts( "a" ).withOptionalArg().ofType( Long.class ).defaultsTo( -1L );
+
+ OptionSet options = parser.parse( "-a", "2" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( optionA ) );
+ assertTrue( options.hasArgument( "a" ) );
+ assertTrue( options.hasArgument( optionA ) );
+ Long expectedArgument = 2L;
+ assertEquals( expectedArgument, options.valueOf( "a" ) );
+ assertEquals( expectedArgument, options.valueOf( optionA ) );
+ assertEquals( expectedArgument, optionA.value( options ) );
+ assertEquals( asList( expectedArgument ), options.valuesOf( "a" ) );
+ assertEquals( asList( expectedArgument ), options.valuesOf( optionA ) );
+ assertEquals( asList( expectedArgument ), optionA.values( options ) );
+ }
+
+ @Test
+ public void requiredArgOptionWithDefaultGivesDefaultIfOptionNotOnCommandLine() {
+ OptionSpec<BigDecimal> optionA =
+ parser.accepts( "a" ).withRequiredArg().ofType( BigDecimal.class ).defaultsTo( TEN );
+
+ OptionSet options = parser.parse();
+
+ assertFalse( options.has( "a" ) );
+ assertFalse( options.has( optionA ) );
+ assertFalse( options.hasArgument( "a" ) );
+ assertFalse( options.hasArgument( optionA ) );
+ assertEquals( TEN, options.valueOf( "a" ) );
+ assertEquals( TEN, options.valueOf( optionA ) );
+ assertEquals( TEN, optionA.value( options ) );
+ assertEquals( asList( TEN ), options.valuesOf( "a" ) );
+ assertEquals( asList( TEN ), options.valuesOf( optionA ) );
+ assertEquals( asList( TEN ), optionA.values( options ) );
+ }
+
+ @Test
+ public void optionalArgOptionWithDefaultGivesDefaultIfOptionNotOnCommandLine() {
+ OptionSpec<BigDecimal> optionA =
+ parser.accepts( "a" ).withOptionalArg().ofType( BigDecimal.class ).defaultsTo( TEN );
+
+ OptionSet options = parser.parse();
+
+ assertFalse( options.has( "a" ) );
+ assertFalse( options.has( optionA ) );
+ assertFalse( options.hasArgument( "a" ) );
+ assertFalse( options.hasArgument( optionA ) );
+ assertEquals( TEN, options.valueOf( "a" ) );
+ assertEquals( TEN, options.valueOf( optionA ) );
+ assertEquals( TEN, optionA.value( options ) );
+ assertEquals( asList( TEN ), options.valuesOf( "a" ) );
+ assertEquals( asList( TEN ), options.valuesOf( optionA ) );
+ assertEquals( asList( TEN ), optionA.values( options ) );
+ }
+
+ @Test
+ public void allowsListOfDefaults() {
+ OptionSpec<Integer> optionC =
+ parser.accepts( "c" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 1, 2, 3 );
+
+ OptionSet options = parser.parse();
+
+ List<Integer> expected = asList( 1, 2, 3 );
+ assertEquals( expected, optionC.values( options ) );
+ assertEquals( expected, options.valuesOf( optionC ) );
+ }
+
+ @Test
+ public void specifiedOptionArgumentsTrumpsListOfDefaults() {
+ OptionSpec<Integer> optionC =
+ parser.accepts( "c" ).withRequiredArg().ofType( Integer.class )
+ .defaultsTo( 1, 2, 3 ).withValuesSeparatedBy( ',' );
+
+ OptionSet options = parser.parse( "-c", "4", "-c", "5", "-c", "6,7,8" );
+
+ List<Integer> expected = asList( 4, 5, 6, 7, 8 );
+ assertEquals( expected, optionC.values( options ) );
+ assertEquals( expected, options.valuesOf( optionC ) );
+ }
+
+ @Test
+ public void withCompileTimeArraySpecifyingDefaults() {
+ OptionSpec<Integer> optionD =
+ parser.accepts( "d" ).withRequiredArg().ofType( Integer.class ).defaultsTo( new Integer[] { 1, 2, 3 } );
+
+ OptionSet options = parser.parse();
+
+ List<Integer> expected = asList( 1, 2, 3 );
+ assertEquals( expected, optionD.values( options ) );
+ assertEquals( expected, options.valuesOf( optionD ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java
new file mode 100644
index 0000000000..e91fbd3210
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java
@@ -0,0 +1,140 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class InterleavedArgumentsTest {
+ @Test
+ public void onlyAppearingToHaveOptionArguments() {
+ OptionParser parser = new OptionParser( "c" );
+
+ OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( emptyList(), options.valuesOf( "c" ) );
+ assertEquals( asList( "a", "b", "c", "d" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void onlyAppearingToHaveOptionArgumentsButPosixlyCorrect() {
+ OptionParser parser = new OptionParser( "+c" );
+
+ OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( emptyList(), options.valuesOf( "c" ) );
+ assertEquals(
+ asList( "a", "-c", "b", "-c", "c", "-c", "d" ),
+ options.nonOptionArguments() );
+ }
+
+ @Test
+ public void requiredArgument() {
+ OptionParser parser = new OptionParser( "c:" );
+
+ OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( asList( "a", "b", "c", "d" ), options.valuesOf( "c" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void requiredArgumentAndPosixlyCorrect() {
+ OptionParser parser = new OptionParser( "+c:" );
+
+ OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( asList( "a", "b", "c", "d" ), options.valuesOf( "c" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionalArgument() {
+ OptionParser parser = new OptionParser( "c::" );
+
+ OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( asList( "a", "b", "c", "d" ), options.valuesOf( "c" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionalArgumentAndPosixlyCorrect() {
+ OptionParser parser = new OptionParser( "+c::" );
+
+ OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( emptyList(), options.valuesOf( "c" ) );
+ assertEquals( asList( "a", "-c", "b", "-c", "c", "-c", "d" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void leadingNonOptionCausesPosixlyCorrectToIgnoreRemainder() {
+ OptionParser parser = new OptionParser( "+c:" );
+ String[] args = { "boo", "-c", "a", "-c", "b", "-c", "c", "-c", "d" };
+
+ OptionSet options = parser.parse( args );
+
+ assertFalse( options.has( "c" ) );
+ assertEquals( emptyList(), options.valuesOf( "c" ) );
+ assertEquals( asList( args ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionalAbuttedArgumentVersusPosixlyCorrect() {
+ OptionParser parser = new OptionParser( "+c::" );
+
+ OptionSet options = parser.parse( "-ca", "-cb", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( asList( "a", "b" ), options.valuesOf( "c" ) );
+ assertEquals( asList( "c", "-c", "d" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionalKeyValuePairArgumentVersusPosixlyCorrect() {
+ OptionParser parser = new OptionParser( "+c::" );
+
+ OptionSet options = parser.parse( "-c=a", "-c=b", "-c", "c", "-c", "d" );
+
+ assertTrue( options.has( "c" ) );
+ assertEquals( asList( "a", "b" ), options.valuesOf( "c" ) );
+ assertEquals( asList( "c", "-c", "d" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java b/third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java
new file mode 100644
index 0000000000..31221deba7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java
@@ -0,0 +1,71 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class Issue76Test {
+ private OptionParser parser;
+ private OptionSpec<Integer> nonOptions;
+
+ @Before
+ public void setUp() {
+ parser = new OptionParser();
+ parser.accepts( "flag" ).withOptionalArg().withValuesConvertedBy( new ValueConverter<Boolean>() {
+ public Boolean convert( String value ) {
+ if ( "true".equals( value ) )
+ return true;
+ if ( "false".equals( value ) )
+ return false;
+ throw new ValueConversionException( "need 'true' or 'false'" );
+ }
+
+ public Class<? extends Boolean> valueType() {
+ return boolean.class;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+ });
+ nonOptions = parser.nonOptions().ofType( Integer.class );
+ }
+
+ @Test
+ public void suppliedExample() {
+ OptionSet parsed = parser.parse( "--flag", "1", "2" );
+
+ assertTrue( parsed.has( "flag" ) );
+ assertEquals( asList( 1, 2 ), nonOptions.values( parsed ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java
new file mode 100644
index 0000000000..49366cf0fb
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java
@@ -0,0 +1,53 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import joptsimple.util.KeyValuePair;
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.util.KeyValuePair.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class JVMSystemPropertiesArgumentParsingTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "D" ).withRequiredArg().ofType( KeyValuePair.class );
+ }
+
+ @Test
+ public void parsingJVMSystemPropertiesArguments() {
+ OptionSet options = parser.parse( "-Dfile.encoding=UTF-8", "-Dpath.separator=:" );
+ assertEquals(
+ asList( valueOf( "file.encoding=UTF-8" ), valueOf( "path.separator=:" ) ),
+ options.valuesOf( "D" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java
new file mode 100644
index 0000000000..c41f9bbd66
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java
@@ -0,0 +1,82 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class LongOptionNoArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "verbose" );
+ parser.accepts( "verb" );
+ }
+
+ @Test
+ public void singleLongOption() {
+ OptionSet options = parser.parse( "--verbose" );
+
+ assertTrue( options.has( "verbose" ) );
+ assertEquals( emptyList(), options.valuesOf( "verbose" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void singleLongOptionAbbreviated() {
+ OptionSet options = parser.parse( "--verbo" );
+
+ assertTrue( options.has( "verbose" ) );
+ assertFalse( options.has( "verb" ) );
+ assertEquals( emptyList(), options.valuesOf( "verbose" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void abbreviationIsALegalOption() {
+ OptionSet options = parser.parse( "--verb" );
+
+ assertFalse( options.has( "verbose" ) );
+ assertTrue( options.has( "verb" ) );
+ assertEquals( emptyList(), options.valuesOf( "verb" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void ambiguousAbbreviation() {
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "ver" ) );
+
+ parser.parse( "--ver" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java
new file mode 100644
index 0000000000..93e4b4d394
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java
@@ -0,0 +1,72 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class LongOptionOptionalArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "output" ).withOptionalArg();
+ parser.accepts( "a" );
+ }
+
+ @Test
+ public void argumentMissingTrailedByAnotherOption() {
+ OptionSet options = parser.parse( "--output", "-a" );
+
+ assertTrue( options.has( "output" ) );
+ assertTrue( options.has( "a" ) );
+ assertEquals( emptyList(), options.valuesOf( "output" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void argumentSeparate() {
+ OptionSet options = parser.parse( "--output", "opt" );
+
+ assertTrue( options.has( "output" ) );
+ assertEquals( singletonList( "opt" ), options.valuesOf( "output" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void argumentTogether() {
+ OptionSet options = parser.parse( "--output=opt" );
+
+ assertTrue( options.has( "output" ) );
+ assertEquals( singletonList( "opt" ), options.valuesOf( "output" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java
new file mode 100644
index 0000000000..fe77f06259
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java
@@ -0,0 +1,103 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class LongOptionRequiredArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "quiet" ).withRequiredArg();
+ parser.accepts( "a" ).withOptionalArg();
+ parser.accepts( "y" ).withRequiredArg();
+ }
+
+ @Test
+ public void argumentSeparate() {
+ OptionSet options = parser.parse( "--quiet", "23" );
+
+ assertOptionDetected( options, "quiet" );
+ assertEquals( singletonList( "23" ), options.valuesOf( "quiet" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void argumentFollowedByLegalOption() {
+ OptionSet options = parser.parse( "--quiet", "-a" );
+
+ assertOptionDetected( options, "quiet" );
+ assertOptionNotDetected( options, "a" );
+ assertEquals( singletonList( "-a" ), options.valuesOf( "quiet" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void argumentTogether() {
+ OptionSet options = parser.parse( "--quiet=23" );
+
+ assertOptionDetected( options, "quiet" );
+ assertEquals( singletonList( "23" ), options.valuesOf( "quiet" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void argumentMissing() {
+ thrown.expect( OptionMissingRequiredArgumentException.class );
+ thrown.expect( withOption( "quiet" ) );
+
+ parser.parse( "--quiet" );
+ }
+
+ @Test
+ public void shortOptionSpecifiedAsLongOptionWithArgument() {
+ OptionSet options = parser.parse( "--y=bar" );
+
+ assertOptionDetected( options, "y" );
+ assertEquals( singletonList( "bar" ), options.valuesOf( "y" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void whenEndOfOptionsMarkerIsInPlaceOfRequiredArgument() {
+ OptionSet options = parser.parse( "--quiet", "--", "-y", "foo", "-a" );
+
+ assertOptionDetected( options, "quiet" );
+ assertOptionDetected( options, "y" );
+ assertOptionDetected( options, "a" );
+ assertEquals( singletonList( "--" ), options.valuesOf( "quiet" ) );
+ assertEquals( singletonList( "foo" ), options.valuesOf( "y" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java
new file mode 100644
index 0000000000..ec9e6a79eb
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java
@@ -0,0 +1,36 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class NoArgumentOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase {
+ @Override
+ protected AbstractOptionSpec<?> newOptionSpec( String option ) {
+ return new NoArgumentOptionSpec( option );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java
new file mode 100644
index 0000000000..e128308c2d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java
@@ -0,0 +1,53 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.infinitest.toolkit.CollectionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class NoArgumentOptionSpecTest extends AbstractOptionSpecFixture {
+ @Override
+ protected NoArgumentOptionSpec createEqualOptionSpecInstance() {
+ return new NoArgumentOptionSpec( "a" );
+ }
+
+ @Override
+ protected NoArgumentOptionSpec createNotEqualOptionSpecInstance() {
+ return new NoArgumentOptionSpec( "b" );
+ }
+
+ @Test
+ public void optionsContents() {
+ assertThat( createNotEqualOptionSpecInstance().options(), hasSameContentsAs( asList( "b" ) ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java
new file mode 100644
index 0000000000..c2212b3213
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java
@@ -0,0 +1,56 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class NoArgumentOptionSpecValuesImmutabilityTest extends AbstractOptionSpecValuesImmutabilityTestCase<Void> {
+ @Override
+ protected AbstractOptionSpec<Void> newOptionSpec() {
+ return new NoArgumentOptionSpec( "verbose" );
+ }
+
+ @Override
+ protected String firstArg() {
+ return "1";
+ }
+
+ @Override
+ protected String secondArg() {
+ return "2";
+ }
+
+ @Override
+ protected Void newItem() {
+ return null;
+ }
+
+ @Override
+ protected Void containedItem() {
+ return null;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java
new file mode 100644
index 0000000000..feef72758c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java
@@ -0,0 +1,108 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+import static joptsimple.util.DateConverter.*;
+import static org.junit.Assert.*;
+
+public class NonOptionArgumentSpecTest extends AbstractOptionParserFixture {
+ @Test
+ public void allowsTypingOfNonOptionArguments() {
+ OptionSpec<File> nonOptions = parser.nonOptions().ofType( File.class );
+
+ OptionSet options = parser.parse( "/opt", "/var" );
+
+ assertEquals( asList( new File( "/opt" ), new File( "/var" ) ), nonOptions.values( options ) );
+ }
+
+ @Test
+ public void allowsDescriptionOfNonOptionArguments() {
+ OptionSpec<String> nonOptions = parser.nonOptions( "directories" );
+
+ OptionSet options = parser.parse( "/opt", "/var" );
+
+ assertEquals( asList( "/opt", "/var" ), nonOptions.values( options ) );
+ }
+
+ @Test
+ public void allowsTypeAndDescriptionOfNonOptionArguments() {
+ OptionSpec<File> nonOptions = parser.nonOptions( "directories" ).ofType( File.class );
+
+ OptionSet options = parser.parse( "/opt", "/var" );
+
+ assertEquals( asList( new File( "/opt" ), new File( "/var" ) ), nonOptions.values( options ) );
+ }
+
+ @Test
+ public void allowsArgumentDescriptionForNonOptionArguments() {
+ OptionSpec<String> nonOptions = parser.nonOptions().describedAs( "dirs" );
+
+ OptionSet options = parser.parse( "/opt", "/var" );
+
+ assertEquals( asList( "/opt", "/var" ), nonOptions.values( options ) );
+ }
+
+ @Test
+ public void doesNotAcceptArguments() {
+ OptionDescriptor nonOptions = parser.nonOptions().describedAs( "dirs" );
+
+ assertFalse( nonOptions.acceptsArguments() );
+ }
+
+ @Test
+ public void convertingUsingConverter() throws Exception {
+ OptionSpec<Date> date = parser.nonOptions().withValuesConvertedBy( datePattern( "MM/dd/yyyy" ) );
+
+ OptionSet options = parser.parse( "01/24/2013" );
+
+ assertEquals(
+ singletonList( new SimpleDateFormat( "MM/dd/yyyy" ).parse( "01/24/2013" ) ),
+ date.values( options ) );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void convertingUsingNullConverter() {
+ parser.nonOptions().withValuesConvertedBy( null );
+ }
+
+ @Test
+ public void noSpecsCorrespondingToNonOptions() {
+ OptionParser parser = new OptionParser();
+ parser.nonOptions();
+
+ OptionSet options = parser.parse( "one", "two" );
+
+ assertEquals( emptyList(), options.specs() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java
new file mode 100644
index 0000000000..e4cd337a2e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java
@@ -0,0 +1,84 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Locale;
+
+import static java.util.Arrays.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+@RunWith( Parameterized.class )
+public class OptionExceptionLocalizedMessageTest {
+ private final OptionException subject;
+ private final String expectedMessage;
+
+ public OptionExceptionLocalizedMessageTest( OptionException subject, String expectedMessage ) {
+ this.subject = subject;
+ this.expectedMessage = expectedMessage;
+ }
+
+ @Parameterized.Parameters
+ public static Collection<?> exceptionsAndMessages() {
+ return asList(
+ new Object[] { new IllegalOptionSpecificationException( "," ), "illegal option specification exception" },
+ new Object[] { new MultipleArgumentsForOptionException(
+ new RequiredArgumentOptionSpec<>( asList( "b", "c" ), "d" ) ),
+ "multiple arguments for option exception" },
+ new Object[] { new OptionArgumentConversionException(
+ new RequiredArgumentOptionSpec<>( asList( "c", "number" ), "x" ), "d", null ),
+ "option argument conversion exception" },
+ new Object[] { new OptionMissingRequiredArgumentException(
+ new RequiredArgumentOptionSpec<>( asList( "e", "honest" ), "" ) ),
+ "option missing required argument exception" },
+ new Object[] { new UnrecognizedOptionException( "f" ), "unrecognized option exception" },
+ new Object[] { new MissingRequiredOptionsException(
+ Arrays.<AbstractOptionSpec<?>> asList(
+ new NoArgumentOptionSpec( "g" ), new NoArgumentOptionSpec( "h" ) ) ),
+ "missing required option exception" },
+ new Object[] { new MissingRequiredOptionsException(
+ Arrays.<AbstractOptionSpec<?>> asList(
+ new RequiredArgumentOptionSpec<>( asList( "p", "place" ), "spot" ),
+ new RequiredArgumentOptionSpec<>( asList( "d", "data-dir" ), "dir" ) ) ),
+ "missing required option exception" },
+ new Object[] { new UnconfiguredOptionException( asList( "i", "j" ) ),
+ "unconfigured option exception" }
+ );
+ }
+
+ @Test
+ public void givesCorrectExceptionMessage() {
+ assertEquals( expectedMessage, subject.localizedMessage( new Locale( "xx", "YY" ) ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java
new file mode 100644
index 0000000000..3afdd8350f
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java
@@ -0,0 +1,91 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Arrays.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+@RunWith( Parameterized.class )
+public class OptionExceptionMessageTest {
+ private final OptionException subject;
+ private final String expectedMessage;
+
+ public OptionExceptionMessageTest( OptionException subject, String expectedMessage ) {
+ this.subject = subject;
+ this.expectedMessage = expectedMessage;
+ }
+
+ @Parameterized.Parameters
+ public static Collection<?> exceptionsAndMessages() {
+ return asList(
+ new Object[] { new IllegalOptionSpecificationException( "," ), ", is not a legal option character" },
+ new Object[] { new MultipleArgumentsForOptionException(
+ new RequiredArgumentOptionSpec<>( asList( "b", "c" ), "d" ) ),
+ "Found multiple arguments for option b/c, but you asked for only one" },
+ new Object[] { new OptionArgumentConversionException(
+ new RequiredArgumentOptionSpec<>( asList( "c", "number" ), "x" ), "d", null ),
+ "Cannot parse argument 'd' of option c/number" },
+ new Object[] { new OptionMissingRequiredArgumentException(
+ new RequiredArgumentOptionSpec<>( asList( "e", "honest" ), "" ) ),
+ "Option e/honest requires an argument" },
+ new Object[] { new UnrecognizedOptionException( "f" ), "f is not a recognized option" },
+ new Object[] { new MissingRequiredOptionsException(
+ Arrays.<AbstractOptionSpec<?>> asList(
+ new NoArgumentOptionSpec( "g" ), new NoArgumentOptionSpec( "h" ) ) ),
+ "Missing required option(s) [g, h]" },
+ new Object[] { new MissingRequiredOptionsException(
+ Arrays.<AbstractOptionSpec<?>> asList(
+ new RequiredArgumentOptionSpec<>( asList( "p", "place" ), "spot" ),
+ new RequiredArgumentOptionSpec<>( asList( "d", "data-dir" ), "dir" ) ) ),
+ "Missing required option(s) [p/place, d/data-dir]" },
+ new Object[] { new UnconfiguredOptionException( asList( "i", "j" ) ),
+ "Option(s) [i, j] not configured on this parser" },
+ new Object[] {
+ new UnavailableOptionException(
+ newArrayList( new NoArgumentOptionSpec( "a" ), new NoArgumentOptionSpec( "b" ) ) ),
+ "Option(s) [a, b] are unavailable given other options on the command line"
+ }
+ );
+ }
+
+ @Test
+ public void givesCorrectExceptionMessage() {
+ assertEquals( expectedMessage, subject.getLocalizedMessage() );
+ assertEquals( expectedMessage, subject.getMessage() );
+ assertEquals( subject.getClass().getName() + ": " + expectedMessage, subject.toString() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java
new file mode 100644
index 0000000000..465d960cf7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java
@@ -0,0 +1,59 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+import static java.util.Arrays.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionExceptionOptionsImmutabilityTest extends UnmodifiableListTestSupport<String> {
+ @Override
+ protected List<String> newList() {
+ return new OptionException( asList( "a", "b" ) ) {
+ private static final long serialVersionUID = -1L;
+
+ @Override
+ Object[] messageArguments() {
+ return new Object[0];
+ }
+ }.options();
+ }
+
+ @Override
+ protected String newItem() {
+ return "c";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "a";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java
new file mode 100644
index 0000000000..b799df696b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java
@@ -0,0 +1,61 @@
+package joptsimple;
+
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static java.util.Arrays.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.infinitest.toolkit.CollectionMatchers.*;
+import static org.junit.Assert.*;
+
+public class OptionParserAlternateHelpFormatterTest extends AbstractOptionParserFixture {
+ private StringWriter sink;
+ private Map<String, ? extends OptionDescriptor> captured;
+
+ @Before
+ public void primeParser() throws Exception {
+ captured = new HashMap<>();
+
+ parser.accepts( "b", "boo" );
+
+ parser.formatHelpWith( new HelpFormatter() {
+ public String format( Map<String, ? extends OptionDescriptor> options ) {
+ captured = options;
+ return "some help you are";
+ }
+ } );
+
+ sink = new StringWriter();
+
+ parser.printHelpOn( sink );
+ }
+
+ @Test
+ public void asksAlternateFormatterForHelpString() {
+ assertEquals( "some help you are", sink.toString() );
+ }
+
+ @Test
+ public void getsFedOptionDescriptorsForRecognizedOptions() {
+ assertEquals( 2, captured.size() );
+ Iterator<? extends Map.Entry<String,? extends OptionDescriptor>> iterator = captured.entrySet().iterator();
+ Map.Entry<String, ? extends OptionDescriptor> first = iterator.next();
+ assertEquals( "[arguments]", first.getKey() );
+ Map.Entry<String, ? extends OptionDescriptor> second = iterator.next();
+ assertEquals("b", second.getKey());
+ OptionDescriptor descriptor = second.getValue();
+ assertThat( descriptor.options(), hasSameContentsAs( asList( "b" ) ) );
+ assertEquals( "boo", descriptor.description() );
+ assertFalse( descriptor.acceptsArguments() );
+ assertFalse( descriptor.requiresArgument() );
+ assertEquals( "", descriptor.argumentDescription() );
+ assertEquals( "", descriptor.argumentTypeIndicator() );
+ assertEquals( Collections.emptyList(), descriptor.defaultValues() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java
new file mode 100644
index 0000000000..4661795a74
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java
@@ -0,0 +1,82 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+
+import static java.util.Collections.*;
+
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionParserArgumentExceptionTest extends AbstractOptionParserFixture {
+ @Test( expected = NullPointerException.class )
+ public void createWithNullOptionSpec() {
+ new OptionParser( null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void parseNull() {
+ parser.parse( (String[]) null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullOptionToAccepts() {
+ parser.accepts( null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullOptionToAcceptsWithDescription() {
+ parser.accepts( null, "a weird option" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullOptionListToAcceptsAll() {
+ parser.acceptsAll( null );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void emptyOptionListToAcceptsAll() {
+ parser.acceptsAll( Collections.<String> emptyList() );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void optionListContainingNullToAcceptsAll() {
+ parser.acceptsAll( singletonList( (String) null ) );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullOptionListToAcceptsAllWithDescription() {
+ parser.acceptsAll( null, "some weird options" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void optionListContainingNullToAcceptsAllWithDescription() {
+ parser.acceptsAll( singletonList( (String) null ), "some weird options" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java
new file mode 100644
index 0000000000..0381af24d4
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java
@@ -0,0 +1,290 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.math.BigInteger;
+import java.sql.Time;
+import java.sql.Timestamp;
+
+import static java.lang.Boolean.*;
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionParserNewDeclarationTest extends AbstractOptionParserFixture {
+ @Test( expected = IllegalOptionSpecificationException.class )
+ public void acceptsIllegalCharacters() {
+ parser.accepts( "!" );
+ }
+
+ @Test
+ public void booleanArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Boolean.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Boolean.class );
+
+ OptionSet options = parser.parse( "-a", "true", "-b", "false" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( TRUE, options.valueOf( "a" ) );
+ assertEquals( singletonList( TRUE ), options.valuesOf( "a" ) );
+ assertEquals( FALSE, options.valueOf( "b" ) );
+ assertEquals( singletonList( FALSE ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void byteArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Byte.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Byte.class );
+
+ OptionSet options = parser.parse( "-a", "-1", "-b", "-2" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Byte.valueOf( "-1" ), options.valueOf( "a" ) );
+ assertEquals( singletonList( Byte.valueOf( "-1" ) ), options.valuesOf( "a" ) );
+ assertEquals( Byte.valueOf( "-2" ), options.valueOf( "b" ) );
+ assertEquals( singletonList( Byte.valueOf( "-2" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void doubleArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Double.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Double.class );
+
+ OptionSet options = parser.parse( "-a", "3.1415926D", "-b", "6.02E23" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Double.valueOf( "3.1415926D" ), options.valueOf( "a" ) );
+ assertEquals( asList( Double.valueOf( "3.1415926D" ) ), options.valuesOf( "a" ) );
+ assertEquals( Double.valueOf( "6.02E23" ), options.valueOf( "b" ) );
+ assertEquals( asList( Double.valueOf( "6.02E23" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void floatArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Float.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Float.class );
+
+ OptionSet options = parser.parse( "-a", "3.1415926F", "-b", "6.02E23F" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Float.valueOf( "3.1415926F" ), options.valueOf( "a" ) );
+ assertEquals( asList( Float.valueOf( "3.1415926F" ) ), options.valuesOf( "a" ) );
+ assertEquals( Float.valueOf( "6.02E23F" ), options.valueOf( "b" ) );
+ assertEquals( asList( Float.valueOf( "6.02E23F" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void integerArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Integer.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-a", "12", "-b", "34" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Integer.valueOf( "12" ), options.valueOf( "a" ) );
+ assertEquals( asList( Integer.valueOf( "12" ) ), options.valuesOf( "a" ) );
+ assertEquals( Integer.valueOf( "34" ), options.valueOf( "b" ) );
+ assertEquals( asList( Integer.valueOf( "34" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void longArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Long.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Long.class );
+
+ OptionSet options = parser.parse( "-a", "123454678901234", "-b", "98765432109876" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Long.valueOf( "123454678901234" ), options.valueOf( "a" ) );
+ assertEquals( singletonList( Long.valueOf( "123454678901234" ) ), options.valuesOf( "a" ) );
+ assertEquals( Long.valueOf( "98765432109876" ), options.valueOf( "b" ) );
+ assertEquals( singletonList( Long.valueOf( "98765432109876" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void shortArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Short.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Short.class );
+
+ OptionSet options = parser.parse( "-a", "5675", "-b", "345" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Short.valueOf( "5675" ), options.valueOf( "a" ) );
+ assertEquals( asList( Short.valueOf( "5675" ) ), options.valuesOf( "a" ) );
+ assertEquals( Short.valueOf( "345" ), options.valueOf( "b" ) );
+ assertEquals( asList( Short.valueOf( "345" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void sqlDateArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( java.sql.Date.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( java.sql.Date.class );
+
+ OptionSet options = parser.parse( "-a", "2001-09-11", "-b", "1941-12-07" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( java.sql.Date.valueOf( "2001-09-11" ), options.valueOf( "a" ) );
+ assertEquals( singletonList( java.sql.Date.valueOf( "2001-09-11" ) ), options.valuesOf( "a" ) );
+ assertEquals( java.sql.Date.valueOf( "1941-12-07" ), options.valueOf( "b" ) );
+ assertEquals( singletonList( java.sql.Date.valueOf( "1941-12-07" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void sqlTimeArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Time.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Time.class );
+
+ OptionSet options = parser.parse( "-a", "08:57:39", "-b", "23:59:59" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Time.valueOf( "08:57:39" ), options.valueOf( "a" ) );
+ assertEquals( asList( Time.valueOf( "08:57:39" ) ), options.valuesOf( "a" ) );
+ assertEquals( Time.valueOf( "23:59:59" ), options.valueOf( "b" ) );
+ assertEquals( asList( Time.valueOf( "23:59:59" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void sqlTimestampArgumentType() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Timestamp.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Timestamp.class );
+
+ OptionSet options = parser.parse( "-a", "1970-01-01 00:00:00", "-b", "1979-12-31 23:59:59.0123456" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Timestamp.valueOf( "1970-01-01 00:00:00" ), options.valueOf( "a" ) );
+ assertEquals( singletonList( Timestamp.valueOf( "1970-01-01 00:00:00" ) ), options.valuesOf( "a" ) );
+ assertEquals( Timestamp.valueOf( "1979-12-31 23:59:59.0123456" ), options.valueOf( "b" ) );
+ assertEquals( singletonList( Timestamp.valueOf( "1979-12-31 23:59:59.0123456" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test( expected = OptionException.class )
+ public void illegalOptionArgumentMethodConversion() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-a", "foo" );
+
+ options.valueOf( "a" );
+ }
+
+ @Test( expected = OptionException.class )
+ public void illegalOptionArgumentConstructorConversion() {
+ parser.accepts( "a" ).withRequiredArg().ofType( BigInteger.class );
+
+ OptionSet options = parser.parse( "-a", "foo" );
+
+ options.valueOf( "a" );
+ }
+
+ @Test
+ public void optionsWithOptionalNegativeNumberArguments() {
+ parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "1" );
+ parser.accepts( "2" );
+
+ OptionSet options = parser.parse( "-a", "-1", "-b", "-2" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( Integer.valueOf( "-1" ), options.valueOf( "a" ) );
+ assertEquals( asList( Integer.valueOf( "-1" ) ), options.valuesOf( "a" ) );
+ assertEquals( Integer.valueOf( "-2" ), options.valueOf( "b" ) );
+ assertEquals( asList( Integer.valueOf( "-2" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionsWithOptionalNegativeNumberArgumentsAndNumberOptions() {
+ parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "1" );
+ parser.accepts( "2" );
+
+ OptionSet options = parser.parse( "-1", "-2", "-a", "-b" );
+
+ assertOptionDetected( options, "1" );
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "2" );
+ assertOptionDetected( options, "b" );
+ assertNull( options.valueOf( "1" ) );
+ assertNull( options.valueOf( "a" ) );
+ assertNull( options.valueOf( "2" ) );
+ assertNull( options.valueOf( "b" ) );
+ assertEquals( emptyList(), options.valuesOf( "1" ) );
+ assertEquals( emptyList(), options.valuesOf( "a" ) );
+ assertEquals( emptyList(), options.valuesOf( "2" ) );
+ assertEquals( emptyList(), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionsWithNegativeNumberArgumentsAndNonNumberOptions() {
+ parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "1" );
+ parser.accepts( "2" );
+
+ OptionSet options = parser.parse( "-1", "-a", "-b", "-2" );
+
+ assertOptionDetected( options, "1" );
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertOptionNotDetected( options, "2" );
+ assertNull( options.valueOf( "1" ) );
+ assertNull( options.valueOf( "a" ) );
+ assertEquals( Integer.valueOf( "-2" ), options.valueOf( "b" ) );
+ assertEquals( emptyList(), options.valuesOf( "1" ) );
+ assertEquals( emptyList(), options.valuesOf( "a" ) );
+ assertEquals( asList( Integer.valueOf( "-2" ) ), options.valuesOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java
new file mode 100644
index 0000000000..3e219d5207
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java
@@ -0,0 +1,78 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionParserOptionExceptionTest extends AbstractOptionParserFixture {
+ @Test
+ public void unrecognizedOption() {
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "a" ) );
+
+ parser.parse( "-a" );
+ }
+
+ @Test
+ public void illegalOptionCharacter() {
+ thrown.expect( IllegalOptionSpecificationException.class );
+ thrown.expect( withOption( "%" ) );
+
+ parser.accepts( "%" );
+ }
+
+ @Test
+ public void asteriskIsIllegalOptionCharacter() {
+ thrown.expect( IllegalOptionSpecificationException.class );
+ thrown.expect( withOption( "*" ) );
+
+ parser.accepts( "*" );
+ }
+
+ @Test
+ public void tooManyHyphens() {
+ parser.accepts( "b" );
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "-b" ) );
+
+ parser.parse( "---b" );
+ }
+
+ @Test
+ public void valueOfWhenMultiples() {
+ parser.accepts( "e" ).withRequiredArg();
+ OptionSet options = parser.parse( "-e", "foo", "-e", "bar" );
+ thrown.expect( MultipleArgumentsForOptionException.class );
+ thrown.expect( withOption( "e" ) );
+
+ options.valueOf( "e" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java
new file mode 100644
index 0000000000..3bddfb998b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java
@@ -0,0 +1,67 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package joptsimple;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class OptionParserRecognizedOptionsTest extends AbstractOptionParserFixture {
+ @Test
+ public void basicOptionsRecognized() {
+ parser.accepts( "first" ).withRequiredArg().required();
+ parser.accepts( "second" ).withOptionalArg();
+ parser.accepts( "third" ).forHelp();
+
+ Map<String, OptionSpec<?>> recognizedOptions = parser.recognizedOptions();
+
+ assertEquals( 4, recognizedOptions.size() );
+ assertTrue( recognizedOptions.keySet().contains( "first" ) );
+ assertTrue( recognizedOptions.keySet().contains( "second" ) );
+ assertTrue( recognizedOptions.keySet().contains( "third" ) );
+ assertTrue( recognizedOptions.keySet().contains( "[arguments]" ) );
+ assertTrue( recognizedOptions.get( "third" ).isForHelp() );
+ assertFalse( recognizedOptions.get( "second" ).isForHelp() );
+ assertNotNull( recognizedOptions.get( "first" ).options() );
+ }
+
+ @Test
+ public void parserPreservesTrainingOrder() {
+ final OptionSpecBuilder z = parser.acceptsAll( asList( "zebra", "aardvark" ) );
+ final OptionSpecBuilder y = parser.accepts( "yak" );
+ final OptionSpecBuilder x = parser.acceptsAll( asList( "baboon", "xantus" ) );
+
+ assertEquals( asList( "[arguments]", "aardvark", "zebra", "yak", "baboon", "xantus" ), new ArrayList<String>(
+ parser.recognizedOptions().keySet() ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java
new file mode 100644
index 0000000000..5538f2d171
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java
@@ -0,0 +1,318 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.lang.Boolean.*;
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionParserTest extends AbstractOptionParserFixture {
+ @Test
+ public void optionsAndNonOptionsInterspersed() {
+ parser.accepts( "i" ).withOptionalArg();
+ parser.accepts( "j" ).withOptionalArg();
+ parser.accepts( "k" );
+
+ OptionSet options =
+ parser.parse( "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" );
+
+ assertOptionDetected( options, "i" );
+ assertOptionDetected( options, "j" );
+ assertOptionDetected( options, "k" );
+ assertEquals( asList( "bar", "junk" ), options.valuesOf( "i" ) );
+ assertEquals( singletonList( "ixnay" ), options.valuesOf( "j" ) );
+ assertEquals( emptyList(), options.valuesOf( "k" ) );
+ assertEquals( asList( "xyz", "foo", "blah", "yermom" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void shortOptionSpecifiedAsLongOptionWithoutArgument() {
+ parser.accepts( "x" );
+
+ OptionSet options = parser.parse( "--x" );
+ assertOptionDetected( options, "x" );
+ assertEquals( emptyList(), options.valuesOf( "x" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void longOptionLeadsWithSingleDash() {
+ parser.accepts( "quiet" );
+ parser.accepts( "queen" );
+
+ OptionSet options = parser.parse( "-quiet" );
+ assertOptionDetected( options, "quiet" );
+ assertEquals( emptyList(), options.valuesOf( "quiet" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void parsesLongOptionAsAbbreviatedShortOption() {
+ parser.accepts( "queen" );
+
+ parser.parse( "-que" );
+ }
+
+ @Test
+ public void parsesLongOptionAsAbbreviatedLongOption() {
+ parser.accepts( "queen" );
+
+ parser.parse( "--que" );
+ }
+
+ @Test
+ public void longOptionLeadsWithSingleDashAmbiguous() {
+ parser.accepts( "quiet" );
+ parser.accepts( "queen" );
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "q" ) );
+
+ parser.parse( "-q" );
+ }
+
+ @Test
+ public void longOptionLeadsWithSingleDashAmbiguousButShortsAreLegal() {
+ parser.accepts( "quiet" );
+ parser.accepts( "queen" );
+ parser.accepts( "q" );
+ parser.accepts( "u" );
+
+ OptionSet options = parser.parse( "-qu" );
+ assertOptionDetected( options, "q" );
+ assertOptionDetected( options, "u" );
+ assertOptionNotDetected( options, "quiet" );
+ assertOptionNotDetected( options, "queen" );
+ assertEquals( emptyList(), options.valuesOf( "q" ) );
+ assertEquals( emptyList(), options.valuesOf( "u" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void longOptionLeadsWithSingleDashAmbiguousButAShortIsIllegal() {
+ parser.accepts( "quiet" );
+ parser.accepts( "queen" );
+ parser.accepts( "q" );
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "u" ) );
+
+ parser.parse( "-qu" );
+ }
+
+ @Test
+ public void longOptionLeadsWithSingleDashAmbiguousButAShortAcceptsAnArgument() {
+ parser.accepts( "quiet" );
+ parser.accepts( "queen" );
+ parser.accepts( "q" ).withOptionalArg();
+
+ OptionSet options = parser.parse( "-qu" );
+ assertOptionDetected( options, "q" );
+ assertOptionNotDetected( options, "quiet" );
+ assertOptionNotDetected( options, "queen" );
+ assertEquals( singletonList( "u" ), options.valuesOf( "q" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void resetHappensAfterParsing() {
+ parser.accepts( "i" ).withOptionalArg();
+ parser.accepts( "j" ).withOptionalArg();
+ parser.accepts( "k" );
+
+ String[] args = { "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" };
+
+ OptionSet options = parser.parse( args );
+ assertEquals( options, parser.parse( args ) );
+ }
+
+ @Test
+ public void typedArguments() {
+ parser.accepts( "a" ).withRequiredArg().ofType( Boolean.class );
+ parser.accepts( "b" ).withOptionalArg().ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-a", "false", "-b", "3", "extra" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertEquals( FALSE, options.valueOf( "a" ) );
+ assertEquals( singletonList( FALSE ), options.valuesOf( "a" ) );
+ assertEquals( Integer.valueOf( "3" ), options.valueOf( "b" ) );
+ assertEquals( singletonList( Integer.valueOf( "3" ) ), options.valuesOf( "b" ) );
+ assertEquals( singletonList( "extra" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void allowsMixingOfOptionsAndNonOptions() {
+ parser.accepts( "i" ).withRequiredArg();
+ parser.accepts( "j" ).withOptionalArg();
+ parser.accepts( "k" );
+
+ OptionSet options = parser.parse( "a", "b", "c", "-i", "boo", "d", "e", "-k", "f", "-j" );
+
+ assertOptionDetected( options, "i" );
+ assertEquals( singletonList( "boo" ), options.valuesOf( "i" ) );
+ assertOptionDetected( options, "j" );
+ assertEquals( emptyList(), options.valuesOf( "j" ) );
+ assertOptionDetected( options, "k" );
+ assertEquals( emptyList(), options.valuesOf( "k" ) );
+ assertEquals( asList( "a", "b", "c", "d", "e", "f" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void disallowsMixingOfOptionsAndNonOptionsUnderPosixlyCorrect() {
+ parser.accepts( "i" ).withRequiredArg();
+ parser.accepts( "j" ).withOptionalArg();
+ parser.accepts( "k" );
+ parser.posixlyCorrect( true );
+
+ OptionSet options = parser.parse( "a", "b", "c", "-i", "boo", "d", "e", "-k", "f", "-j" );
+
+ assertOptionNotDetected( options, "i" );
+ assertEquals( emptyList(), options.valuesOf( "i" ) );
+ assertOptionNotDetected( options, "j" );
+ assertEquals( emptyList(), options.valuesOf( "j" ) );
+ assertOptionNotDetected( options, "k" );
+ assertEquals( emptyList(), options.valuesOf( "j" ) );
+ assertEquals( asList( "a", "b", "c", "-i", "boo", "d", "e", "-k", "f", "-j" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void doubleHyphenSignalsEndsOfOptions() {
+ OptionSet options = new OptionParser( "ab:c::de:f::" ) {
+ {
+ accepts( "verbose" );
+ }
+ }.parse( "-a", "-b=foo", "-c=bar", "--", "-d", "-verbose", "-e", "baz", "-f", "biz" );
+
+ assertOptionDetected( options, "a" );
+ assertEquals( emptyList(), options.valuesOf( "a" ) );
+ assertOptionDetected( options, "b" );
+ assertEquals( singletonList( "foo" ), options.valuesOf( "b" ) );
+ assertOptionDetected( options, "c" );
+ assertEquals( singletonList( "bar" ), options.valuesOf( "c" ) );
+ assertOptionNotDetected( options, "d" );
+ assertOptionNotDetected( options, "verbose" );
+ assertOptionNotDetected( options, "e" );
+ assertOptionNotDetected( options, "f" );
+ assertEquals( asList( "-d", "-verbose", "-e", "baz", "-f", "biz" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void allowsEmptyStringAsArgumentOfOption() {
+ OptionSpec<String> optionI = parser.accepts( "i" ).withOptionalArg();
+
+ OptionSet options = parser.parse( "-i", "" );
+
+ assertOptionDetected( options, "i" );
+ assertEquals( "", optionI.value( options ) );
+ }
+
+ @Test
+ public void allowsWhitespaceyStringAsArgumentOfOption() {
+ String whitespace = " \t\t\n\n\f\f \r\r ";
+ OptionSpec<String> optionJ = parser.accepts( "j" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-j", whitespace );
+
+ assertOptionDetected( options, "j" );
+ assertEquals( whitespace, optionJ.value( options ) );
+ }
+
+ @Test
+ public void allowsEmbeddedWhitespaceInArgumentOfOption() {
+ String withEmbeddedWhitespace = " look at me, I'm flaunting the rules! ";
+ OptionSpec<String> optionJ = parser.accepts( "j" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-j", withEmbeddedWhitespace );
+
+ assertOptionDetected( options, "j" );
+ assertEquals( withEmbeddedWhitespace, optionJ.value( options ) );
+ }
+
+ @Test
+ public void requiredOptionWithArgMissing() {
+ parser.accepts( "t" ).withOptionalArg().required();
+ thrown.expect( MissingRequiredOptionsException.class );
+ thrown.expect( withOption( "t" ) );
+
+ parser.parse();
+ }
+
+ @Test
+ public void requiredOptionButHelpOptionPresent() {
+ parser.accepts( "t" ).withOptionalArg().required();
+ parser.accepts( "h" ).forHelp();
+
+ parser.parse( "-h" );
+ }
+
+ @Test
+ public void configurationPerformedLaterOverrideThosePerformedEarlierForTheSameOption() {
+ parser.accepts( "t" ).withRequiredArg();
+ parser.accepts( "t" ).withOptionalArg();
+
+ parser.parse( "-t" );
+ }
+
+ @Test
+ public void requiredOptionWithSynonymsMissing() {
+ parser.acceptsAll( asList( "h", "help", "?" ) );
+ parser.acceptsAll( asList( "f", "ff", "csv-file-name" ) ).withRequiredArg().required();
+
+ thrown.expect( MissingRequiredOptionsException.class );
+ thrown.expectMessage( new TypeSafeMatcher<String>() {
+ @Override
+ protected boolean matchesSafely( String item ) {
+ return "Missing required option(s) [f/csv-file-name/ff]".equals( item );
+ }
+
+ public void describeTo(Description description) {
+ // purposely doing nothing here
+ }
+ } );
+
+ parser.parse();
+ }
+
+ @Test
+ public void abbreviationsCanBeDisallowed() {
+ OptionParser parser = new OptionParser(false);
+ parser.accepts( "abbreviatable" );
+
+ thrown.expect( UnrecognizedOptionException.class );
+
+ parser.parse( "--abb" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java
new file mode 100644
index 0000000000..8df74cacb2
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java
@@ -0,0 +1,54 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static joptsimple.ExceptionMatchers.withOption;
+import static java.util.Arrays.asList;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class OptionParserUnrecognizedOptionsAllowedTest extends AbstractOptionParserFixture {
+ @Test
+ public void unrecognizedOptionDisallowed() {
+ assertFalse( parser.doesAllowsUnrecognizedOptions() );
+
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "a" ) );
+
+ parser.parse( "-a" );
+ }
+
+ @Test
+ public void unrecognizedOptionAllowed() {
+ parser.allowsUnrecognizedOptions();
+
+ OptionSet options = parser.parse( "-a" );
+
+ assertEquals( asList( "-a" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java
new file mode 100644
index 0000000000..0a8c9a67d6
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java
@@ -0,0 +1,49 @@
+package joptsimple;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.*;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
+ */
+public class OptionSetAsMapTest extends AbstractOptionParserFixture {
+ @Test
+ public void gives() {
+ final OptionSpec<Void> a = parser.accepts( "a" );
+ final OptionSpec<String> b = parser.accepts( "b" ).withRequiredArg();
+ final OptionSpec<String> c = parser.accepts( "c" ).withOptionalArg();
+ final OptionSpec<String> d = parser.accepts( "d" ).withRequiredArg().defaultsTo( "1" );
+ final OptionSpec<String> e = parser.accepts( "e" ).withOptionalArg().defaultsTo( "2" );
+ final OptionSpec<String> f = parser.accepts( "f" ).withRequiredArg().defaultsTo( "3" );
+ final OptionSpec<String> g = parser.accepts( "g" ).withOptionalArg().defaultsTo( "4" );
+ final OptionSpec<Void> h = parser.accepts( "h" );
+
+ OptionSet options = parser.parse( "-a", "-e", "-c", "5", "-d", "6", "-b", "4", "-d", "7", "-e", "8" );
+
+ Map<OptionSpec<?>, List<?>> expected = new HashMap<OptionSpec<?>, List<?>>() {
+ private static final long serialVersionUID = Long.MIN_VALUE;
+
+ {
+ put( a, emptyList() );
+ put( b, asList( "4" ) );
+ put( c, asList( "5" ) );
+ put( d, asList( "6", "7" ) );
+ put( e, asList( "8" ) );
+ put( f, asList( "3" ) );
+ put( g, asList( "4" ) );
+ put( h, emptyList() );
+ }
+ };
+
+ assertThat( options.asMap(), is( equalTo( expected ) ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java
new file mode 100644
index 0000000000..3a7766472e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java
@@ -0,0 +1,50 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSetDetectedOptionsTest extends AbstractOptionParserFixture {
+ @Test
+ public void givesSpecsInOrderOfCommandLinePresentation() {
+ OptionSpec<Void> a = parser.accepts( "a" );
+ OptionSpec<String> b = parser.accepts( "b" ).withRequiredArg();
+ OptionSpec<String> c = parser.accepts( "c" ).withOptionalArg();
+ OptionSpec<String> d = parser.accepts( "d" ).withRequiredArg().defaultsTo( "1" );
+ OptionSpec<String> e = parser.accepts( "e" ).withOptionalArg().defaultsTo( "2" );
+
+ OptionSet options = parser.parse( "-a", "-e", "-c", "5", "-d", "6", "-b", "4", "-d", "7", "-e", "8" );
+
+ assertEquals( Arrays.asList( a, e, c, d, b, d, e ), options.specs() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java
new file mode 100644
index 0000000000..28757ff0c8
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java
@@ -0,0 +1,59 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+
+import org.infinitest.toolkit.StrictEqualsHashCodeTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSetEqualsHashCodeTest extends StrictEqualsHashCodeTestSupport {
+ @Override
+ protected OptionSet equal() {
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ options.addWithArgument( new RequiredArgumentOptionSpec<String>( "anOption" ), "anArg" );
+ return options;
+ }
+
+ @Override
+ protected OptionSet notEqual() {
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ options.addWithArgument( new RequiredArgumentOptionSpec<String>( "anOption" ), "aDifferentArg" );
+ return options;
+ }
+
+ @Override
+ protected Object equalButDifferentClass() {
+ OptionSet options =
+ new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ) {
+ // anonymous subclass
+ };
+ options.addWithArgument( new RequiredArgumentOptionSpec<String>( "anOption" ), "anArg" );
+ return options;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java
new file mode 100644
index 0000000000..7a2f352a51
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java
@@ -0,0 +1,56 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSetNonOptionArgumentsImmutabilityTest extends UnmodifiableListTestSupport<String> {
+ @SuppressWarnings( "unchecked" )
+ @Override
+ protected List<String> newList() {
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ NonOptionArgumentSpec<String> nonOptions = new NonOptionArgumentSpec<>( null );
+ options.addWithArgument( nonOptions, "1" );
+ options.addWithArgument( nonOptions, "2" );
+ return (List<String>) options.nonOptionArguments();
+ }
+
+ @Override
+ protected String newItem() {
+ return "3";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "2";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java
new file mode 100644
index 0000000000..d728828c12
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java
@@ -0,0 +1,53 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSetSpecsImmutabilityTest extends UnmodifiableListTestSupport<OptionSpec<?>> {
+ @Override
+ protected List<OptionSpec<?>> newList() {
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ options.add( new NoArgumentOptionSpec( "a" ) );
+ return options.specs();
+ }
+
+ @Override
+ protected OptionSpec<?> newItem() {
+ return new NoArgumentOptionSpec( "b" );
+ }
+
+ @Override
+ protected OptionSpec<?> containedItem() {
+ return new NoArgumentOptionSpec( "a" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java
new file mode 100644
index 0000000000..6f5189a196
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java
@@ -0,0 +1,57 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSetValuesOfOptionStringImmutabilityTest extends UnmodifiableListTestSupport<Object> {
+ @SuppressWarnings( "unchecked" )
+ @Override
+ protected List<Object> newList() {
+ RequiredArgumentOptionSpec<String> optionB = new RequiredArgumentOptionSpec<>( "b" );
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ options.addWithArgument( optionB, "foo" );
+ options.addWithArgument( optionB, "bar" );
+
+ return (List<Object>) options.valuesOf( "b" );
+ }
+
+ @Override
+ protected String newItem() {
+ return "baz";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "bar";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java
new file mode 100644
index 0000000000..146652a861
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java
@@ -0,0 +1,55 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.infinitest.toolkit.UnmodifiableListTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSetValuesOfSpecImmutabilityTest extends UnmodifiableListTestSupport<String> {
+ @Override
+ protected List<String> newList() {
+ RequiredArgumentOptionSpec<String> optionA = new RequiredArgumentOptionSpec<>( "a" );
+ OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ options.addWithArgument( optionA, "anArgument" );
+ options.addWithArgument( optionA, "anotherArgument" );
+ return options.valuesOf( optionA );
+ }
+
+ @Override
+ protected String newItem() {
+ return "yetAnotherArgument";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "anArgument";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java
new file mode 100644
index 0000000000..231e690cc3
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java
@@ -0,0 +1,38 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSpecBuilderOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase {
+ @Override
+ protected AbstractOptionSpec<?> newOptionSpec( String option ) {
+ return new OptionSpecBuilder( new OptionParser(), asList( option ), "" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java
new file mode 100644
index 0000000000..3adc17dadc
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSpecBuilderValuesImmutabilityTest extends AbstractOptionSpecValuesImmutabilityTestCase<Void> {
+ @Override
+ protected AbstractOptionSpec<Void> newOptionSpec() {
+ return new OptionSpecBuilder( new OptionParser(), asList( "a" ), "" );
+ }
+
+ @Override
+ protected String firstArg() {
+ return "Q";
+ }
+
+ @Override
+ protected String secondArg() {
+ return "W";
+ }
+
+ @Override
+ protected Void newItem() {
+ return null;
+ }
+
+ @Override
+ protected Void containedItem() {
+ return null;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java
new file mode 100644
index 0000000000..6e403078f7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java
@@ -0,0 +1,205 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.NoSuchElementException;
+
+import static java.util.Collections.*;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.infinitest.toolkit.CollectionMatchers.*;
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSpecTokenizerTest {
+ @Rule public final ExpectedException thrown = none();
+
+ @Test
+ public void tokenizeEmpty() {
+ assertNoMoreTokens( new OptionSpecTokenizer( "" ) );
+ }
+
+ @Test
+ public void tokenizeOptionsWithoutArguments() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "ab" );
+ assertNextTokenTakesNoArgument( lexer, 'a', false );
+ assertNextTokenTakesNoArgument( lexer, 'b', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithRequiredArguments() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "c:d:" );
+ assertNextTokenRequiresAnArgument( lexer, 'c', false );
+ assertNextTokenRequiresAnArgument( lexer, 'd', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithOptionalArguments() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "e::f::" );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'e', false );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'f', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithMixtureOfSpecTypes() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "gh:i::j" );
+ assertNextTokenTakesNoArgument( lexer, 'g', false );
+ assertNextTokenRequiresAnArgument( lexer, 'h', false );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'i', false );
+ assertNextTokenTakesNoArgument( lexer, 'j', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void wByItself() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W" );
+ assertNextTokenTakesNoArgument( lexer, 'W', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void wRequiredArg() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W:" );
+ assertNextTokenRequiresAnArgument( lexer, 'W', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void wOptionalArg() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W::" );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'W', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void alternativeLongOptionsMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W;" );
+ assertNextTokenRequiresAnArgument( lexer, 'W', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithoutArgumentsAndHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "ab*" );
+ assertNextTokenTakesNoArgument( lexer, 'a', false );
+ assertNextTokenTakesNoArgument( lexer, 'b', true );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithRequiredArgumentsAndHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "c*:d:" );
+ assertNextTokenRequiresAnArgument( lexer, 'c', true );
+ assertNextTokenRequiresAnArgument( lexer, 'd', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithOptionalArgumentsAndHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "e*::f*::" );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'e', true );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'f', true );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void tokenizeOptionsWithMixtureOfSpecTypesAndHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "g*h:i*::j" );
+ assertNextTokenTakesNoArgument( lexer, 'g', true );
+ assertNextTokenRequiresAnArgument( lexer, 'h', false );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'i', true );
+ assertNextTokenTakesNoArgument( lexer, 'j', false );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void wByItselfWithHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*" );
+ assertNextTokenTakesNoArgument( lexer, 'W', true );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void wRequiredArgWithHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*:" );
+ assertNextTokenRequiresAnArgument( lexer, 'W', true );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void wOptionalArgWithHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*::" );
+ assertNextTokenTakesAnOptionalArgument( lexer, 'W', true );
+ assertNoMoreTokens( lexer );
+ }
+
+ @Test
+ public void alternativeLongOptionsMarkerWithHelpMarker() {
+ OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*;" );
+ assertNextTokenTakesNoArgument( lexer, 'W', true );
+ }
+
+ private void assertNoMoreTokens( OptionSpecTokenizer lexer ) {
+ assertFalse( lexer.hasMore() );
+
+ thrown.expect( NoSuchElementException.class );
+ lexer.next();
+ }
+
+ private static void assertNextTokenTakesNoArgument( OptionSpecTokenizer lexer, char option, boolean forHelp ) {
+ assertNextToken( lexer, option, false, false, forHelp );
+ }
+
+ private static void assertNextTokenRequiresAnArgument( OptionSpecTokenizer lexer, char option, boolean forHelp ) {
+ assertNextToken( lexer, option, true, true, forHelp );
+ }
+
+ private static void assertNextTokenTakesAnOptionalArgument( OptionSpecTokenizer lexer, char option,
+ boolean forHelp ) {
+
+ assertNextToken( lexer, option, true, false, forHelp );
+ }
+
+ private static void assertNextToken( OptionSpecTokenizer lexer, char option, boolean acceptsArguments,
+ boolean requiresArgument, boolean forHelp ) {
+
+ assertTrue( "no more tokens?", lexer.hasMore() );
+ AbstractOptionSpec<?> spec = lexer.next();
+ assertThat( "option?", spec.options(), hasSameContentsAs( singleton( String.valueOf( option ) ) ) );
+ assertEquals( "accepts args?", acceptsArguments, spec.acceptsArguments() );
+ assertEquals( "requires arg?", requiresArgument, spec.requiresArgument() );
+ assertEquals( "for help?", forHelp, spec.isForHelp() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java
new file mode 100644
index 0000000000..ff531dd198
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java
@@ -0,0 +1,49 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSpecsReportTheirOptionsSortedSpeciallyTest {
+ @Test
+ public void shortOptionsComeFirstFollowedByLongOptionsLexicographically() {
+ AbstractOptionSpec<Void> spec = new NoArgumentOptionSpec( asList( "after-date", "n", "N", "past" ), "" );
+
+ List<String> actualOptions = new ArrayList<>( spec.options() );
+
+ assertEquals( asList( "N", "n", "after-date", "past" ), actualOptions );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java
new file mode 100644
index 0000000000..986761d7ff
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java
@@ -0,0 +1,88 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSynonymCommonPrefixesTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.acceptsAll( asList( "v", "verbose" ) );
+ }
+
+ @Test
+ public void parsingFirstPrefix() {
+ assertDetections( "-v" );
+ }
+
+ @Test
+ public void parsingSecondPrefix() {
+ assertDetections( "-ve" );
+ }
+
+ @Test
+ public void parsingThirdPrefix() {
+ assertDetections( "-ver" );
+ }
+
+ @Test
+ public void parsingFourthPrefix() {
+ assertDetections( "-verb" );
+ }
+
+ @Test
+ public void parsingFifthPrefix() {
+ assertDetections( "-verbo" );
+ }
+
+ @Test
+ public void parsingSixthPrefix() {
+ assertDetections( "-verbos" );
+ }
+
+ @Test
+ public void parsingSeventhPrefix() {
+ assertDetections( "-verbose" );
+ }
+
+ private void assertDetections( String option ) {
+ OptionSet options = parser.parse( option );
+
+ assertOptionDetected( options, "v" );
+ assertOptionNotDetected( options, "ve" );
+ assertOptionNotDetected( options, "ver" );
+ assertOptionNotDetected( options, "verb" );
+ assertOptionNotDetected( options, "verbo" );
+ assertOptionNotDetected( options, "verbos" );
+ assertOptionDetected( options, "verbose" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java
new file mode 100644
index 0000000000..2b66176194
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java
@@ -0,0 +1,71 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSynonymNoArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.acceptsAll( asList( "N", "after-date", "newer" ) );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenFirstSynonymParsed() {
+ assertDetections( "-N" );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenSecondSynonymParsed() {
+ assertDetections( "--after-d" );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenThirdSynonymParsed() {
+ assertDetections( "--n" );
+ }
+
+ private void assertDetections( String option ) {
+ OptionSet options = parser.parse( option );
+
+ assertOptionDetected( options, "N" );
+ assertOptionDetected( options, "after-date" );
+ assertOptionDetected( options, "newer" );
+ assertEquals( emptyList(), options.valuesOf( "N" ) );
+ assertEquals( emptyList(), options.valuesOf( "after-date" ) );
+ assertEquals( emptyList(), options.valuesOf( "newer" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java
new file mode 100644
index 0000000000..5ff03e5cba
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java
@@ -0,0 +1,80 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.io.File;
+import java.util.List;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSynonymOptionalArgumentTest extends AbstractOptionParserFixture {
+ private String optionArgument;
+
+ @Before
+ public final void initializeParser() {
+ parser.acceptsAll( asList( "d", "output-dir", "folder" ), "file" ).withRequiredArg().ofType( File.class );
+ optionArgument = "tmp";
+ }
+
+ @Test
+ public void hasAllSynonymsWhenFirstSynonymParsed() {
+ assertDetections( new String[] { "-d", optionArgument }, singletonList( new File( optionArgument ) ) );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenSecondSynonymParsed() {
+ assertDetections( new String[] { "--ou", optionArgument }, singletonList( new File( optionArgument ) ) );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenThirdSynonymParsed() {
+ assertDetections( new String[] { "--fold", optionArgument }, singletonList( new File( optionArgument ) ) );
+ }
+
+ @Test
+ public void reportsSameListOfArgumentsForEverySynonymOption() {
+ assertDetections(
+ new String[] { "-d", "opt", "--output-dir", "tmp", "--folder", "usr" },
+ asList( new File( "opt" ), new File( "tmp" ), new File( "usr" ) ) );
+ }
+
+ private void assertDetections( String[] args, List<?> optionArguments ) {
+ OptionSet options = parser.parse( args );
+ assertEquals( optionArguments, options.valuesOf( "d" ) );
+ assertEquals( optionArguments, options.valuesOf( "output-dir" ) );
+ assertEquals( optionArguments, options.valuesOf( "folder" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java
new file mode 100644
index 0000000000..3294d341fa
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java
@@ -0,0 +1,51 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSynonymOverwritingTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.acceptsAll( asList( "h", "help" ) );
+ parser.acceptsAll( asList( "h", "oops" ) );
+ }
+
+ @Test
+ public void treatsHAsThoughItWereLastDefinedSynonymOfH() {
+ OptionSet options = parser.parse( "-h" );
+
+ assertOptionDetected( options, "h" );
+ assertOptionDetected( options, "oops" );
+ assertOptionNotDetected( options, "help" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java
new file mode 100644
index 0000000000..10d788907d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java
@@ -0,0 +1,82 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSynonymRequiredArgumentTest extends AbstractOptionParserFixture {
+ private String optionArgument;
+
+ @Before
+ public final void initializeParser() {
+ parser.acceptsAll( asList( "N", "after-date", "newer" ), "date" ).withRequiredArg().ofType( Integer.class );
+ optionArgument = "2000";
+ }
+
+ @Test
+ public void hasAllSynonymsWhenFirstSynonymParsed() {
+ assertDetections( new String[] { "-N", optionArgument }, singletonList( Integer.valueOf( optionArgument ) ) );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenSecondSynonymParsed() {
+ assertDetections(
+ new String[] { "--after-date", optionArgument },
+ singletonList( Integer.valueOf( optionArgument ) ) );
+ }
+
+ @Test
+ public void hasAllSynonymsWhenThirdSynonymParsed() {
+ assertDetections(
+ new String[] { "--newer", optionArgument },
+ singletonList( Integer.valueOf( optionArgument ) ) );
+ }
+
+ @Test
+ public void reportsSameListOfArgumentsForEverySynonymOption() {
+ assertDetections( new String[] { "-N", "1", "-aft", "2", "--ne", "3" }, asList( 1, 2, 3 ) );
+ }
+
+ private void assertDetections( String[] args, List<?> optionArguments ) {
+ OptionSet options = parser.parse( args );
+
+ assertEquals( optionArguments, options.valuesOf( "N" ) );
+ assertEquals( optionArguments, options.valuesOf( "after-date" ) );
+ assertEquals( optionArguments, options.valuesOf( "newer" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java
new file mode 100644
index 0000000000..86765a55ab
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java
@@ -0,0 +1,36 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionalArgumentOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase {
+ @Override
+ protected AbstractOptionSpec<?> newOptionSpec( String option ) {
+ return new OptionalArgumentOptionSpec<Integer>( option );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java
new file mode 100644
index 0000000000..6f5c275ced
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java
@@ -0,0 +1,53 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.infinitest.toolkit.CollectionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionalArgumentOptionSpecTest extends AbstractOptionSpecFixture {
+ @Override
+ protected OptionalArgumentOptionSpec<?> createEqualOptionSpecInstance() {
+ return new OptionalArgumentOptionSpec<Void>( "d" );
+ }
+
+ @Override
+ protected OptionalArgumentOptionSpec<?> createNotEqualOptionSpecInstance() {
+ return new OptionalArgumentOptionSpec<Void>( "c" );
+ }
+
+ @Test
+ public void optionsContents() {
+ assertThat( createNotEqualOptionSpecInstance().options(), hasSameContentsAs( asList( "c" ) ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java
new file mode 100644
index 0000000000..841b9460c7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionalArgumentOptionSpecValuesImmutabilityTest
+ extends AbstractOptionSpecValuesImmutabilityTestCase<Integer> {
+
+ @Override
+ protected AbstractOptionSpec<Integer> newOptionSpec() {
+ return new OptionalArgumentOptionSpec<Integer>( "life" ).ofType( Integer.class );
+ }
+
+ @Override
+ protected String firstArg() {
+ return "1";
+ }
+
+ @Override
+ protected String secondArg() {
+ return "2";
+ }
+
+ @Override
+ protected Integer newItem() {
+ return 3;
+ }
+
+ @Override
+ protected Integer containedItem() {
+ return 2;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java
new file mode 100644
index 0000000000..82317befba
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java
@@ -0,0 +1,35 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ParserRulesUtilityClassTest extends UtilityClassesUninstantiabilityHarness {
+ public ParserRulesUtilityClassTest() {
+ super( ParserRules.class );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java
new file mode 100644
index 0000000000..4e18003782
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java
@@ -0,0 +1,82 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.io.File;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ParsingSeparatedConvertedOptionValuesTest extends AbstractOptionParserFixture {
+ @Test
+ public void parsesSeparatedValuesAsSeparateArgument() {
+ assertCorrectParse( "classpath", ':', "--classpath", "/usr:/opt:/var" );
+ }
+
+ @Test
+ public void parsesSeparatedValuesWhenArgumentAbuttedWithEquals() {
+ assertCorrectParse( "classpath", ':', "--classpath=/usr:/opt:/var" );
+ }
+
+ @Test
+ public void parsesEqualsSeparatedValuesWhenArgumentAbuttedWithEquals() {
+ assertCorrectParse( "classpath", '=', "--classpath=/usr=/opt=/var" );
+ }
+
+ @Test
+ public void parsesSeparatedValuesAbutting() {
+ assertCorrectParse( "c", ':', "-c/usr:/opt:/var" );
+ }
+
+ private void assertCorrectParse( String option, char separator, String... args ) {
+ parser.accepts( option ).withRequiredArg().withValuesSeparatedBy( separator )
+ .withValuesConvertedBy( new ValueConverter<File>() {
+ public File convert( String value ) {
+ return new File( value );
+ }
+
+ public Class<File> valueType() {
+ return File.class;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+ } );
+
+ OptionSet options = parser.parse( args );
+
+ assertEquals(
+ asList( new File( "/usr" ), new File( "/opt" ), new File( "/var" ) ),
+ options.valuesOf( option ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java
new file mode 100644
index 0000000000..6cfe17f862
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java
@@ -0,0 +1,75 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ParsingSeparatedStringOptionValuesTest extends AbstractOptionParserFixture {
+ @Test
+ public void parsesSeparatedValuesAsSeparateArgument() {
+ assertCorrectParse( "classpath", ":::", "--classpath", "/usr:::/opt:::/var" );
+ }
+
+ @Test
+ public void parsesSeparatedValuesWhenArgumentAbuttedWithEquals() {
+ assertCorrectParse( "classpath", ":", "--classpath=/usr:/opt:/var" );
+ }
+
+ @Test
+ public void parsesEqualsSeparatedValuesWhenArgumentAbuttedWithEquals() {
+ assertCorrectParse( "classpath", ":=", "--classpath=/usr:=/opt:=/var" );
+ }
+
+ @Test
+ public void parsesSeparatedValuesAbutting() {
+ assertCorrectParse( "c", ";", "-c/usr;/opt;/var" );
+ }
+
+ @Test
+ public void parsesHyphenSeparatedValuesAbutting() {
+ assertCorrectParse( "c", "--", "-c/usr--/opt--/var" );
+ }
+
+ @Test
+ public void handlesConsecutiveDelimiters() {
+ assertCorrectParse( "c", ",", "-c,/usr,,,/opt,,,/var,,,,," );
+ }
+
+ private void assertCorrectParse( String option, String separator, String... args ) {
+ parser.accepts( option ).withRequiredArg().withValuesSeparatedBy( separator );
+
+ OptionSet options = parser.parse( args );
+
+ assertEquals( asList( "/usr", "/opt", "/var" ), options.valuesOf( option ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java
new file mode 100644
index 0000000000..0cfc1e93fb
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java
@@ -0,0 +1,69 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.io.File;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ParsingSeparatedTypedOptionValuesTest extends AbstractOptionParserFixture {
+ @Test
+ public void parsesSeparatedValuesAsSeparateArgument() {
+ assertCorrectParse( "classpath", ':', "--classpath", "/usr:/opt:/var" );
+ }
+
+ @Test
+ public void parsesSeparatedValuesWhenArgumentAbuttedWithEquals() {
+ assertCorrectParse( "classpath", ':', "--classpath=/usr:/opt:/var" );
+ }
+
+ @Test
+ public void parsesEqualsSeparatedValuesWhenArgumentAbuttedWithEquals() {
+ assertCorrectParse( "classpath", '=', "--classpath=/usr=/opt=/var" );
+ }
+
+ @Test
+ public void parsesSeparatedValuesAbutting() {
+ assertCorrectParse( "c", ':', "-c/usr:/opt:/var" );
+ }
+
+ private void assertCorrectParse( String option, char separator, String... args ) {
+ parser.accepts( option ).withRequiredArg().ofType( File.class ).withValuesSeparatedBy( separator );
+
+ OptionSet options = parser.parse( args );
+
+ assertEquals(
+ asList( new File( "/usr" ), new File( "/opt" ), new File( "/var" ) ),
+ options.valuesOf( option ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java
new file mode 100644
index 0000000000..3fe8f509f8
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java
@@ -0,0 +1,46 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class PlainOldOptionParserTest extends AbstractOptionParserFixture {
+ @Test
+ public void nonOptionsOnly() {
+ String[] arguments = { "foo", "bar" };
+
+ OptionSet options = parser.parse( arguments );
+
+ assertEquals( asList( arguments ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java
new file mode 100644
index 0000000000..5ac50368d2
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java
@@ -0,0 +1,72 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package joptsimple;
+
+import java.util.Collections;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class PopulatedOptionSetTest {
+ private OptionSet populated;
+
+ @Before
+ public void setUp() {
+ populated = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() );
+ populated.add( new NoArgumentOptionSpec( "a" ) );
+ populated.addWithArgument( new RequiredArgumentOptionSpec<String>( "b" ), "arg-of-b" );
+ }
+
+ @Test
+ public void hasArgument() {
+ assertFalse( populated.hasArgument( "a" ) );
+ assertTrue( populated.hasArgument( "b" ) );
+ }
+
+ @Test
+ public void valueOf() {
+ assertNull( populated.valueOf( "a" ) );
+ assertEquals( "arg-of-b", populated.valueOf( "b" ) );
+ }
+
+ @Test
+ public void valuesOf() {
+ assertEquals( emptyList(), populated.valuesOf( "a" ) );
+ assertEquals( singletonList( "arg-of-b" ), populated.valuesOf( "b" ) );
+ }
+
+ @Test
+ public void hasOptions() {
+ assertTrue( populated.hasOptions() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java
new file mode 100644
index 0000000000..027c0a29c7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java
@@ -0,0 +1,74 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collection;
+
+import static java.util.Arrays.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+@RunWith( Parameterized.class )
+public class PosixlyCorrectOptionParserTest {
+ private final OptionParser parser;
+
+ public PosixlyCorrectOptionParserTest( OptionParser parser ) {
+ this.parser = parser;
+ }
+
+ @Parameterized.Parameters
+ public static Collection<?> parsers() {
+ return asList( new Object[] {
+ new OptionParser() { {
+ posixlyCorrect( true );
+ accepts( "i" ).withRequiredArg();
+ accepts( "j" ).withOptionalArg();
+ accepts( "k" );
+ } } },
+ new Object[] { new OptionParser( "+i:j::k" ) } );
+ }
+
+ @Test
+ public void parseWithPosixlyCorrect() {
+ OptionSet options =
+ parser.parse( "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" );
+
+ assertTrue( "i?", options.has( "i" ) );
+ assertFalse( "j?", options.has( "j" ) );
+ assertFalse( "k?", options.has( "k" ) );
+ assertEquals( "args of i?", asList( "bar", "junk" ), options.valuesOf( "i" ) );
+ assertEquals( "non-option args?",
+ asList( "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" ),
+ options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java
new file mode 100644
index 0000000000..94e4e23a76
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java
@@ -0,0 +1,73 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class PunctuationInLongOptionTest extends AbstractOptionParserFixture {
+ @Test
+ public void allowsHyphensInTheMiddleOfOptionNames() {
+ assertOptionAllowed( "hyphenated-option" );
+ }
+
+ @Test
+ public void allowsHyphensPrettyMuchAnywhereButTheFront() {
+ assertOptionAllowed( "a-cra-zy-but-le--gal---o-p-t-i-o--n-----" );
+ }
+
+ @Test( expected = IllegalOptionSpecificationException.class )
+ public void disallowsHyphensAtFrontOfOptionName() {
+ parser.accepts( "-weird-option" );
+ }
+
+ @Test
+ public void allowsDotInOptionNames() {
+ assertOptionAllowed( "..what.is.the.d..e...a....l..." );
+ }
+
+ @Test
+ public void allowsQuestionMarkInOptionNames() {
+ assertOptionAllowed( "??who?k??n???e????w?" );
+ }
+
+ @Test
+ public void allowsUnderscoreInOptionNames() {
+ assertOptionAllowed( "super_long_option_name" );
+ }
+
+ private void assertOptionAllowed( String option ) {
+ parser.accepts( option );
+
+ OptionSet options = parser.parse( "--" + option );
+
+ assertTrue( options.has( option ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java
new file mode 100644
index 0000000000..20565b9b9b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java
@@ -0,0 +1,61 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class PunctuationInShortOptionTest {
+ @Test( expected = IllegalOptionSpecificationException.class )
+ public void disallowsHyphenAsShortOption() {
+ new OptionParser( "-" );
+ }
+
+ @Test
+ public void allowsQuestionMarkAsShortOption() {
+ assertOptionAllowed( "?" );
+ }
+
+ @Test
+ public void allowsDotAsShortOption() {
+ assertOptionAllowed( "." );
+ }
+
+ @Test
+ public void allowsUnderscoreAsShortOption() {
+ assertOptionAllowed( "_" );
+ }
+
+ private void assertOptionAllowed( String option ) {
+ OptionSet options = new OptionParser( option ).parse( '-' + option );
+
+ assertTrue( options.has( option ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java
new file mode 100644
index 0000000000..9235d5cc12
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java
@@ -0,0 +1,41 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RequiredArgumentOptionSpecEqualsHashCodeTest extends AbstractOptionSpecFixture {
+ @Override
+ protected RequiredArgumentOptionSpec<?> createEqualOptionSpecInstance() {
+ return new RequiredArgumentOptionSpec<Void>( "a" );
+ }
+
+ @Override
+ protected RequiredArgumentOptionSpec<?> createNotEqualOptionSpecInstance() {
+ return new RequiredArgumentOptionSpec<Void>( "b" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java
new file mode 100644
index 0000000000..e834d1b745
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java
@@ -0,0 +1,36 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RequiredArgumentOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase {
+ @Override
+ protected AbstractOptionSpec<?> newOptionSpec( String option ) {
+ return new RequiredArgumentOptionSpec<String>( option );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java
new file mode 100644
index 0000000000..f75a068b75
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java
@@ -0,0 +1,58 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RequiredArgumentOptionSpecValuesImmutabilityTest
+ extends AbstractOptionSpecValuesImmutabilityTestCase<String> {
+
+ @Override
+ protected AbstractOptionSpec<String> newOptionSpec() {
+ return new RequiredArgumentOptionSpec<>( "file" );
+ }
+
+ @Override
+ protected String firstArg() {
+ return "arg1";
+ }
+
+ @Override
+ protected String secondArg() {
+ return "arg2";
+ }
+
+ @Override
+ protected String newItem() {
+ return "arg3";
+ }
+
+ @Override
+ protected String containedItem() {
+ return "arg1";
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java
new file mode 100644
index 0000000000..75c39d8121
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java
@@ -0,0 +1,86 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RequiredIfAnyTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ parser.accepts( "a" );
+ parser.accepts( "b" );
+ OptionSpec<Void> c = parser.accepts( "c" );
+ OptionSpec<Void> d = parser.accepts( "d" );
+ parser.accepts( "e" );
+ parser.accepts( "n" ).requiredIf( "a", "b" ).requiredIf( c, d );
+ }
+
+ @Test
+ public void rejectsCommandLineMissingConditionallyRequiredOption() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "-a" );
+ }
+
+ @Test
+ public void rejectsCommandLineMissingOtherConditionallyRequiredOption() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "-b" );
+ }
+
+ @Test
+ public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "-a", "-b", "-c", "-d" );
+ }
+
+ @Test
+ public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() {
+ OptionSet options = parser.parse( "-b", "-n" );
+
+ assertOptionDetected( options, "b" );
+ assertOptionDetected( options, "n" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void acceptsOptionWithPrerequisiteAsNormalIfPrerequisiteNotInPlay() {
+ OptionSet options = parser.parse( "-n" );
+
+ assertOptionDetected( options, "n" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java
new file mode 100644
index 0000000000..d5cbb17c28
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java
@@ -0,0 +1,112 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RequiredIfTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ OptionSpec<Void> ftp = parser.acceptsAll( asList( "ftp", "file-transfer" ) );
+ parser.acceptsAll( asList( "username", "userid" ) ).requiredIf( "file-transfer" ).withRequiredArg();
+ parser.acceptsAll( asList( "password", "pwd" ) ).requiredIf( ftp ).withRequiredArg();
+ parser.accepts( "?" ).forHelp();
+ }
+
+ @Test
+ public void rejectsCommandLineMissingConditionallyRequiredOption() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "--ftp" );
+ }
+
+ @Test
+ public void rejectsCommandLineMissingConditionallyRequiredOptionSynonym() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "--file-transfer" );
+ }
+
+ @Test
+ public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "--ftp", "--username", "joe" );
+ }
+
+ @Test
+ public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() {
+ OptionSet options = parser.parse( "--ftp", "--userid", "joe", "--password=secret" );
+
+ assertOptionDetected( options, "ftp" );
+ assertOptionDetected( options, "username" );
+ assertOptionDetected( options, "password" );
+ assertEquals( singletonList( "joe" ), options.valuesOf( "username" ) );
+ assertEquals( singletonList( "secret" ), options.valuesOf( "password" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void acceptsOptionWithPrerequisiteAsNormalIfPrerequisiteNotInPlay() {
+ OptionSet options = parser.parse( "--pwd", "secret" );
+
+ assertOptionDetected( options, "pwd" );
+ assertEquals( singletonList( "secret" ), options.valuesOf( "pwd" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void rejectsOptionNotAlreadyConfigured() {
+ thrown.expect( UnconfiguredOptionException.class );
+
+ parser.accepts( "foo" ).requiredIf( "bar" );
+ }
+
+ @Test
+ public void rejectsOptionSpecNotAlreadyConfigured() {
+ thrown.expect( UnconfiguredOptionException.class );
+
+ parser.accepts( "foo" ).requiredIf( "bar" );
+ }
+
+ @Test
+ public void presenceOfHelpOptionNegatesRequiredIfness() {
+ OptionSet options = parser.parse( "--ftp", "-?" );
+
+ assertOptionDetected( options, "ftp" );
+ assertOptionDetected( options, "?" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java
new file mode 100644
index 0000000000..d61dd78206
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java
@@ -0,0 +1,78 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.Collections.emptyList;
+import static org.junit.Assert.assertEquals;
+
+public class RequiredUnlessAnyTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ parser.accepts( "a" );
+ parser.accepts( "b" );
+ OptionSpec<Void> c = parser.accepts( "c" );
+ OptionSpec<Void> d = parser.accepts( "d" );
+ parser.accepts( "e" );
+ parser.accepts( "n" ).requiredUnless( "a", "b" ).requiredUnless( c, d );
+ }
+
+ @Test
+ public void commandLineMissingConditionallyRequiredOption() {
+ OptionSet options = parser.parse( "-a" );
+ assertOptionDetected( options, "a" );
+ assertOptionNotDetected( options, "n" );
+ }
+
+ @Test
+ public void commandLineWithNotAllConditionallyRequiredOptionsPresent() {
+ OptionSet options = parser.parse( "-a", "-b", "-c", "-d" );
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertOptionDetected( options, "c" );
+ assertOptionDetected( options, "d" );
+ assertOptionNotDetected( options, "n" );
+ }
+
+ @Test
+ public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() {
+ OptionSet options = parser.parse( "-n" );
+
+ assertOptionDetected( options, "n" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void acceptsOptionWithPrerequisiteAsNormalIfPrerequisiteNotInPlay() {
+ OptionSet options = parser.parse( "-a", "-n" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "n" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java
new file mode 100644
index 0000000000..ed5b47b023
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java
@@ -0,0 +1,110 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+
+public class RequiredUnlessTest extends AbstractOptionParserFixture {
+ @Before
+ public void configureParser() {
+ OptionSpec<Void> anonymous = parser.accepts( "anonymous" );
+ parser.acceptsAll( asList( "username", "userid" ) ).requiredUnless( "anonymous" ).withRequiredArg();
+ parser.acceptsAll( asList( "password", "pwd" ) ).requiredUnless( anonymous ).withRequiredArg();
+ parser.accepts( "?" ).forHelp();
+ }
+
+ @Test
+ public void rejectsCommandLineMissingConditionallyRequiredOption() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "" );
+ }
+
+ @Test
+ public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() {
+ thrown.expect( MissingRequiredOptionsException.class );
+
+ parser.parse( "--username", "joe" );
+ }
+
+ @Test
+ public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() {
+ OptionSet options = parser.parse( "--userid", "joe", "--password=secret" );
+
+ assertOptionNotDetected( options, "anonymous" );
+ assertOptionDetected( options, "username" );
+ assertOptionDetected( options, "password" );
+ assertEquals( singletonList( "joe" ), options.valuesOf( "username" ) );
+ assertEquals( singletonList( "secret" ), options.valuesOf( "password" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void acceptsOptionWithPrerequisite() {
+ OptionSet options = parser.parse( "--anonymous" );
+
+ assertOptionDetected( options, "anonymous" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void acceptsOptionWithPrerequisiteAsNormal() {
+ OptionSet options = parser.parse( "--anonymous", "--pwd", "secret" );
+
+ assertOptionDetected( options, "anonymous" );
+ assertOptionDetected( options, "pwd" );
+ assertEquals( singletonList( "secret" ), options.valuesOf( "pwd" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void rejectsOptionNotAlreadyConfigured() {
+ thrown.expect( UnconfiguredOptionException.class );
+
+ parser.accepts( "foo" ).requiredIf( "bar" );
+ }
+
+ @Test
+ public void rejectsOptionSpecNotAlreadyConfigured() {
+ thrown.expect( UnconfiguredOptionException.class );
+
+ parser.accepts( "foo" ).requiredIf( "bar" );
+ }
+
+ @Test
+ public void presenceOfHelpOptionNegatesRequiredUnlessness() {
+ OptionSet options = parser.parse( "-?" );
+
+ assertOptionDetected( options, "?" );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java
new file mode 100644
index 0000000000..6c2af89cda
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java
@@ -0,0 +1,108 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ParserRules.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ShortOptionsNoArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "a" );
+ parser.accepts( "b" );
+ parser.accepts( "c" );
+ }
+
+ @Test
+ public void singleOption() {
+ OptionSet options = parser.parse( "-a" );
+
+ assertOptionDetected( options, "a" );
+ assertNull( options.valueOf( "a" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void twoSingleOptions() {
+ OptionSet options = parser.parse( "-a", "-b" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertNull( options.valueOf( "a" ) );
+ assertNull( options.valueOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void singleOptionWithOneNonOptionArgument() {
+ OptionSet options = parser.parse( "-c", "foo" );
+
+ assertOptionDetected( options, "c" );
+ assertNull( options.valueOf( "c" ) );
+ assertEquals( singletonList( "foo" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void clusteredOptions() {
+ OptionSet options = parser.parse( "-bac" );
+
+ assertOptionDetected( options, "a" );
+ assertOptionDetected( options, "b" );
+ assertOptionDetected( options, "c" );
+ assertNull( options.valueOf( "a" ) );
+ assertNull( options.valueOf( "b" ) );
+ assertNull( options.valueOf( "c" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionsTerminator() {
+ OptionSet options = parser.parse( "-a", OPTION_TERMINATOR, "-a", "-b" );
+
+ assertOptionDetected( options, "a" );
+ assertNull( options.valueOf( "a" ) );
+ assertOptionNotDetected( options, "b" );
+ assertEquals( asList( "-a", "-b" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void appearingMultipleTimes() {
+ OptionSet options = parser.parse( "-b", "-b", "-b" );
+
+ assertOptionDetected( options, "b" );
+ assertNull( options.valueOf( "b" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java
new file mode 100644
index 0000000000..3616d88c04
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java
@@ -0,0 +1,103 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ShortOptionsOptionalArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "f" ).withOptionalArg();
+ parser.accepts( "g" ).withOptionalArg();
+ parser.accepts( "bar" ).withOptionalArg();
+ }
+
+ @Test
+ public void optionWithOptionalArgumentNotPresent() {
+ OptionSet options = parser.parse( "-f" );
+
+ assertOptionDetected( options, "f" );
+ assertEquals( emptyList(), options.valuesOf( "f" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionWithOptionalArgumentPresent() {
+ OptionSet options = parser.parse( "-f", "bar" );
+
+ assertOptionDetected( options, "f" );
+ assertEquals( singletonList( "bar" ), options.valuesOf( "f" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionWithOptionalArgumentThatLooksLikeAnInvalidOption() {
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "biz" ) );
+
+ parser.parse( "-f", "--biz" );
+ }
+
+ @Test
+ public void optionWithOptionalArgumentThatLooksLikeAValidOption() {
+ OptionSet options = parser.parse( "-f", "--bar" );
+
+ assertOptionDetected( options, "f" );
+ assertOptionDetected( options, "bar" );
+ assertEquals( emptyList(), options.valuesOf( "f" ) );
+ assertEquals( emptyList(), options.valuesOf( "bar" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void optionWithOptionalArgumentFollowedByLegalOption() {
+ OptionSet options = parser.parse( "-f", "-g" );
+
+ assertOptionDetected( options, "f" );
+ assertOptionDetected( options, "g" );
+ assertEquals( emptyList(), options.valuesOf( "f" ) );
+ assertEquals( emptyList(), options.valuesOf( "g" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void multipleOfSameOptionSomeWithArgsAndSomeWithout() {
+ OptionSet options = parser.parse( "-f", "-f", "foo", "-f", "-f", "bar", "-f" );
+
+ assertEquals( asList( "foo", "bar" ), options.valuesOf( "f" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java
new file mode 100644
index 0000000000..dea86ca34e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java
@@ -0,0 +1,130 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ShortOptionsRequiredArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "d" ).withRequiredArg();
+ parser.accepts( "e" );
+ parser.accepts( "f" );
+ parser.accepts( "infile" ).withOptionalArg();
+ }
+
+ @Test
+ public void argumentNotPresent() {
+ thrown.expect( OptionMissingRequiredArgumentException.class );
+ thrown.expect( withOption( "d" ) );
+
+ parser.parse( "-d" );
+ }
+
+ @Test
+ public void withArgument() {
+ OptionSet options = parser.parse( "-d", "foo" );
+
+ assertOptionDetected( options, "d" );
+ assertEquals( "foo", options.valueOf( "d" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void clusteredOptionsWithLastOneAcceptingAnArgumentButMissing() {
+ thrown.expect( OptionMissingRequiredArgumentException.class );
+
+ parser.parse( "-fed" );
+ }
+
+ @Test
+ public void clusteredOptionsWithLastOneAcceptingAnArgument() {
+ OptionSet options = parser.parse( "-fed", "foo" );
+
+ assertOptionDetected( options, "d" );
+ assertOptionDetected( options, "f" );
+ assertOptionDetected( options, "e" );
+ assertEquals( "foo", options.valueOf( "d" ) );
+ }
+
+ @Test
+ public void clusteredOptionsWithOneAcceptingAnArgument() {
+ OptionSet options = parser.parse( "-fde" );
+
+ assertOptionDetected( options, "f" );
+ assertOptionDetected( options, "d" );
+ assertOptionNotDetected( options, "e" );
+
+ assertEquals( "e", options.valueOf( "d" ) );
+ }
+
+ @Test
+ public void argumentNotPresentFollowedByAnotherOption() {
+ OptionSet options = parser.parse( "-d", "--infile" );
+
+ assertOptionDetected( options, "d" );
+ assertOptionNotDetected( options, "infile" );
+ assertEquals( "--infile", options.valueOf( "d" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void appearingMultipleTimes() {
+ OptionSet options = parser.parse( "-d", "foo", "-d", "bar" );
+
+ assertOptionDetected( options, "d" );
+ assertEquals( asList( "foo", "bar" ), options.valuesOf( "d" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void inSameToken() {
+ OptionSet options = parser.parse( "-dfoo" );
+
+ assertOptionDetected( options, "d" );
+ assertEquals( singletonList( "foo" ), options.valuesOf( "d" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void whenEndOfOptionsMarkerIsInPlaceOfRequiredArgument() {
+ OptionSet options = parser.parse( "-d", "--", "foo", "bar" );
+
+ assertOptionDetected( options, "d" );
+ assertEquals( singletonList( "--" ), options.valuesOf( "d" ) );
+ assertEquals( asList( "foo", "bar" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java
new file mode 100644
index 0000000000..7c88a7ddd2
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java
@@ -0,0 +1,68 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class SingleHyphenTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "o" ).withOptionalArg();
+ }
+
+ @Test
+ public void singleHyphen() {
+ OptionSet options = parser.parse( "-" );
+
+ assertEquals( singletonList( "-" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void asArgumentOfOption() {
+ OptionSet options = parser.parse( "-o", "-" );
+
+ assertOptionDetected( options, "o" );
+ assertEquals( singletonList( "-" ), options.valuesOf( "o" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void asArgumentOfOptionInSameToken() {
+ OptionSet options = parser.parse( "-o-" );
+
+ assertOptionDetected( options, "o" );
+ assertEquals( singletonList( "-" ), options.valuesOf( "o" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java
new file mode 100644
index 0000000000..0b01a789bb
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java
@@ -0,0 +1,73 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.Collection;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Arrays.*;
+
+import joptsimple.util.KeyValuePair;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+@RunWith( Parameterized.class )
+public class ToStringTest {
+ private final Object subject;
+ private final String[] substrings;
+
+ public ToStringTest( Object subject, String[] substrings ) {
+ this.subject = subject;
+ this.substrings = substrings.clone();
+ }
+
+ @Parameterized.Parameters
+ public static Collection<?> objectsAndStringRepresentations() {
+ return asList( new Object[][] {
+ { KeyValuePair.valueOf( "key=value" ), new String[] { "key", "=", "value" } },
+ { new UnrecognizedOptionException( "a" ), new String[] { "a" } },
+ { new NoArgumentOptionSpec( asList( "a", "b" ), "" ), new String[] { "[a, b]" } },
+ { new UnavailableOptionException(
+ newArrayList( new NoArgumentOptionSpec( "a" ), new NoArgumentOptionSpec( "b" ) ) ),
+ new String[] { "[a, b]" } },
+ } );
+ }
+
+ @Test
+ public void givesUsefulStringRepresentations() {
+ String stringRepresentation = subject.toString();
+
+ for ( String each : substrings )
+ assertThat( stringRepresentation, containsString( each ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java
new file mode 100644
index 0000000000..cea1e728a1
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java
@@ -0,0 +1,317 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import static java.lang.Short.*;
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class TypesafeOptionArgumentRetrievalTest extends AbstractOptionParserFixture {
+ @Test
+ public void retrievalOfTypedRequiredArgumentsInATypesafeManner() {
+ OptionSpec<Integer> optionA = parser.accepts( "a" ).withRequiredArg().ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-a", "1" );
+
+ assertTrue( options.has( optionA ) );
+ Integer valueFromOption = optionA.value( options );
+ assertEquals( Integer.valueOf( 1 ), valueFromOption );
+ Integer valueFromOptionSet = options.valueOf( optionA );
+ assertEquals( valueFromOption, valueFromOptionSet );
+
+ List<Integer> valuesFromOption = optionA.values( options );
+ assertEquals( asList( 1 ), valuesFromOption );
+ List<Integer> valuesFromOptionSet = options.valuesOf( optionA );
+ assertEquals( valuesFromOption, valuesFromOptionSet );
+ }
+
+ @Test
+ public void retrievalOfTypedOptionalArgumentsInATypesafeManner() {
+ OptionSpec<Double> optionB = parser.accepts( "b" ).withOptionalArg().ofType( Double.class );
+
+ OptionSet options = parser.parse( "-b", "3.14D" );
+
+ assertTrue( options.has( optionB ) );
+ assertEquals( Double.valueOf( 3.14D ), optionB.value( options ) );
+ assertEquals( asList( 3.14D ), optionB.values( options ) );
+ }
+
+ @Test
+ public void retrievalOfUntypedRequiredArgumentsInATypesafeManner() {
+ OptionSpec<String> optionC = parser.accepts( "c" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-c", "foo", "-c", "bar" );
+
+ assertTrue( options.has( optionC ) );
+ assertEquals( asList( "foo", "bar" ), optionC.values( options ) );
+ }
+
+ @Test
+ public void retrievalOfUntypedOptionalArgumentsInATypesafeManner() {
+ OptionSpec<String> optionD = parser.accepts( "d" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-d", "foo", "-d", "bar", "-d", "baz" );
+
+ assertTrue( options.has( optionD ) );
+ List<String> valuesFromOption = optionD.values( options );
+ assertEquals( asList( "foo", "bar", "baz" ), valuesFromOption );
+ List<String> valuesFromOptionSet = options.valuesOf( optionD );
+ assertEquals( valuesFromOption, valuesFromOptionSet );
+ }
+
+ @Test
+ public void retrievalWithVoidOption() {
+ OptionSpec<Void> optionE = parser.accepts( "e" );
+
+ OptionSet options = parser.parse( "-e" );
+
+ assertTrue( options.has( optionE ) );
+ assertEquals( emptyList(), options.valuesOf( optionE ) );
+ }
+
+ @Test
+ public void primitiveBooleanAllowedAsTypeSpecifier() {
+ OptionSpec<Boolean> optionA = parser.accepts( "a" ).withRequiredArg().ofType( boolean.class );
+
+ OptionSet options = parser.parse( "-a", "false" );
+
+ assertTrue( options.has( optionA ) );
+ assertEquals( asList( false ), options.valuesOf( optionA ) );
+ }
+
+ @Test
+ public void primitiveByteAllowedAsTypeSpecifier() {
+ OptionSpec<Byte> optionB = parser.accepts( "b" ).withOptionalArg().ofType( byte.class );
+
+ OptionSet options = parser.parse( "-b", "3" );
+
+ assertTrue( options.has( optionB ) );
+ assertEquals( asList( Byte.valueOf( "3" ) ), options.valuesOf( optionB ) );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void primitiveCharAllowedAsTypeSpecifier() {
+ parser.accepts( "c" ).withRequiredArg().ofType( char.class );
+ }
+
+ @Test
+ public void primitiveDoubleAllowedAsTypeSpecifier() {
+ OptionSpec<Double> optionD = parser.accepts( "d" ).withOptionalArg().ofType( double.class );
+
+ OptionSet options = parser.parse( "-d", "3.1" );
+
+ assertTrue( options.has( optionD ) );
+ assertEquals( asList( 3.1D ), options.valuesOf( optionD ) );
+ }
+
+ @Test
+ public void primitiveFloatAllowedAsTypeSpecifier() {
+ OptionSpec<Float> optionE = parser.accepts( "e" ).withRequiredArg().ofType( float.class );
+
+ OptionSet options = parser.parse( "-e", "2.09" );
+
+ assertTrue( options.has( optionE ) );
+ assertEquals( asList( 2.09F ), options.valuesOf( optionE ) );
+ }
+
+ @Test
+ public void primitiveIntAllowedAsTypeSpecifier() {
+ OptionSpec<Integer> optionF = parser.accepts( "F" ).withRequiredArg().ofType( int.class );
+
+ OptionSet options = parser.parse( "-F", "91" );
+
+ assertTrue( options.has( optionF ) );
+ assertEquals( asList( 91 ), options.valuesOf( optionF ) );
+ }
+
+ @Test
+ public void primitiveLongAllowedAsTypeSpecifier() {
+ OptionSpec<Long> optionG = parser.accepts( "g" ).withOptionalArg().ofType( long.class );
+
+ OptionSet options = parser.parse("-g", "12");
+
+ assertTrue( options.has( optionG ) );
+ assertEquals( asList( 12L ), options.valuesOf( optionG ) );
+ }
+
+ @Test
+ public void primitiveShortAllowedAsTypeSpecifier() {
+ OptionSpec<Short> optionH = parser.accepts( "H" ).withRequiredArg().ofType( short.class );
+
+ OptionSet options = parser.parse( "-H", "8" );
+
+ assertTrue( options.has( optionH ) );
+ assertEquals( asList( Short.valueOf( "8" ) ), options.valuesOf( optionH ) );
+ }
+
+ @Test
+ public void cannotFoolHasWithAnOptionNotIssuedFromBuilder() {
+ parser.accepts( "e" );
+
+ OptionSet options = parser.parse( "-e" );
+
+ assertFalse( options.has( new FakeOptionSpec<Void>( "e" ) ) );
+ }
+
+ @Test
+ public void cannotFoolHasArgumentWithAnOptionNotIssuedFromBuilder() {
+ parser.accepts( "f" ).withRequiredArg();
+ OptionSpec<String> fakeOptionF = new FakeOptionSpec<>( "f" );
+
+ OptionSet options = parser.parse( "-f", "boo" );
+
+ assertFalse( options.hasArgument( fakeOptionF ) );
+ }
+
+ @Test
+ public void cannotFoolValueOfWithAnOptionNotIssuedFromBuilder() {
+ parser.accepts( "g" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-g", "foo" );
+
+ assertNull( options.valueOf( new FakeOptionSpec<String>( "g" ) ) );
+ }
+
+ @Test
+ public void cannotFoolValuesOfWithAnOptionNotIssuedFromBuilder() {
+ parser.accepts( "h" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-h", "foo", "-h", "bar" );
+
+ assertEquals( emptyList(), options.valuesOf( new FakeOptionSpec<String>( "h" ) ) );
+ }
+
+ @Test( expected = ClassCastException.class )
+ public void canSubvertTypeSafetyIfYouUseAnOptionSpecAsTheWrongType() {
+ ArgumentAcceptingOptionSpec<String> optionI = parser.accepts( "i" ).withRequiredArg();
+ optionI.ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-i", "2" );
+
+ @SuppressWarnings( "unused" )
+ String value = optionI.value( options );
+ }
+
+ @Test( expected = ClassCastException.class )
+ public void canSubvertTypeSafetyIfYouGiveAnOptionSpecToOptionSetAsTheWrongType() {
+ ArgumentAcceptingOptionSpec<String> optionJ = parser.accepts( "j" ).withRequiredArg();
+ optionJ.ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-j", "3" );
+
+ @SuppressWarnings( "unused" )
+ String value = options.valuesOf( optionJ ).get( 0 );
+ }
+
+ @Test
+ public void canUseBooleanType() {
+ OptionSpec<Boolean> optionK = parser.accepts( "k" ).withRequiredArg().ofType( Boolean.class );
+
+ OptionSet options = parser.parse( "-k", "true" );
+
+ assertTrue( optionK.value( options ) );
+ }
+
+ @Test
+ public void usesConverterIfProvided() {
+ OptionSpec<Short> optionL = parser.accepts( "L" ).withRequiredArg().withValuesConvertedBy(
+ new ValueConverter<Short>() {
+ public Short convert( String value ) {
+ return parseShort( value );
+ }
+
+ public Class<Short> valueType() {
+ return Short.class;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+ } );
+
+ OptionSet options = parser.parse( "-L", "34" );
+
+ assertEquals( new Short( (short) 34 ), optionL.value( options ) );
+ }
+
+ @Test
+ public void wrapsValueConversionExceptionsRaisedByConverter() {
+ OptionSpec<Character> optionM = parser.accepts( "m" ).withRequiredArg().withValuesConvertedBy(
+ new ValueConverter<Character>() {
+ public Character convert( String value ) {
+ throw new ValueConversionException( value );
+ }
+
+ public Class<Character> valueType() {
+ return Character.class;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+ } );
+
+ OptionSet options = parser.parse( "-m", "a" );
+
+ thrown.expect( OptionArgumentConversionException.class );
+ thrown.expect( withCauseOfType( ValueConversionException.class ) );
+
+ optionM.value( options );
+ }
+
+ private static class FakeOptionSpec<V> implements OptionSpec<V> {
+ private final String option;
+
+ FakeOptionSpec( String option ) {
+ this.option = option;
+ }
+
+ public List<String> options() {
+ return asList( option );
+ }
+
+ public V value( OptionSet detectedOptions ) {
+ return detectedOptions.valueOf( this );
+ }
+
+ public List<V> values( OptionSet detectedOptions ) {
+ return detectedOptions.valuesOf( this );
+ }
+
+ public boolean isForHelp() {
+ return false;
+ }
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java b/third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java
new file mode 100644
index 0000000000..e70dba7135
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java
@@ -0,0 +1,60 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.rules.ExpectedException.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class UtilityClassesUninstantiabilityHarness {
+ @Rule public final ExpectedException thrown = none();
+
+ private final Class<?> utility;
+
+ protected UtilityClassesUninstantiabilityHarness( Class<?> utility ) {
+ this.utility = utility;
+ }
+
+ @Test
+ public final void attemptToInstantiate() throws Exception {
+ Constructor<?> constructor = utility.getDeclaredConstructor();
+ constructor.setAccessible( true );
+
+ thrown.expect( InvocationTargetException.class );
+ thrown.expect( withTargetOfType( UnsupportedOperationException.class ) );
+
+ constructor.newInstance();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java
new file mode 100644
index 0000000000..a7e726ed91
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java
@@ -0,0 +1,63 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ValueConverterAdmitsSubclassesOfValueTypeTest {
+ @Test
+ public void subclassOfValueType() {
+ ValueConverter<List<String>> converter = new ValueConverter<List<String>>() {
+ public List<String> convert( String value ) {
+ return Collections.singletonList( value );
+ }
+
+ public Class<? extends List<String>> valueType() {
+ return ListOfStrings.class;
+ }
+
+ public String valuePattern() {
+ return null;
+ }
+ };
+
+ assertEquals( Arrays.asList( "foo" ), converter.convert( "foo" ) );
+ }
+
+ static class ListOfStrings extends ArrayList<String> {
+ private static final long serialVersionUID = 1L;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java
new file mode 100644
index 0000000000..a3092601d8
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java
@@ -0,0 +1,39 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ValueOfHaver {
+ private ValueOfHaver() {
+ // no-op
+ }
+
+ public static ValueOfHaver valueOf( String s ) {
+ return null;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java
new file mode 100644
index 0000000000..119c14b810
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java
@@ -0,0 +1,64 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class WAsAbbreviationForLongOptionTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "Wally" ).withRequiredArg();
+ }
+
+ @Test
+ public void abbreviation() {
+ OptionSet options = parser.parse( "--W", "silent" );
+
+ assertOptionDetected( options, "Wally" );
+ assertOptionNotDetected( options, "W" );
+ assertEquals( singletonList( "silent" ), options.valuesOf( "Wally" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void recognizeLongOptionsTrumpsLongOptionAbbreviation() {
+ parser.recognizeAlternativeLongOptions( true );
+
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "silent" ) );
+
+ parser.parse( "--W", "silent" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java
new file mode 100644
index 0000000000..8cfb5231ae
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java
@@ -0,0 +1,63 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class WAsShortOptionTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "W" );
+ }
+
+ @Test
+ public void wIsLegal() {
+ OptionSet options = parser.parse( "-W", "silent" );
+
+ assertOptionDetected( options, "W" );
+ assertEquals( emptyList(), options.valuesOf( "W" ) );
+ assertEquals( singletonList( "silent" ), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void recognizeLongOptionsTrumpsShortOptionW() {
+ parser.recognizeAlternativeLongOptions( true );
+
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "silent" ) );
+
+ parser.parse( "-W", "silent" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java
new file mode 100644
index 0000000000..cb8a5e93ef
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java
@@ -0,0 +1,65 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class WExtensionNoArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.accepts( "silent" );
+ parser.recognizeAlternativeLongOptions( true );
+ }
+
+ @Test
+ public void turnOffWExtension() {
+ parser.recognizeAlternativeLongOptions( false );
+
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "W" ) );
+
+ parser.parse( "-W", "silent" );
+ }
+
+ @Test
+ public void wExtensionWithLongOptionWithoutAnArgument() {
+ OptionSet options = parser.parse( "-W", "silent" );
+
+ assertOptionNotDetected( options, "W" );
+ assertOptionDetected( options, "silent" );
+ assertEquals( emptyList(), options.valuesOf( "silent" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java
new file mode 100644
index 0000000000..76f247a3a3
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java
@@ -0,0 +1,116 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static joptsimple.ExceptionMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class WExtensionWithArgumentTest extends AbstractOptionParserFixture {
+ @Before
+ public final void initializeParser() {
+ parser.recognizeAlternativeLongOptions( true );
+ parser.accepts( "silent" ).withOptionalArg();
+ }
+
+ @Test
+ public void separateArgument() {
+ OptionSet options = parser.parse( "-W", "silent", "4" );
+
+ assertOptionNotDetected( options, "W" );
+ assertOptionDetected( options, "silent" );
+ assertEquals( singletonList( "4" ), options.valuesOf( "silent" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void togetherArgument() {
+ OptionSet options = parser.parse( "-W", "silent=6" );
+
+ assertOptionNotDetected( options, "W" );
+ assertOptionDetected( options, "silent" );
+ assertEquals( singletonList( "6" ), options.valuesOf( "silent" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void abbreviationWithTogetherArgument() {
+ OptionSet options = parser.parse( "-W", "s=6" );
+
+ assertOptionNotDetected( options, "W" );
+ assertOptionDetected( options, "silent" );
+ assertOptionNotDetected( options, "s" );
+ assertEquals( singletonList( "6" ), options.valuesOf( "silent" ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void illegalLongOption() {
+ thrown.expect( UnrecognizedOptionException.class );
+ thrown.expect( withOption( "foo" ) );
+
+ parser.parse( "-W", "foo=bar" );
+ }
+
+ @Test
+ public void noMoreArguments() {
+ thrown.expect( OptionMissingRequiredArgumentException.class );
+ thrown.expect( withOption( "W" ) );
+
+ parser.parse( "-W" );
+ }
+
+ @Test
+ public void typedTogetherArg() {
+ OptionSpec<Integer> level = parser.accepts( "level" ).withRequiredArg().ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-W", "level=4" );
+
+ assertOptionNotDetected( options, "W" );
+ assertOptionDetected( options, "level" );
+ assertEquals( singletonList( 4 ), options.valuesOf( level ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+
+ @Test
+ public void typedSeparateArg() {
+ OptionSpec<Integer> floor = parser.accepts( "floor" ).withRequiredArg().ofType( Integer.class );
+
+ OptionSet options = parser.parse( "-W", "floor", "5" );
+
+ assertOptionNotDetected( options, "W" );
+ assertOptionDetected( options, "floor" );
+ assertEquals( singletonList( 5 ), options.valuesOf( floor ) );
+ assertEquals( emptyList(), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java
new file mode 100644
index 0000000000..3657a40eab
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java
@@ -0,0 +1,22 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class AlternativeLongOptionsTest {
+ @Test
+ public void handlesAlternativeLongOptions() {
+ OptionParser parser = new OptionParser( "W;" );
+ parser.recognizeAlternativeLongOptions( true ); // same effect as above
+ parser.accepts( "level" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-W", "level=5" );
+
+ assertTrue( options.has( "level" ) );
+ assertTrue( options.hasArgument( "level" ) );
+ assertEquals( "5", options.valueOf( "level" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java
new file mode 100644
index 0000000000..cd11f07b63
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java
@@ -0,0 +1,58 @@
+package joptsimple.examples;
+
+import java.io.File;
+
+import joptsimple.OptionException;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static joptsimple.examples.Level.*;
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.*;
+
+public class DefaultValuesForOptionArgumentsTest {
+ @Rule public final ExpectedException thrown = none();
+
+ @Test
+ public void allowsSpecificationOfDefaultValues() throws Exception {
+ File tempDir = new File( System.getProperty( "java.io.tmpdir" ) );
+ File tempFile = File.createTempFile( "aFile", ".txt" );
+ OptionParser parser = new OptionParser();
+ OptionSpec<File> infile =
+ parser.accepts( "infile" ).withRequiredArg().ofType( File.class ).defaultsTo( tempFile );
+ OptionSpec<File> outdir =
+ parser.accepts( "outdir" ).withRequiredArg().ofType( File.class ).defaultsTo( tempDir );
+ OptionSpec<Integer> bufferSize =
+ parser.accepts( "buffer-size" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 4096 );
+ OptionSpec<Level> level =
+ parser.accepts( "level" ).withOptionalArg().ofType( Level.class ).defaultsTo( INFO );
+ OptionSpec<Integer> count =
+ parser.accepts( "count" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 10 );
+
+ OptionSet options = parser.parse( "--level", "WARNING", "--count", "--infile", "/etc/passwd" );
+
+ assertEquals( new File( "/etc/passwd" ), infile.value( options ) );
+ assertTrue( options.has( infile ) );
+ assertTrue( options.hasArgument( infile ) );
+ assertEquals( tempDir, outdir.value( options ) );
+ assertFalse( options.has( outdir ) );
+ assertFalse( options.hasArgument( outdir ) );
+ assertEquals( Integer.valueOf( 4096 ), bufferSize.value( options ) );
+ assertFalse( options.has( bufferSize ) );
+ assertFalse( options.hasArgument( bufferSize ) );
+ assertEquals( WARNING, level.value( options ) );
+ assertTrue( options.has( level ) );
+ assertTrue( options.hasArgument( level ) );
+ assertEquals( Integer.valueOf( 10 ), count.value( options ) );
+ assertTrue( options.has( count ) );
+ assertFalse( options.hasArgument( count ) );
+
+ thrown.expect( OptionException.class );
+
+ parser.parse( "--outdir" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java
new file mode 100644
index 0000000000..fb4a9e723a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java
@@ -0,0 +1,11 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+
+public class ExceptionExample {
+ public static void main( String[] args ) {
+ OptionParser parser = new OptionParser();
+
+ parser.parse( "-x" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java
new file mode 100644
index 0000000000..730e31834c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java
@@ -0,0 +1,61 @@
+package joptsimple.examples;
+
+import com.google.common.base.Joiner;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+
+public class ExportOptionsTest {
+ private static Properties asProperties( OptionSet options, String prefix ) {
+ Properties properties = new Properties();
+ for ( Entry<OptionSpec<?>, List<?>> entry : options.asMap().entrySet() ) {
+ OptionSpec<?> spec = entry.getKey();
+ properties.setProperty(
+ asPropertyKey( prefix, spec ),
+ asPropertyValue( entry.getValue(), options.has( spec ) ) );
+ }
+ return properties;
+ }
+
+ private static String asPropertyKey( String prefix, OptionSpec<?> spec ) {
+ List<String> flags = spec.options();
+ for ( String flag : flags )
+ if ( 1 < flag.length() )
+ return null == prefix ? flag : ( prefix + '.' + flag );
+ throw new IllegalArgumentException( "No usable non-short flag: " + flags );
+ }
+
+ private static String asPropertyValue( List<?> values, boolean present ) {
+ // Simple flags have no values; treat presence/absence as true/false
+ return values.isEmpty() ? String.valueOf( present ) : Joiner.on( "," ).join( values );
+ }
+
+ @Test
+ public void allowsExportOfOptions() {
+ Properties expected = new Properties();
+ expected.setProperty( "rice.count", "3" );
+ // Cannot check path as string directly - Windows flips the leading slash
+ expected.setProperty( "rice.output-dir", new File( "/tmp" ).toString() );
+ expected.setProperty( "rice.fun", "false" );
+ expected.setProperty( "rice.verbose", "true" );
+
+ OptionParser parser = new OptionParser();
+ OptionSpec<Integer> count = parser.accepts( "count" ).withRequiredArg().ofType( Integer.class );
+ OptionSpec<File> outputDir = parser.accepts( "output-dir" ).withOptionalArg().ofType( File.class );
+ OptionSpec<Void> verbose = parser.accepts( "verbose" );
+ OptionSpec<Void> fun = parser.accepts( "fun" );
+ OptionSpec<File> files = parser.nonOptions().ofType( File.class );
+
+ OptionSet options = parser.parse( "--count", "3", "--output-dir", "/tmp", "--verbose", "a.txt", "b.txt" );
+
+ assertEquals( expected, asProperties( options, "rice" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java
new file mode 100644
index 0000000000..0262d2a76a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java
@@ -0,0 +1,69 @@
+package joptsimple.examples;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Map;
+
+import static java.io.File.*;
+import static java.util.Arrays.*;
+
+import joptsimple.HelpFormatter;
+import joptsimple.OptionDescriptor;
+import joptsimple.OptionParser;
+
+import static joptsimple.util.DateConverter.*;
+
+public class HelpFormatterExample {
+ static class MyFormatter implements HelpFormatter {
+ public String format( Map<String, ? extends OptionDescriptor> options ) {
+ StringBuilder buffer = new StringBuilder();
+ for ( OptionDescriptor each : new HashSet<>( options.values() ) ) {
+ buffer.append( lineFor( each ) );
+ }
+ return buffer.toString();
+ }
+
+ private String lineFor( OptionDescriptor descriptor ) {
+ if ( descriptor.representsNonOptions() ) {
+ return descriptor.argumentDescription() + '(' + descriptor.argumentTypeIndicator() + "): "
+ + descriptor.description() + System.getProperty( "line.separator" );
+ }
+
+ StringBuilder line = new StringBuilder( descriptor.options().toString() );
+ line.append( ": description = " ).append( descriptor.description() );
+ line.append( ", required = " ).append( descriptor.isRequired() );
+ line.append( ", accepts arguments = " ).append( descriptor.acceptsArguments() );
+ line.append( ", requires argument = " ).append( descriptor.requiresArgument() );
+ line.append( ", argument description = " ).append( descriptor.argumentDescription() );
+ line.append( ", argument type indicator = " ).append( descriptor.argumentTypeIndicator() );
+ line.append( ", default values = " ).append( descriptor.defaultValues() );
+ line.append( System.getProperty( "line.separator" ) );
+ return line.toString();
+ }
+ }
+
+ public static void main( String[] args ) throws Exception {
+ OptionParser parser = new OptionParser() {
+ {
+ accepts( "c" ).withRequiredArg().ofType( Integer.class )
+ .describedAs( "count" ).defaultsTo( 1 );
+ accepts( "q" ).withOptionalArg().ofType( Double.class )
+ .describedAs( "quantity" );
+ accepts( "d", "some date" ).withRequiredArg().required()
+ .withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+ acceptsAll( asList( "v", "talkative", "chatty" ), "be more verbose" );
+ accepts( "output-file" ).withOptionalArg().ofType( File.class )
+ .describedAs( "file" );
+ acceptsAll( asList( "h", "?" ), "show help" ).forHelp();
+ acceptsAll( asList( "cp", "classpath" ) ).withRequiredArg()
+ .describedAs( "path1" + pathSeparatorChar + "path2:..." )
+ .ofType( File.class )
+ .withValuesSeparatedBy( pathSeparatorChar );
+ nonOptions( "files to chew on" ).ofType( File.class ).describedAs( "input files" );
+ }
+ };
+
+ parser.formatHelpWith( new MyFormatter() );
+ parser.printHelpOn( System.out );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java
new file mode 100644
index 0000000000..44f024b793
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java
@@ -0,0 +1,35 @@
+package joptsimple.examples;
+
+import java.io.File;
+
+import static java.io.File.*;
+import static java.util.Arrays.*;
+
+import joptsimple.OptionParser;
+
+import static joptsimple.util.DateConverter.*;
+
+public class HelpScreenExample {
+ public static void main( String[] args ) throws Exception {
+ OptionParser parser = new OptionParser() {
+ {
+ accepts( "c" ).withRequiredArg().ofType( Integer.class )
+ .describedAs( "count" ).defaultsTo( 1 );
+ accepts( "q" ).withOptionalArg().ofType( Double.class )
+ .describedAs( "quantity" );
+ accepts( "d", "some date" ).withRequiredArg().required()
+ .withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+ acceptsAll( asList( "v", "talkative", "chatty" ), "be more verbose" );
+ accepts( "output-file" ).withOptionalArg().ofType( File.class )
+ .describedAs( "file" );
+ acceptsAll( asList( "h", "?" ), "show help" ).forHelp();
+ acceptsAll( asList( "cp", "classpath" ) ).withRequiredArg()
+ .describedAs( "path1" + pathSeparatorChar + "path2:..." )
+ .ofType( File.class )
+ .withValuesSeparatedBy( pathSeparatorChar );
+ }
+ };
+
+ parser.printHelpOn( System.out );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java
new file mode 100644
index 0000000000..b3d95d4e58
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java
@@ -0,0 +1,7 @@
+package joptsimple.examples;
+
+public enum Level {
+ WARNING,
+ INFO,
+ DEBUG
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java
new file mode 100644
index 0000000000..30fac0c4d1
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java
@@ -0,0 +1,21 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class LongOptionsTest {
+ @Test
+ public void acceptsLongOptions() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "flag" );
+ parser.accepts( "verbose" );
+
+ OptionSet options = parser.parse( "--flag" );
+
+ assertTrue( options.has( "flag" ) );
+ assertFalse( options.has( "verbose" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java
new file mode 100644
index 0000000000..1cf018b867
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java
@@ -0,0 +1,26 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class LongOptionsWithArgumentPositioningTest {
+ @Test
+ public void allowsDifferentFormsOfPairingArgumentWithOption() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "count" ).withRequiredArg();
+ parser.accepts( "level" ).withOptionalArg();
+
+ OptionSet options = parser.parse( "--count", "4", "--level=3" );
+
+ assertTrue( options.has( "count" ) );
+ assertTrue( options.hasArgument( "count" ) );
+ assertEquals( "4", options.valueOf( "count" ) );
+
+ assertTrue( options.has( "level" ) );
+ assertTrue( options.hasArgument( "level" ) );
+ assertEquals( "3", options.valueOf( "level" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java
new file mode 100644
index 0000000000..38ef67cfec
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java
@@ -0,0 +1,34 @@
+package joptsimple.examples;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class LongOptionsWithArgumentsTest {
+ @Test
+ public void supportsLongOptionsWithArgumentsAndAbbreviations() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "flag" );
+ parser.accepts( "count" ).withRequiredArg();
+ parser.accepts( "level" ).withOptionalArg();
+
+ OptionSet options = parser.parse( "-flag", "--co", "3", "--lev" );
+
+ assertTrue( options.has( "flag" ) );
+
+ assertTrue( options.has( "count" ) );
+ assertTrue( options.hasArgument( "count" ) );
+ assertEquals( "3", options.valueOf( "count" ) );
+ assertEquals( asList( "3" ), options.valuesOf( "count" ) );
+
+ assertTrue( options.has( "level" ) );
+ assertFalse( options.hasArgument( "level" ) );
+ assertNull( options.valueOf( "level" ) );
+ assertEquals( emptyList(), options.valuesOf( "level" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java
new file mode 100644
index 0000000000..47eefd066e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java
@@ -0,0 +1,29 @@
+package joptsimple.examples;
+
+import java.io.File;
+
+import static java.io.File.*;
+import static java.util.Arrays.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.junit.Test;
+
+import static joptsimple.examples.Strings.*;
+import static org.junit.Assert.*;
+
+public class MultipleDelimitedArgumentsTest {
+ @Test
+ public void supportsMultipleDelimitedArguments() {
+ OptionParser parser = new OptionParser();
+ OptionSpec<File> path = parser.accepts( "path" ).withRequiredArg().ofType( File.class )
+ .withValuesSeparatedBy( pathSeparatorChar );
+
+ OptionSet options = parser.parse( "--path", join( pathSeparatorChar, "/tmp", "/var", "/opt" ) );
+
+ assertTrue( options.has( path ) );
+ assertTrue( options.hasArgument( path ) );
+ assertEquals( asList( new File( "/tmp" ), new File( "/var" ), new File( "/opt" ) ), options.valuesOf( path ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java
new file mode 100644
index 0000000000..5841794d83
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java
@@ -0,0 +1,49 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2014 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.joda.time.LocalDate;
+import org.junit.Test;
+
+import static joptsimple.util.DateConverter.*;
+import static joptsimple.util.RegexMatcher.*;
+import static org.junit.Assert.*;
+
+public class OptionArgumentConverterTest {
+ @Test
+ public void usesConvertersOnOptionArgumentsWhenTold() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "birthdate" ).withRequiredArg().withValuesConvertedBy( datePattern( "MM/dd/yy" ) );
+ parser.accepts( "ssn" ).withRequiredArg().withValuesConvertedBy( regex( "\\d{3}-\\d{2}-\\d{4}" ));
+
+ OptionSet options = parser.parse( "--birthdate", "02/24/05", "--ssn", "123-45-6789" );
+
+ assertEquals( new LocalDate( 2005, 2, 24 ).toDate(), options.valueOf( "birthdate" ) );
+ assertEquals( "123-45-6789", options.valueOf( "ssn" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java
new file mode 100644
index 0000000000..2f8e51c630
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java
@@ -0,0 +1,27 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class OptionArgumentValueTypeTest {
+ @Test
+ public void convertsArgumentsToJavaValueTypes() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "flag" );
+ parser.accepts( "count" ).withRequiredArg().ofType( Integer.class );
+ parser.accepts( "level" ).withOptionalArg().ofType( Level.class );
+
+ OptionSet options = parser.parse( "--count", "3", "--level", "DEBUG" );
+
+ assertTrue( options.has( "count" ) );
+ assertTrue( options.hasArgument( "count" ) );
+ assertEquals( 3, options.valueOf( "count" ) );
+
+ assertTrue( options.has( "level" ) );
+ assertTrue( options.hasArgument( "level" ) );
+ assertEquals( Level.DEBUG, options.valueOf( "level" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java
new file mode 100644
index 0000000000..336c4d005c
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java
@@ -0,0 +1,30 @@
+package joptsimple.examples;
+
+import java.util.List;
+
+import static java.util.Arrays.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class OptionSynonymTest {
+ @Test
+ public void supportsOptionSynonyms() {
+ OptionParser parser = new OptionParser();
+ List<String> synonyms = asList( "message", "blurb", "greeting" );
+ parser.acceptsAll( synonyms ).withRequiredArg();
+ String expectedMessage = "Hello";
+
+ OptionSet options = parser.parse( "--message", expectedMessage );
+
+ for ( String each : synonyms ) {
+ assertTrue( each, options.has( each ) );
+ assertTrue( each, options.hasArgument( each ) );
+ assertEquals( each, expectedMessage, options.valueOf( each ) );
+ assertEquals( each, asList( expectedMessage ), options.valuesOf( each ) );
+ }
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java
new file mode 100644
index 0000000000..7acb957a77
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java
@@ -0,0 +1,37 @@
+package joptsimple.examples;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class PosixlyCorrectTest {
+ @Test
+ public void supportsPosixlyCorrectBehavior() {
+ OptionParser parser = new OptionParser( "i:j::k" );
+ String[] arguments = { "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "bah" };
+
+ OptionSet options = parser.parse( arguments );
+
+ assertTrue( options.has( "i" ) );
+ assertTrue( options.has( "j" ) );
+ assertTrue( options.has( "k" ) );
+ assertEquals( asList( "bar", "junk" ), options.valuesOf( "i" ) );
+ assertEquals( asList( "ixnay" ), options.valuesOf( "j" ) );
+ assertEquals( asList( "xyz", "foo", "blah", "bah" ), options.nonOptionArguments() );
+
+ parser.posixlyCorrect( true );
+ options = parser.parse( arguments );
+
+ assertTrue( options.has( "i" ) );
+ assertFalse( options.has( "j" ) );
+ assertFalse( options.has( "k" ) );
+ assertEquals( asList( "bar", "junk" ), options.valuesOf( "i" ) );
+ assertEquals( emptyList(), options.valuesOf( "j" ) );
+ assertEquals( asList( "xyz", "-jixnay", "foo", "-k", "blah", "--", "bah" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java
new file mode 100644
index 0000000000..c062fff87e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java
@@ -0,0 +1,14 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+
+public class RequiredIfExample {
+ public static void main( String[] args ) {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "ftp" );
+ parser.accepts( "username" ).requiredIf( "ftp" ).withRequiredArg();
+ parser.accepts( "password" ).requiredIf( "ftp" ).withRequiredArg();
+
+ parser.parse( "--ftp" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java
new file mode 100644
index 0000000000..5a40ea2ed9
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java
@@ -0,0 +1,49 @@
+package joptsimple.examples;
+
+import joptsimple.OptionException;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class RequiredOptionsTest {
+ @Test( expected = OptionException.class )
+ public void allowsSpecificationOfRequiredOptions() {
+ OptionParser parser = new OptionParser() {
+ {
+ accepts( "userid" ).withRequiredArg().required();
+ accepts( "password" ).withRequiredArg().required();
+ }
+ };
+
+ parser.parse( "--userid", "bob" );
+ }
+
+ @Test
+ public void aHelpOptionMeansRequiredOptionsNeedNotBePresent() {
+ OptionParser parser = new OptionParser() {
+ {
+ accepts( "userid" ).withRequiredArg().required();
+ accepts( "password" ).withRequiredArg().required();
+ accepts( "help" ).forHelp();
+ }
+ };
+
+ OptionSet options = parser.parse( "--help" );
+ assertTrue( options.has( "help" ) );
+ }
+
+ @Test( expected = OptionException.class )
+ public void missingHelpOptionMeansRequiredOptionsMustBePresent() {
+ OptionParser parser = new OptionParser() {
+ {
+ accepts( "userid" ).withRequiredArg().required();
+ accepts( "password" ).withRequiredArg().required();
+ accepts( "help" ).forHelp();
+ }
+ };
+
+ parser.parse( "" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java
new file mode 100644
index 0000000000..f55f6ca91d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java
@@ -0,0 +1,14 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+
+public class RequiredUnlessExample {
+ public static void main( String[] args ) {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "anonymous" );
+ parser.accepts( "username" ).requiredUnless( "anonymous" ).withRequiredArg();
+ parser.accepts( "password" ).requiredUnless( "anonymous" ).withRequiredArg();
+
+ parser.parse( "--anonymous" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java
new file mode 100644
index 0000000000..9143e45d7d
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java
@@ -0,0 +1,21 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ShortOptionsClusteringTest {
+ @Test
+ public void allowsClusteringShortOptions() {
+ OptionParser parser = new OptionParser( "aBcd" );
+
+ OptionSet options = parser.parse( "-cdBa" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( "B" ) );
+ assertTrue( options.has( "c" ) );
+ assertTrue( options.has( "d" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java
new file mode 100644
index 0000000000..695f6cebbc
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java
@@ -0,0 +1,24 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ShortOptionsClusteringWithArgumentTest {
+ @Test
+ public void allowsClusteringShortOptionsThatAcceptArguments() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "a" );
+ parser.accepts( "B" );
+ parser.accepts( "c" ).withRequiredArg();
+
+ OptionSet options = parser.parse( "-aBcfoo" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( "B" ) );
+ assertTrue( options.has( "c" ) );
+ assertEquals( "foo", options.valueOf( "c" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java
new file mode 100644
index 0000000000..4e3487cd0e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java
@@ -0,0 +1,21 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ShortOptionsTest {
+ @Test
+ public void supportsShortOptions() {
+ OptionParser parser = new OptionParser( "aB?*." );
+
+ OptionSet options = parser.parse( "-a", "-B", "-?" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( "B" ) );
+ assertTrue( options.has( "?" ) );
+ assertFalse( options.has( "." ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java
new file mode 100644
index 0000000000..720253ebf2
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java
@@ -0,0 +1,28 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ShortOptionsWithArgumentPositioningTest {
+ @Test
+ public void allowsDifferentFormsOfPairingArgumentWithOption() {
+ OptionParser parser = new OptionParser( "a:b:c::" );
+
+ OptionSet options = parser.parse( "-a", "foo", "-bbar", "-c=baz" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.hasArgument( "a" ) );
+ assertEquals( "foo", options.valueOf( "a" ) );
+
+ assertTrue( options.has( "b" ) );
+ assertTrue( options.hasArgument( "b" ) );
+ assertEquals( "bar", options.valueOf( "b" ) );
+
+ assertTrue( options.has( "c" ) );
+ assertTrue( options.hasArgument( "c" ) );
+ assertEquals( "baz", options.valueOf( "c" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java
new file mode 100644
index 0000000000..3ee7911bd0
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java
@@ -0,0 +1,31 @@
+package joptsimple.examples;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ShortOptionsWithArgumentsTest {
+ @Test
+ public void allowsOptionsToAcceptArguments() {
+ OptionParser parser = new OptionParser( "fc:q::" );
+
+ OptionSet options = parser.parse( "-f", "-c", "foo", "-q" );
+
+ assertTrue( options.has( "f" ) );
+
+ assertTrue( options.has( "c" ) );
+ assertTrue( options.hasArgument( "c" ) );
+ assertEquals( "foo", options.valueOf( "c" ) );
+ assertEquals( asList( "foo" ), options.valuesOf( "c" ) );
+
+ assertTrue( options.has( "q" ) );
+ assertFalse( options.hasArgument( "q" ) );
+ assertNull( options.valueOf( "q" ) );
+ assertEquals( emptyList(), options.valuesOf( "q" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java
new file mode 100644
index 0000000000..8f113f859a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java
@@ -0,0 +1,31 @@
+package joptsimple.examples;
+
+import static java.util.Arrays.*;
+
+import joptsimple.OptionException;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.*;
+
+public class ShortOptionsWithMultipleArgumentsForSingleOptionTest {
+ @Rule public final ExpectedException thrown = none();
+
+ @Test
+ public void allowsMultipleValuesForAnOption() {
+ OptionParser parser = new OptionParser( "a:" );
+
+ OptionSet options = parser.parse( "-a", "foo", "-abar", "-a=baz" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.hasArgument( "a" ) );
+ assertEquals( asList( "foo", "bar", "baz" ), options.valuesOf( "a" ) );
+
+ thrown.expect( OptionException.class );
+ options.valueOf( "a" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java
new file mode 100644
index 0000000000..9fd1faefe7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java
@@ -0,0 +1,31 @@
+package joptsimple.examples;
+
+import static java.util.Arrays.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class SignallingEndOfOptionsTest {
+ @Test
+ public void doubleHyphenSignalsEndOfOptions() {
+ OptionParser parser = new OptionParser( "ab:c::de:f::" );
+
+ OptionSet options = parser.parse( "-a", "-b=foo", "-c=bar", "--", "-d", "-e", "baz", "-f", "biz" );
+
+ assertTrue( options.has( "a" ) );
+ assertFalse( options.hasArgument( "a" ) );
+ assertTrue( options.has( "b" ) );
+ assertTrue( options.hasArgument( "b" ) );
+ assertEquals( asList( "foo" ), options.valuesOf( "b" ) );
+ assertTrue( options.has( "c" ) );
+ assertTrue( options.hasArgument( "c" ) );
+ assertEquals( asList( "bar" ), options.valuesOf( "c" ) );
+ assertFalse( options.has( "d" ) );
+ assertFalse( options.has( "e" ) );
+ assertFalse( options.has( "f" ) );
+ assertEquals( asList( "-d", "-e", "baz", "-f", "biz" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java
new file mode 100644
index 0000000000..4f05559310
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java
@@ -0,0 +1,31 @@
+package joptsimple.examples;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class SpecialOptionalArgumentHandlingTest {
+ @Test
+ public void handlesNegativeNumberOptionalArguments() {
+ OptionParser parser = new OptionParser();
+ parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
+ parser.accepts( "2" );
+
+ OptionSet options = parser.parse( "-a", "-2" );
+
+ assertTrue( options.has( "a" ) );
+ assertFalse( options.has( "2" ) );
+ assertEquals( asList( -2 ), options.valuesOf( "a" ) );
+
+ options = parser.parse( "-2", "-a" );
+
+ assertTrue( options.has( "a" ) );
+ assertTrue( options.has( "2" ) );
+ assertEquals( emptyList(), options.valuesOf( "a" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java
new file mode 100644
index 0000000000..432350632e
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java
@@ -0,0 +1,19 @@
+package joptsimple.examples;
+
+import java.util.Iterator;
+
+import static java.util.Arrays.*;
+
+public class Strings {
+ public static String join( char delimiter, String... pieces ) {
+ StringBuilder builder = new StringBuilder();
+
+ for ( Iterator<String> iter = asList( pieces ).iterator(); iter.hasNext(); ) {
+ builder.append( iter.next() );
+ if ( iter.hasNext() )
+ builder.append( delimiter );
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java
new file mode 100644
index 0000000000..93cd0a5c5b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java
@@ -0,0 +1,45 @@
+package joptsimple.examples;
+
+import java.io.File;
+
+import static java.util.Arrays.*;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TypesafeOptionArgumentRetrievalTest {
+ @Test
+ public void allowsTypesafeRetrievalOfOptionArguments() {
+ OptionParser parser = new OptionParser();
+ OptionSpec<Integer> count = parser.accepts( "count" ).withRequiredArg().ofType( Integer.class );
+ OptionSpec<File> outputDir = parser.accepts( "output-dir" ).withOptionalArg().ofType( File.class );
+ OptionSpec<Void> verbose = parser.accepts( "verbose" );
+ OptionSpec<File> files = parser.nonOptions().ofType( File.class );
+
+ OptionSet options = parser.parse( "--count", "3", "--output-dir", "/tmp", "--verbose", "a.txt", "b.txt" );
+
+ assertTrue( options.has( verbose ) );
+
+ assertTrue( options.has( count ) );
+ assertTrue( options.hasArgument( count ) );
+ Integer expectedCount = 3;
+ assertEquals( expectedCount, options.valueOf( count ) );
+ assertEquals( expectedCount, count.value( options ) );
+ assertEquals( asList( expectedCount ), options.valuesOf( count ) );
+ assertEquals( asList( expectedCount ), count.values( options ) );
+ assertEquals( asList( new File( "a.txt" ), new File( "b.txt" ) ), options.valuesOf( files ) );
+
+ assertTrue( options.has( outputDir ) );
+ assertTrue( options.hasArgument( outputDir ) );
+ File expectedFile = new File( "/tmp" );
+ assertEquals( expectedFile, options.valueOf( outputDir ) );
+ assertEquals( expectedFile, outputDir.value( options ) );
+ assertEquals( asList( expectedFile ), options.valuesOf( outputDir ) );
+ assertEquals( asList( expectedFile ), outputDir.values( options ) );
+ assertEquals( asList( new File( "a.txt" ), new File( "b.txt" ) ), files.values( options ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java
new file mode 100644
index 0000000000..6dc9972028
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java
@@ -0,0 +1,23 @@
+package joptsimple.examples;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import org.junit.Test;
+
+import static java.util.Arrays.*;
+import static org.junit.Assert.*;
+
+public class UnrecognizedOptionsAllowedTest {
+ @Test
+ public void acceptsLongOptions() {
+ OptionParser parser = new OptionParser();
+ parser.allowsUnrecognizedOptions();
+ parser.accepts( "f" );
+
+ OptionSet options = parser.parse( "-f", "-d" );
+
+ assertTrue( options.has( "f" ) );
+ assertFalse( options.has( "d" ) );
+ assertEquals( asList( "-d" ), options.nonOptionArguments() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java
new file mode 100644
index 0000000000..0eabe4ffa7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java
@@ -0,0 +1,80 @@
+package joptsimple.examples.ant.filters;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tools.ant.filters.BaseFilterReader;
+import org.apache.tools.ant.filters.ChainableReader;
+
+/**
+ * Ant filter class that transforms HTML special characters into their equivalent entities.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class HTMLEntitifier extends BaseFilterReader implements ChainableReader {
+ private static final Map<Integer, String> ENTITIES = new HashMap<>();
+
+ static {
+ ENTITIES.put( (int) '<', "&lt;" );
+ ENTITIES.put( (int) '>', "&gt;" );
+ ENTITIES.put( (int) '"', "&quot;" );
+ ENTITIES.put( (int) '&', "&amp;" );
+ }
+
+ private String replacementData;
+ private int replacementIndex = -1;
+
+ /**
+ * Creates "dummy" instances.
+ */
+ public HTMLEntitifier() {
+ // empty on purpose
+ }
+
+ /**
+ * @param source where the data to filter comes from
+ */
+ public HTMLEntitifier( Reader source ) {
+ super( source );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Reader chain( Reader source ) {
+ HTMLEntitifier newFilter = new HTMLEntitifier( source );
+ newFilter.setInitialized( true );
+
+ return newFilter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read() throws IOException {
+ if ( !getInitialized() )
+ setInitialized( true );
+
+ if ( replacementIndex > -1 ) {
+ int ch = replacementData.charAt( replacementIndex++ );
+
+ if ( replacementIndex >= replacementData.length() )
+ replacementIndex = -1;
+
+ return ch;
+ }
+
+ int nextChar = in.read();
+
+ if ( ENTITIES.containsKey( nextChar ) ) {
+ replacementData = ENTITIES.get( nextChar );
+ replacementIndex = 1;
+ return replacementData.charAt( 0 );
+ }
+
+ return nextChar;
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java
new file mode 100644
index 0000000000..abd4302a0b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java
@@ -0,0 +1,361 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class AbbreviationMapTest {
+ private AbbreviationMap<String> abbreviations;
+
+ @Before
+ public void setUp() {
+ abbreviations = new AbbreviationMap<>();
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullValuesAreIllegal() {
+ abbreviations.put( "cannotAddNullValue", null );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullKeysAreIllegalToAdd() {
+ abbreviations.put( null, "-1" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullKeysAreIllegalToCheckForContains() {
+ abbreviations.contains( null );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void zeroLengthKeysAreIllegalToAdd() {
+ abbreviations.put( "", "1" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void nullKeysAreIllegalToRemove() {
+ abbreviations.remove( null );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void zeroLengthKeysAreIllegalToRemove() {
+ abbreviations.remove( "" );
+ }
+
+ @Test
+ public void empty() {
+ assertFalse( abbreviations.contains( "boo" ) );
+ assertNull( abbreviations.get( "boo" ) );
+ }
+
+ @Test
+ public void addingOne() {
+ abbreviations.put( "box", "2" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "2", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "2", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addingManyWithNoCommonPrefix() {
+ abbreviations.put( "box", "1" );
+ abbreviations.put( "cat", "2" );
+ abbreviations.put( "dog", "3" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "1", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "1", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "1", abbreviations.get( "b" ) );
+ assertTrue( abbreviations.contains( "cat" ) );
+ assertEquals( "2", abbreviations.get( "cat" ) );
+ assertTrue( abbreviations.contains( "ca" ) );
+ assertEquals( "2", abbreviations.get( "ca" ) );
+ assertTrue( abbreviations.contains( "c" ) );
+ assertEquals( "2", abbreviations.get( "c" ) );
+ assertTrue( abbreviations.contains( "dog" ) );
+ assertEquals( "3", abbreviations.get( "dog" ) );
+ assertTrue( abbreviations.contains( "do" ) );
+ assertEquals( "3", abbreviations.get( "do" ) );
+ assertTrue( abbreviations.contains( "d" ) );
+ assertEquals( "3", abbreviations.get( "d" ) );
+ }
+
+ @Test
+ public void addingTwoWithCommonPrefix() {
+ abbreviations.put( "box", "3" );
+ abbreviations.put( "boy", "4" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "3", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "boy" ) );
+ assertEquals( "4", abbreviations.get( "boy" ) );
+ assertFalse( abbreviations.contains( "bo" ) );
+ assertNull( abbreviations.get( "bo" ) );
+ assertFalse( abbreviations.contains( "b" ) );
+ assertNull( abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addingThreeWithSuccessivelySmallerPrefixes() {
+ abbreviations.put( "boy", "3" );
+ abbreviations.put( "bo", "2" );
+ abbreviations.put( "b", "1" );
+
+ assertTrue( abbreviations.contains( "boy" ) );
+ assertEquals( "3", abbreviations.get( "boy" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "1", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addingThreeWithSuccessivelyLargerPrefixes() {
+ abbreviations.put( "b", "1" );
+ abbreviations.put( "bo", "2" );
+ abbreviations.put( "boy", "3" );
+
+ assertTrue( abbreviations.contains( "boy" ) );
+ assertEquals( "3", abbreviations.get( "boy" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "1", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addingThreeWithMixOfPrefixSize() {
+ abbreviations.put( "boy", "3" );
+ abbreviations.put( "b", "1" );
+ abbreviations.put( "bo", "2" );
+
+ assertTrue( abbreviations.contains( "boy" ) );
+ assertEquals( "3", abbreviations.get( "boy" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "1", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addingOneThenReplacing() {
+ abbreviations.put( "box", "2" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "2", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "2", abbreviations.get( "b" ) );
+
+ abbreviations.put( "box", "3" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "3", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "3", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "3", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void removingNonExistentKeyHasNoEffect() {
+ abbreviations.put( "box", "2" );
+
+ abbreviations.remove( "cat" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "2", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "2", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void removingSingleKey() {
+ abbreviations.put( "box", "3" );
+
+ abbreviations.remove( "box" );
+
+ assertFalse( abbreviations.contains( "box" ) );
+ assertNull( abbreviations.get( "box" ) );
+ assertFalse( abbreviations.contains( "bo" ) );
+ assertNull( abbreviations.get( "bo" ) );
+ assertFalse( abbreviations.contains( "b" ) );
+ assertNull( abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void cannotRemoveByUniqueAbbreviation() {
+ abbreviations.put( "box", "4" );
+
+ abbreviations.remove( "bo" );
+ abbreviations.remove( "b" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "4", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "4", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "4", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void removeKeyWithCommonPrefix() {
+ abbreviations.put( "box", "-1" );
+ abbreviations.put( "boy", "-2" );
+
+ abbreviations.remove( "box" );
+
+ assertFalse( abbreviations.contains( "box" ) );
+ assertNull( abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "boy" ) );
+ assertEquals( "-2", abbreviations.get( "boy" ) );
+ assertTrue( abbreviations.contains( "bo" ) );
+ assertEquals( "-2", abbreviations.get( "bo" ) );
+ assertTrue( abbreviations.contains( "b" ) );
+ assertEquals( "-2", abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addKeysWithCommonPrefixThenRemoveNonExistentKeyWithCommonPrefix() {
+ abbreviations.put( "box", "-1" );
+ abbreviations.put( "boy", "-2" );
+
+ abbreviations.remove( "bop" );
+
+ assertTrue( abbreviations.contains( "box" ) );
+ assertEquals( "-1", abbreviations.get( "box" ) );
+ assertTrue( abbreviations.contains( "boy" ) );
+ assertEquals( "-2", abbreviations.get( "boy" ) );
+ assertFalse( abbreviations.contains( "bo" ) );
+ assertNull( abbreviations.get( "bo" ) );
+ assertFalse( abbreviations.contains( "b" ) );
+ assertNull( abbreviations.get( "b" ) );
+ }
+
+ @Test
+ public void addKeysWithCommonPrefixesStairstepStyle() {
+ abbreviations.put( "a", "1" );
+ abbreviations.put( "abc", "2" );
+
+ assertTrue( abbreviations.contains( "a" ) );
+ assertEquals( "1", abbreviations.get( "a" ) );
+ assertTrue( abbreviations.contains( "ab" ) );
+ assertEquals( "2", abbreviations.get( "ab" ) );
+ assertTrue( abbreviations.contains( "abc" ) );
+ assertEquals( "2", abbreviations.get( "abc" ) );
+
+ abbreviations.put( "abcde", "3" );
+
+ assertTrue( abbreviations.contains( "a" ) );
+ assertEquals( "1", abbreviations.get( "a" ) );
+ assertFalse( abbreviations.contains( "ab" ) );
+ assertNull( abbreviations.get( "ab" ) );
+ assertTrue( abbreviations.contains( "abc" ) );
+ assertEquals( "2", abbreviations.get( "abc" ) );
+ assertTrue( abbreviations.contains( "abcd" ) );
+ assertEquals( "3", abbreviations.get( "abcd" ) );
+ assertTrue( abbreviations.contains( "abcde" ) );
+ assertEquals( "3", abbreviations.get( "abcde" ) );
+ }
+
+ @Test
+ public void addKeysWithCommonPrefixesStairstepStyleJumbled() {
+ abbreviations.put( "a", "1" );
+ abbreviations.put( "abcde", "3" );
+ abbreviations.put( "abc", "2" );
+
+ assertTrue( abbreviations.contains( "a" ) );
+ assertEquals( "1", abbreviations.get( "a" ) );
+ assertFalse( abbreviations.contains( "ab" ) );
+ assertNull( abbreviations.get( "ab" ) );
+ assertTrue( abbreviations.contains( "abc" ) );
+ assertEquals( "2", abbreviations.get( "abc" ) );
+ assertTrue( abbreviations.contains( "abcd" ) );
+ assertEquals( "3", abbreviations.get( "abcd" ) );
+ assertTrue( abbreviations.contains( "abcde" ) );
+ assertEquals( "3", abbreviations.get( "abcde" ) );
+ }
+
+ @Test
+ public void multipleKeysWithCommonPrefix() {
+ abbreviations.put( "good", "4" );
+ abbreviations.put( "goodyear", "8" );
+ abbreviations.put( "go", "2" );
+ abbreviations.put( "goodyea", "7" );
+ abbreviations.put( "goodye", "6" );
+
+ assertFalse( abbreviations.contains( "g" ) );
+ assertNull( abbreviations.get( "g" ) );
+ assertTrue( abbreviations.contains( "go" ) );
+ assertEquals( "2", abbreviations.get( "go" ) );
+ assertFalse( abbreviations.contains( "goo" ) );
+ assertNull( abbreviations.get( "goo" ) );
+ assertTrue( abbreviations.contains( "good" ) );
+ assertEquals( "4", abbreviations.get( "good" ) );
+ assertFalse( abbreviations.contains( "goody" ) );
+ assertNull( abbreviations.get( "goody" ) );
+ assertTrue( abbreviations.contains( "goodye" ) );
+ assertEquals( "6", abbreviations.get( "goodye" ) );
+ assertTrue( abbreviations.contains( "goodyea" ) );
+ assertEquals( "7", abbreviations.get( "goodyea" ) );
+ assertTrue( abbreviations.contains( "goodyea" ) );
+ assertEquals( "8", abbreviations.get( "goodyear" ) );
+
+ abbreviations.remove( "goodyea" );
+
+ assertFalse( abbreviations.contains( "g" ) );
+ assertNull( abbreviations.get( "g" ) );
+ assertTrue( abbreviations.contains( "go" ) );
+ assertEquals( "2", abbreviations.get( "go" ) );
+ assertFalse( abbreviations.contains( "goo" ) );
+ assertNull( abbreviations.get( "goo" ) );
+ assertTrue( abbreviations.contains( "good" ) );
+ assertEquals( "4", abbreviations.get( "good" ) );
+ assertFalse( abbreviations.contains( "goody" ) );
+ assertNull( abbreviations.get( "goody" ) );
+ assertTrue( abbreviations.contains( "goodye" ) );
+ assertEquals( "6", abbreviations.get( "goodye" ) );
+ assertTrue( abbreviations.contains( "goodyea" ) );
+ assertEquals( "8", abbreviations.get( "goodyea" ) );
+ assertTrue( abbreviations.contains( "goodyea" ) );
+ assertEquals( "8", abbreviations.get( "goodyear" ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java
new file mode 100644
index 0000000000..8bc062135b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java
@@ -0,0 +1,148 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import static java.util.Collections.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class AbbreviationMapToJavaUtilMapTest {
+ private AbbreviationMap<String> abbreviations;
+
+ @Before
+ public void setUp() {
+ abbreviations = new AbbreviationMap<>();
+ }
+
+ @Test
+ public void empty() {
+ assertEquals( emptyMap(), abbreviations.toJavaUtilMap() );
+ }
+
+ @Test
+ public void addingOne() {
+ abbreviations.put( "box", "2" );
+
+ assertEquals( singletonMap( "box", "2" ), abbreviations.toJavaUtilMap() );
+ }
+
+ @Test
+ public void addingManyWithNoCommonPrefix() {
+ abbreviations.put( "box", "1" );
+ abbreviations.put( "cat", "2" );
+ abbreviations.put( "dog", "3" );
+
+ assertEquals( "{box=1, cat=2, dog=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addingTwoWithCommonPrefix() {
+ abbreviations.put( "box", "3" );
+ abbreviations.put( "boy", "4" );
+
+ assertEquals( "{box=3, boy=4}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addingThreeWithSuccessivelySmallerPrefixes() {
+ abbreviations.put( "boy", "3" );
+ abbreviations.put( "bo", "2" );
+ abbreviations.put( "b", "1" );
+
+ assertEquals( "{b=1, bo=2, boy=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addingThreeWithSuccessivelyLargerPrefixes() {
+ abbreviations.put( "b", "1" );
+ abbreviations.put( "bo", "2" );
+ abbreviations.put( "boy", "3" );
+
+ assertEquals( "{b=1, bo=2, boy=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addingThreeWithMixOfPrefixSize() {
+ abbreviations.put( "boy", "3" );
+ abbreviations.put( "b", "1" );
+ abbreviations.put( "bo", "2" );
+
+ assertEquals( "{b=1, bo=2, boy=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addingOneThenReplacing() {
+ abbreviations.put( "box", "2" );
+ abbreviations.put( "box", "3" );
+
+ assertEquals( "{box=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void removeKeyWithCommonPrefix() {
+ abbreviations.put( "box", "-1" );
+ abbreviations.put( "boy", "-2" );
+ abbreviations.remove( "box" );
+
+ assertEquals( "{boy=-2}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addKeysWithCommonPrefixesStairstepStyle() {
+ abbreviations.put( "a", "1" );
+ abbreviations.put( "abc", "2" );
+ abbreviations.put( "abcde", "3" );
+
+ assertEquals( "{a=1, abc=2, abcde=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void addKeysWithCommonPrefixesStairstepStyleJumbled() {
+ abbreviations.put( "a", "1" );
+ abbreviations.put( "abcde", "3" );
+ abbreviations.put( "abc", "2" );
+
+ assertEquals( "{a=1, abc=2, abcde=3}", abbreviations.toJavaUtilMap().toString() );
+ }
+
+ @Test
+ public void multipleKeysWithCommonPrefix() {
+ abbreviations.put( "good", "4" );
+ abbreviations.put( "goodyear", "8" );
+ abbreviations.put( "go", "2" );
+ abbreviations.put( "goodyea", "7" );
+ abbreviations.put( "goodye", "6" );
+ abbreviations.remove( "goodyea" );
+
+ assertEquals( "{go=2, good=4, goodye=6, goodyear=8}", abbreviations.toJavaUtilMap().toString() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java
new file mode 100644
index 0000000000..89f3ea2430
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java
@@ -0,0 +1,37 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import joptsimple.UtilityClassesUninstantiabilityHarness;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ClassesUtilityClassTest extends UtilityClassesUninstantiabilityHarness {
+ public ClassesUtilityClassTest() {
+ super( Classes.class );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java
new file mode 100644
index 0000000000..a0c1051ed8
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java
@@ -0,0 +1,37 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import joptsimple.UtilityClassesUninstantiabilityHarness;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class MessagesUtilityClassTest extends UtilityClassesUninstantiabilityHarness {
+ public MessagesUtilityClassTest() {
+ super( Messages.class );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java
new file mode 100644
index 0000000000..9ec93d62a7
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java
@@ -0,0 +1,51 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class Problematic {
+ private Problematic() {
+ // no-op
+ }
+
+ Problematic( String s ) {
+ throw new IllegalStateException(s);
+ }
+
+ private static void boo() {
+ // no-op
+ }
+
+ static void mute() {
+ new Problematic().stuff();
+ }
+
+ void stuff() {
+ boo();
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java
new file mode 100644
index 0000000000..06f96829c4
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java
@@ -0,0 +1,109 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static joptsimple.internal.Reflection.*;
+import static org.junit.rules.ExpectedException.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ReflectionTest {
+ @Rule public final ExpectedException thrown = none();
+
+ @Test
+ public void invokingConstructorQuietlyWrapsInstantiationException() throws Exception {
+ Constructor<AbstractProblematic> constructor = AbstractProblematic.class.getDeclaredConstructor();
+
+ thrown.expect( ReflectionException.class );
+ thrown.expectMessage( InstantiationException.class.getName() );
+
+ instantiate( constructor );
+ }
+
+ @Test
+ public void invokingConstructorQuietlyWrapsIllegalAccessException() throws Exception {
+ Constructor<Problematic> constructor = Problematic.class.getDeclaredConstructor();
+
+ thrown.expect( ReflectionException.class );
+ thrown.expectMessage( IllegalAccessException.class.getName() );
+
+ instantiate( constructor );
+ }
+
+ @Test
+ public void invokingConstructorQuietlyWrapsCauseOfInvocationTargetException() throws Exception {
+ Constructor<Problematic> constructor = Problematic.class.getDeclaredConstructor( String.class );
+
+ thrown.expect( ReflectionException.class );
+ thrown.expectMessage( IllegalStateException.class.getName() );
+
+ instantiate( constructor, "arg" );
+ }
+
+ @Test
+ public void invokingConstructorQuietlyWrapsIllegalArgumentException() throws Exception {
+ Constructor<Problematic> constructor = Problematic.class.getDeclaredConstructor(String.class);
+
+ thrown.expect( ReflectionException.class );
+ thrown.expectMessage( IllegalArgumentException.class.getName() );
+
+ instantiate( constructor );
+ }
+
+ @Test
+ public void invokingStaticMethodQuietlyWrapsIllegalAccessException() throws Exception {
+ Method method = Problematic.class.getDeclaredMethod( "boo" );
+
+ thrown.expect( ReflectionException.class );
+ thrown.expectMessage( IllegalAccessException.class.getName() );
+
+ invoke( method );
+ }
+
+ @Test
+ public void invokingStaticMethodQuietlyWrapsIllegalArgumentException() throws Exception {
+ Method method = Problematic.class.getDeclaredMethod( "mute" );
+
+ thrown.expect( ReflectionException.class );
+ thrown.expectMessage( IllegalArgumentException.class.getName() );
+
+ invoke( method, new Object() );
+ }
+
+ private abstract static class AbstractProblematic {
+ protected AbstractProblematic() {
+ // no-op
+ }
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java
new file mode 100644
index 0000000000..7634a4900f
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java
@@ -0,0 +1,37 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import joptsimple.UtilityClassesUninstantiabilityHarness;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class ReflectionUtilityClassTest extends UtilityClassesUninstantiabilityHarness {
+ public ReflectionUtilityClassTest() {
+ super( Reflection.class );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java
new file mode 100644
index 0000000000..e1ad850945
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java
@@ -0,0 +1,49 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import org.infinitest.toolkit.StrictEqualsHashCodeTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RowEqualsHashCodeTest extends StrictEqualsHashCodeTestSupport {
+ @Override
+ protected Object equalButDifferentClass() {
+ return new Row( "o", "d" ) {
+ };
+ }
+
+ @Override
+ protected Object equal() throws Exception {
+ return new Row( "o", "d" );
+ }
+
+ @Override
+ protected Object notEqual() throws Exception {
+ return new Row( "o", "e" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java
new file mode 100644
index 0000000000..c07522de15
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java
@@ -0,0 +1,83 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import org.junit.Test;
+
+import static joptsimple.internal.Strings.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RowsTest {
+ @Test
+ public void optionsAndDescriptionsWithinOverallWidth() {
+ Rows rows = new Rows( 40, 2 );
+ rows.add( "left one", "right one" );
+ rows.add( "another left one", "another right one" );
+
+ assertRows( rows,
+ "left one right one ",
+ "another left one another right one" );
+ }
+
+ @Test
+ public void someOptionsExceedOverallWidth() {
+ Rows rows = new Rows( 40, 2 );
+ rows.add( "left one is pretty freaking long to be over here", "right one" );
+ rows.add( "another left one also has length that is quite excessive", "another right one" );
+
+ assertRows( rows,
+ "left one is pretty right one ",
+ " freaking long to ",
+ " be over here ",
+ "another left one another right one",
+ " also has length ",
+ " that is quite ",
+ " excessive " );
+ }
+
+ @Test
+ public void someDescriptionsExceedOverallWidth() {
+ Rows rows = new Rows( 40, 2 );
+ rows.add( "left one", "right one for the time we have chosen" );
+ rows.add( "another left one", "another right one could be used here instead" );
+
+ assertRows( rows,
+ "left one right one for the ",
+ " time we have chosen",
+ "another left one another right one ",
+ " could be used here ",
+ " instead " );
+ }
+
+ private void assertRows( Rows rows, String... expected ) {
+ rows.fitToWidth();
+
+ assertEquals( join( expected, LINE_SEPARATOR ) + LINE_SEPARATOR, rows.render() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java
new file mode 100644
index 0000000000..ae9ae0d4fd
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java
@@ -0,0 +1,93 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static java.util.Arrays.*;
+
+import static org.junit.Assert.*;
+
+public class SimpleOptionNameMapTest {
+ private static final Integer VALUE = 1;
+ private static final String KEY = "someKey";
+ private static final String KEY2 = "someOtherKey";
+
+ @Test
+ public void putAndContains() {
+ SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>();
+ assertFalse( map.contains( KEY ) );
+
+ map.put( KEY, 1 );
+
+ assertTrue( map.contains( KEY ) );
+ }
+
+ @Test
+ public void get() {
+ SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>();
+ assertNull( map.get( KEY ) );
+
+ map.put( KEY, VALUE );
+
+ assertEquals( VALUE, map.get( KEY ) );
+ }
+
+ @Test
+ public void putAll() {
+ SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>();
+ List<String> keys = asList( KEY, KEY2 );
+
+ map.putAll( keys, VALUE );
+
+ assertEquals( VALUE, map.get( KEY ) );
+ assertEquals( VALUE, map.get( KEY2 ) );
+ }
+
+ @Test
+ public void remove() {
+ SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>();
+ map.put( KEY, 1 );
+
+ map.remove( KEY );
+
+ assertFalse( map.contains( KEY ) );
+ }
+
+ @Test
+ public void toJavaUtilMap() {
+ SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>();
+ map.put( KEY, VALUE );
+
+ Map<String, Integer> javaUtilMap = map.toJavaUtilMap();
+
+ assertEquals( VALUE, javaUtilMap.get( KEY ) );
+ assertEquals( 1, javaUtilMap.size() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java
new file mode 100644
index 0000000000..a56b2a53c5
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java
@@ -0,0 +1,37 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.internal;
+
+import joptsimple.UtilityClassesUninstantiabilityHarness;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class StringsUtilityClassTest extends UtilityClassesUninstantiabilityHarness {
+ public StringsUtilityClassTest() {
+ super( Strings.class );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java
new file mode 100644
index 0000000000..93baa0bacc
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java
@@ -0,0 +1,152 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import static java.text.DateFormat.*;
+
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+import org.joda.time.LocalDate;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static joptsimple.util.DateConverter.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class DateConverterTest {
+ @Rule public final ExpectedException thrown = none();
+
+ private DateFormat notASimpleDateFormat;
+ private SimpleDateFormat monthDayYear;
+
+ @Before
+ public void setUp() {
+ notASimpleDateFormat = new DateFormat() {
+ private static final long serialVersionUID = -1L;
+
+ {
+ setNumberFormat( NumberFormat.getInstance() );
+ }
+
+ @Override
+ public StringBuffer format( Date date, StringBuffer toAppendTo, FieldPosition fieldPosition ) {
+ return null;
+ }
+
+ @Override
+ public Date parse( String source, ParsePosition pos ) {
+ return null;
+ }
+ };
+
+ monthDayYear = new SimpleDateFormat( "MM/dd/yyyy" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void rejectsNullDateFormatter() {
+ new DateConverter( null );
+ }
+
+ @Test
+ public void shouldConvertValuesToDatesUsingADateFormat() {
+ ValueConverter<Date> converter = new DateConverter( monthDayYear );
+
+ assertEquals( new LocalDate( 2009, 1, 24 ).toDate(), converter.convert( "01/24/2009" ) );
+ }
+
+ @Test
+ public void rejectsNonParsableValues() {
+ thrown.expect( ValueConversionException.class );
+
+ new DateConverter( getDateInstance() ).convert( "@(#*^" );
+ }
+
+ @Test
+ public void rejectsValuesThatDoNotEntirelyMatch() {
+ thrown.expect( ValueConversionException.class );
+
+ new DateConverter( monthDayYear ).convert( "12/25/09 00:00:00" );
+ }
+
+ @Test
+ public void shouldCreateSimpleDateFormatConverter() {
+ assertEquals( new LocalDate( 2009, 7, 4 ).toDate(), datePattern( "MM/dd/yyyy" ).convert( "07/04/2009" ) );
+ }
+
+ @Test
+ public void rejectsNullDatePattern() {
+ thrown.expect( NullPointerException.class );
+
+ datePattern( null );
+ }
+
+ @Test
+ public void shouldRaiseExceptionThatContainsDatePatternAndValue() {
+ thrown.expect( ValueConversionException.class );
+ thrown.expectMessage( "qwe" );
+ thrown.expectMessage( monthDayYear.toPattern() );
+
+ new DateConverter( monthDayYear ).convert( "qwe" );
+ }
+
+ @Test
+ public void shouldRaiseExceptionThatContainsValueOnlyIfNotASimpleDateFormat() {
+ thrown.expect( ValueConversionException.class );
+ thrown.expectMessage( "asdf" );
+ thrown.expectMessage( not( containsString( notASimpleDateFormat.toString() ) ) );
+
+ new DateConverter( notASimpleDateFormat ).convert( "asdf" );
+ }
+
+ @Test
+ public void shouldAnswerCorrectValueType() {
+ assertSame( Date.class, new DateConverter( monthDayYear ).valueType() );
+ }
+
+ @Test
+ public void shouldGiveNoValuePatternIfFormatterNotASimpleDateFormat() {
+ assertEquals( "", new DateConverter( notASimpleDateFormat ).valuePattern() );
+ }
+
+ @Test
+ public void shouldGiveValuePatternIfFormatterIsASimpleDateFormat() {
+ assertEquals( monthDayYear.toPattern(), datePattern( monthDayYear.toPattern() ).valuePattern() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java
new file mode 100644
index 0000000000..617f1462c1
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java
@@ -0,0 +1,95 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2014 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import joptsimple.ValueConversionException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.rules.ExpectedException.none;
+
+/**
+ * @author <a href="mailto:christian.ohr@gmail.com">Christian Ohr</a>
+ */
+public class EnumConverterTest {
+ @Rule
+ public final ExpectedException thrown = none();
+
+ private EnumConverter<TestEnum> converter;
+
+ @Before
+ public void setUp() {
+ converter = new TestEnumConverter();
+ }
+
+ @Test
+ public void convertsEnumValuesToEnum() {
+ assertEquals( TestEnum.A, converter.convert( "A" ) );
+ }
+
+ @Test
+ public void rejectsNonEnumeratedValues() {
+ thrown.expect( ValueConversionException.class );
+
+ converter.convert( "Z" );
+ }
+
+ @Test
+ public void answersCorrectValueType() {
+ assertSame( TestEnum.class, converter.valueType() );
+ }
+
+ @Test
+ public void givesDefaultValuePattern() {
+ assertEquals( "[A,B,C,D]", converter.valuePattern() );
+ }
+
+ @Test
+ public void givesCustomValuePattern() {
+ converter.setDelimiters( "(|)" );
+
+ assertEquals( "(A|B|C|D)", converter.valuePattern() );
+ }
+
+ @Test
+ public void ignoresCase() {
+ assertEquals( TestEnum.A, converter.convert( "a" ) );
+ }
+
+ private static class TestEnumConverter extends EnumConverter<TestEnum> {
+ TestEnumConverter() {
+ super( TestEnum.class );
+ }
+ }
+
+ private static enum TestEnum {
+ A, B, C, D
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java
new file mode 100644
index 0000000000..98f418ff3a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java
@@ -0,0 +1,60 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import java.net.InetAddress;
+import java.util.Random;
+
+import joptsimple.ValueConversionException;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class InetAddressConverterTest {
+ private InetAddressConverter converter;
+
+ @Before
+ public void setUp() {
+ converter = new InetAddressConverter();
+ }
+
+ @Test
+ public void localhost() throws Exception {
+ assumeTrue( InetAddress.getByName( "127.0.0.1" ).isReachable( 5000 ) );
+
+ assertEquals( "127.0.0.1", converter.convert( "localhost" ).getHostAddress() );
+ }
+
+ @Test( expected = ValueConversionException.class )
+ public void unknownHost() {
+ converter.convert( "!(@&#()!*@&#" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java
new file mode 100644
index 0000000000..e0c64e9efd
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java
@@ -0,0 +1,88 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class KeyValuePairTest {
+ @Test( expected = NullPointerException.class )
+ public void nullArg() {
+ KeyValuePair.valueOf( null );
+ }
+
+ @Test
+ public void empty() {
+ KeyValuePair pair = KeyValuePair.valueOf( "" );
+
+ assertEquals( "", pair.key );
+ assertEquals( "", pair.value );
+ }
+
+ @Test
+ public void noEqualsSign() {
+ KeyValuePair pair = KeyValuePair.valueOf( "aString" );
+
+ assertEquals( "aString", pair.key );
+ assertEquals( "", pair.value );
+ }
+
+ @Test
+ public void signAtEnd() {
+ KeyValuePair pair = KeyValuePair.valueOf( "aKey=" );
+
+ assertEquals( "aKey", pair.key );
+ assertEquals( "", pair.value );
+ }
+
+ @Test
+ public void signAtStart() {
+ KeyValuePair pair = KeyValuePair.valueOf( "=aValue" );
+
+ assertEquals( "", pair.key );
+ assertEquals( "aValue", pair.value );
+ }
+
+ @Test
+ public void typical() {
+ KeyValuePair pair = KeyValuePair.valueOf( "aKey=aValue" );
+
+ assertEquals( "aKey", pair.key );
+ assertEquals( "aValue", pair.value );
+ }
+
+ @Test
+ public void multipleEqualsSignsDoNotMatter() {
+ KeyValuePair pair = KeyValuePair.valueOf( "aKey=1=2=3=4" );
+
+ assertEquals( "aKey", pair.key );
+ assertEquals( "1=2=3=4", pair.value );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java
new file mode 100644
index 0000000000..fc130bf938
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java
@@ -0,0 +1,43 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import org.infinitest.toolkit.EqualsHashCodeTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class KeyValuePairUnequalKeysTest extends EqualsHashCodeTestSupport {
+ @Override
+ protected KeyValuePair equal() {
+ return KeyValuePair.valueOf( "x=z" );
+ }
+
+ @Override
+ protected KeyValuePair notEqual() {
+ return KeyValuePair.valueOf( "y=z" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java
new file mode 100644
index 0000000000..4bb36b71c5
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java
@@ -0,0 +1,43 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import org.infinitest.toolkit.EqualsHashCodeTestSupport;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class KeyValuePairUnequalValuesTest extends EqualsHashCodeTestSupport {
+ @Override
+ protected KeyValuePair equal() {
+ return KeyValuePair.valueOf( "x=y" );
+ }
+
+ @Override
+ protected KeyValuePair notEqual() {
+ return KeyValuePair.valueOf( "x=z" );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java
new file mode 100644
index 0000000000..6b543936cd
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java
@@ -0,0 +1,104 @@
+package joptsimple.util;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import joptsimple.ValueConversionException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static joptsimple.util.PathProperties.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class PathConverterTest {
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void convertsValuesToPaths() throws Exception {
+ Path path = Files.createTempFile( "prefix", null );
+ path.toFile().deleteOnExit();
+
+ String pathName = path.toString();
+
+ assertEquals( path, new PathConverter( null ).convert( pathName ) );
+ assertEquals( path, new PathConverter().convert( pathName ) );
+ }
+
+ @Test
+ public void answersCorrectValueType() {
+ assertEquals( Path.class, new PathConverter().valueType() );
+ }
+
+ @Test
+ public void testReadableAndOverwritableFile() throws Exception {
+ Path path = Files.createTempFile( "prefix", null );
+ path.toFile().deleteOnExit();
+
+ String pathName = path.toString();
+
+ assertTrue( Files.isReadable( new PathConverter( READABLE ).convert( pathName ) ) );
+ assertTrue( Files.exists( new PathConverter( READABLE ).convert( pathName ) ) );
+ assertTrue( Files.isWritable( new PathConverter( READABLE ).convert( pathName ) ) );
+ assertTrue( Files.isWritable( new PathConverter( FILE_OVERWRITABLE).convert( pathName ) ) );
+ }
+
+ @Test
+ public void testNotExisting() throws Exception {
+ Path path = Files.createTempFile( "prefix", null );
+
+ Files.deleteIfExists( path );
+
+ assertFalse( Files.exists( new PathConverter( NOT_EXISTING ).convert( path.toString() ) ) );
+ }
+
+ @Test
+ public void testNotReadable() throws Exception {
+ Path path = Files.createTempFile( "prefix", null );
+ String pathName = path.toString();
+ Files.deleteIfExists( path );
+
+ exception.expect( ValueConversionException.class );
+ exception.expectMessage( "File [" + pathName );
+
+ new PathConverter( READABLE ).convert( pathName );
+ }
+
+ @Test
+ public void testDirectoryExisting() throws Exception {
+ Path path = Files.createTempDirectory( "prefix" );
+ path.toFile().deleteOnExit();
+
+ String pathName = path.toString();
+
+ assertTrue( Files.isDirectory( new PathConverter( DIRECTORY_EXISTING ).convert( pathName ) ) );
+ }
+
+ @Test
+ public void testDirectoryNotOverwritable() throws Exception {
+ Path path = Files.createTempDirectory( "prefix" );
+ path.toFile().deleteOnExit();
+
+ String pathName = path.toString();
+
+ exception.expect( ValueConversionException.class );
+ exception.expectMessage( "File [" + pathName );
+
+ new PathConverter( FILE_OVERWRITABLE).convert( pathName );
+ }
+
+ @Test
+ public void testNotExistingNotOverwritable() throws Exception {
+ Path path = Files.createTempDirectory( "prefix" );
+ String pathName = path.toString();
+ Files.deleteIfExists( path );
+
+ exception.expect( ValueConversionException.class );
+ exception.expectMessage( "File [" + pathName );
+
+ new PathConverter( FILE_OVERWRITABLE ).convert( pathName );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java
new file mode 100644
index 0000000000..1c6bf59718
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java
@@ -0,0 +1,54 @@
+package joptsimple.util;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import static joptsimple.util.PathProperties.*;
+
+public class PathPropertiesTest {
+ @Test
+ public void readableFile() throws Exception {
+ Path path = Files.createTempFile("prefix", null);
+
+ path.toFile().deleteOnExit();
+
+ assertTrue( READABLE.accept( path ) );
+ assertFalse( DIRECTORY_EXISTING.accept( path ) );
+ assertTrue( FILE_EXISTING.accept( path ) );
+ assertTrue( FILE_OVERWRITABLE.accept( path ) );
+ assertTrue( WRITABLE.accept( path ) );
+ assertFalse( NOT_EXISTING.accept( path ) );
+ }
+
+ @Test
+ public void nonExisting() throws Exception {
+ Path path = Files.createTempFile( "prefix", null );
+
+ Files.deleteIfExists( path );
+
+ assertFalse( READABLE.accept( path ) );
+ assertFalse( DIRECTORY_EXISTING.accept( path ) );
+ assertFalse( FILE_EXISTING.accept( path ) );
+ assertFalse( FILE_OVERWRITABLE.accept( path ) );
+ assertTrue( NOT_EXISTING.accept( path ) );
+ assertFalse( WRITABLE.accept( path ) );
+ }
+
+ @Test
+ public void directory() throws Exception {
+ Path path = Files.createTempDirectory( "prefix" );
+
+ path.toFile().deleteOnExit();
+
+ assertTrue( READABLE.accept( path ) );
+ assertTrue( DIRECTORY_EXISTING.accept( path ) );
+ assertFalse( FILE_EXISTING.accept( path ) );
+ assertFalse( FILE_OVERWRITABLE.accept( path ) );
+ assertFalse( NOT_EXISTING.accept( path ) );
+ assertTrue( WRITABLE.accept( path ) );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java
new file mode 100644
index 0000000000..56eae7ec5a
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java
@@ -0,0 +1,84 @@
+/*
+ The MIT License
+
+ Copyright (c) 2004-2015 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package joptsimple.util;
+
+import joptsimple.ValueConversionException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static joptsimple.util.RegexMatcher.*;
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.*;
+
+/**
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class RegexMatcherTest {
+ @Rule public final ExpectedException thrown = none();
+
+ private RegexMatcher abc;
+
+ @Before
+ public void setUp() {
+ abc = new RegexMatcher( "abc", 0 );
+ }
+
+ @Test
+ public void shouldAttemptToMatchValueAgainstARegex() {
+ assertEquals( "abc", abc.convert( "abc" ) );
+ }
+
+ @Test( expected = ValueConversionException.class )
+ public void rejectsValueThatDoesNotMatchRegex() {
+ abc.convert( "abcd" );
+ }
+
+ @Test
+ public void raisesExceptionContainingValueAndPattern() {
+ thrown.expect( ValueConversionException.class );
+ thrown.expectMessage( "\\d+" );
+ thrown.expectMessage( "asdf" );
+
+ new RegexMatcher( "\\d+", 0 ).convert( "asdf" );
+ }
+
+ @Test
+ public void shouldOfferConvenienceMethodForCreatingMatcherWithNoFlags() {
+ assertEquals( "sourceforge.net", regex( "\\w+\\.\\w+" ).convert( "sourceforge.net" ) );
+ }
+
+ @Test
+ public void shouldAnswerCorrectValueType() {
+ assertEquals( String.class, abc.valueType() );
+ }
+
+ @Test
+ public void shouldGiveCorrectValuePattern() {
+ assertEquals( "abc", abc.valuePattern() );
+ }
+}
diff --git a/third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties b/third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties
new file mode 100644
index 0000000000..ac78a6227b
--- /dev/null
+++ b/third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties
@@ -0,0 +1,10 @@
+joptsimple.IllegalOptionSpecificationException.message = illegal option specification exception
+joptsimple.MissingRequiredOptionsException.message = missing required option exception
+joptsimple.MultipleArgumentsForOptionException.message = multiple arguments for option exception
+joptsimple.OptionArgumentConversionException.message = option argument conversion exception
+joptsimple.OptionMissingRequiredArgumentException.message = option missing required argument exception
+joptsimple.UnconfiguredOptionException.message = unconfigured option exception
+joptsimple.UnrecognizedOptionException.message = unrecognized option exception
+joptsimple.util.DateConverter.without.pattern.message = date converter without pattern
+joptsimple.util.DateConverter.with.pattern.message = date converter with pattern
+joptsimple.util.RegexMatcher.message = regex matcher \ No newline at end of file