getOptions()
+ {
+ return options;
+ }
+
+ public CommandLineOption hasArgument()
+ {
+ argumentType = String.class;
+ return this;
+ }
+
+ public CommandLineOption hasArguments()
+ {
+ argumentType = List.class;
+ return this;
+ }
+
+ public String getSubcommand()
+ {
+ return subcommand;
+ }
+
+ public CommandLineOption mapsToSubcommand( String command )
+ {
+ this.subcommand = command;
+ return this;
+ }
+
+ public String getDescription()
+ {
+ StringBuilder result = new StringBuilder();
+ if ( description != null )
+ {
+ result.append( description );
+ }
+ if ( deprecationWarning != null )
+ {
+ if ( result.length() > 0 )
+ {
+ result.append( ' ' );
+ }
+ result.append( "[deprecated - " );
+ result.append( deprecationWarning );
+ result.append( "]" );
+ }
+ if ( incubating )
+ {
+ if ( result.length() > 0 )
+ {
+ result.append( ' ' );
+ }
+ result.append( "[incubating]" );
+ }
+ return result.toString();
+ }
+
+ public CommandLineOption hasDescription( String description )
+ {
+ this.description = description;
+ return this;
+ }
+
+ public boolean getAllowsArguments()
+ {
+ return argumentType != Void.TYPE;
+ }
+
+ public boolean getAllowsMultipleArguments()
+ {
+ return argumentType == List.class;
+ }
+
+ public CommandLineOption deprecated( String deprecationWarning )
+ {
+ this.deprecationWarning = deprecationWarning;
+ return this;
+ }
+
+ public CommandLineOption incubating()
+ {
+ incubating = true;
+ return this;
+ }
+
+ public String getDeprecationWarning()
+ {
+ return deprecationWarning;
+ }
+}
diff --git a/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/CommandLineParser.java b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/CommandLineParser.java
new file mode 100644
index 0000000000..77460130fb
--- /dev/null
+++ b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/CommandLineParser.java
@@ -0,0 +1,675 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.maven.wrapper.cli;
+
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * A command-line parser which supports a command/sub-command style command-line interface. Supports the following
+ * syntax:
+ *
+ *
+ *
+ * <option>* (<sub-command> <sub-command-option>*)*
+ *
+ *
+ * - Short options are a '-' followed by a single character. For example: {@code -a}.
+ * - Long options are '--' followed by multiple characters. For example: {@code --long-option}.
+ * - Options can take arguments. The argument follows the option. For example: {@code -a arg} or {@code --long arg}.
+ * - Arguments can be attached to the option using '='. For example: {@code -a=arg} or {@code --long=arg}.
+ * - Arguments can be attached to short options. For example: {@code -aarg}.
+ * - Short options can be combined. For example {@code -ab} is equivalent to {@code -a -b}.
+ * - Anything else is treated as an extra argument. This includes a single {@code -} character.
+ * - '--' indicates the end of the options. Anything following is not parsed and is treated as extra arguments.
+ * - The parser is forgiving, and allows '--' to be used with short options and '-' to be used with long options.
+ * - The set of options must be known at parse time. Sub-commands and their options do not need to be known at parse
+ * time. Use {@link ParsedCommandLine#getExtraArguments()} to obtain the non-option command-line arguments.
+ *
+ */
+public class CommandLineParser
+{
+ private Map optionsByString = new HashMap();
+
+ private boolean allowMixedOptions;
+
+ private boolean allowUnknownOptions;
+
+ private final PrintWriter deprecationPrinter;
+
+ public CommandLineParser()
+ {
+ this( new OutputStreamWriter( System.out ) );
+ }
+
+ public CommandLineParser( Writer deprecationPrinter )
+ {
+ this.deprecationPrinter = new PrintWriter( deprecationPrinter );
+ }
+
+ /**
+ * Parses the given command-line.
+ *
+ * @param commandLine The command-line.
+ * @return The parsed command line.
+ * @throws org.apache.maven.wrapper.cli.CommandLineArgumentException On parse failure.
+ */
+ public ParsedCommandLine parse( String... commandLine )
+ throws CommandLineArgumentException
+ {
+ return parse( Arrays.asList( commandLine ) );
+ }
+
+ /**
+ * Parses the given command-line.
+ *
+ * @param commandLine The command-line.
+ * @return The parsed command line.
+ * @throws org.apache.maven.wrapper.cli.CommandLineArgumentException On parse failure.
+ */
+ public ParsedCommandLine parse( Iterable commandLine )
+ throws CommandLineArgumentException
+ {
+ ParsedCommandLine parsedCommandLine =
+ new ParsedCommandLine( new HashSet( optionsByString.values() ) );
+ ParserState parseState = new BeforeFirstSubCommand( parsedCommandLine );
+ for ( String arg : commandLine )
+ {
+ if ( parseState.maybeStartOption( arg ) )
+ {
+ if ( arg.equals( "--" ) )
+ {
+ parseState = new AfterOptions( parsedCommandLine );
+ }
+ else if ( arg.matches( "--[^=]+" ) )
+ {
+ OptionParserState parsedOption = parseState.onStartOption( arg, arg.substring( 2 ) );
+ parseState = parsedOption.onStartNextArg();
+ }
+ else if ( arg.matches( "--[^=]+=.*" ) )
+ {
+ int endArg = arg.indexOf( '=' );
+ OptionParserState parsedOption = parseState.onStartOption( arg, arg.substring( 2, endArg ) );
+ parseState = parsedOption.onArgument( arg.substring( endArg + 1 ) );
+ }
+ else if ( arg.matches( "-[^=]=.*" ) )
+ {
+ OptionParserState parsedOption = parseState.onStartOption( arg, arg.substring( 1, 2 ) );
+ parseState = parsedOption.onArgument( arg.substring( 3 ) );
+ }
+ else
+ {
+ assert arg.matches( "-[^-].*" );
+ String option = arg.substring( 1 );
+ if ( optionsByString.containsKey( option ) )
+ {
+ OptionParserState parsedOption = parseState.onStartOption( arg, option );
+ parseState = parsedOption.onStartNextArg();
+ }
+ else
+ {
+ String option1 = arg.substring( 1, 2 );
+ OptionParserState parsedOption;
+ if ( optionsByString.containsKey( option1 ) )
+ {
+ parsedOption = parseState.onStartOption( "-" + option1, option1 );
+ if ( parsedOption.getHasArgument() )
+ {
+ parseState = parsedOption.onArgument( arg.substring( 2 ) );
+ }
+ else
+ {
+ parseState = parsedOption.onComplete();
+ for ( int i = 2; i < arg.length(); i++ )
+ {
+ String optionStr = arg.substring( i, i + 1 );
+ parsedOption = parseState.onStartOption( "-" + optionStr, optionStr );
+ parseState = parsedOption.onComplete();
+ }
+ }
+ }
+ else
+ {
+ if ( allowUnknownOptions )
+ {
+ // if we are allowing unknowns, just pass through the whole arg
+ parsedOption = parseState.onStartOption( arg, option );
+ parseState = parsedOption.onComplete();
+ }
+ else
+ {
+ // We are going to throw a CommandLineArgumentException below, but want the message
+ // to reflect that we didn't recognise the first char (i.e. the option specifier)
+ parsedOption = parseState.onStartOption( "-" + option1, option1 );
+ parseState = parsedOption.onComplete();
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ parseState = parseState.onNonOption( arg );
+ }
+ }
+
+ parseState.onCommandLineEnd();
+ return parsedCommandLine;
+ }
+
+ public CommandLineParser allowMixedSubcommandsAndOptions()
+ {
+ allowMixedOptions = true;
+ return this;
+ }
+
+ public CommandLineParser allowUnknownOptions()
+ {
+ allowUnknownOptions = true;
+ return this;
+ }
+
+ /**
+ * Prints a usage message to the given stream.
+ *
+ * @param out The output stream to write to.
+ */
+ public void printUsage( Appendable out )
+ {
+ Formatter formatter = new Formatter( out );
+ Set orderedOptions = new TreeSet( new OptionComparator() );
+ orderedOptions.addAll( optionsByString.values() );
+ Map lines = new LinkedHashMap();
+ for ( CommandLineOption option : orderedOptions )
+ {
+ Set orderedOptionStrings = new TreeSet( new OptionStringComparator() );
+ orderedOptionStrings.addAll( option.getOptions() );
+ List prefixedStrings = new ArrayList();
+ for ( String optionString : orderedOptionStrings )
+ {
+ if ( optionString.length() == 1 )
+ {
+ prefixedStrings.add( "-" + optionString );
+ }
+ else
+ {
+ prefixedStrings.add( "--" + optionString );
+ }
+ }
+
+ String key = join( prefixedStrings, ", " );
+ String value = option.getDescription();
+ if ( value == null || value.length() == 0 )
+ {
+ value = "";
+ }
+
+ lines.put( key, value );
+ }
+ int max = 0;
+ for ( String optionStr : lines.keySet() )
+ {
+ max = Math.max( max, optionStr.length() );
+ }
+ for ( Map.Entry entry : lines.entrySet() )
+ {
+ if ( entry.getValue().length() == 0 )
+ {
+ formatter.format( "%s%n", entry.getKey() );
+ }
+ else
+ {
+ formatter.format( "%-" + max + "s %s%n", entry.getKey(), entry.getValue() );
+ }
+ }
+ formatter.flush();
+ }
+
+ private static String join( Collection> things, String separator )
+ {
+ StringBuffer buffer = new StringBuffer();
+ boolean first = true;
+
+ if ( separator == null )
+ {
+ separator = "";
+ }
+
+ for ( Object thing : things )
+ {
+ if ( !first )
+ {
+ buffer.append( separator );
+ }
+ buffer.append( thing.toString() );
+ first = false;
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Defines a new option. By default, the option takes no arguments and has no description.
+ *
+ * @param options The options values.
+ * @return The option, which can be further configured.
+ */
+ public CommandLineOption option( String... options )
+ {
+ for ( String option : options )
+ {
+ if ( optionsByString.containsKey( option ) )
+ {
+ throw new IllegalArgumentException( String.format( "Option '%s' is already defined.", option ) );
+ }
+ if ( option.startsWith( "-" ) )
+ {
+ throw new IllegalArgumentException(
+ String.format( "Cannot add option '%s' as an option cannot start with '-'.",
+ option ) );
+ }
+ }
+ CommandLineOption option = new CommandLineOption( Arrays.asList( options ) );
+ for ( String optionStr : option.getOptions() )
+ {
+ this.optionsByString.put( optionStr, option );
+ }
+ return option;
+ }
+
+ private static class OptionString
+ {
+ private final String arg;
+
+ private final String option;
+
+ private OptionString( String arg, String option )
+ {
+ this.arg = arg;
+ this.option = option;
+ }
+
+ public String getDisplayName()
+ {
+ return arg.startsWith( "--" ) ? "--" + option : "-" + option;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getDisplayName();
+ }
+ }
+
+ private static abstract class ParserState
+ {
+ public abstract boolean maybeStartOption( String arg );
+
+ boolean isOption( String arg )
+ {
+ return arg.matches( "-.+" );
+ }
+
+ public abstract OptionParserState onStartOption( String arg, String option );
+
+ public abstract ParserState onNonOption( String arg );
+
+ public void onCommandLineEnd()
+ {
+ }
+ }
+
+ private abstract class OptionAwareParserState
+ extends ParserState
+ {
+ protected final ParsedCommandLine commandLine;
+
+ protected OptionAwareParserState( ParsedCommandLine commandLine )
+ {
+ this.commandLine = commandLine;
+ }
+
+ @Override
+ public boolean maybeStartOption( String arg )
+ {
+ return isOption( arg );
+ }
+
+ @Override
+ public ParserState onNonOption( String arg )
+ {
+ commandLine.addExtraValue( arg );
+ return allowMixedOptions ? new AfterFirstSubCommand( commandLine ) : new AfterOptions( commandLine );
+ }
+ }
+
+ private class BeforeFirstSubCommand
+ extends OptionAwareParserState
+ {
+ private BeforeFirstSubCommand( ParsedCommandLine commandLine )
+ {
+ super( commandLine );
+ }
+
+ @Override
+ public OptionParserState onStartOption( String arg, String option )
+ {
+ OptionString optionString = new OptionString( arg, option );
+ CommandLineOption commandLineOption = optionsByString.get( option );
+ if ( commandLineOption == null )
+ {
+ if ( allowUnknownOptions )
+ {
+ return new UnknownOptionParserState( arg, commandLine, this );
+ }
+ else
+ {
+ throw new CommandLineArgumentException( String.format( "Unknown command-line option '%s'.",
+ optionString ) );
+ }
+ }
+ return new KnownOptionParserState( optionString, commandLineOption, commandLine, this );
+ }
+ }
+
+ private class AfterFirstSubCommand
+ extends OptionAwareParserState
+ {
+ private AfterFirstSubCommand( ParsedCommandLine commandLine )
+ {
+ super( commandLine );
+ }
+
+ @Override
+ public OptionParserState onStartOption( String arg, String option )
+ {
+ CommandLineOption commandLineOption = optionsByString.get( option );
+ if ( commandLineOption == null )
+ {
+ return new UnknownOptionParserState( arg, commandLine, this );
+ }
+ return new KnownOptionParserState( new OptionString( arg, option ), commandLineOption, commandLine, this );
+ }
+ }
+
+ private static class AfterOptions
+ extends ParserState
+ {
+ private final ParsedCommandLine commandLine;
+
+ private AfterOptions( ParsedCommandLine commandLine )
+ {
+ this.commandLine = commandLine;
+ }
+
+ @Override
+ public boolean maybeStartOption( String arg )
+ {
+ return false;
+ }
+
+ @Override
+ public OptionParserState onStartOption( String arg, String option )
+ {
+ return new UnknownOptionParserState( arg, commandLine, this );
+ }
+
+ @Override
+ public ParserState onNonOption( String arg )
+ {
+ commandLine.addExtraValue( arg );
+ return this;
+ }
+ }
+
+ private static class MissingOptionArgState
+ extends ParserState
+ {
+ private final OptionParserState option;
+
+ private MissingOptionArgState( OptionParserState option )
+ {
+ this.option = option;
+ }
+
+ @Override
+ public boolean maybeStartOption( String arg )
+ {
+ return isOption( arg );
+ }
+
+ @Override
+ public OptionParserState onStartOption( String arg, String option )
+ {
+ return this.option.onComplete().onStartOption( arg, option );
+ }
+
+ @Override
+ public ParserState onNonOption( String arg )
+ {
+ return option.onArgument( arg );
+ }
+
+ @Override
+ public void onCommandLineEnd()
+ {
+ option.onComplete();
+ }
+ }
+
+ private static abstract class OptionParserState
+ {
+ public abstract ParserState onStartNextArg();
+
+ public abstract ParserState onArgument( String argument );
+
+ public abstract boolean getHasArgument();
+
+ public abstract ParserState onComplete();
+ }
+
+ private class KnownOptionParserState
+ extends OptionParserState
+ {
+ private final OptionString optionString;
+
+ private final CommandLineOption option;
+
+ private final ParsedCommandLine commandLine;
+
+ private final ParserState state;
+
+ private final List values = new ArrayList();
+
+ private KnownOptionParserState( OptionString optionString, CommandLineOption option,
+ ParsedCommandLine commandLine, ParserState state )
+ {
+ this.optionString = optionString;
+ this.option = option;
+ this.commandLine = commandLine;
+ this.state = state;
+ }
+
+ @Override
+ public ParserState onArgument( String argument )
+ {
+ if ( !getHasArgument() )
+ {
+ throw new CommandLineArgumentException(
+ String.format( "Command-line option '%s' does not take an argument.",
+ optionString ) );
+ }
+ if ( argument.length() == 0 )
+ {
+ throw new CommandLineArgumentException(
+ String.format( "An empty argument was provided for command-line option '%s'.",
+ optionString ) );
+ }
+ values.add( argument );
+ return onComplete();
+ }
+
+ @Override
+ public ParserState onStartNextArg()
+ {
+ if ( option.getAllowsArguments() && values.isEmpty() )
+ {
+ return new MissingOptionArgState( this );
+ }
+ return onComplete();
+ }
+
+ @Override
+ public boolean getHasArgument()
+ {
+ return option.getAllowsArguments();
+ }
+
+ @Override
+ public ParserState onComplete()
+ {
+ if ( getHasArgument() && values.isEmpty() )
+ {
+ throw new CommandLineArgumentException(
+ String.format( "No argument was provided for command-line option '%s'.",
+ optionString ) );
+ }
+
+ ParsedCommandLineOption parsedOption = commandLine.addOption( optionString.option, option );
+ if ( values.size() + parsedOption.getValues().size() > 1 && !option.getAllowsMultipleArguments() )
+ {
+ throw new CommandLineArgumentException(
+ String.format( "Multiple arguments were provided for command-line option '%s'.",
+ optionString ) );
+ }
+ for ( String value : values )
+ {
+ parsedOption.addArgument( value );
+ }
+ if ( option.getDeprecationWarning() != null )
+ {
+ deprecationPrinter.println( "The " + optionString + " option is deprecated - "
+ + option.getDeprecationWarning() );
+ }
+ if ( option.getSubcommand() != null )
+ {
+ return state.onNonOption( option.getSubcommand() );
+ }
+
+ return state;
+ }
+ }
+
+ private static class UnknownOptionParserState
+ extends OptionParserState
+ {
+ private final ParserState state;
+
+ private final String arg;
+
+ private final ParsedCommandLine commandLine;
+
+ private UnknownOptionParserState( String arg, ParsedCommandLine commandLine, ParserState state )
+ {
+ this.arg = arg;
+ this.commandLine = commandLine;
+ this.state = state;
+ }
+
+ @Override
+ public boolean getHasArgument()
+ {
+ return true;
+ }
+
+ @Override
+ public ParserState onStartNextArg()
+ {
+ return onComplete();
+ }
+
+ @Override
+ public ParserState onArgument( String argument )
+ {
+ return onComplete();
+ }
+
+ @Override
+ public ParserState onComplete()
+ {
+ commandLine.addExtraValue( arg );
+ return state;
+ }
+ }
+
+ private static final class OptionComparator
+ implements Comparator
+ {
+ public int compare( CommandLineOption option1, CommandLineOption option2 )
+ {
+ String min1 = Collections.min( option1.getOptions(), new OptionStringComparator() );
+ String min2 = Collections.min( option2.getOptions(), new OptionStringComparator() );
+ return new CaseInsensitiveStringComparator().compare( min1, min2 );
+ }
+ }
+
+ private static final class CaseInsensitiveStringComparator
+ implements Comparator
+ {
+ public int compare( String option1, String option2 )
+ {
+ int diff = option1.compareToIgnoreCase( option2 );
+ if ( diff != 0 )
+ {
+ return diff;
+ }
+ return option1.compareTo( option2 );
+ }
+ }
+
+ private static final class OptionStringComparator
+ implements Comparator
+ {
+ public int compare( String option1, String option2 )
+ {
+ boolean short1 = option1.length() == 1;
+ boolean short2 = option2.length() == 1;
+ if ( short1 && !short2 )
+ {
+ return -1;
+ }
+ if ( !short1 && short2 )
+ {
+ return 1;
+ }
+ return new CaseInsensitiveStringComparator().compare( option1, option2 );
+ }
+ }
+}
diff --git a/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ParsedCommandLine.java b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ParsedCommandLine.java
new file mode 100644
index 0000000000..e7e34451cc
--- /dev/null
+++ b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ParsedCommandLine.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.maven.wrapper.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ParsedCommandLine
+{
+ private final Map optionsByString = new HashMap();
+
+ private final Set presentOptions = new HashSet();
+
+ private final List extraArguments = new ArrayList();
+
+ ParsedCommandLine( Iterable options )
+ {
+ for ( CommandLineOption option : options )
+ {
+ ParsedCommandLineOption parsedOption = new ParsedCommandLineOption();
+ for ( String optionStr : option.getOptions() )
+ {
+ optionsByString.put( optionStr, parsedOption );
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format( "options: %s, extraArguments: %s", quoteAndJoin( presentOptions ),
+ quoteAndJoin( extraArguments ) );
+ }
+
+ private String quoteAndJoin( Iterable strings )
+ {
+ StringBuilder output = new StringBuilder();
+ boolean isFirst = true;
+ for ( String string : strings )
+ {
+ if ( !isFirst )
+ {
+ output.append( ", " );
+ }
+ output.append( "'" );
+ output.append( string );
+ output.append( "'" );
+ isFirst = false;
+ }
+ return output.toString();
+ }
+
+ /**
+ * Returns true if the given option is present in this command-line.
+ *
+ * @param option The option, without the '-' or '--' prefix.
+ * @return true if the option is present.
+ */
+ public boolean hasOption( String option )
+ {
+ option( option );
+ return presentOptions.contains( option );
+ }
+
+ /**
+ * See also {@link #hasOption}.
+ *
+ * @param logLevelOptions the options to check
+ * @return true if any of the passed options is present
+ */
+ public boolean hasAnyOption( Collection logLevelOptions )
+ {
+ for ( String option : logLevelOptions )
+ {
+ if ( hasOption( option ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the value of the given option.
+ *
+ * @param option The option, without the '-' or '--' prefix.
+ * @return The option. never returns null.
+ */
+ public ParsedCommandLineOption option( String option )
+ {
+ ParsedCommandLineOption parsedOption = optionsByString.get( option );
+ if ( parsedOption == null )
+ {
+ throw new IllegalArgumentException( String.format( "Option '%s' not defined.", option ) );
+ }
+ return parsedOption;
+ }
+
+ public List getExtraArguments()
+ {
+ return extraArguments;
+ }
+
+ void addExtraValue( String value )
+ {
+ extraArguments.add( value );
+ }
+
+ ParsedCommandLineOption addOption( String optionStr, CommandLineOption option )
+ {
+ ParsedCommandLineOption parsedOption = optionsByString.get( optionStr );
+ presentOptions.addAll( option.getOptions() );
+ return parsedOption;
+ }
+}
diff --git a/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ParsedCommandLineOption.java b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ParsedCommandLineOption.java
new file mode 100644
index 0000000000..7d75a8fec1
--- /dev/null
+++ b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ParsedCommandLineOption.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.maven.wrapper.cli;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ParsedCommandLineOption
+{
+ private final List values = new ArrayList();
+
+ public String getValue()
+ {
+ if ( !hasValue() )
+ {
+ throw new IllegalStateException( "Option does not have any value." );
+ }
+ if ( values.size() > 1 )
+ {
+ throw new IllegalStateException( "Option has multiple values." );
+ }
+ return values.get( 0 );
+ }
+
+ public List getValues()
+ {
+ return values;
+ }
+
+ public void addArgument( String argument )
+ {
+ values.add( argument );
+ }
+
+ public boolean hasValue()
+ {
+ return !values.isEmpty();
+ }
+}
diff --git a/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ProjectPropertiesCommandLineConverter.java b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ProjectPropertiesCommandLineConverter.java
new file mode 100644
index 0000000000..8b1a110f87
--- /dev/null
+++ b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/ProjectPropertiesCommandLineConverter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.maven.wrapper.cli;
+
+public class ProjectPropertiesCommandLineConverter
+ extends AbstractPropertiesCommandLineConverter
+{
+
+ @Override
+ protected String getPropertyOption()
+ {
+ return "P";
+ }
+
+ @Override
+ protected String getPropertyOptionDetailed()
+ {
+ return "project-prop";
+ }
+
+ @Override
+ protected String getPropertyOptionDescription()
+ {
+ return "Set project property for the build script (e.g. -Pmyprop=myvalue).";
+ }
+}
diff --git a/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/SystemPropertiesCommandLineConverter.java b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/SystemPropertiesCommandLineConverter.java
new file mode 100644
index 0000000000..fb7bc9ac5d
--- /dev/null
+++ b/maven-wrapper/src/main/java/org/apache/maven/wrapper/cli/SystemPropertiesCommandLineConverter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.maven.wrapper.cli;
+
+public class SystemPropertiesCommandLineConverter
+ extends AbstractPropertiesCommandLineConverter
+{
+
+ @Override
+ protected String getPropertyOption()
+ {
+ return "D";
+ }
+
+ @Override
+ protected String getPropertyOptionDetailed()
+ {
+ return "system-prop";
+ }
+
+ @Override
+ protected String getPropertyOptionDescription()
+ {
+ return "Set system property of the JVM (e.g. -Dmyprop=myvalue).";
+ }
+}
\ No newline at end of file
diff --git a/maven-wrapper/src/test/java/org/apache/maven/wrapper/DownloaderTest.java b/maven-wrapper/src/test/java/org/apache/maven/wrapper/DownloaderTest.java
new file mode 100644
index 0000000000..c84096a867
--- /dev/null
+++ b/maven-wrapper/src/test/java/org/apache/maven/wrapper/DownloaderTest.java
@@ -0,0 +1,49 @@
+package org.apache.maven.wrapper;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.net.URI;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DownloaderTest
+{
+
+ private DefaultDownloader download;
+
+ private File testDir;
+
+ private File downloadFile;
+
+ private File rootDir;
+
+ private URI sourceRoot;
+
+ private File remoteFile;
+
+ @Before
+ public void setUp()
+ throws Exception
+ {
+ download = new DefaultDownloader( "mvnw", "aVersion" );
+ testDir = new File( "target/test-files/DownloadTest" );
+ rootDir = new File( testDir, "root" );
+ downloadFile = new File( rootDir, "file" );
+ remoteFile = new File( testDir, "remoteFile" );
+ FileUtils.write( remoteFile, "sometext" );
+ sourceRoot = remoteFile.toURI();
+ }
+
+ @Test
+ public void testDownload()
+ throws Exception
+ {
+ assert !downloadFile.exists();
+ download.download( sourceRoot, downloadFile );
+ assert downloadFile.exists();
+ assertEquals( "sometext", FileUtils.readFileToString( downloadFile ) );
+ }
+}
diff --git a/maven-wrapper/src/test/java/org/apache/maven/wrapper/InstallerTest.java b/maven-wrapper/src/test/java/org/apache/maven/wrapper/InstallerTest.java
new file mode 100644
index 0000000000..fc02d60940
--- /dev/null
+++ b/maven-wrapper/src/test/java/org/apache/maven/wrapper/InstallerTest.java
@@ -0,0 +1,196 @@
+package org.apache.maven.wrapper;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.net.URI;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Zip;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Hans Dockter
+ */
+public class InstallerTest
+{
+ private File testDir = new File( "target/test-files/SystemPropertiesHandlerTest-" + System.currentTimeMillis() );
+
+ private Installer install;
+
+ private Downloader downloadMock;
+
+ private PathAssembler pathAssemblerMock;
+
+ private boolean downloadCalled;
+
+ private File zip;
+
+ private File distributionDir;
+
+ private File zipStore;
+
+ private File mavenHomeDir;
+
+ private File zipDestination;
+
+ private WrapperConfiguration configuration = new WrapperConfiguration();
+
+ private Downloader download;
+
+ private PathAssembler pathAssembler;
+
+ private PathAssembler.LocalDistribution localDistribution;
+
+ @Before
+ public void setup()
+ throws Exception
+ {
+
+ testDir.mkdirs();
+
+ downloadCalled = false;
+ configuration.setZipBase( PathAssembler.PROJECT_STRING );
+ configuration.setZipPath( "someZipPath" );
+ configuration.setDistributionBase( PathAssembler.MAVEN_USER_HOME_STRING );
+ configuration.setDistributionPath( "someDistPath" );
+ configuration.setDistribution( new URI( "http://server/maven-0.9.zip" ) );
+ configuration.setAlwaysDownload( false );
+ configuration.setAlwaysUnpack( false );
+ distributionDir = new File( testDir, "someDistPath" );
+ mavenHomeDir = new File( distributionDir, "maven-0.9" );
+ zipStore = new File( testDir, "zips" );
+ zipDestination = new File( zipStore, "maven-0.9.zip" );
+
+ download = mock( Downloader.class );
+ pathAssembler = mock( PathAssembler.class );
+ localDistribution = mock( PathAssembler.LocalDistribution.class );
+
+ when( localDistribution.getZipFile() ).thenReturn( zipDestination );
+ when( localDistribution.getDistributionDir() ).thenReturn( distributionDir );
+ when( pathAssembler.getDistribution( configuration ) ).thenReturn( localDistribution );
+
+ install = new Installer( download, pathAssembler );
+
+ }
+
+ private void createTestZip( File zipDestination )
+ throws Exception
+ {
+ File explodedZipDir = new File( testDir, "explodedZip" );
+ explodedZipDir.mkdirs();
+ zipDestination.getParentFile().mkdirs();
+ File mavenScript = new File( explodedZipDir, "maven-0.9/bin/mvn" );
+ mavenScript.getParentFile().mkdirs();
+ FileUtils.write( mavenScript, "something" );
+
+ zipTo( explodedZipDir, zipDestination );
+ }
+
+ public void testCreateDist()
+ throws Exception
+ {
+ File homeDir = install.createDist( configuration );
+
+ Assert.assertEquals( mavenHomeDir, homeDir );
+ Assert.assertTrue( homeDir.isDirectory() );
+ Assert.assertTrue( new File( homeDir, "bin/mvn" ).exists() );
+ Assert.assertTrue( zipDestination.exists() );
+
+ Assert.assertEquals( localDistribution, pathAssembler.getDistribution( configuration ) );
+ Assert.assertEquals( distributionDir, localDistribution.getDistributionDir() );
+ Assert.assertEquals( zipDestination, localDistribution.getZipFile() );
+
+ // download.download(new URI("http://some/test"), distributionDir);
+ // verify(download).download(new URI("http://some/test"), distributionDir);
+ }
+
+ @Test
+ public void testCreateDistWithExistingDistribution()
+ throws Exception
+ {
+
+ FileUtils.touch( zipDestination );
+ mavenHomeDir.mkdirs();
+ File someFile = new File( mavenHomeDir, "some-file" );
+ FileUtils.touch( someFile );
+
+ File homeDir = install.createDist( configuration );
+
+ Assert.assertEquals( mavenHomeDir, homeDir );
+ Assert.assertTrue( mavenHomeDir.isDirectory() );
+ Assert.assertTrue( new File( homeDir, "some-file" ).exists() );
+ Assert.assertTrue( zipDestination.exists() );
+
+ Assert.assertEquals( localDistribution, pathAssembler.getDistribution( configuration ) );
+ Assert.assertEquals( distributionDir, localDistribution.getDistributionDir() );
+ Assert.assertEquals( zipDestination, localDistribution.getZipFile() );
+ }
+
+ @Test
+ public void testCreateDistWithExistingDistAndZipAndAlwaysUnpackTrue()
+ throws Exception
+ {
+
+ createTestZip( zipDestination );
+ mavenHomeDir.mkdirs();
+ File garbage = new File( mavenHomeDir, "garbage" );
+ FileUtils.touch( garbage );
+ configuration.setAlwaysUnpack( true );
+
+ File homeDir = install.createDist( configuration );
+
+ Assert.assertEquals( mavenHomeDir, homeDir );
+ Assert.assertTrue( mavenHomeDir.isDirectory() );
+ Assert.assertFalse( new File( homeDir, "garbage" ).exists() );
+ Assert.assertTrue( zipDestination.exists() );
+
+ Assert.assertEquals( localDistribution, pathAssembler.getDistribution( configuration ) );
+ Assert.assertEquals( distributionDir, localDistribution.getDistributionDir() );
+ Assert.assertEquals( zipDestination, localDistribution.getZipFile() );
+ }
+
+ @Test
+ public void testCreateDistWithExistingZipAndDistAndAlwaysDownloadTrue()
+ throws Exception
+ {
+
+ createTestZip( zipDestination );
+ File garbage = new File( mavenHomeDir, "garbage" );
+ FileUtils.touch( garbage );
+ configuration.setAlwaysUnpack( true );
+
+ File homeDir = install.createDist( configuration );
+
+ Assert.assertEquals( mavenHomeDir, homeDir );
+ Assert.assertTrue( mavenHomeDir.isDirectory() );
+ Assert.assertTrue( new File( homeDir, "bin/mvn" ).exists() );
+ Assert.assertFalse( new File( homeDir, "garbage" ).exists() );
+ Assert.assertTrue( zipDestination.exists() );
+
+ Assert.assertEquals( localDistribution, pathAssembler.getDistribution( configuration ) );
+ Assert.assertEquals( distributionDir, localDistribution.getDistributionDir() );
+ Assert.assertEquals( zipDestination, localDistribution.getZipFile() );
+
+ // download.download(new URI("http://some/test"), distributionDir);
+ // verify(download).download(new URI("http://some/test"), distributionDir);
+ }
+
+ public void zipTo( File directoryToZip, File zipFile )
+ {
+ Zip zip = new Zip();
+ zip.setBasedir( directoryToZip );
+ zip.setDestFile( zipFile );
+ zip.setProject( new Project() );
+
+ Zip.WhenEmpty whenEmpty = new Zip.WhenEmpty();
+ whenEmpty.setValue( "create" );
+ zip.setWhenempty( whenEmpty );
+ zip.execute();
+ }
+
+}
diff --git a/maven-wrapper/src/test/java/org/apache/maven/wrapper/PathAssemblerTest.java b/maven-wrapper/src/test/java/org/apache/maven/wrapper/PathAssemblerTest.java
new file mode 100644
index 0000000000..fbd0d648de
--- /dev/null
+++ b/maven-wrapper/src/test/java/org/apache/maven/wrapper/PathAssemblerTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2007-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.maven.wrapper;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.net.URI;
+import java.util.regex.Pattern;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Hans Dockter
+ */
+public class PathAssemblerTest
+{
+ public static final String TEST_MAVEN_USER_HOME = "someUserHome";
+
+ private PathAssembler pathAssembler = new PathAssembler( new File( TEST_MAVEN_USER_HOME ) );
+
+ final WrapperConfiguration configuration = new WrapperConfiguration();
+
+ @Before
+ public void setup()
+ {
+ configuration.setDistributionBase( PathAssembler.MAVEN_USER_HOME_STRING );
+ configuration.setDistributionPath( "somePath" );
+ configuration.setZipBase( PathAssembler.MAVEN_USER_HOME_STRING );
+ configuration.setZipPath( "somePath" );
+ }
+
+ @Test
+ public void distributionDirWithMavenUserHomeBase()
+ throws Exception
+ {
+ configuration.setDistribution( new URI( "http://server/dist/maven-0.9-bin.zip" ) );
+
+ File distributionDir = pathAssembler.getDistribution( configuration ).getDistributionDir();
+ assertThat( distributionDir.getName(), matchesRegexp( "[a-z0-9]+" ) );
+ assertThat( distributionDir.getParentFile(), equalTo( file( TEST_MAVEN_USER_HOME + "/somePath/maven-0.9-bin" ) ) );
+ }
+
+ @Test
+ public void distributionDirWithProjectBase()
+ throws Exception
+ {
+ configuration.setDistributionBase( PathAssembler.PROJECT_STRING );
+ configuration.setDistribution( new URI( "http://server/dist/maven-0.9-bin.zip" ) );
+
+ File distributionDir = pathAssembler.getDistribution( configuration ).getDistributionDir();
+ assertThat( distributionDir.getName(), matchesRegexp( "[a-z0-9]+" ) );
+ assertThat( distributionDir.getParentFile(), equalTo( file( currentDirPath() + "/somePath/maven-0.9-bin" ) ) );
+ }
+
+ @Test
+ public void distributionDirWithUnknownBase()
+ throws Exception
+ {
+ configuration.setDistribution( new URI( "http://server/dist/maven-1.0.zip" ) );
+ configuration.setDistributionBase( "unknownBase" );
+
+ try
+ {
+ pathAssembler.getDistribution( configuration );
+ fail();
+ }
+ catch ( RuntimeException e )
+ {
+ assertEquals( "Base: unknownBase is unknown", e.getMessage() );
+ }
+ }
+
+ @Test
+ public void distZipWithMavenUserHomeBase()
+ throws Exception
+ {
+ configuration.setDistribution( new URI( "http://server/dist/maven-1.0.zip" ) );
+
+ File dist = pathAssembler.getDistribution( configuration ).getZipFile();
+ assertThat( dist.getName(), equalTo( "maven-1.0.zip" ) );
+ assertThat( dist.getParentFile().getName(), matchesRegexp( "[a-z0-9]+" ) );
+ assertThat( dist.getParentFile().getParentFile(),
+ equalTo( file( TEST_MAVEN_USER_HOME + "/somePath/maven-1.0" ) ) );
+ }
+
+ @Test
+ public void distZipWithProjectBase()
+ throws Exception
+ {
+ configuration.setZipBase( PathAssembler.PROJECT_STRING );
+ configuration.setDistribution( new URI( "http://server/dist/maven-1.0.zip" ) );
+
+ File dist = pathAssembler.getDistribution( configuration ).getZipFile();
+ assertThat( dist.getName(), equalTo( "maven-1.0.zip" ) );
+ assertThat( dist.getParentFile().getName(), matchesRegexp( "[a-z0-9]+" ) );
+ assertThat( dist.getParentFile().getParentFile(), equalTo( file( currentDirPath() + "/somePath/maven-1.0" ) ) );
+ }
+
+ private File file( String path )
+ {
+ return new File( path );
+ }
+
+ private String currentDirPath()
+ {
+ return System.getProperty( "user.dir" );
+ }
+
+ public static Matcher matchesRegexp( final String pattern )
+ {
+ return new BaseMatcher()
+ {
+ public boolean matches( Object o )
+ {
+ return Pattern.compile( pattern ).matcher( (CharSequence) o ).matches();
+ }
+
+ public void describeTo( Description description )
+ {
+ description.appendText( "a CharSequence that matches regexp " ).appendValue( pattern );
+ }
+ };
+ }
+}
diff --git a/maven-wrapper/src/test/java/org/apache/maven/wrapper/SystemPropertiesHandlerTest.java b/maven-wrapper/src/test/java/org/apache/maven/wrapper/SystemPropertiesHandlerTest.java
new file mode 100644
index 0000000000..54b5d3c596
--- /dev/null
+++ b/maven-wrapper/src/test/java/org/apache/maven/wrapper/SystemPropertiesHandlerTest.java
@@ -0,0 +1,60 @@
+package org.apache.maven.wrapper;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SystemPropertiesHandlerTest
+{
+
+ private File tmpDir = new File( "target/test-files/SystemPropertiesHandlerTest" );
+
+ @Before
+ public void setupTempDir()
+ {
+ tmpDir.mkdirs();
+ }
+
+ @Test
+ public void testParsePropertiesFile()
+ throws Exception
+ {
+ File propFile = new File( tmpDir, "props" );
+ Properties props = new Properties();
+ props.put( "a", "b" );
+ props.put( "systemProp.c", "d" );
+ props.put( "systemProp.", "e" );
+
+ FileOutputStream fos = null;
+ try
+ {
+ fos = new FileOutputStream( propFile );
+ props.store( fos, "" );
+ }
+ finally
+ {
+ IOUtils.closeQuietly( fos );
+ }
+
+ Map expected = new HashMap();
+ expected.put( "c", "d" );
+
+ assertThat( SystemPropertiesHandler.getSystemProperties( propFile ), equalTo( expected ) );
+ }
+
+ @Test
+ public void ifNoPropertyFileExistShouldReturnEmptyMap()
+ {
+ Map expected = new HashMap();
+ assertThat( SystemPropertiesHandler.getSystemProperties( new File( tmpDir, "unknown" ) ), equalTo( expected ) );
+ }
+}
diff --git a/maven-wrapper/src/test/java/org/apache/maven/wrapper/WrapperExecutorTest.java b/maven-wrapper/src/test/java/org/apache/maven/wrapper/WrapperExecutorTest.java
new file mode 100644
index 0000000000..b258f83c0e
--- /dev/null
+++ b/maven-wrapper/src/test/java/org/apache/maven/wrapper/WrapperExecutorTest.java
@@ -0,0 +1,192 @@
+package org.apache.maven.wrapper;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.Properties;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class WrapperExecutorTest
+{
+ private final Installer install;
+
+ private final BootstrapMainStarter start;
+
+ private File propertiesFile;
+
+ private Properties properties = new Properties();
+
+ private File testDir = new File( "target/test-files/SystemPropertiesHandlerTest-" + System.currentTimeMillis() );
+
+ private File mockInstallDir = new File( testDir, "mock-dir" );
+
+ public WrapperExecutorTest()
+ throws Exception
+ {
+ install = mock( Installer.class );
+ when( install.createDist( Mockito.any( WrapperConfiguration.class ) ) ).thenReturn( mockInstallDir );
+ start = mock( BootstrapMainStarter.class );
+
+ testDir.mkdirs();
+ propertiesFile = new File( testDir, "maven/wrapper/maven-wrapper.properties" );
+
+ properties.put( "distributionUrl", "http://server/test/maven.zip" );
+ properties.put( "distributionBase", "testDistBase" );
+ properties.put( "distributionPath", "testDistPath" );
+ properties.put( "zipStoreBase", "testZipBase" );
+ properties.put( "zipStorePath", "testZipPath" );
+
+ writePropertiesFile( properties, propertiesFile, "header" );
+
+ }
+
+ @Test
+ public void loadWrapperMetadataFromFile()
+ throws Exception
+ {
+ WrapperExecutor wrapper = WrapperExecutor.forWrapperPropertiesFile( propertiesFile, System.out );
+
+ Assert.assertEquals( new URI( "http://server/test/maven.zip" ), wrapper.getDistribution() );
+ Assert.assertEquals( new URI( "http://server/test/maven.zip" ), wrapper.getConfiguration().getDistribution() );
+ Assert.assertEquals( "testDistBase", wrapper.getConfiguration().getDistributionBase() );
+ Assert.assertEquals( "testDistPath", wrapper.getConfiguration().getDistributionPath() );
+ Assert.assertEquals( "testZipBase", wrapper.getConfiguration().getZipBase() );
+ Assert.assertEquals( "testZipPath", wrapper.getConfiguration().getZipPath() );
+ }
+
+ @Test
+ public void loadWrapperMetadataFromDirectory()
+ throws Exception
+ {
+ WrapperExecutor wrapper = WrapperExecutor.forProjectDirectory( testDir, System.out );
+
+ Assert.assertEquals( new URI( "http://server/test/maven.zip" ), wrapper.getDistribution() );
+ Assert.assertEquals( new URI( "http://server/test/maven.zip" ), wrapper.getConfiguration().getDistribution() );
+ Assert.assertEquals( "testDistBase", wrapper.getConfiguration().getDistributionBase() );
+ Assert.assertEquals( "testDistPath", wrapper.getConfiguration().getDistributionPath() );
+ Assert.assertEquals( "testZipBase", wrapper.getConfiguration().getZipBase() );
+ Assert.assertEquals( "testZipPath", wrapper.getConfiguration().getZipPath() );
+ }
+
+ @Test
+ public void useDefaultMetadataNoProeprtiesFile()
+ throws Exception
+ {
+ WrapperExecutor wrapper = WrapperExecutor.forProjectDirectory( new File( testDir, "unknown" ), System.out );
+
+ Assert.assertNull( wrapper.getDistribution() );
+ Assert.assertNull( wrapper.getConfiguration().getDistribution() );
+ Assert.assertEquals( PathAssembler.MAVEN_USER_HOME_STRING, wrapper.getConfiguration().getDistributionBase() );
+ Assert.assertEquals( Installer.DEFAULT_DISTRIBUTION_PATH, wrapper.getConfiguration().getDistributionPath() );
+ Assert.assertEquals( PathAssembler.MAVEN_USER_HOME_STRING, wrapper.getConfiguration().getZipBase() );
+ Assert.assertEquals( Installer.DEFAULT_DISTRIBUTION_PATH, wrapper.getConfiguration().getZipPath() );
+ }
+
+ @Test
+ public void propertiesFileOnlyContainsDistURL()
+ throws Exception
+ {
+
+ properties = new Properties();
+ properties.put( "distributionUrl", "http://server/test/maven.zip" );
+ writePropertiesFile( properties, propertiesFile, "header" );
+
+ WrapperExecutor wrapper = WrapperExecutor.forWrapperPropertiesFile( propertiesFile, System.out );
+
+ Assert.assertEquals( new URI( "http://server/test/maven.zip" ), wrapper.getDistribution() );
+ Assert.assertEquals( new URI( "http://server/test/maven.zip" ), wrapper.getConfiguration().getDistribution() );
+ Assert.assertEquals( PathAssembler.MAVEN_USER_HOME_STRING, wrapper.getConfiguration().getDistributionBase() );
+ Assert.assertEquals( Installer.DEFAULT_DISTRIBUTION_PATH, wrapper.getConfiguration().getDistributionPath() );
+ Assert.assertEquals( PathAssembler.MAVEN_USER_HOME_STRING, wrapper.getConfiguration().getZipBase() );
+ Assert.assertEquals( Installer.DEFAULT_DISTRIBUTION_PATH, wrapper.getConfiguration().getZipPath() );
+ }
+
+ @Test
+ public void executeInstallAndLaunch()
+ throws Exception
+ {
+ WrapperExecutor wrapper = WrapperExecutor.forProjectDirectory( propertiesFile, System.out );
+
+ wrapper.execute( new String[] { "arg" }, install, start );
+ verify( install ).createDist( Mockito.any( WrapperConfiguration.class ) );
+ verify( start ).start( new String[] { "arg" }, mockInstallDir );
+ }
+
+ @Test( )
+ public void failWhenDistNotSetInProperties()
+ throws Exception
+ {
+ properties = new Properties();
+ writePropertiesFile( properties, propertiesFile, "header" );
+
+ try
+ {
+ WrapperExecutor.forWrapperPropertiesFile( propertiesFile, System.out );
+ Assert.fail( "Expected RuntimeException" );
+ }
+ catch ( RuntimeException e )
+ {
+ Assert.assertEquals( "Could not load wrapper properties from '" + propertiesFile + "'.", e.getMessage() );
+ Assert.assertEquals( "No value with key 'distributionUrl' specified in wrapper properties file '"
+ + propertiesFile + "'.", e.getCause().getMessage() );
+ }
+
+ }
+
+ @Test
+ public void failWhenPropertiesFileDoesNotExist()
+ {
+ propertiesFile = new File( testDir, "unknown.properties" );
+
+ try
+ {
+ WrapperExecutor.forWrapperPropertiesFile( propertiesFile, System.out );
+ Assert.fail( "Expected RuntimeException" );
+ }
+ catch ( RuntimeException e )
+ {
+ Assert.assertEquals( "Wrapper properties file '" + propertiesFile + "' does not exist.", e.getMessage() );
+ }
+ }
+
+ @Test
+ public void testRelativeDistUrl()
+ throws Exception
+ {
+
+ properties = new Properties();
+ properties.put( "distributionUrl", "some/relative/url/to/bin.zip" );
+ writePropertiesFile( properties, propertiesFile, "header" );
+
+ WrapperExecutor wrapper = WrapperExecutor.forWrapperPropertiesFile( propertiesFile, System.out );
+ Assert.assertNotEquals( "some/relative/url/to/bin.zip", wrapper.getDistribution().getSchemeSpecificPart() );
+ Assert.assertTrue( wrapper.getDistribution().getSchemeSpecificPart().endsWith( "some/relative/url/to/bin.zip" ) );
+ }
+
+ private void writePropertiesFile( Properties properties, File propertiesFile, String message )
+ throws Exception
+ {
+
+ propertiesFile.getParentFile().mkdirs();
+
+ OutputStream outStream = null;
+ try
+ {
+ outStream = new FileOutputStream( propertiesFile );
+ properties.store( outStream, message );
+ }
+ finally
+ {
+ IOUtils.closeQuietly( outStream );
+ }
+ }
+}
diff --git a/maven-wrapper/src/test/resources/org/apache/maven/wrapper/wrapper.properties b/maven-wrapper/src/test/resources/org/apache/maven/wrapper/wrapper.properties
new file mode 100644
index 0000000000..6ff45e7805
--- /dev/null
+++ b/maven-wrapper/src/test/resources/org/apache/maven/wrapper/wrapper.properties
@@ -0,0 +1,5 @@
+distributionUrl=http://server/test/maven.zip
+distributionBase=testDistBase
+zipStoreBase=testZipBase
+distributionPath=testDistPath
+zipStorePath=testZipPath