[Jython-checkins] jython (2.5): Move installer into mercurial repository.
frank.wierzbicki
jython-checkins at python.org
Sat Feb 9 02:05:44 CET 2013
http://hg.python.org/jython/rev/402cab975983
changeset: 7015:402cab975983
branch: 2.5
parent: 7012:723492dbab02
user: Oti Humbel <ohumbel at gmail.com>
date: Fri Feb 08 11:54:19 2013 -0800
summary:
Move installer into mercurial repository.
Committed with user Oti Humbel.
files:
installer/src/java/org/apache/LICENSE.txt | 202 +++
installer/src/java/org/apache/commons/cli/AlreadySelectedException.java | 81 +
installer/src/java/org/apache/commons/cli/BasicParser.java | 92 +
installer/src/java/org/apache/commons/cli/CommandLine.java | 328 +++++
installer/src/java/org/apache/commons/cli/CommandLineParser.java | 97 +
installer/src/java/org/apache/commons/cli/GnuParser.java | 187 ++
installer/src/java/org/apache/commons/cli/HelpFormatter.java | 542 ++++++++
installer/src/java/org/apache/commons/cli/MissingArgumentException.java | 82 +
installer/src/java/org/apache/commons/cli/MissingOptionException.java | 81 +
installer/src/java/org/apache/commons/cli/Option.java | 575 +++++++++
installer/src/java/org/apache/commons/cli/OptionBuilder.java | 368 +++++
installer/src/java/org/apache/commons/cli/OptionGroup.java | 187 ++
installer/src/java/org/apache/commons/cli/Options.java | 331 +++++
installer/src/java/org/apache/commons/cli/ParseException.java | 82 +
installer/src/java/org/apache/commons/cli/Parser.java | 282 ++++
installer/src/java/org/apache/commons/cli/PatternOptionBuilder.java | 204 +++
installer/src/java/org/apache/commons/cli/PosixParser.java | 342 +++++
installer/src/java/org/apache/commons/cli/TypeHandler.java | 252 +++
installer/src/java/org/apache/commons/cli/UnrecognizedOptionException.java | 82 +
installer/src/java/org/python/util/install/AbstractWizard.java | 438 ++++++
installer/src/java/org/python/util/install/AbstractWizardHeader.java | 12 +
installer/src/java/org/python/util/install/AbstractWizardPage.java | 153 ++
installer/src/java/org/python/util/install/AbstractWizardValidator.java | 132 ++
installer/src/java/org/python/util/install/ChildProcess.java | 357 +++++
installer/src/java/org/python/util/install/ConsoleInstaller.java | 609 +++++++++
installer/src/java/org/python/util/install/DirectoryFilter.java | 23 +
installer/src/java/org/python/util/install/DirectorySelectionPage.java | 200 +++
installer/src/java/org/python/util/install/DirectorySelectionPageValidator.java | 36 +
installer/src/java/org/python/util/install/EmptyValidator.java | 8 +
installer/src/java/org/python/util/install/FileHelper.java | 208 +++
installer/src/java/org/python/util/install/FrameInstaller.java | 186 ++
installer/src/java/org/python/util/install/Installation.java | 439 ++++++
installer/src/java/org/python/util/install/InstallationCancelledException.java | 9 +
installer/src/java/org/python/util/install/InstallationListener.java | 7 +
installer/src/java/org/python/util/install/InstallationType.java | 120 +
installer/src/java/org/python/util/install/InstallerCommandLine.java | 456 +++++++
installer/src/java/org/python/util/install/InstallerException.java | 21 +
installer/src/java/org/python/util/install/JarInfo.java | 235 +++
installer/src/java/org/python/util/install/JarInstaller.java | 283 ++++
installer/src/java/org/python/util/install/JavaHomeHandler.java | 209 +++
installer/src/java/org/python/util/install/JavaSelectionPage.java | 199 +++
installer/src/java/org/python/util/install/JavaSelectionPageValidator.java | 31 +
installer/src/java/org/python/util/install/JavaVersionTester.java | 61 +
installer/src/java/org/python/util/install/LanguagePage.java | 121 +
installer/src/java/org/python/util/install/LicensePage.java | 120 +
installer/src/java/org/python/util/install/LicensePageValidator.java | 17 +
installer/src/java/org/python/util/install/OverviewPage.java | 243 +++
installer/src/java/org/python/util/install/ProgressListener.java | 15 +
installer/src/java/org/python/util/install/ProgressPage.java | 122 +
installer/src/java/org/python/util/install/ReadmePage.java | 75 +
installer/src/java/org/python/util/install/StandalonePackager.java | 184 ++
installer/src/java/org/python/util/install/StartScriptGenerator.java | 240 +++
installer/src/java/org/python/util/install/SuccessPage.java | 55 +
installer/src/java/org/python/util/install/TextConstants.java | 148 ++
installer/src/java/org/python/util/install/TextConstants_de.java | 148 ++
installer/src/java/org/python/util/install/TextConstants_en.java | 5 +
installer/src/java/org/python/util/install/TextKeys.java | 135 ++
installer/src/java/org/python/util/install/TypePage.java | 268 ++++
installer/src/java/org/python/util/install/UnicodeSequences.java | 19 +
installer/src/java/org/python/util/install/ValidationEvent.java | 14 +
installer/src/java/org/python/util/install/ValidationException.java | 19 +
installer/src/java/org/python/util/install/ValidationInformationException.java | 21 +
installer/src/java/org/python/util/install/ValidationListener.java | 11 +
installer/src/java/org/python/util/install/Wizard.java | 90 +
installer/src/java/org/python/util/install/WizardEvent.java | 13 +
installer/src/java/org/python/util/install/WizardHeader.java | 89 +
installer/src/java/org/python/util/install/WizardListener.java | 13 +
installer/src/java/org/python/util/install/driver/Autotest.java | 274 ++++
installer/src/java/org/python/util/install/driver/ConsoleAutotest.java | 30 +
installer/src/java/org/python/util/install/driver/ConsoleDriver.java | 58 +
installer/src/java/org/python/util/install/driver/DriverException.java | 17 +
installer/src/java/org/python/util/install/driver/GuiAutotest.java | 188 ++
installer/src/java/org/python/util/install/driver/InstallationDriver.java | 416 ++++++
installer/src/java/org/python/util/install/driver/NormalVerifier.java | 287 ++++
installer/src/java/org/python/util/install/driver/SilentAutotest.java | 25 +
installer/src/java/org/python/util/install/driver/StandaloneVerifier.java | 74 +
installer/src/java/org/python/util/install/driver/Tunnel.java | 61 +
installer/src/java/org/python/util/install/driver/Verifier.java | 17 +
installer/src/java/org/python/util/install/driver/jython_test.bat.template | 73 +
installer/src/java/org/python/util/install/driver/jython_test.template | 58 +
installer/src/java/org/python/util/install/jython_small_c.png | Bin
installer/test/java/org/AllTests.java | 101 +
installer/test/java/org/apache/commons/cli/ApplicationTest.java | 120 +
installer/test/java/org/apache/commons/cli/BugsTest.java | 348 +++++
installer/test/java/org/apache/commons/cli/BuildTest.java | 96 +
installer/test/java/org/apache/commons/cli/GnuParseTest.java | 265 ++++
installer/test/java/org/apache/commons/cli/HelpFormatterExamples.java | 106 +
installer/test/java/org/apache/commons/cli/HelpFormatterTest.java | 82 +
installer/test/java/org/apache/commons/cli/OptionBuilderTest.java | 160 ++
installer/test/java/org/apache/commons/cli/OptionGroupSortTest.java | 43 +
installer/test/java/org/apache/commons/cli/OptionGroupTest.java | 246 +++
installer/test/java/org/apache/commons/cli/OptionsTest.java | 28 +
installer/test/java/org/apache/commons/cli/ParseRequiredTest.java | 113 +
installer/test/java/org/apache/commons/cli/ParseTest.java | 285 ++++
installer/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java | 82 +
installer/test/java/org/apache/commons/cli/PosixParserTest.java | 138 ++
installer/test/java/org/apache/commons/cli/TestHelpFormatter.java | 170 ++
installer/test/java/org/apache/commons/cli/ValueTest.java | 271 ++++
installer/test/java/org/apache/commons/cli/ValuesTest.java | 248 +++
installer/test/java/org/python/util/install/ChildProcessExample.java | 32 +
installer/test/java/org/python/util/install/ChildProcessTest.java | 80 +
installer/test/java/org/python/util/install/ChmodTest_Standalone.java | 57 +
installer/test/java/org/python/util/install/FileHelperTest.java | 271 ++++
installer/test/java/org/python/util/install/FrameInstallerTest.java | 88 +
installer/test/java/org/python/util/install/InstallationTest.java | 107 +
installer/test/java/org/python/util/install/InstallationTypeTest.java | 119 +
installer/test/java/org/python/util/install/InstallerCommandLineTest.java | 637 ++++++++++
installer/test/java/org/python/util/install/JavaHomeHandlerTest.java | 114 +
installer/test/java/org/python/util/install/JavaTest_Standalone.java | 32 +
installer/test/java/org/python/util/install/StandalonePackagerTest.java | 183 ++
installer/test/java/org/python/util/install/StartScriptGeneratorTest.java | 277 ++++
installer/test/java/org/python/util/install/UnicodeSequencesTest.java | 34 +
installer/test/java/org/python/util/install/driver/AutotestTest.java | 78 +
installer/test/java/org/python/util/install/driver/DrivableConsole.java | 82 +
installer/test/java/org/python/util/install/driver/DrivableConsoleTest.java | 37 +
installer/test/java/org/python/util/install/driver/NormalVerifierTest.java | 131 ++
installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java | 72 +
117 files changed, 17925 insertions(+), 0 deletions(-)
diff --git a/installer/src/java/org/apache/LICENSE.txt b/installer/src/java/org/apache/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/LICENSE.txt
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
diff --git a/installer/src/java/org/apache/commons/cli/AlreadySelectedException.java b/installer/src/java/org/apache/commons/cli/AlreadySelectedException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/AlreadySelectedException.java
@@ -0,0 +1,81 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+/**
+ * <p>Thrown when more than one option in an option group
+ * has been provided.</p>
+ *
+ * @author John Keyes ( john at integralsource.com )
+ * @see ParseException
+ */
+public class AlreadySelectedException extends ParseException {
+
+ /**
+ * <p>Construct a new <code>AlreadySelectedException</code>
+ * with the specified detail message.</p>
+ *
+ * @param message the detail message
+ */
+ public AlreadySelectedException( String message ) {
+ super( message );
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/BasicParser.java b/installer/src/java/org/apache/commons/cli/BasicParser.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/BasicParser.java
@@ -0,0 +1,92 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+/**
+ * The class BasicParser provides a very simple implementation of
+ * the {@link Parser#flatten(Options,String[],boolean) flatten} method.
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see Parser
+ */
+public class BasicParser extends Parser {
+
+ /**
+ * <p>A simple implementation of {@link Parser}'s abstract
+ * {@link Parser#flatten(Options,String[],boolean) flatten} method.</p>
+ *
+ * <p><b>Note:</b> <code>options</code> and <code>stopAtNonOption</code>
+ * are not used in this <code>flatten</code> method.</p>
+ *
+ * @param options The command line {@link Options}
+ * @param arguments The command line arguments to be parsed
+ * @param stopAtNonOption Specifies whether to stop flattening
+ * when an non option is found.
+ * @return The <code>arguments</code> String array.
+ */
+ protected String[] flatten( Options options,
+ String[] arguments,
+ boolean stopAtNonOption )
+ {
+ // just echo the arguments
+ return arguments;
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/apache/commons/cli/CommandLine.java b/installer/src/java/org/apache/commons/cli/CommandLine.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/CommandLine.java
@@ -0,0 +1,328 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * <p>Represents list of arguments parsed against
+ * a {@link Options} descriptor.<p>
+ *
+ * <p>It allows querying of a boolean {@link #hasOption(String opt)},
+ * in addition to retrieving the {@link #getOptionValue(String opt)}
+ * for options requiring arguments.</p>
+ *
+ * <p>Additionally, any left-over or unrecognized arguments,
+ * are available for further processing.</p>
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
+ * @author John Keyes (john at integralsource.com)
+ */
+public class CommandLine {
+
+ /** the unrecognised options/arguments */
+ private List args = new LinkedList();
+
+ /** the processed options */
+ private Map options = new HashMap();
+
+ /** Map of unique options for ease to get complete list of options */
+ private Map hashcodeMap = new HashMap();
+
+ /** the processed options */
+ private Option[] optionsArray;
+
+ /**
+ * <p>Creates a command line.</p>
+ */
+ CommandLine() {
+ }
+
+ /**
+ * <p>Query to see if an option has been set.</p>
+ *
+ * @param opt Short name of the option
+ * @return true if set, false if not
+ */
+ public boolean hasOption(String opt) {
+ return options.containsKey( opt );
+ }
+
+ /**
+ * <p>Query to see if an option has been set.</p>
+ *
+ * @param opt character name of the option
+ * @return true if set, false if not
+ */
+ public boolean hasOption( char opt ) {
+ return hasOption( String.valueOf( opt ) );
+ }
+
+ /**
+ * <p>Return the <code>Object</code> type of this <code>Option</code>.</p>
+ *
+ * @param opt the name of the option
+ * @return the type of this <code>Option</code>
+ */
+ public Object getOptionObject( String opt ) {
+ String res = getOptionValue( opt );
+
+ Object type = ((Option)((List)options.get(opt)).iterator().next()).getType();
+ return res == null ? null : TypeHandler.createValue(res, type);
+ }
+
+ /**
+ * <p>Return the <code>Object</code> type of this <code>Option</code>.</p>
+ *
+ * @param opt the name of the option
+ * @return the type of opt
+ */
+ public Object getOptionObject( char opt ) {
+ return getOptionObject( String.valueOf( opt ) );
+ }
+
+ /**
+ * <p>Retrieve the argument, if any, of this option.</p>
+ *
+ * @param opt the name of the option
+ * @return Value of the argument if option is set, and has an argument,
+ * otherwise null.
+ */
+ public String getOptionValue( String opt ) {
+ String[] values = getOptionValues(opt);
+ return (values == null) ? null : values[0];
+ }
+
+ /**
+ * <p>Retrieve the argument, if any, of this option.</p>
+ *
+ * @param opt the character name of the option
+ * @return Value of the argument if option is set, and has an argument,
+ * otherwise null.
+ */
+ public String getOptionValue( char opt ) {
+ return getOptionValue( String.valueOf( opt ) );
+ }
+
+ /**
+ * <p>Retrieves the array of values, if any, of an option.</p>
+ *
+ * @param opt string name of the option
+ * @return Values of the argument if option is set, and has an argument,
+ * otherwise null.
+ */
+ public String[] getOptionValues( String opt ) {
+ List values = new java.util.ArrayList();
+
+ if( options.containsKey( opt ) ) {
+ List opts = (List)options.get( opt );
+ Iterator iter = opts.iterator();
+
+ while( iter.hasNext() ) {
+ Option optt = (Option)iter.next();
+ values.addAll( optt.getValuesList() );
+ }
+ }
+ return (values.size() == 0) ? null : (String[])values.toArray(new String[]{});
+ }
+
+ /**
+ * <p>Retrieves the array of values, if any, of an option.</p>
+ *
+ * @param opt character name of the option
+ * @return Values of the argument if option is set, and has an argument,
+ * otherwise null.
+ */
+ public String[] getOptionValues( char opt ) {
+ return getOptionValues( String.valueOf( opt ) );
+ }
+
+ /**
+ * <p>Retrieve the argument, if any, of an option.</p>
+ *
+ * @param opt name of the option
+ * @param defaultValue is the default value to be returned if the option is not specified
+ * @return Value of the argument if option is set, and has an argument,
+ * otherwise <code>defaultValue</code>.
+ */
+ public String getOptionValue( String opt, String defaultValue ) {
+ String answer = getOptionValue( opt );
+ return ( answer != null ) ? answer : defaultValue;
+ }
+
+ /**
+ * <p>Retrieve the argument, if any, of an option.</p>
+ *
+ * @param opt character name of the option
+ * @param defaultValue is the default value to be returned if the option is not specified
+ * @return Value of the argument if option is set, and has an argument,
+ * otherwise <code>defaultValue</code>.
+ */
+ public String getOptionValue( char opt, String defaultValue ) {
+ return getOptionValue( String.valueOf( opt ), defaultValue );
+ }
+
+ /**
+ * <p>Retrieve any left-over non-recognized options and arguments</p>
+ *
+ * @return remaining items passed in but not parsed as an array
+ */
+ public String[] getArgs() {
+ String[] answer = new String[ args.size() ];
+ args.toArray( answer );
+ return answer;
+ }
+
+ /**
+ * <p>Retrieve any left-over non-recognized options and arguments</p>
+ *
+ * @return remaining items passed in but not parsed as a <code>List</code>.
+ */
+ public List getArgList() {
+ return args;
+ }
+
+ /**
+ * jkeyes
+ * - commented out until it is implemented properly
+ * <p>Dump state, suitable for debugging.</p>
+ *
+ * @return Stringified form of this object
+ */
+ /*
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append( "[ CommandLine: [ options: " );
+ buf.append( options.toString() );
+ buf.append( " ] [ args: ");
+ buf.append( args.toString() );
+ buf.append( " ] ]" );
+
+ return buf.toString();
+ }
+ */
+
+ /**
+ * <p>Add left-over unrecognized option/argument.</p>
+ *
+ * @param arg the unrecognised option/argument.
+ */
+ void addArg(String arg) {
+ args.add( arg );
+ }
+
+ /**
+ * <p>Add an option to the command line. The values of
+ * the option are stored.</p>
+ *
+ * @param opt the processed option
+ */
+ void addOption( Option opt ) {
+ hashcodeMap.put( new Integer( opt.hashCode() ), opt );
+
+ String key = opt.getOpt();
+ if( " ".equals(key) ) {
+ key = opt.getLongOpt();
+ }
+
+ if( options.get( key ) != null ) {
+ ((java.util.List)options.get( key )).add( opt );
+ }
+ else {
+ options.put( key, new java.util.ArrayList() );
+ ((java.util.List)options.get( key ) ).add( opt );
+ }
+ }
+
+ /**
+ * <p>Returns an iterator over the Option members of CommandLine.</p>
+ *
+ * @return an <code>Iterator</code> over the processed {@link Option}
+ * members of this {@link CommandLine}
+ */
+ public Iterator iterator( ) {
+ return hashcodeMap.values().iterator();
+ }
+
+ /**
+ * <p>Returns an array of the processed {@link Option}s.</p>
+ *
+ * @return an array of the processed {@link Option}s.
+ */
+ public Option[] getOptions( ) {
+ Collection processed = hashcodeMap.values();
+
+ // reinitialise array
+ optionsArray = new Option[ processed.size() ];
+
+ // return the array
+ return (Option[]) processed.toArray( optionsArray );
+ }
+
+}
diff --git a/installer/src/java/org/apache/commons/cli/CommandLineParser.java b/installer/src/java/org/apache/commons/cli/CommandLineParser.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/CommandLineParser.java
@@ -0,0 +1,97 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+/**
+ * A class that implements the <code>CommandLineParser</code> interface
+ * can parse a String array according to the {@link Options} specified
+ * and return a {@link CommandLine}.
+ *
+ * @author John Keyes (john at integralsource.com)
+ */
+public interface CommandLineParser {
+
+ /**
+ * Parse the arguments according to the specified options.
+ *
+ * @param options the specified Options
+ * @param arguments the command line arguments
+ * @return the list of atomic option and value tokens
+ * @throws ParseException if there are any problems encountered
+ * while parsing the command line tokens.
+ */
+ public CommandLine parse( Options options, String[] arguments )
+ throws ParseException;
+
+ /**
+ * Parse the arguments according to the specified options.
+ *
+ * @param options the specified Options
+ * @param arguments the command line arguments
+ * @param stopAtNonOption specifies whether to continue parsing the
+ * arguments if a non option is encountered.
+ * @return the list of atomic option and value tokens
+ * @throws ParseException if there are any problems encountered
+ * while parsing the command line tokens.
+ */
+ public CommandLine parse( Options options, String[] arguments, boolean stopAtNonOption )
+ throws ParseException;
+}
\ No newline at end of file
diff --git a/installer/src/java/org/apache/commons/cli/GnuParser.java b/installer/src/java/org/apache/commons/cli/GnuParser.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/GnuParser.java
@@ -0,0 +1,187 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * The class GnuParser provides an implementation of the
+ * {@link Parser#flatten(Options,String[],boolean) flatten} method.
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see Parser
+ * @version $Revision: 2662 $
+ */
+public class GnuParser extends Parser {
+
+ /** holder for flattened tokens */
+ private ArrayList tokens = new ArrayList();
+
+ /**
+ * <p>Resets the members to their original state i.e. remove
+ * all of <code>tokens</code> entries.
+ */
+ private void init() {
+ tokens.clear();
+ }
+
+ /**
+ * <p>This flatten method does so using the following rules:
+ * <ol>
+ * <li>If an {@link Option} exists for the first character of
+ * the <code>arguments</code> entry <b>AND</b> an {@link Option}
+ * does not exist for the whole <code>argument</code> then
+ * add the first character as an option to the processed tokens
+ * list e.g. "-D" and add the rest of the entry to the also.</li>
+ * <li>Otherwise just add the token to the processed tokens list.
+ * </li>
+ * </ol>
+ * </p>
+ */
+ protected String[] flatten( Options options,
+ String[] arguments,
+ boolean stopAtNonOption )
+ {
+ init();
+ boolean eatTheRest = false;
+ Option currentOption = null;
+
+ for( int i = 0; i < arguments.length; i++ ) {
+ if( "--".equals( arguments[i] ) ) {
+ eatTheRest = true;
+ tokens.add( "--" );
+ }
+ else if ( "-".equals( arguments[i] ) ) {
+ tokens.add( "-" );
+ }
+ else if( arguments[i].startsWith( "-" ) ) {
+ Option option = options.getOption( arguments[i] );
+
+ // this is not an Option
+ if( option == null ) {
+ // handle special properties Option
+ Option specialOption = options.getOption( arguments[i].substring(0,2) );
+ if( specialOption != null ) {
+ tokens.add( arguments[i].substring(0,2) );
+ tokens.add( arguments[i].substring(2) );
+ }
+ else if( stopAtNonOption ) {
+ eatTheRest = true;
+ tokens.add( arguments[i] );
+ }
+ else {
+ tokens.add( arguments[i] );
+ }
+ }
+ else {
+ currentOption = option;
+ // special option
+ Option specialOption = options.getOption( arguments[i].substring(0,2) );
+ if( specialOption != null && option == null ) {
+ tokens.add( arguments[i].substring(0,2) );
+ tokens.add( arguments[i].substring(2) );
+ }
+ else if( currentOption != null && currentOption.hasArg() ) {
+ if( currentOption.hasArg() ) {
+ tokens.add( arguments[i] );
+ currentOption= null;
+ }
+ else if ( currentOption.hasArgs() ) {
+ tokens.add( arguments[i] );
+ }
+ else if ( stopAtNonOption ) {
+ eatTheRest = true;
+ tokens.add( "--" );
+ tokens.add( arguments[i] );
+ }
+ else {
+ tokens.add( arguments[i] );
+ }
+ }
+ else if (currentOption != null ) {
+ tokens.add( arguments[i] );
+ }
+ else if ( stopAtNonOption ) {
+ eatTheRest = true;
+ tokens.add( "--" );
+ tokens.add( arguments[i] );
+ }
+ else {
+ tokens.add( arguments[i] );
+ }
+ }
+ }
+ else {
+ tokens.add( arguments[i] );
+ }
+
+ if( eatTheRest ) {
+ for( i++; i < arguments.length; i++ ) {
+ tokens.add( arguments[i] );
+ }
+ }
+ }
+ return (String[])tokens.toArray( new String[] {} );
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/apache/commons/cli/HelpFormatter.java b/installer/src/java/org/apache/commons/cli/HelpFormatter.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/HelpFormatter.java
@@ -0,0 +1,542 @@
+/*
+ * $Header$
+ * $Revision: 2690 $
+ * $Date: 2006-03-25 23:39:57 -0800 (Sat, 25 Mar 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A formatter of help messages for the current command line options
+ *
+ * @author Slawek Zachcial
+ * @author John Keyes (john at integralsource.com)
+ **/
+public class HelpFormatter
+{
+ // --------------------------------------------------------------- Constants
+
+ public static final int DEFAULT_WIDTH = 74;
+ public static final int DEFAULT_LEFT_PAD = 1;
+ public static final int DEFAULT_DESC_PAD = 3;
+ public static final String DEFAULT_SYNTAX_PREFIX = "usage: ";
+ public static final String DEFAULT_OPT_PREFIX = "-";
+ public static final String DEFAULT_LONG_OPT_PREFIX = "--";
+ public static final String DEFAULT_ARG_NAME = "arg";
+
+ // ------------------------------------------------------------------ Static
+
+ // -------------------------------------------------------------- Attributes
+
+ public int defaultWidth;
+ public int defaultLeftPad;
+ public int defaultDescPad;
+ public String defaultSyntaxPrefix;
+ public String defaultNewLine;
+ public String defaultOptPrefix;
+ public String defaultLongOptPrefix;
+ public String defaultArgName;
+
+ // ------------------------------------------------------------ Constructors
+ public HelpFormatter()
+ {
+ defaultWidth = DEFAULT_WIDTH;
+ defaultLeftPad = DEFAULT_LEFT_PAD;
+ defaultDescPad = DEFAULT_DESC_PAD;
+ defaultSyntaxPrefix = DEFAULT_SYNTAX_PREFIX;
+ defaultNewLine = System.getProperty("line.separator");
+ defaultOptPrefix = DEFAULT_OPT_PREFIX;
+ defaultLongOptPrefix = DEFAULT_LONG_OPT_PREFIX;
+ defaultArgName = DEFAULT_ARG_NAME;
+ }
+
+ // ------------------------------------------------------------------ Public
+
+ public void printHelp( String cmdLineSyntax,
+ Options options )
+ {
+ printHelp( defaultWidth, cmdLineSyntax, null, options, null, false );
+ }
+
+ public void printHelp( String cmdLineSyntax,
+ Options options,
+ boolean autoUsage )
+ {
+ printHelp( defaultWidth, cmdLineSyntax, null, options, null, autoUsage );
+ }
+
+ public void printHelp( String cmdLineSyntax,
+ String header,
+ Options options,
+ String footer )
+ {
+ printHelp( cmdLineSyntax, header, options, footer, false );
+ }
+
+ public void printHelp( String cmdLineSyntax,
+ String header,
+ Options options,
+ String footer,
+ boolean autoUsage )
+ {
+ printHelp(defaultWidth, cmdLineSyntax, header, options, footer, autoUsage );
+ }
+
+ public void printHelp( int width,
+ String cmdLineSyntax,
+ String header,
+ Options options,
+ String footer )
+ {
+ printHelp( width, cmdLineSyntax, header, options, footer, false );
+ }
+
+ public void printHelp( int width,
+ String cmdLineSyntax,
+ String header,
+ Options options,
+ String footer,
+ boolean autoUsage )
+ {
+ PrintWriter pw = new PrintWriter(System.out);
+ printHelp( pw, width, cmdLineSyntax, header,
+ options, defaultLeftPad, defaultDescPad, footer, autoUsage );
+ pw.flush();
+ }
+ public void printHelp( PrintWriter pw,
+ int width,
+ String cmdLineSyntax,
+ String header,
+ Options options,
+ int leftPad,
+ int descPad,
+ String footer )
+ throws IllegalArgumentException
+ {
+ printHelp( pw, width, cmdLineSyntax, header, options, leftPad, descPad, footer, false );
+ }
+
+ public void printHelp( PrintWriter pw,
+ int width,
+ String cmdLineSyntax,
+ String header,
+ Options options,
+ int leftPad,
+ int descPad,
+ String footer,
+ boolean autoUsage )
+ throws IllegalArgumentException
+ {
+ if ( cmdLineSyntax == null || cmdLineSyntax.length() == 0 )
+ {
+ throw new IllegalArgumentException("cmdLineSyntax not provided");
+ }
+
+ if ( autoUsage ) {
+ printUsage( pw, width, cmdLineSyntax, options );
+ }
+ else {
+ printUsage( pw, width, cmdLineSyntax );
+ }
+
+ if ( header != null && header.trim().length() > 0 )
+ {
+ printWrapped( pw, width, header );
+ }
+ printOptions( pw, width, options, leftPad, descPad );
+ if ( footer != null && footer.trim().length() > 0 )
+ {
+ printWrapped( pw, width, footer );
+ }
+ }
+
+ /**
+ * <p>Prints the usage statement for the specified application.</p>
+ *
+ * @param pw The PrintWriter to print the usage statement
+ * @param width ??
+ * @param appName The application name
+ * @param options The command line Options
+ *
+ */
+ public void printUsage( PrintWriter pw, int width, String app, Options options )
+ {
+ // initialise the string buffer
+ StringBuffer buff = new StringBuffer( defaultSyntaxPrefix ).append( app ).append( " " );
+
+ // create a list for processed option groups
+ ArrayList list = new ArrayList();
+
+ // temp variable
+ Option option;
+
+ // iterate over the options
+ for ( Iterator i = options.getOptions().iterator(); i.hasNext(); )
+ {
+ // get the next Option
+ option = (Option) i.next();
+
+ // check if the option is part of an OptionGroup
+ OptionGroup group = options.getOptionGroup( option );
+
+ // if the option is part of a group
+ if( group != null ) {
+ // if the group has not already been processed
+ if(!list.contains(group)) {
+
+ // add the group to the processed list
+ list.add( group );
+
+ // get the names of the options from the OptionGroup
+ Collection names = group.getNames();
+
+ buff.append( "[" );
+
+ // for each option in the OptionGroup
+ for( Iterator iter = names.iterator(); iter.hasNext(); ) {
+ buff.append( iter.next() );
+ if( iter.hasNext() ) {
+ buff.append( " | " );
+ }
+ }
+ buff.append( "] " );
+ }
+ } else { // if the Option is not part of an OptionGroup
+ // if the Option is not a required option
+ if( !option.isRequired() ) {
+ buff.append( "[" );
+ }
+
+ if( !" ".equals( option.getOpt() ) ) {
+ buff.append( "-" ).append( option.getOpt() );
+ }
+ else {
+ buff.append( "--" ).append( option.getLongOpt() );
+ }
+
+ if( option.hasArg() ){
+ buff.append( " " );
+ }
+
+ // if the Option has a value
+ if( option.hasArg() ) {
+ buff.append( option.getArgName() );
+ }
+
+ // if the Option is not a required option
+ if( !option.isRequired() ) {
+ buff.append( "]" );
+ }
+ buff.append( " " );
+ }
+ }
+
+ // call printWrapped
+ printWrapped( pw, width, buff.toString().indexOf(' ')+1,
+ buff.toString() );
+ }
+
+ public void printUsage( PrintWriter pw, int width, String cmdLineSyntax )
+ {
+ int argPos = cmdLineSyntax.indexOf(' ') + 1;
+ printWrapped(pw, width, defaultSyntaxPrefix.length() + argPos,
+ defaultSyntaxPrefix + cmdLineSyntax);
+ }
+
+ public void printOptions( PrintWriter pw, int width, Options options, int leftPad, int descPad )
+ {
+ StringBuffer sb = new StringBuffer();
+ renderOptions(sb, width, options, leftPad, descPad);
+ pw.println(sb.toString());
+ }
+
+ public void printWrapped( PrintWriter pw, int width, String text )
+ {
+ printWrapped(pw, width, 0, text);
+ }
+
+ public void printWrapped( PrintWriter pw, int width, int nextLineTabStop, String text )
+ {
+ StringBuffer sb = new StringBuffer(text.length());
+ renderWrappedText(sb, width, nextLineTabStop, text);
+ pw.println(sb.toString());
+ }
+
+ // --------------------------------------------------------------- Protected
+
+ protected StringBuffer renderOptions( StringBuffer sb,
+ int width,
+ Options options,
+ int leftPad,
+ int descPad )
+ {
+ final String lpad = createPadding(leftPad);
+ final String dpad = createPadding(descPad);
+
+ //first create list containing only <lpad>-a,--aaa where -a is opt and --aaa is
+ //long opt; in parallel look for the longest opt string
+ //this list will be then used to sort options ascending
+ int max = 0;
+ StringBuffer optBuf;
+ List prefixList = new ArrayList();
+ Option option;
+ List optList = options.helpOptions();
+ if (!options.isSortAsAdded()) {
+ Collections.sort(optList, new StringBufferComparator());
+ }
+ for ( Iterator i = optList.iterator(); i.hasNext(); )
+ {
+ option = (Option) i.next();
+ optBuf = new StringBuffer(8);
+
+ if (option.getOpt().equals(" "))
+ {
+ optBuf.append(lpad).append(" " + defaultLongOptPrefix).append(option.getLongOpt());
+ }
+ else
+ {
+ optBuf.append(lpad).append(defaultOptPrefix).append(option.getOpt());
+ if ( option.hasLongOpt() )
+ {
+ optBuf.append(',').append(defaultLongOptPrefix).append(option.getLongOpt());
+ }
+
+ }
+
+ if( option.hasArg() ) {
+ if( option.hasArgName() ) {
+ optBuf.append(" <").append( option.getArgName() ).append( '>' );
+ }
+ else {
+ optBuf.append(' ');
+ }
+ }
+
+ prefixList.add(optBuf);
+ max = optBuf.length() > max ? optBuf.length() : max;
+ }
+ int x = 0;
+ for ( Iterator i = optList.iterator(); i.hasNext(); )
+ {
+ option = (Option) i.next();
+ optBuf = new StringBuffer( prefixList.get( x++ ).toString() );
+
+ if ( optBuf.length() < max )
+ {
+ optBuf.append(createPadding(max - optBuf.length()));
+ }
+ optBuf.append( dpad );
+
+ int nextLineTabStop = max + descPad;
+ renderWrappedText(sb, width, nextLineTabStop,
+ optBuf.append(option.getDescription()).toString());
+ if ( i.hasNext() )
+ {
+ sb.append(defaultNewLine);
+ }
+ }
+
+ return sb;
+ }
+
+ protected StringBuffer renderWrappedText( StringBuffer sb,
+ int width,
+ int nextLineTabStop,
+ String text )
+ {
+ int pos = findWrapPos( text, width, 0);
+ if ( pos == -1 )
+ {
+ sb.append(rtrim(text));
+ return sb;
+ }
+ else
+ {
+ sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
+ }
+
+ //all following lines must be padded with nextLineTabStop space characters
+ final String padding = createPadding(nextLineTabStop);
+
+ while ( true )
+ {
+ text = padding + text.substring(pos).trim();
+ pos = findWrapPos( text, width, nextLineTabStop );
+ if ( pos == -1 )
+ {
+ sb.append(text);
+ return sb;
+ }
+
+ sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
+ }
+
+ }
+
+ /**
+ * Finds the next text wrap position after <code>startPos</code> for the text
+ * in <code>sb</code> with the column width <code>width</code>.
+ * The wrap point is the last postion before startPos+width having a whitespace
+ * character (space, \n, \r).
+ *
+ * @param sb text to be analyzed
+ * @param width width of the wrapped text
+ * @param startPos position from which to start the lookup whitespace character
+ * @return postion on which the text must be wrapped or -1 if the wrap position is at the end
+ * of the text
+ */
+ protected int findWrapPos( String text, int width, int startPos )
+ {
+ int pos = -1;
+ // the line ends before the max wrap pos or a new line char found
+ if ( ((pos = text.indexOf('\n', startPos)) != -1 && pos <= width) ||
+ ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width) )
+ {
+ return pos;
+ }
+ else if ( (startPos + width) >= text.length() )
+ {
+ return -1;
+ }
+
+ //look for the last whitespace character before startPos+width
+ pos = startPos + width;
+ char c;
+ while ( pos >= startPos && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r' )
+ {
+ --pos;
+ }
+ //if we found it - just return
+ if ( pos > startPos )
+ {
+ return pos;
+ }
+ else
+ {
+ //must look for the first whitespace chearacter after startPos + width
+ pos = startPos + width;
+ while ( pos <= text.length() && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r' )
+ {
+ ++pos;
+ }
+ return pos == text.length() ? -1 : pos;
+ }
+ }
+
+ protected String createPadding(int len)
+ {
+ StringBuffer sb = new StringBuffer(len);
+ for ( int i = 0; i < len; ++i )
+ {
+ sb.append(' ');
+ }
+ return sb.toString();
+ }
+
+ protected String rtrim( String s )
+ {
+ if ( s == null || s.length() == 0 )
+ {
+ return s;
+ }
+
+ int pos = s.length();
+ while ( pos >= 0 && Character.isWhitespace(s.charAt(pos-1)) )
+ {
+ --pos;
+ }
+ return s.substring(0, pos);
+ }
+
+ // ------------------------------------------------------- Package protected
+
+ // ----------------------------------------------------------------- Private
+
+ // ----------------------------------------------------------- Inner classes
+
+ private static class StringBufferComparator
+ implements Comparator
+ {
+ public int compare( Object o1, Object o2 )
+ {
+ String str1 = stripPrefix(o1.toString());
+ String str2 = stripPrefix(o2.toString());
+ return (str1.compareTo(str2));
+ }
+
+ private String stripPrefix(String strOption)
+ {
+ // Strip any leading '-' characters
+ int iStartIndex = strOption.lastIndexOf('-');
+ if (iStartIndex == -1)
+ {
+ iStartIndex = 0;
+ }
+ return strOption.substring(iStartIndex);
+
+ }
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/MissingArgumentException.java b/installer/src/java/org/apache/commons/cli/MissingArgumentException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/MissingArgumentException.java
@@ -0,0 +1,82 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/**
+ * <p>Thrown when an option requiring an argument
+ * is not provided with an argument.</p>
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see ParseException
+ */
+public class MissingArgumentException extends ParseException {
+
+ /**
+ * <p>Construct a new <code>MissingArgumentException</code>
+ * with the specified detail message.</p>
+ *
+ * @param message the detail message
+ */
+ public MissingArgumentException( String message ) {
+ super( message );
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/MissingOptionException.java b/installer/src/java/org/apache/commons/cli/MissingOptionException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/MissingOptionException.java
@@ -0,0 +1,81 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/**
+ * <p>Thrown when a required option has not been provided.</p>
+ *
+ * @author John Keyes ( john at integralsource.com )
+ * @see ParseException
+ */
+public class MissingOptionException extends ParseException {
+
+ /**
+ * <p>Construct a new <code>MissingSelectedException</code>
+ * with the specified detail message.</p>
+ *
+ * @param message the detail message
+ */
+ public MissingOptionException( String message ) {
+ super( message );
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/Option.java b/installer/src/java/org/apache/commons/cli/Option.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/Option.java
@@ -0,0 +1,575 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: Option.java 2662 2006-02-18 14:20:33Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+
+/** <p>Describes a single command-line option. It maintains
+ * information regarding the short-name of the option, the long-name,
+ * if any exists, a flag indicating if an argument is required for
+ * this option, and a self-documenting description of the option.</p>
+ *
+ * <p>An Option is not created independantly, but is create through
+ * an instance of {@link Options}.<p>
+ *
+ * @see org.apache.commons.cli.Options
+ * @see org.apache.commons.cli.CommandLine
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
+ * @version $Revision: 2662 $
+ */
+
+public class Option implements Cloneable {
+
+ /** constant that specifies the number of argument values has not been specified */
+ public final static int UNINITIALIZED = -1;
+
+ /** constant that specifies the number of argument values is infinite */
+ public final static int UNLIMITED_VALUES = -2;
+
+ /** opt the single character representation of the option */
+ private String opt;
+
+ /** longOpt is the long representation of the option */
+ private String longOpt;
+
+ /** hasArg specifies whether this option has an associated argument */
+ private boolean hasArg;
+
+ /** argName specifies the name of the argument for this option */
+ private String argName;
+
+ /** description of the option */
+ private String description;
+
+ /** required specifies whether this option is required to be present */
+ private boolean required;
+
+ /** specifies whether the argument value of this Option is optional */
+ private boolean optionalArg;
+
+ /**
+ * numberOfArgs specifies the number of argument values this option
+ * can have
+ */
+ private int numberOfArgs = UNINITIALIZED;
+
+ /** the type of this Option */
+ private Object type;
+
+ /** the list of argument values **/
+ private ArrayList values = new ArrayList();
+
+ /** option char (only valid for single character options) */
+ private char id;
+
+ /** the character that is the value separator */
+ private char valuesep;
+
+ /**
+ * <p>Validates whether <code>opt</code> is a permissable Option
+ * shortOpt. The rules that specify if the <code>opt</code>
+ * is valid are:</p>
+ * <ul>
+ * <li><code>opt</code> is not NULL</li>
+ * <li>a single character <code>opt</code> that is either
+ * ' '(special case), '?', '@' or a letter</li>
+ * <li>a multi character <code>opt</code> that only contains
+ * letters.</li>
+ * </ul>
+ *
+ * @param opt The option string to validate
+ * @throws IllegalArgumentException if the Option is not valid.
+ */
+ private void validateOption( String opt )
+ throws IllegalArgumentException
+ {
+ // check that opt is not NULL
+ if( opt == null ) {
+ throw new IllegalArgumentException( "opt is null" );
+ }
+ // handle the single character opt
+ else if( opt.length() == 1 ) {
+ char ch = opt.charAt( 0 );
+ if ( !isValidOpt( ch ) ) {
+ throw new IllegalArgumentException( "illegal option value '"
+ + ch + "'" );
+ }
+ id = ch;
+ }
+ // handle the multi character opt
+ else {
+ char[] chars = opt.toCharArray();
+ for( int i = 0; i < chars.length; i++ ) {
+ if( !isValidChar( chars[i] ) ) {
+ throw new IllegalArgumentException( "opt contains illegal character value '" + chars[i] + "'" );
+ }
+ }
+ }
+ }
+
+ /**
+ * <p>Returns whether the specified character is a valid Option.</p>
+ *
+ * @param c the option to validate
+ * @return true if <code>c</code> is a letter, ' ', '?' or '@', otherwise false.
+ */
+ private boolean isValidOpt( char c ) {
+ return ( isValidChar( c ) || c == ' ' || c == '?' || c == '@' );
+ }
+
+ /**
+ * <p>Returns whether the specified character is a valid character.</p>
+ *
+ * @param c the character to validate
+ * @return true if <code>c</code> is a letter.
+ */
+ private boolean isValidChar( char c ) {
+ return Character.isJavaIdentifierPart( c );
+ }
+
+ /**
+ * <p>Returns the id of this Option. This is only set when the
+ * Option shortOpt is a single character. This is used for switch
+ * statements.</p>
+ *
+ * @return the id of this Option
+ */
+ public int getId( ) {
+ return id;
+ }
+
+ /**
+ * Creates an Option using the specified parameters.
+ *
+ * @param opt short representation of the option
+ * @param hasArg specifies whether the Option takes an argument or not
+ * @param description describes the function of the option
+ */
+ public Option( String opt, String description )
+ throws IllegalArgumentException
+ {
+ this( opt, null, false, description );
+ }
+
+ /**
+ * Creates an Option using the specified parameters.
+ *
+ * @param opt short representation of the option
+ * @param hasArg specifies whether the Option takes an argument or not
+ * @param description describes the function of the option
+ */
+ public Option( String opt, boolean hasArg, String description )
+ throws IllegalArgumentException
+ {
+ this( opt, null, hasArg, description );
+ }
+
+ /**
+ * <p>Creates an Option using the specified parameters.</p>
+ *
+ * @param opt short representation of the option
+ * @param longOpt the long representation of the option
+ * @param hasArg specifies whether the Option takes an argument or not
+ * @param description describes the function of the option
+ */
+ public Option( String opt, String longOpt, boolean hasArg, String description )
+ throws IllegalArgumentException
+ {
+ // ensure that the option is valid
+ validateOption( opt );
+
+ this.opt = opt;
+ this.longOpt = longOpt;
+
+ // if hasArg is set then the number of arguments is 1
+ if( hasArg ) {
+ this.numberOfArgs = 1;
+ }
+
+ this.hasArg = hasArg;
+ this.description = description;
+ }
+
+ /** <p>Retrieve the name of this Option.</p>
+ *
+ * <p>It is this String which can be used with
+ * {@link CommandLine#hasOption(String opt)} and
+ * {@link CommandLine#getOptionValue(String opt)} to check
+ * for existence and argument.<p>
+ *
+ * @return The name of this option
+ */
+ public String getOpt() {
+ return this.opt;
+ }
+
+ /**
+ * <p>Retrieve the type of this Option.</p>
+ *
+ * @return The type of this option
+ */
+ public Object getType() {
+ return this.type;
+ }
+
+ /**
+ * <p>Sets the type of this Option.</p>
+ *
+ * @param type the type of this Option
+ */
+ public void setType( Object type ) {
+ this.type = type;
+ }
+
+ /**
+ * <p>Retrieve the long name of this Option.</p>
+ *
+ * @return Long name of this option, or null, if there is no long name
+ */
+ public String getLongOpt() {
+ return this.longOpt;
+ }
+
+ /**
+ * <p>Sets the long name of this Option.</p>
+ *
+ * @param longOpt the long name of this Option
+ */
+ public void setLongOpt( String longOpt ) {
+ this.longOpt = longOpt;
+ }
+
+ /**
+ * <p>Sets whether this Option can have an optional argument.</p>
+ *
+ * @param optionalArg specifies whether the Option can have
+ * an optional argument.
+ */
+ public void setOptionalArg( boolean optionalArg ) {
+ this.optionalArg = optionalArg;
+ }
+
+ /**
+ * @return whether this Option can have an optional argument
+ */
+ public boolean hasOptionalArg( ) {
+ return this.optionalArg;
+ }
+
+ /** <p>Query to see if this Option has a long name</p>
+ *
+ * @return boolean flag indicating existence of a long name
+ */
+ public boolean hasLongOpt() {
+ return ( this.longOpt != null );
+ }
+
+ /** <p>Query to see if this Option requires an argument</p>
+ *
+ * @return boolean flag indicating if an argument is required
+ */
+ public boolean hasArg() {
+ return this.numberOfArgs > 0 || numberOfArgs == UNLIMITED_VALUES;
+ }
+
+ /** <p>Retrieve the self-documenting description of this Option</p>
+ *
+ * @return The string description of this option
+ */
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * <p>Query to see if this Option requires an argument</p>
+ *
+ * @return boolean flag indicating if an argument is required
+ */
+ public boolean isRequired() {
+ return this.required;
+ }
+
+ /**
+ * <p>Sets whether this Option is mandatory.</p>
+ *
+ * @param required specifies whether this Option is mandatory
+ */
+ public void setRequired( boolean required ) {
+ this.required = required;
+ }
+
+ /**
+ * <p>Sets the display name for the argument value.</p>
+ *
+ * @param argName the display name for the argument value.
+ */
+ public void setArgName( String argName ) {
+ this.argName = argName;
+ }
+
+ /**
+ * <p>Gets the display name for the argument value.</p>
+ *
+ * @return the display name for the argument value.
+ */
+ public String getArgName() {
+ return this.argName;
+ }
+
+ /**
+ * <p>Returns whether the display name for the argument value
+ * has been set.</p>
+ *
+ * @return if the display name for the argument value has been
+ * set.
+ */
+ public boolean hasArgName() {
+ return (this.argName != null && this.argName.length() > 0 );
+ }
+
+ /**
+ * <p>Query to see if this Option can take many values</p>
+ *
+ * @return boolean flag indicating if multiple values are allowed
+ */
+ public boolean hasArgs() {
+ return ( this.numberOfArgs > 1 || this.numberOfArgs == UNLIMITED_VALUES );
+ }
+
+ /**
+ * <p>Sets the number of argument values this Option can take.</p>
+ *
+ * @param num the number of argument values
+ */
+ public void setArgs( int num ) {
+ this.numberOfArgs = num;
+ }
+
+ /**
+ * <p>Sets the value separator. For example if the argument value
+ * was a Java property, the value separator would be '='.</p>
+ *
+ * @param sep The value separator.
+ */
+ public void setValueSeparator( char sep ) {
+ this.valuesep = sep;
+ }
+
+ /**
+ * <p>Returns the value separator character.</p>
+ *
+ * @return the value separator character.
+ */
+ public char getValueSeparator() {
+ return this.valuesep;
+ }
+
+ /**
+ * <p>Returns the number of argument values this Option can take.</p>
+ *
+ * @return num the number of argument values
+ */
+ public int getArgs( ) {
+ return this.numberOfArgs;
+ }
+
+ /**
+ * <p>Dump state, suitable for debugging.</p>
+ *
+ * @return Stringified form of this object
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer().append("[ option: ");
+
+ buf.append( this.opt );
+
+ if ( this.longOpt != null ) {
+ buf.append(" ")
+ .append(this.longOpt);
+ }
+
+ buf.append(" ");
+
+ if ( hasArg ) {
+ buf.append( "+ARG" );
+ }
+
+ buf.append(" :: ")
+ .append( this.description );
+
+ if ( this.type != null ) {
+ buf.append(" :: ")
+ .append( this.type );
+ }
+
+ buf.append(" ]");
+ return buf.toString();
+ }
+
+ /**
+ * <p>Adds the specified value to this Option.</p>
+ *
+ * @param value is a/the value of this Option
+ */
+ public boolean addValue( String value ) {
+
+ switch( numberOfArgs ) {
+ case UNINITIALIZED:
+ return false;
+ case UNLIMITED_VALUES:
+ if( getValueSeparator() > 0 ) {
+ int index = 0;
+ while( (index = value.indexOf( getValueSeparator() ) ) != -1 ) {
+ this.values.add( value.substring( 0, index ) );
+ value = value.substring( index+1 );
+ }
+ }
+ this.values.add( value );
+ return true;
+ default:
+ if( getValueSeparator() > 0 ) {
+ int index = 0;
+ while( (index = value.indexOf( getValueSeparator() ) ) != -1 ) {
+ if( values.size() > numberOfArgs-1 ) {
+ return false;
+ }
+ this.values.add( value.substring( 0, index ) );
+ value = value.substring( index+1 );
+ }
+ }
+ if( values.size() > numberOfArgs-1 ) {
+ return false;
+ }
+ this.values.add( value );
+ return true;
+ }
+ }
+
+ /**
+ * @return the value/first value of this Option or
+ * <code>null</code> if there are no values.
+ */
+ public String getValue() {
+ return this.values.size()==0 ? null : (String)this.values.get( 0 );
+ }
+
+ /**
+ * @return the specified value of this Option or
+ * <code>null</code> if there are no values.
+ */
+ public String getValue( int index )
+ throws IndexOutOfBoundsException
+ {
+ return ( this.values.size()==0 ) ? null : (String)this.values.get( index );
+ }
+
+ /**
+ * @return the value/first value of this Option or the
+ * <code>defaultValue</code> if there are no values.
+ */
+ public String getValue( String defaultValue ) {
+ String value = getValue( );
+ return ( value != null ) ? value : defaultValue;
+ }
+
+ /**
+ * @return the values of this Option as a String array
+ * or null if there are no values
+ */
+ public String[] getValues() {
+ return this.values.size()==0 ? null : (String[])this.values.toArray(new String[]{});
+ }
+
+ /**
+ * @return the values of this Option as a List
+ * or null if there are no values
+ */
+ public java.util.List getValuesList() {
+ return this.values;
+ }
+
+ /**
+ * @return a copy of this Option
+ */
+ public Object clone() {
+ Option option = new Option( getOpt(), getDescription() );
+ option.setArgs( getArgs() );
+ option.setOptionalArg( hasOptionalArg() );
+ option.setRequired( isRequired() );
+ option.setLongOpt( getLongOpt() );
+ option.setType( getType() );
+ option.setValueSeparator( getValueSeparator() );
+ return option;
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/OptionBuilder.java b/installer/src/java/org/apache/commons/cli/OptionBuilder.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/OptionBuilder.java
@@ -0,0 +1,368 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/**
+ * <p>OptionBuilder allows the user to create Options using descriptive
+ * methods.</p>
+ * <p>Details on the Builder pattern can be found at
+ * <a href="http://c2.com/cgi-bin/wiki?BuilderPattern">http://c2.com/cgi-bin/wiki?BuilderPattern</a>.</p>
+ *
+ * @author John Keyes ( john at integralsource.com )
+ * @since 1.0
+ */
+public class OptionBuilder {
+
+ /** long option */
+ private static String longopt;
+ /** option description */
+ private static String description;
+ /** argument name */
+ private static String argName;
+ /** is required? */
+ private static boolean required;
+ /** the number of arguments */
+ private static int numberOfArgs = Option.UNINITIALIZED;
+ /** option type */
+ private static Object type;
+ /** option can have an optional argument value */
+ private static boolean optionalArg;
+ /** value separator for argument value */
+ private static char valuesep;
+
+ /** option builder instance */
+ private static OptionBuilder instance = new OptionBuilder();
+
+ // private constructor
+ private OptionBuilder() {
+ }
+
+ /**
+ * <p>Resets the member variables to their default values.</p>
+ */
+ private static void reset() {
+ description = null;
+ argName = null;
+ longopt = null;
+ type = null;
+ required = false;
+ numberOfArgs = Option.UNINITIALIZED;
+
+ // PMM 9/6/02 - these were missing
+ optionalArg = false;
+ valuesep = (char) 0;
+ }
+
+ /**
+ * <p>The next Option created will have the following long option value.</p>
+ *
+ * @param longopt the long option value
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder withLongOpt( String longopt ) {
+ instance.longopt = longopt;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will require an argument value.</p>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasArg( ) {
+ instance.numberOfArgs = 1;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will require an argument value if
+ * <code>hasArg</code> is true.</p>
+ *
+ * @param hasArg if true then the Option has an argument value
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasArg( boolean hasArg ) {
+ instance.numberOfArgs = ( hasArg == true ) ? 1 : Option.UNINITIALIZED;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will have the specified argument value
+ * name.</p>
+ *
+ * @param name the name for the argument value
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder withArgName( String name ) {
+ instance.argName = name;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will be required.</p>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder isRequired( ) {
+ instance.required = true;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created uses <code>sep</code> as a means to
+ * separate argument values.</p>
+ *
+ * <b>Example:</b>
+ * <pre>
+ * Option opt = OptionBuilder.withValueSeparator( ':' )
+ * .create( 'D' );
+ *
+ * CommandLine line = parser.parse( args );
+ * String propertyName = opt.getValue( 0 );
+ * String propertyValue = opt.getValue( 1 );
+ * </pre>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder withValueSeparator( char sep ) {
+ instance.valuesep = sep;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created uses '<code>=</code>' as a means to
+ * separate argument values.</p>
+ *
+ * <b>Example:</b>
+ * <pre>
+ * Option opt = OptionBuilder.withValueSeparator( )
+ * .create( 'D' );
+ *
+ * CommandLine line = parser.parse( args );
+ * String propertyName = opt.getValue( 0 );
+ * String propertyValue = opt.getValue( 1 );
+ * </pre>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder withValueSeparator( ) {
+ instance.valuesep = '=';
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will be required if <code>required</code>
+ * is true.</p>
+ *
+ * @param required if true then the Option is required
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder isRequired( boolean required ) {
+ instance.required = required;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created can have unlimited argument values.</p>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasArgs( ) {
+ instance.numberOfArgs = Option.UNLIMITED_VALUES;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created can have <code>num</code>
+ * argument values.</p>
+ *
+ * @param num the number of args that the option can have
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasArgs( int num ) {
+ instance.numberOfArgs = num;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option can have an optional argument.</p>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasOptionalArg( ) {
+ instance.numberOfArgs = 1;
+ instance.optionalArg = true;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option can have an unlimited number of
+ * optional arguments.</p>
+ *
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasOptionalArgs( ) {
+ instance.numberOfArgs = Option.UNLIMITED_VALUES;
+ instance.optionalArg = true;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option can have the specified number of
+ * optional arguments.</p>
+ *
+ * @param numArgs - the maximum number of optional arguments
+ * the next Option created can have.
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder hasOptionalArgs( int numArgs ) {
+ instance.numberOfArgs = numArgs;
+ instance.optionalArg = true;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will have a value that will be an instance
+ * of <code>type</code>.</p>
+ *
+ * @param type the type of the Options argument value
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder withType( Object type ) {
+ instance.type = type;
+ return instance;
+ }
+
+ /**
+ * <p>The next Option created will have the specified description</p>
+ *
+ * @param description a description of the Option's purpose
+ * @return the OptionBuilder instance
+ */
+ public static OptionBuilder withDescription( String description ) {
+ instance.description = description;
+ return instance;
+ }
+
+ /**
+ * <p>Create an Option using the current settings and with
+ * the specified Option <code>char</code>.</p>
+ *
+ * @param opt the character representation of the Option
+ * @return the Option instance
+ * @throws IllegalArgumentException if <code>opt</code> is not
+ * a valid character. See Option.
+ */
+ public static Option create( char opt )
+ throws IllegalArgumentException
+ {
+ return create( String.valueOf( opt ) );
+ }
+
+ /**
+ * <p>Create an Option using the current settings</p>
+ *
+ * @return the Option instance
+ * @throws IllegalArgumentException if <code>longOpt</code> has
+ * not been set.
+ */
+ public static Option create()
+ throws IllegalArgumentException
+ {
+ if( longopt == null ) {
+ throw new IllegalArgumentException( "must specify longopt" );
+ }
+
+ return create( " " );
+ }
+
+ /**
+ * <p>Create an Option using the current settings and with
+ * the specified Option <code>char</code>.</p>
+ *
+ * @param opt the <code>java.lang.String</code> representation
+ * of the Option
+ * @return the Option instance
+ * @throws IllegalArgumentException if <code>opt</code> is not
+ * a valid character. See Option.
+ */
+ public static Option create( String opt )
+ throws IllegalArgumentException
+ {
+ // create the option
+ Option option = new Option( opt, description );
+
+ // set the option properties
+ option.setLongOpt( longopt );
+ option.setRequired( required );
+ option.setOptionalArg( optionalArg );
+ option.setArgs( numberOfArgs );
+ option.setType( type );
+ option.setValueSeparator( valuesep );
+ option.setArgName( argName );
+ // reset the OptionBuilder properties
+ instance.reset();
+
+ // return the Option instance
+ return option;
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/apache/commons/cli/OptionGroup.java b/installer/src/java/org/apache/commons/cli/OptionGroup.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/OptionGroup.java
@@ -0,0 +1,187 @@
+/*
+ * $Header$
+ * $Revision: 2690 $
+ * $Date: 2006-03-25 23:39:57 -0800 (Sat, 25 Mar 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A group of mutually exclusive options.
+ * @author John Keyes ( john at integralsource.com )
+ * @version $Revision: 2690 $
+ */
+public class OptionGroup {
+
+ /** hold the options in added order */
+ private List optionList = new ArrayList();
+
+ /** the name of the selected option */
+ private String selected;
+
+ /** specified whether this group is required */
+ private boolean required;
+
+ /**
+ * add <code>opt</code> to this group
+ *
+ * @param opt the option to add to this group
+ * @return this option group with opt added
+ */
+ public OptionGroup addOption(Option opt) {
+ optionList.add(opt);
+ return this;
+ }
+
+ /**
+ * @return the names of the options in this group as a
+ * <code>Collection</code>
+ */
+ public Collection getNames() {
+ List namesList = new ArrayList();
+ Iterator optionsIterator = optionList.iterator();
+ while (optionsIterator.hasNext()) {
+ Option option = (Option) optionsIterator.next();
+ namesList.add("-" + option.getOpt());
+ }
+ return namesList;
+ }
+
+ /**
+ * @return the options in this group as a <code>Collection</code>
+ */
+ public Collection getOptions() {
+ return optionList;
+ }
+
+ /**
+ * set the selected option of this group to <code>name</code>.
+ * @param opt the option that is selected
+ * @throws AlreadySelectedException if an option from this group has
+ * already been selected.
+ */
+ public void setSelected(Option opt) throws AlreadySelectedException {
+ // if no option has already been selected or the
+ // same option is being reselected then set the
+ // selected member variable
+
+ if ( this.selected == null || this.selected.equals( opt.getOpt() ) ) {
+ this.selected = opt.getOpt();
+ }
+ else {
+ throw new AlreadySelectedException( "an option from this group has " +
+ "already been selected: '" +
+ selected + "'");
+ }
+ }
+
+ /**
+ * @return the selected option name
+ */
+ public String getSelected() {
+ return selected;
+ }
+
+ /**
+ * @param required specifies if this group is required
+ */
+ public void setRequired( boolean required ) {
+ this.required = required;
+ }
+
+ /**
+ * Returns whether this option group is required.
+ *
+ * @returns whether this option group is required
+ */
+ public boolean isRequired() {
+ return this.required;
+ }
+
+ /**
+ * <p>Returns the stringified version of this OptionGroup.</p>
+ * @return the stringified representation of this group
+ */
+ public String toString() {
+ StringBuffer buff = new StringBuffer();
+
+ Iterator iter = getOptions().iterator();
+
+ buff.append( "[" );
+ while( iter.hasNext() ) {
+ Option option = (Option)iter.next();
+
+ buff.append( "-" );
+ buff.append( option.getOpt() );
+ buff.append( " " );
+ buff.append( option.getDescription( ) );
+
+ if( iter.hasNext() ) {
+ buff.append( ", " );
+ }
+ }
+ buff.append( "]" );
+
+ return buff.toString();
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/Options.java b/installer/src/java/org/apache/commons/cli/Options.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/Options.java
@@ -0,0 +1,331 @@
+/*
+ * $Header$
+ * $Revision: 2694 $
+ * $Date: 2006-03-27 11:45:13 -0800 (Mon, 27 Mar 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/** <p>Main entry-point into the library.</p>
+ *
+ * <p>Options represents a collection of {@link Option} objects, which
+ * describe the possible options for a command-line.<p>
+ *
+ * <p>It may flexibly parse long and short options, with or without
+ * values. Additionally, it may parse only a portion of a commandline,
+ * allowing for flexible multi-stage parsing.<p>
+ *
+ * @see org.apache.commons.cli.CommandLine
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
+ * @version $Revision: 2694 $
+ */
+public class Options {
+
+ /** a map of the options with the character key */
+ private Map shortOpts = new HashMap();
+
+ /** a map of the options with the long key */
+ private Map longOpts = new HashMap();
+
+ /** a list of the required options */
+ private List requiredOpts = new ArrayList();
+
+ /** a map of the option groups */
+ private Map optionGroups = new HashMap();
+
+ /** a list of all options, in sequence of addition, only in use when isSortAsAdded() */
+ private List _addedOpts = new ArrayList();
+
+ /** flag for the sort behaviour */
+ private boolean _sortAsAdded;
+
+ /**
+ * Construct a new Options descriptor
+ */
+ public Options() {
+ setSortAsAdded(false);
+ }
+
+ /**
+ * Set the sort sequence: <code>true</code> means in sequence of addition, <code>false</code> will use the
+ * default (undefined) sorting
+ */
+ public void setSortAsAdded(boolean sortAsAdded) {
+ _sortAsAdded = sortAsAdded;
+ }
+
+ /**
+ * <p>Add the specified option group.</p>
+ *
+ * @param group the OptionGroup that is to be added
+ * @return the resulting Options instance
+ */
+ public Options addOptionGroup( OptionGroup group ) {
+ Iterator options = group.getOptions().iterator();
+
+ if( group.isRequired() ) {
+ requiredOpts.add( group );
+ }
+
+ while( options.hasNext() ) {
+ Option option = (Option)options.next();
+ // an Option cannot be required if it is in an
+ // OptionGroup, either the group is required or
+ // nothing is required
+ option.setRequired( false );
+ addOption( option );
+
+ optionGroups.put( option.getOpt(), group );
+ }
+
+ return this;
+ }
+
+ /** <p>Add an option that only contains a short-name</p>
+ * <p>It may be specified as requiring an argument.</p>
+ *
+ * @param opt Short single-character name of the option.
+ * @param hasArg flag signally if an argument is required after this option
+ * @param description Self-documenting description
+ * @return the resulting Options instance
+ */
+ public Options addOption(String opt, boolean hasArg, String description) {
+ addOption( opt, null, hasArg, description );
+ return this;
+ }
+
+ /** <p>Add an option that contains a short-name and a long-name</p>
+ * <p>It may be specified as requiring an argument.</p>
+ *
+ * @param opt Short single-character name of the option.
+ * @param longOpt Long multi-character name of the option.
+ * @param hasArg flag signally if an argument is required after this option
+ * @param description Self-documenting description
+ * @return the resulting Options instance
+ */
+ public Options addOption(String opt, String longOpt, boolean hasArg, String description) {
+ addOption( new Option( opt, longOpt, hasArg, description ) );
+ return this;
+ }
+
+ /**
+ * <p>Adds an option instance</p>
+ *
+ * @param opt the option that is to be added
+ * @return the resulting Options instance
+ */
+ public Options addOption(Option opt) {
+ String shortOpt = "-" + opt.getOpt();
+
+ // add it to the long option list
+ if ( opt.hasLongOpt() ) {
+ longOpts.put( "--" + opt.getLongOpt(), opt );
+ }
+
+ // if the option is required add it to the required list
+ if ( opt.isRequired() ) {
+ requiredOpts.add( shortOpt );
+ }
+
+ shortOpts.put( shortOpt, opt );
+
+ if (isSortAsAdded()) {
+ _addedOpts.add(opt);
+ }
+
+ return this;
+ }
+
+ /** <p>Retrieve a read-only list of options in this set</p>
+ *
+ * @return read-only Collection of {@link Option} objects in this descriptor
+ */
+ public Collection getOptions() {
+ if (isSortAsAdded()) {
+ return _addedOpts;
+ } else {
+ List opts = new ArrayList(shortOpts.values());
+
+ // now look through the long opts to see if there are any Long-opt
+ // only options
+ Iterator iter = longOpts.values().iterator();
+ while (iter.hasNext()) {
+ Object item = iter.next();
+ if (!opts.contains(item)) {
+ opts.add(item);
+ }
+ }
+ return Collections.unmodifiableCollection(opts);
+ }
+ }
+
+ /**
+ * @return true if options should be sorted in sequence of addition.
+ */
+ public boolean isSortAsAdded() {
+ return _sortAsAdded;
+ }
+
+ /**
+ * <p>Returns the Options for use by the HelpFormatter.</p>
+ *
+ * @return the List of Options
+ */
+ List helpOptions() {
+ if (isSortAsAdded()) {
+ return _addedOpts;
+ } else {
+ return new ArrayList(shortOpts.values());
+ }
+ }
+
+ /** <p>Returns the required options as a
+ * <code>java.util.Collection</code>.</p>
+ *
+ * @return Collection of required options
+ */
+ public List getRequiredOptions() {
+ return requiredOpts;
+ }
+
+ /** <p>Retrieve the named {@link Option}</p>
+ *
+ * @param opt short or long name of the {@link Option}
+ * @return the option represented by opt
+ */
+ public Option getOption( String opt ) {
+
+ Option option = null;
+
+ // short option
+ if( opt.length() == 1 ) {
+ option = (Option)shortOpts.get( "-" + opt );
+ }
+ // long option
+ else if( opt.startsWith( "--" ) ) {
+ option = (Option)longOpts.get( opt );
+ }
+ // a just-in-case
+ else {
+ option = (Option)shortOpts.get( opt );
+ }
+
+ return (option == null) ? null : (Option)option.clone();
+ }
+
+ /**
+ * <p>Returns whether the named {@link Option} is a member
+ * of this {@link Options}</p>
+ *
+ * @param opt short or long name of the {@link Option}
+ * @return true if the named {@link Option} is a member
+ * of this {@link Options}
+ */
+ public boolean hasOption( String opt ) {
+
+ // short option
+ if( opt.length() == 1 ) {
+ return shortOpts.containsKey( "-" + opt );
+ }
+ // long option
+ else if( opt.startsWith( "--" ) ) {
+ return longOpts.containsKey( opt );
+ }
+ // a just-in-case
+ else {
+ return shortOpts.containsKey( opt );
+ }
+ }
+
+ /** <p>Returns the OptionGroup the <code>opt</code>
+ * belongs to.</p>
+ * @param opt the option whose OptionGroup is being queried.
+ *
+ * @return the OptionGroup if <code>opt</code> is part
+ * of an OptionGroup, otherwise return null
+ */
+ public OptionGroup getOptionGroup( Option opt ) {
+ return (OptionGroup)optionGroups.get( opt.getOpt() );
+ }
+
+ /** <p>Dump state, suitable for debugging.</p>
+ *
+ * @return Stringified form of this object
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("[ Options: [ short ");
+ buf.append( shortOpts.toString() );
+ buf.append( " ] [ long " );
+ buf.append( longOpts );
+ buf.append( " ]");
+
+ return buf.toString();
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/ParseException.java b/installer/src/java/org/apache/commons/cli/ParseException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/ParseException.java
@@ -0,0 +1,82 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/**
+ * <p>Base for Exceptions thrown during parsing of a command-line.</p>
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @version $Revision: 2662 $
+ */
+public class ParseException extends Exception
+{
+
+ /**
+ * <p>Construct a new <code>ParseException</code>
+ * with the specified detail message.</p>
+ *
+ * @param message the detail message
+ */
+ public ParseException( String message ) {
+ super( message );
+ }
+}
diff --git a/installer/src/java/org/apache/commons/cli/Parser.java b/installer/src/java/org/apache/commons/cli/Parser.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/Parser.java
@@ -0,0 +1,282 @@
+/*
+ * $Header$
+ * $Revision: 2665 $
+ * $Date: 2006-02-18 14:24:36 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * <p><code>Parser</code> creates {@link CommandLine}s.</p>
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see Parser
+ * @version $Revision: 2665 $
+ */
+public abstract class Parser implements CommandLineParser {
+
+ /** commandline instance */
+ private CommandLine cmd;
+ /** current Options */
+ private Options options;
+ /** list of required options strings */
+ private List requiredOptions;
+
+ /**
+ * <p>Subclasses must implement this method to reduce
+ * the <code>arguments</code> that have been passed to the parse
+ * method.</p>
+ *
+ * @param opts The Options to parse the arguments by.
+ * @param args The arguments that have to be flattened.
+ * @param stopAtNonOption specifies whether to stop
+ * flattening when a non option has been encountered
+ * @return a String array of the flattened arguments
+ */
+ abstract protected String[] flatten( Options opts,
+ String[] arguments,
+ boolean stopAtNonOption );
+
+ /**
+ * <p>Parses the specified <code>arguments</code>
+ * based on the specifed {@link Options}.</p>
+ *
+ * @param options the <code>Options</code>
+ * @param arguments the <code>arguments</code>
+ * @return the <code>CommandLine</code>
+ * @throws ParseException if an error occurs when parsing the
+ * arguments.
+ */
+ public CommandLine parse( Options options, String[] arguments )
+ throws ParseException
+ {
+ return parse( options, arguments, false );
+ }
+
+ /**
+ * <p>Parses the specified <code>arguments</code>
+ * based on the specifed {@link Options}.</p>
+ *
+ * @param options the <code>Options</code>
+ * @param arguments the <code>arguments</code>
+ * @param stopAtNonOption specifies whether to stop
+ * interpreting the arguments when a non option has
+ * been encountered and to add them to the CommandLines
+ * args list.
+ * @return the <code>CommandLine</code>
+ * @throws ParseException if an error occurs when parsing the
+ * arguments.
+ */
+ public CommandLine parse( Options opts,
+ String[] arguments,
+ boolean stopAtNonOption )
+ throws ParseException
+ {
+ // initialise members
+ options = opts;
+ requiredOptions = options.getRequiredOptions();
+ cmd = new CommandLine();
+
+ boolean eatTheRest = false;
+
+ List tokenList = Arrays.asList( flatten( opts, arguments, stopAtNonOption ) );
+ ListIterator iterator = tokenList.listIterator();
+
+ // process each flattened token
+ while( iterator.hasNext() ) {
+ String t = (String)iterator.next();
+
+ // the value is the double-dash
+ if( "--".equals( t ) ) {
+ eatTheRest = true;
+ }
+ // the value is a single dash
+ else if( "-".equals( t ) ) {
+ if( stopAtNonOption ) {
+ eatTheRest = true;
+ }
+ else {
+ cmd.addArg(t );
+ }
+ }
+ // the value is an option
+ else if( t.startsWith( "-" ) ) {
+ if ( stopAtNonOption && !options.hasOption( t ) ) {
+ eatTheRest = true;
+ cmd.addArg( t );
+ }
+ else {
+ processOption( t, iterator );
+ }
+ }
+ // the value is an argument
+ else {
+ cmd.addArg( t );
+ if( stopAtNonOption ) {
+ eatTheRest = true;
+ }
+ }
+
+ // eat the remaining tokens
+ if( eatTheRest ) {
+ while( iterator.hasNext() ) {
+ String str = (String)iterator.next();
+ // ensure only one double-dash is added
+ if( !"--".equals( str ) ) {
+ cmd.addArg( str );
+ }
+ }
+ }
+ }
+ checkRequiredOptions();
+ return cmd;
+ }
+
+ /**
+ * <p>Throws a {@link MissingOptionException} if all of the
+ * required options are no present.</p>
+ */
+ private void checkRequiredOptions()
+ throws MissingOptionException
+ {
+
+ // if there are required options that have not been
+ // processsed
+ if( requiredOptions.size() > 0 ) {
+ Iterator iter = requiredOptions.iterator();
+ StringBuffer buff = new StringBuffer();
+
+ // loop through the required options
+ while( iter.hasNext() ) {
+ buff.append( iter.next() );
+ }
+
+ throw new MissingOptionException( buff.toString() );
+ }
+ }
+
+ public void processArgs( Option opt, ListIterator iter )
+ throws ParseException
+ {
+ // loop until an option is found
+ while( iter.hasNext() ) {
+ String var = (String)iter.next();
+
+ // found an Option
+ if( options.hasOption( var ) ) {
+ iter.previous();
+ break;
+ }
+ // found a value
+ else if( !opt.addValue( var ) ) {
+ iter.previous();
+ break;
+ }
+ }
+
+ if( opt.getValues() == null && !opt.hasOptionalArg() ) {
+ throw new MissingArgumentException( "no argument for option: " + opt.getOpt() + " / " + opt.getLongOpt() );
+ }
+ }
+
+ private void processOption( String arg, ListIterator iter )
+ throws ParseException
+ {
+ // get the option represented by arg
+ Option opt = null;
+
+ boolean hasOption = options.hasOption( arg );
+
+ // if there is no option throw an UnrecognisedOptionException
+ if( !hasOption ) {
+ throw new UnrecognizedOptionException("Unrecognized option: " + arg);
+ }
+ else {
+ opt = (Option) options.getOption( arg );
+ }
+
+ // if the option is a required option remove the option from
+ // the requiredOptions list
+ if ( opt.isRequired() ) {
+ requiredOptions.remove( "-" + opt.getOpt() );
+ }
+
+ // if the option is in an OptionGroup make that option the selected
+ // option of the group
+ if ( options.getOptionGroup( opt ) != null ) {
+ OptionGroup group = ( OptionGroup ) options.getOptionGroup( opt );
+ if( group.isRequired() ) {
+ requiredOptions.remove( group );
+ }
+ group.setSelected( opt );
+ }
+
+ // if the option takes an argument value
+ if ( opt.hasArg() ) {
+ processArgs( opt, iter );
+ }
+
+ // set the option on the command line
+ cmd.addOption( opt );
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/apache/commons/cli/PatternOptionBuilder.java b/installer/src/java/org/apache/commons/cli/PatternOptionBuilder.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/PatternOptionBuilder.java
@@ -0,0 +1,204 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/**
+ * Allows Options to be created from a single String.
+ *
+ *
+ * @author Henri Yandell (bayard @ generationjava.com)
+ * @version $Revision: 2662 $
+ */
+public class PatternOptionBuilder {
+
+ /// TODO: These need to break out to OptionType and also to be pluggable.
+
+ /** String class */
+ public static final Class STRING_VALUE = java.lang.String.class;
+ /** Object class */
+ public static final Class OBJECT_VALUE = java.lang.Object.class;
+ /** Number class */
+ public static final Class NUMBER_VALUE = java.lang.Number.class;
+ /** Date class */
+ public static final Class DATE_VALUE = java.util.Date.class;
+ /** Class class */
+ public static final Class CLASS_VALUE = java.lang.Class.class;
+
+/// can we do this one??
+// is meant to check that the file exists, else it errors.
+// ie) it's for reading not writing.
+ /** FileInputStream class */
+ public static final Class EXISTING_FILE_VALUE = java.io.FileInputStream.class;
+ /** File class */
+ public static final Class FILE_VALUE = java.io.File.class;
+ /** File array class */
+ public static final Class FILES_VALUE = java.io.File[].class;
+ /** URL class */
+ public static final Class URL_VALUE = java.net.URL.class;
+
+ /**
+ * <p>Retrieve the class that <code>ch</code> represents.</p>
+ *
+ * @param ch the specified character
+ * @return The class that <code>ch</code> represents
+ */
+ public static Object getValueClass(char ch) {
+ if (ch == '@') {
+ return PatternOptionBuilder.OBJECT_VALUE;
+ } else if (ch == ':') {
+ return PatternOptionBuilder.STRING_VALUE;
+ } else if (ch == '%') {
+ return PatternOptionBuilder.NUMBER_VALUE;
+ } else if (ch == '+') {
+ return PatternOptionBuilder.CLASS_VALUE;
+ } else if (ch == '#') {
+ return PatternOptionBuilder.DATE_VALUE;
+ } else if (ch == '<') {
+ return PatternOptionBuilder.EXISTING_FILE_VALUE;
+ } else if (ch == '>') {
+ return PatternOptionBuilder.FILE_VALUE;
+ } else if (ch == '*') {
+ return PatternOptionBuilder.FILES_VALUE;
+ } else if (ch == '/') {
+ return PatternOptionBuilder.URL_VALUE;
+ }
+ return null;
+ }
+
+ /**
+ * <p>Returns whether <code>ch</code> is a value code, i.e.
+ * whether it represents a class in a pattern.</p>
+ *
+ * @param ch the specified character
+ * @return true if <code>ch</code> is a value code, otherwise false.
+ */
+ public static boolean isValueCode(char ch) {
+ if( (ch != '@') &&
+ (ch != ':') &&
+ (ch != '%') &&
+ (ch != '+') &&
+ (ch != '#') &&
+ (ch != '<') &&
+ (ch != '>') &&
+ (ch != '*') &&
+ (ch != '/')
+ )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Returns the {@link Options} instance represented by
+ * <code>pattern</code>.</p>
+ *
+ * @param pattern the pattern string
+ * @return The {@link Options} instance
+ */
+ public static Options parsePattern(String pattern) {
+ int sz = pattern.length();
+
+ char opt = ' ';
+ char ch = ' ';
+ boolean required = false;
+ Object type = null;
+
+ Options options = new Options();
+
+ for(int i=0; i<sz; i++) {
+ ch = pattern.charAt(i);
+
+ // a value code comes after an option and specifies
+ // details about it
+ if(!isValueCode(ch)) {
+ if(opt != ' ') {
+ // we have a previous one to deal with
+ options.addOption( OptionBuilder.hasArg( type != null )
+ .isRequired( required )
+ .withType( type )
+ .create( opt ) );
+ required = false;
+ type = null;
+ opt = ' ';
+ }
+ opt = ch;
+ } else
+ if(ch == '!') {
+ required = true;
+ } else {
+ type = getValueClass(ch);
+ }
+ }
+
+ if(opt != ' ') {
+ // we have a final one to deal with
+ options.addOption( OptionBuilder.hasArg( type != null )
+ .isRequired( required )
+ .withType( type )
+ .create( opt ) );
+ }
+
+ return options;
+ }
+
+}
diff --git a/installer/src/java/org/apache/commons/cli/PosixParser.java b/installer/src/java/org/apache/commons/cli/PosixParser.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/PosixParser.java
@@ -0,0 +1,342 @@
+/*
+ * $Header$
+ * $Revision: 2833 $
+ * $Date: 2006-06-28 22:51:26 -0700 (Wed, 28 Jun 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * The class PosixParser provides an implementation of the
+ * {@link Parser#flatten(Options,String[],boolean) flatten} method.
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see Parser
+ * @version $Revision: 2833 $
+ */
+public class PosixParser extends Parser {
+
+ /** holder for flattened tokens */
+ private ArrayList tokens = new ArrayList();
+ /** specifies if bursting should continue */
+ private boolean eatTheRest;
+ /** holder for the current option */
+ private Option currentOption;
+ /** the command line Options */
+ private Options options;
+
+ /**
+ * <p>Resets the members to their original state i.e. remove
+ * all of <code>tokens</code> entries, set <code>eatTheRest</code>
+ * to false and set <code>currentOption</code> to null.</p>
+ */
+ private void init() {
+ eatTheRest = false;
+ tokens.clear();
+ currentOption = null;
+ }
+
+ /**
+ * <p>An implementation of {@link Parser}'s abstract
+ * {@link Parser#flatten(Options,String[],boolean) flatten} method.</p>
+ *
+ * <p>The following are the rules used by this flatten method.
+ * <ol>
+ * <li>if <code>stopAtNonOption</code> is <b>true</b> then do not
+ * burst anymore of <code>arguments</code> entries, just add each
+ * successive entry without further processing. Otherwise, ignore
+ * <code>stopAtNonOption</code>.</li>
+ * <li>if the current <code>arguments</code> entry is "<b>--</b>"
+ * just add the entry to the list of processed tokens</li>
+ * <li>if the current <code>arguments</code> entry is "<b>-</b>"
+ * just add the entry to the list of processed tokens</li>
+ * <li>if the current <code>arguments</code> entry is two characters
+ * in length and the first character is "<b>-</b>" then check if this
+ * is a valid {@link Option} id. If it is a valid id, then add the
+ * entry to the list of processed tokens and set the current {@link Option}
+ * member. If it is not a valid id and <code>stopAtNonOption</code>
+ * is true, then the remaining entries are copied to the list of
+ * processed tokens. Otherwise, the current entry is ignored.</li>
+ * <li>if the current <code>arguments</code> entry is more than two
+ * characters in length and the first character is "<b>-</b>" then
+ * we need to burst the entry to determine its constituents. For more
+ * information on the bursting algorithm see
+ * {@link PosixParser#burstToken( String, boolean) burstToken}.</li>
+ * <li>if the current <code>arguments</code> entry is not handled
+ * by any of the previous rules, then the entry is added to the list
+ * of processed tokens.</li>
+ * </ol>
+ * </p>
+ *
+ * @param options The command line {@link Options}
+ * @param arguments The command line arguments to be parsed
+ * @param stopAtNonOption Specifies whether to stop flattening
+ * when an non option is found.
+ * @return The flattened <code>arguments</code> String array.
+ */
+ protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption) {
+ init();
+ this.options = options;
+
+ // an iterator for the command line tokens
+ Iterator iter = Arrays.asList(arguments).iterator();
+ String token = null;
+
+ // process each command line token
+ while (iter.hasNext()) {
+
+ // get the next command line token
+ token = (String) iter.next();
+
+ // handle SPECIAL TOKEN
+ if (token.startsWith("--")) {
+ processLongOptionToken(token, stopAtNonOption);
+ } else if ("-".equals(token)) {
+ // single hyphen
+ processSingleHyphen(token);
+ } else if (token.startsWith("-")) {
+ int tokenLength = token.length();
+ if (tokenLength == 2) {
+ processOptionToken(token, stopAtNonOption);
+ } else {
+ boolean burst = true;
+ if (token.length() > 2) {
+ // check for misspelled long option
+ String longOptionCandidate = "-" + token;
+ if (this.options.hasOption(longOptionCandidate)) {
+ tokens.add(token);
+ burst = false;
+ }
+ }
+ if (burst) {
+ burstToken(token, stopAtNonOption);
+ }
+ }
+ } else {
+ if (stopAtNonOption) {
+ process(token);
+ } else {
+ tokens.add(token);
+ }
+ }
+
+ gobble(iter);
+ }
+
+ return (String[]) tokens.toArray(new String[] {});
+ }
+
+ /**
+ * <p>Adds the remaining tokens to the processed tokens list.</p>
+ *
+ * @param iter An iterator over the remaining tokens
+ */
+ private void gobble( Iterator iter ) {
+ if( eatTheRest ) {
+ while( iter.hasNext() ) {
+ tokens.add( iter.next() );
+ }
+ }
+ }
+
+ /**
+ * <p>If there is a current option and it can have an argument
+ * value then add the token to the processed tokens list and
+ * set the current option to null.</p>
+ * <p>If there is a current option and it can have argument
+ * values then add the token to the processed tokens list.</p>
+ * <p>If there is not a current option add the special token
+ * "<b>--</b>" and the current <code>value</code> to the processed
+ * tokens list. The add all the remaining <code>argument</code>
+ * values to the processed tokens list.</p>
+ *
+ * @param value The current token
+ */
+ private void process( String value ) {
+ if( currentOption != null && currentOption.hasArg() ) {
+ if( currentOption.hasArg() ) {
+ tokens.add( value );
+ currentOption = null;
+ }
+ else if (currentOption.hasArgs() ) {
+ tokens.add( value );
+ }
+ }
+ else {
+ eatTheRest = true;
+ tokens.add( "--" );
+ tokens.add( value );
+ }
+ }
+
+ /**
+ * <p>If it is a hyphen then add the hyphen directly to
+ * the processed tokens list.</p>
+ *
+ * @param hyphen The hyphen token
+ */
+ private void processSingleHyphen( String hyphen ) {
+ tokens.add( hyphen );
+ }
+
+ /**
+ * <p>If an {@link Option} exists for <code>token</code> then
+ * set the current option and add the token to the processed
+ * list.</p>
+ * <p>If an {@link Option} does not exist and <code>stopAtNonOption</code>
+ * is set then ignore the current token and add the remaining tokens
+ * to the processed tokens list directly.</p>
+ *
+ * @param token The current option token
+ * @param stopAtNonOption Specifies whether flattening should halt
+ * at the first non option.
+ */
+ private void processOptionToken( String token, boolean stopAtNonOption ) {
+ if( this.options.hasOption( token ) ) {
+ currentOption = this.options.getOption( token );
+ tokens.add( token );
+ } else {
+ if( stopAtNonOption ) {
+ eatTheRest = true;
+ } else {
+ tokens.add(token);
+ }
+ }
+ }
+
+ /**
+ * same stop logic as for single hyphen options
+ * @param longToken
+ * @param stopAtNonOption
+ */
+ private void processLongOptionToken(String longToken, boolean stopAtNonOption ) {
+ String token;
+ String value = null;
+ if( longToken.indexOf( '=' ) != -1 ) {
+ token = longToken.substring( 0, longToken.indexOf( '=' ));
+ value = longToken.substring( longToken.indexOf( '=' ) + 1, longToken.length() );
+ } else {
+ token = longToken;
+ }
+ if( this.options.hasOption(token)) {
+ tokens.add(token);
+ if( value != null) {
+ tokens.add(value);
+ }
+ } else {
+ if(stopAtNonOption) {
+ eatTheRest = true;
+ } else {
+ tokens.add(token);
+ if( value != null) {
+ tokens.add(value);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * <p>Breaks <code>token</code> into its constituent parts
+ * using the following algorithm.
+ * <ul>
+ * <li>ignore the first character ("<b>-</b>" )</li>
+ * <li>foreach remaining character check if an {@link Option}
+ * exists with that id.</li>
+ * <li>if an {@link Option} does exist then add that character
+ * prepended with "<b>-</b>" to the list of processed tokens.</li>
+ * <li>if the {@link Option} can have an argument value and there
+ * are remaining characters in the token then add the remaining
+ * characters as a token to the list of processed tokens.</li>
+ * <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b>
+ * <code>stopAtNonOption</code> <b>IS</b> set then add the special token
+ * "<b>--</b>" followed by the remaining characters and also
+ * the remaining tokens directly to the processed tokens list.</li>
+ * <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b>
+ * <code>stopAtNonOption</code> <b>IS NOT</b> set then add that
+ * character prepended with "<b>-</b>".</li>
+ * </ul>
+ * </p>
+ */
+ protected void burstToken( String token, boolean stopAtNonOption ) {
+ int tokenLength = token.length();
+
+ for( int i = 1; i < tokenLength; i++) {
+ String ch = String.valueOf( token.charAt( i ) );
+ boolean hasOption = options.hasOption( ch );
+
+ if( hasOption ) {
+ tokens.add( "-" + ch );
+ currentOption = options.getOption( ch );
+ if( currentOption.hasArg() && token.length()!=i+1 ) {
+ tokens.add( token.substring( i+1 ) );
+ break;
+ }
+ }
+ else if( stopAtNonOption ) {
+ process( token.substring( i ) );
+ }
+ else {
+ tokens.add( "-" + ch );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/apache/commons/cli/TypeHandler.java b/installer/src/java/org/apache/commons/cli/TypeHandler.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/TypeHandler.java
@@ -0,0 +1,252 @@
+/*
+ * $Header$
+ * $Revision: 2664 $
+ * $Date: 2006-02-18 14:20:35 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Date;
+
+/**
+ * This is a temporary implementation. TypeHandler will handle the
+ * pluggableness of OptionTypes and it will direct all of these types
+ * of conversion functionalities to ConvertUtils component in Commons
+ * alreayd. BeanUtils I think.
+ *
+ * @author Henri Yandell (bayard @ generationjava.com)
+ * @version $Revision: 2664 $
+ */
+public class TypeHandler {
+
+ /**
+ * <p>Returns the <code>Object</code> of type <code>obj</code>
+ * with the value of <code>str</code>.</p>
+ *
+ * @param str the command line value
+ * @param obj the type of argument
+ * @return The instance of <code>obj</code> initialised with
+ * the value of <code>str</code>.
+ */
+ public static Object createValue(String str, Object obj) {
+ return createValue(str, (Class)obj);
+ }
+
+ /**
+ * <p>Returns the <code>Object</code> of type <code>clazz</code>
+ * with the value of <code>str</code>.</p>
+ *
+ * @param str the command line value
+ * @param clazz the type of argument
+ * @return The instance of <code>clazz</code> initialised with
+ * the value of <code>str</code>.
+ */
+ public static Object createValue(String str, Class clazz) {
+ if( PatternOptionBuilder.STRING_VALUE == clazz) {
+ return str;
+ } else
+ if( PatternOptionBuilder.OBJECT_VALUE == clazz) {
+ return createObject(str);
+ } else
+ if( PatternOptionBuilder.NUMBER_VALUE == clazz) {
+ return createNumber(str);
+ } else
+ if( PatternOptionBuilder.DATE_VALUE == clazz) {
+ return createDate(str);
+ } else
+ if( PatternOptionBuilder.CLASS_VALUE == clazz) {
+ return createClass(str);
+ } else
+ if( PatternOptionBuilder.FILE_VALUE == clazz) {
+ return createFile(str);
+ } else
+ if( PatternOptionBuilder.EXISTING_FILE_VALUE == clazz) {
+ return createFile(str);
+ } else
+ if( PatternOptionBuilder.FILES_VALUE == clazz) {
+ return createFiles(str);
+ } else
+ if( PatternOptionBuilder.URL_VALUE == clazz) {
+ return createURL(str);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * <p>Create an Object from the classname and empty constructor.</p>
+ *
+ * @param str the argument value
+ * @return the initialised object, or null if it couldn't create the Object.
+ */
+ public static Object createObject(String str) {
+ Class cl = null;
+ try {
+ cl = Class.forName(str);
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("Unable to find: "+str);
+ return null;
+ }
+
+ Object instance = null;
+
+ try {
+ instance = cl.newInstance();
+ } catch (InstantiationException cnfe) {
+ System.err.println("InstantiationException; Unable to create: "+str);
+ return null;
+ }
+ catch (IllegalAccessException cnfe) {
+ System.err.println("IllegalAccessException; Unable to create: "+str);
+ return null;
+ }
+
+ return instance;
+ }
+
+ /**
+ * <p>Create a number from a String.</p>
+ *
+ * @param str the value
+ * @return the number represented by <code>str</code>, if <code>str</code>
+ * is not a number, null is returned.
+ */
+ public static Number createNumber(String str) {
+ // Needs to be able to create
+ try {
+ // do searching for decimal point etc, but atm just make an Integer
+ return new BigDecimal(str);
+ } catch (NumberFormatException nfe) {
+ System.err.println(nfe.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns the class whose name is <code>str</code>.</p>
+ *
+ * @param str the class name
+ * @return The class if it is found, otherwise return null
+ */
+ public static Class createClass(String str) {
+ try {
+ return Class.forName(str);
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("Unable to find: "+str);
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns the date represented by <code>str</code>.</p>
+ *
+ * @param str the date string
+ * @return The date if <code>str</code> is a valid date string,
+ * otherwise return null.
+ */
+ public static Date createDate(String str) {
+ Date date = null;
+ if(date == null) {
+ System.err.println("Unable to parse: "+str);
+ }
+ return date;
+ }
+
+ /**
+ * <p>Returns the URL represented by <code>str</code>.</p>
+ *
+ * @param str the URL string
+ * @return The URL is <code>str</code> is well-formed, otherwise
+ * return null.
+ */
+ public static URL createURL(String str) {
+ try {
+ return new URL(str);
+ } catch (MalformedURLException mue) {
+ System.err.println("Unable to parse: "+str);
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns the File represented by <code>str</code>.</p>
+ *
+ * @param str the File location
+ * @return The file represented by <code>str</code>.
+ */
+ public static File createFile(String str) {
+ return new File(str);
+ }
+
+ /**
+ * <p>Returns the File[] represented by <code>str</code>.</p>
+ *
+ * @param str the paths to the files
+ * @return The File[] represented by <code>str</code>.
+ */
+ public static File[] createFiles(String str) {
+// to implement/port:
+// return FileW.findFiles(str);
+ return null;
+ }
+
+}
diff --git a/installer/src/java/org/apache/commons/cli/UnrecognizedOptionException.java b/installer/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
@@ -0,0 +1,82 @@
+/*
+ * $Header$
+ * $Revision: 2662 $
+ * $Date: 2006-02-18 06:20:33 -0800 (Sat, 18 Feb 2006) $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/**
+ * <p>Exception thrown during parsing signalling an unrecognized
+ * option was seen.<p>
+ *
+ * @author bob mcwhiter (bob @ werken.com)
+ * @version $Revision: 2662 $
+ */
+public class UnrecognizedOptionException extends ParseException {
+
+ /**
+ * <p>Construct a new <code>UnrecognizedArgumentException</code>
+ * with the specified detail message.</p>
+ *
+ * @param message the detail message
+ */
+ public UnrecognizedOptionException( String message ) {
+ super( message );
+ }
+}
diff --git a/installer/src/java/org/python/util/install/AbstractWizard.java b/installer/src/java/org/python/util/install/AbstractWizard.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/AbstractWizard.java
@@ -0,0 +1,438 @@
+package org.python.util.install;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Cursor;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.HeadlessException;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+
+public abstract class AbstractWizard extends JDialog implements ValidationListener {
+
+ private class WizardGlassPane extends JPanel implements MouseListener, KeyListener {
+ WizardGlassPane() {
+ super();
+ setOpaque(false);
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ public void keyPressed(KeyEvent e) {
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+
+ public void keyTyped(KeyEvent e) {
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ public void mouseExited(MouseEvent e) {
+ }
+
+ public void mousePressed(MouseEvent e) {
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ }
+ }
+
+ private AbstractWizardPage _activePage = null;
+ private JPanel _buttonPanel;
+ private JSeparator _buttonSeparator;
+ private Action _cancelAction;
+ private JButton _cancelButton;
+ private CardLayout _cards;
+ private JPanel _content;
+ private WizardGlassPane _glassPane;
+ private AbstractWizardHeader _header;
+ private boolean _headerVisible = false;
+ private ArrayList _listeners;
+ private Action _nextAction;
+ private JButton _nextButton;
+ private ArrayList _pages;
+ private Action _previousAction;
+ private JButton _previousButton;
+
+ public AbstractWizard() {
+ super();
+ initWindow();
+ initActions();
+ initComponents();
+ }
+
+ public AbstractWizard(Dialog parent) throws HeadlessException {
+ super(parent);
+ initWindow();
+ initActions();
+ initComponents();
+ }
+
+ public AbstractWizard(Frame parent) throws HeadlessException {
+ super(parent);
+ initWindow();
+ initActions();
+ initComponents();
+ }
+
+ public final void addPage(AbstractWizardPage page) {
+ if (_pages == null)
+ _pages = new ArrayList();
+ if (page == null || _pages.contains(page))
+ return;
+ _pages.add(page);
+ page.setWizard(this);
+ int number = _pages.indexOf(page);
+ _content.add(page, "page" + number);
+ }
+
+ public final void addWizardListener(WizardListener listener) {
+ if (listener == null)
+ return;
+ if (_listeners == null)
+ _listeners = new ArrayList(5);
+ if (_listeners.contains(listener))
+ return;
+ _listeners.add(listener);
+ }
+
+ private void cancel() {
+ fireCancelEvent();
+ setVisible(false);
+ }
+
+ /**
+ * @return whether the wizard finished succesfully
+ */
+ protected abstract boolean finish();
+
+ private void fireCancelEvent() {
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ WizardEvent event = new WizardEvent(this);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ WizardListener listener = (WizardListener) it.next();
+ listener.wizardCancelled(event);
+ }
+ }
+
+ private void fireFinishedEvent() {
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ WizardEvent event = new WizardEvent(this);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ WizardListener listener = (WizardListener) it.next();
+ listener.wizardFinished(event);
+ }
+ }
+
+ private void fireNextEvent() {
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ WizardEvent event = new WizardEvent(this);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ WizardListener listener = (WizardListener) it.next();
+ listener.wizardNext(event);
+ }
+ }
+
+ private void firePreviousEvent() {
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ WizardEvent event = new WizardEvent(this);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ WizardListener listener = (WizardListener) it.next();
+ listener.wizardPrevious(event);
+ }
+ }
+
+ private void fireStartedEvent() {
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ WizardEvent event = new WizardEvent(this);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ WizardListener listener = (WizardListener) it.next();
+ listener.wizardStarted(event);
+ }
+ }
+
+ /**
+ * @return the String that will appear on the Cancel button
+ */
+ protected abstract String getCancelString();
+
+ /**
+ * @return the String that will appear on the Finish button
+ */
+ protected abstract String getFinishString();
+
+ /**
+ * @return the wizard header panel
+ */
+ public AbstractWizardHeader getHeader() {
+ return _header;
+ }
+
+ /**
+ * @return the String that will appear on the Next button
+ */
+ protected abstract String getNextString();
+
+ /**
+ * @return the String that will appear on the Previous button
+ */
+ protected abstract String getPreviousString();
+
+ /**
+ * usually only called from the WizardValidator, after validation succeeds
+ *
+ * validation always occurs when the 'next' or 'finish' button was clicked, so when the validation succeeds, the
+ * wizard can go to the next page
+ */
+ public final void gotoNextPage() {
+ next();
+ }
+
+ private void initActions() {
+ _nextAction = new AbstractAction(getNextString()) {
+ public void actionPerformed(ActionEvent e) {
+ tryNext();
+ }
+ };
+ _previousAction = new AbstractAction(getPreviousString()) {
+ public void actionPerformed(ActionEvent e) {
+ previous();
+ }
+ };
+ _cancelAction = new AbstractAction(getCancelString()) {
+ public void actionPerformed(ActionEvent e) {
+ cancel();
+ }
+ };
+ }
+
+ private void initComponents() {
+ _pages = new ArrayList();
+ getContentPane().setLayout(new BorderLayout(0, 0));
+ _header = new WizardHeader();
+ getContentPane().add(_header, BorderLayout.NORTH);
+ _content = new JPanel();
+ _cards = new CardLayout();
+ _content.setLayout(_cards);
+
+ getContentPane().add(_content, BorderLayout.CENTER); // was: WEST
+
+ _buttonPanel = new JPanel();
+ _buttonSeparator = new JSeparator();
+ _cancelButton = new JButton();
+ _previousButton = new JButton();
+ _nextButton = new JButton();
+ _cancelButton.setAction(_cancelAction);
+ _previousButton.setAction(_previousAction);
+ _nextButton.setAction(_nextAction);
+ GridBagConstraints gridBagConstraints;
+ _buttonPanel.setLayout(new GridBagLayout());
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridwidth = 3;
+ gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.insets = new Insets(1, 1, 1, 1);
+ gridBagConstraints.weightx = 1.0;
+ _buttonPanel.add(_buttonSeparator, gridBagConstraints);
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.weighty = 1.0;
+ _buttonPanel.add(_cancelButton, gridBagConstraints);
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
+ _buttonPanel.add(_previousButton, gridBagConstraints);
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 2;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
+ _buttonPanel.add(_nextButton, gridBagConstraints);
+ getContentPane().add(_buttonPanel, BorderLayout.SOUTH);
+ }
+
+ private void initWindow() {
+ _glassPane = new WizardGlassPane();
+ setGlassPane(_glassPane);
+ }
+
+ /**
+ * @return whether the wizard header is visible
+ */
+ public final boolean isHeaderVisible() {
+ return _headerVisible;
+ }
+
+ /**
+ * lock the wizard dialog, preventing any user input
+ */
+ public final void lock() {
+ _glassPane.setVisible(true);
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ }
+
+ private void next() {
+ if (_activePage == null)
+ return;
+ _activePage.passivate();
+ int activeIndex = _pages.indexOf(_activePage);
+ int nextIndex = activeIndex + 1;
+ if (nextIndex >= _pages.size()) {
+ tryFinish();
+ return;
+ } else {
+ _activePage = (AbstractWizardPage) _pages.get(nextIndex);
+ showActivePage();
+ }
+ fireNextEvent();
+ }
+
+ private void previous() {
+ if (_activePage == null)
+ return;
+ _activePage.passivate();
+ int activeIndex = _pages.indexOf(_activePage);
+ int previousIndex = activeIndex - 1;
+ if (previousIndex < 0)
+ return;
+ else {
+ _activePage = (AbstractWizardPage) _pages.get(previousIndex);
+ showActivePage();
+ }
+ firePreviousEvent();
+ }
+
+ public final void removeWizardListener(WizardListener listener) {
+ if (listener == null || _listeners == null || !_listeners.contains(listener))
+ return;
+ _listeners.remove(listener);
+ }
+
+ /**
+ * @param header the wizard header panel
+ */
+ public void setHeader(AbstractWizardHeader header) {
+ if (this._header != null) {
+ getContentPane().remove(header);
+ }
+ this._header = header;
+ if (this._header != null) {
+ getContentPane().add(header, BorderLayout.NORTH);
+ }
+ }
+
+ /**
+ * @param visible show the header in this wizard?
+ */
+ public final void setHeaderVisible(boolean visible) {
+ _headerVisible = visible;
+ if (_header != null)
+ _header.setVisible(visible);
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ if (visible) {
+ fireStartedEvent();
+ if (_pages.size() > 0) {
+ _activePage = (AbstractWizardPage) _pages.get(0);
+ showActivePage();
+ }
+ }
+ super.setVisible(visible);
+ }
+
+ private void showActivePage() {
+ if (_activePage == null)
+ return;
+ int number = _pages.indexOf(_activePage);
+ // show the active page
+ _cards.show(_content, "page" + number);
+ // update the wizard header
+ if (_header != null) {
+ _header.setTitle(_activePage.getTitle());
+ _header.setDescription(_activePage.getDescription());
+ _header.setIcon(_activePage.getIcon());
+ }
+ // set visibility and localized text of buttons
+ if (number == 0) {
+ _previousButton.setVisible(false);
+ } else {
+ _previousButton.setVisible(_activePage.isPreviousVisible());
+ }
+ _previousAction.putValue(Action.NAME, getPreviousString());
+ _cancelButton.setVisible(_activePage.isCancelVisible());
+ _cancelAction.putValue(Action.NAME, getCancelString());
+ _nextButton.setVisible(_activePage.isNextVisible());
+ _nextAction.putValue(Action.NAME, getNextString());
+ if (number + 1 == _pages.size()) {
+ _nextAction.putValue(Action.NAME, getFinishString());
+ } else {
+ _nextAction.putValue(Action.NAME, getNextString());
+ }
+ if (_nextButton.isVisible()) {
+ getRootPane().setDefaultButton(_nextButton);
+ // workaround wrong default button (e.g. on OverviewPage)
+ if (_activePage.getFocusField() == null) {
+ _nextButton.grabFocus();
+ }
+ }
+ _activePage.doActivate();
+ }
+
+ private void tryFinish() {
+ if (finish()) {
+ this.setVisible(false);
+ fireFinishedEvent();
+ }
+ }
+
+ private void tryNext() {
+ if (_activePage == null)
+ return;
+ _activePage.validateInput();
+ }
+
+ /**
+ * unlock the wizard dialog, allowing user input
+ */
+ public final void unlock() {
+ _glassPane.setVisible(false);
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/AbstractWizardHeader.java b/installer/src/java/org/python/util/install/AbstractWizardHeader.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/AbstractWizardHeader.java
@@ -0,0 +1,12 @@
+package org.python.util.install;
+
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+
+abstract class AbstractWizardHeader extends JPanel {
+ protected abstract void setTitle(String title);
+
+ protected abstract void setDescription(String description);
+
+ protected abstract void setIcon(ImageIcon icon);
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/AbstractWizardPage.java b/installer/src/java/org/python/util/install/AbstractWizardPage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/AbstractWizardPage.java
@@ -0,0 +1,153 @@
+package org.python.util.install;
+
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.net.URL;
+
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+public abstract class AbstractWizardPage extends JPanel implements TextKeys {
+ private static final long serialVersionUID = -5233805023557214279L;
+
+ private static final String _ICON_FILE_NAME = "jython_small_c.png";
+
+ private static ImageIcon _imageIcon = null;
+ private AbstractWizardValidator _validator = null;
+ private AbstractWizard _wizard;
+
+ public AbstractWizardPage() {
+ super();
+ setValidator(null);
+ }
+
+ /**
+ * This method is called when the wizard page is activated, after Wizard.next();
+ */
+ protected abstract void activate();
+
+ /**
+ * This method is called right before validation of the page
+ */
+ protected abstract void beforeValidate();
+
+ /**
+ * called from Wizard, right after this page is set visible
+ */
+ final void doActivate() {
+ if (getFocusField() != null)
+ this.getFocusField().grabFocus();
+ activate();
+ }
+
+ /**
+ * @return the description of this page, which will be displayed in the wizard header
+ */
+ protected abstract String getDescription();
+
+ /**
+ * @return the input field on the page that should grab the focus when the page is activated
+ */
+ protected abstract JComponent getFocusField();
+
+ /**
+ * @return the icon that should be displayed in the header in all steps
+ */
+ protected ImageIcon getIcon() {
+ if (_imageIcon == null) {
+ URL iconURL = FileHelper.getRelativeURL(getClass(), _ICON_FILE_NAME);
+ if (iconURL != null) {
+ _imageIcon = new ImageIcon(iconURL);
+ }
+ }
+ return _imageIcon;
+ }
+
+ /**
+ * @return the title of this page, which will be displayed in the wizard header
+ */
+ protected abstract String getTitle();
+
+ /**
+ * @return the wizard this page belongs to
+ */
+ public final AbstractWizard getWizard() {
+ return _wizard;
+ }
+
+ /**
+ * @return whether the <i>cancel </i> button is visible
+ */
+ protected abstract boolean isCancelVisible();
+
+ /**
+ * @return whether the <i>next </i> button is visible
+ */
+ protected abstract boolean isNextVisible();
+
+ /**
+ * @return whether the <i>previous </i> button is visible
+ */
+ protected abstract boolean isPreviousVisible();
+
+ /**
+ * this method is called right before the page is hidden, but after the validation
+ */
+ protected abstract void passivate();
+
+ /**
+ * Set the validator for this page. The validator is called when the <i>next </i> button is clicked.
+ *
+ * @param validator the validator for this page. If this is null, a EmptyValidator is assigned
+ */
+ public final void setValidator(AbstractWizardValidator validator) {
+ if (validator == null)
+ this._validator = new EmptyValidator();
+ else
+ this._validator = validator;
+ this._validator.setWizardPage(this);
+ this._validator.addValidationListener(_wizard);
+ }
+
+ /**
+ * @param wizard the wizard this page belongs to
+ */
+ final void setWizard(AbstractWizard wizard) {
+ this._wizard = wizard;
+ _validator.addValidationListener(wizard);
+ }
+
+ /**
+ * perform the validation of this page, using the assigned WizardValidator
+ */
+ final void validateInput() {
+ beforeValidate();
+ if (_validator == null)
+ return;
+ _validator.start();
+ }
+
+ /**
+ * @return default grid bag constraints
+ */
+ protected GridBagConstraints newGridBagConstraints() {
+ GridBagConstraints gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.anchor = GridBagConstraints.WEST;
+ gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+ return gridBagConstraints;
+ }
+
+ final String getText(String textKey) {
+ return Installation.getText(textKey);
+ }
+
+ final String getText(String textKey, String parameter0) {
+ return Installation.getText(textKey, parameter0);
+ }
+
+ final String getText(String textKey, String parameter0, String parameter1) {
+ return Installation.getText(textKey, parameter0, parameter1);
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/AbstractWizardValidator.java b/installer/src/java/org/python/util/install/AbstractWizardValidator.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/AbstractWizardValidator.java
@@ -0,0 +1,132 @@
+package org.python.util.install;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public abstract class AbstractWizardValidator implements TextKeys {
+
+ /**
+ * The thread that performs the validation
+ */
+ private class ValidatorThread extends Thread {
+ public final void run() {
+ try {
+ fireValidationStarted();
+ validate();
+ fireValidationSucceeded();
+ } catch (ValidationException e) {
+ fireValidationFailed(e);
+ } catch (ValidationInformationException vie) {
+ fireValidationInformationRequired(vie);
+ }
+ }
+ }
+
+ private ArrayList _listeners;
+ private AbstractWizardPage _page;
+ private Thread _validatorThread;
+
+ public final void addValidationListener(ValidationListener listener) {
+ if (listener == null)
+ return;
+ if (_listeners == null)
+ _listeners = new ArrayList(5);
+ if (_listeners.contains(listener))
+ return;
+ _listeners.add(listener);
+ }
+
+ private void fireValidationFailed(ValidationException exception) {
+ if (getWizard() != null)
+ getWizard().unlock();
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ ValidationEvent event = new ValidationEvent(_page);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ ValidationListener listener = (ValidationListener) it.next();
+ listener.validationFailed(event, exception);
+ }
+ }
+
+ private void fireValidationInformationRequired(ValidationInformationException exception) {
+ if (getWizard() != null)
+ getWizard().unlock();
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ ValidationEvent event = new ValidationEvent(_page);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ ValidationListener listener = (ValidationListener) it.next();
+ listener.validationInformationRequired(event, exception);
+ }
+ }
+
+ private void fireValidationStarted() {
+ if (getWizard() != null)
+ getWizard().lock();
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ ValidationEvent event = new ValidationEvent(_page);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ ValidationListener listener = (ValidationListener) it.next();
+ listener.validationStarted(event);
+ }
+ }
+
+ private void fireValidationSucceeded() {
+ if (getWizard() != null) {
+ getWizard().unlock();
+ getWizard().gotoNextPage();
+ }
+ if (_listeners == null || _listeners.isEmpty())
+ return;
+ ValidationEvent event = new ValidationEvent(_page);
+ for (Iterator it = _listeners.iterator(); it.hasNext();) {
+ ValidationListener listener = (ValidationListener) it.next();
+ listener.validationSucceeded(event);
+ }
+ }
+
+ protected final AbstractWizard getWizard() {
+ if (_page != null) {
+ return _page.getWizard();
+ } else {
+ return null;
+ }
+ }
+
+ protected final AbstractWizardPage getWizardPage() {
+ return _page;
+ }
+
+ public final void removeValidationListener(ValidationListener listener) {
+ if (listener == null || _listeners == null || !_listeners.contains(listener))
+ return;
+ _listeners.remove(listener);
+ }
+
+ public final void setWizardPage(AbstractWizardPage page) {
+ this._page = page;
+ }
+
+ public final void start() {
+ _validatorThread = new ValidatorThread();
+ _validatorThread.start();
+ }
+
+ /**
+ * perform the actual validation
+ *
+ * @throws ValidationException when the validation failed
+ * @throws ValidationInformationException when an information should be displayed
+ */
+ protected abstract void validate() throws ValidationException, ValidationInformationException;
+
+ final String getText(String textKey) {
+ return Installation.getText(textKey);
+ }
+
+ final String getText(String textKey, String parameter0) {
+ return Installation.getText(textKey, parameter0);
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ChildProcess.java b/installer/src/java/org/python/util/install/ChildProcess.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ChildProcess.java
@@ -0,0 +1,357 @@
+package org.python.util.install;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Easy start of a child process.
+ * <p>
+ * Features are:
+ * <ul>
+ * <li>wait for the child process to finish.
+ * <li>kill the child process after a specified timeout.
+ * <li>get the output of the child process (System.out and System.err) redirected to the calling
+ * process, unless in silent mode.
+ * </ul>
+ */
+public class ChildProcess {
+
+ /**
+ * Inner class for reading stdout of the child process and printing it onto the caller's stdout.
+ */
+ private class StdoutMonitor extends Thread {
+
+ private StdoutMonitor() {}
+
+ public void run() {
+ String line = null;
+ BufferedReader stdout = new BufferedReader(new InputStreamReader(_process.getInputStream()));
+ try {
+ // blocks until input found or process dead
+ while ((line = stdout.readLine()) != null) {
+ if (!isSilent()) {
+ System.out.println(line);
+ }
+ }
+ } catch (IOException ioe) {
+ if (!isSilent()) {
+ ioe.printStackTrace();
+ }
+ } finally {
+ if (stdout != null)
+ try {
+ stdout.close();
+ } catch (IOException e) {}
+ }
+ }
+ }
+
+ /**
+ * Inner class for reading stderr of the child process and printing it onto the caller's stderr.
+ */
+ private class StderrMonitor extends Thread {
+
+ private StderrMonitor() {}
+
+ public void run() {
+ String line = null;
+ BufferedReader stderr = new BufferedReader(new InputStreamReader(_process.getErrorStream()));
+ try {
+ // blocks until input found or process dead
+ while ((line = stderr.readLine()) != null) {
+ if (!isSilent()) {
+ System.err.println(line);
+ }
+ }
+ } catch (IOException ioe) {
+ if (!isSilent()) {
+ ioe.printStackTrace();
+ }
+ } finally {
+ if (stderr != null)
+ try {
+ stderr.close();
+ } catch (IOException e) {}
+ }
+ }
+ }
+
+ /**
+ * Constant indicating no timeout at all.
+ */
+ public static final long INFINITE_TIMEOUT = -1;
+
+ /**
+ * Constant indicating the exit value if the child process was destroyed due to a timeout.
+ */
+ public static final int DESTROYED_AFTER_TIMEOUT = -9898;
+
+ /**
+ * Constant indicating that the exit value was not yet set
+ */
+ private static final int NOT_SET_EXITVALUE = -9;
+
+ /**
+ * The command as an array of strings
+ */
+ private String _command[] = null;
+
+ /**
+ * The timeout (in milliseconds)
+ */
+ private long _timeout = INFINITE_TIMEOUT;
+
+ /**
+ * The interval for checking if the child process is still alive
+ */
+ private long _pollAliveInterval = 1000;
+
+ /**
+ * the effective child process
+ */
+ Process _process;
+
+ /**
+ * the exit value
+ */
+ private int _exitValue = NOT_SET_EXITVALUE;
+
+ /**
+ * The start time of the child process
+ */
+ private long _startTime;
+
+ /**
+ * debug option (default is false)
+ */
+ private boolean _debug = false;
+
+ /**
+ * silent flag
+ */
+ private boolean _silent = false;
+
+ /**
+ * Default constructor
+ */
+ public ChildProcess() {}
+
+ /**
+ * Constructor taking a command array as an argument
+ *
+ * @param command
+ * The command to be executed, every token as array element.
+ */
+ public ChildProcess(String command[]) {
+ setCommand(command);
+ }
+
+ /**
+ * Constructor taking a command array and the timeout as an argument
+ *
+ * @param command
+ * The command to be executed, every token as array element.
+ * @param timeout
+ * in milliseconds. Special value: <code>INFINITE_TIMEOUT</code> indicates no timeout
+ * at all.
+ */
+ public ChildProcess(String command[], long timeout) {
+ setCommand(command);
+ setTimeout(timeout);
+ }
+
+ /**
+ * Set the command array. This will override (but not overwrite) a previously set command
+ */
+ public void setCommand(String command[]) {
+ _command = command;
+ }
+
+ /**
+ * Returns the command array
+ */
+ public String[] getCommand() {
+ return _command;
+ }
+
+ /**
+ * Set the timeout (how long should the calling process wait for the child).
+ *
+ * @param timeout
+ * in milliseconds. Special value: <code>INFINITE_TIMEOUT</code> indicates no timeout
+ * at all. This is the default.
+ */
+ public void setTimeout(long timeout) {
+ _timeout = timeout;
+ }
+
+ /**
+ * Returns the timeout in milliseconds.
+ */
+ public long getTimeout() {
+ return _timeout;
+ }
+
+ /**
+ * Set the debug flag.
+ * <p>
+ * Setting this to true will print the submitted command and an information if the child process
+ * is destroyed after the timeout.
+ */
+ public void setDebug(boolean debug) {
+ _debug = debug;
+ }
+
+ /**
+ * Returns the debug flag
+ */
+ public boolean isDebug() {
+ return _debug;
+ }
+
+ /**
+ * Set the silent flag.
+ * <p>
+ * Setting this to true will suppress output of the called command.
+ */
+ public void setSilent(boolean silent) {
+ _silent = silent;
+ }
+
+ /**
+ * Returns the silent flag.
+ */
+ public boolean isSilent() {
+ return _silent;
+ }
+
+ /**
+ * Set the interval (in milliseconds) after which the subprocess is checked if it is still
+ * alive. Defaults to 1000 ms.
+ */
+ public void setPollAliveInterval(long pollAliveInterval) {
+ _pollAliveInterval = pollAliveInterval;
+ }
+
+ /**
+ * Returns the interval (in milliseconds) after which the subprocess is checked if it is still
+ * alive.
+ */
+ public long getPollAliveInterval() {
+ return _pollAliveInterval;
+ }
+
+ /**
+ * returns true if the timeout has expired
+ */
+ private boolean isTimeout() {
+ boolean isTimeout = false;
+ long currentTime = System.currentTimeMillis();
+ long diff = 0;
+ long timeout = getTimeout();
+ if (timeout != INFINITE_TIMEOUT) {
+ diff = currentTime - _startTime;
+ if (diff > timeout) {
+ isTimeout = true;
+ }
+ }
+ return isTimeout;
+ }
+
+ /**
+ * Start the child process
+ */
+ public int run() {
+ try {
+ // determine start time
+ _startTime = System.currentTimeMillis();
+ // start the process
+ _process = Runtime.getRuntime().exec(getCommand());
+ debugCommand();
+ // handle stdout and stderr
+ StdoutMonitor stdoutMonitor = new StdoutMonitor();
+ stdoutMonitor.start();
+ StderrMonitor stderrMonitor = new StderrMonitor();
+ stderrMonitor.start();
+ // run the subprocess as long as wanted
+ while (!isTimeout() && isAlive()) {
+ try {
+ Thread.sleep(getPollAliveInterval());
+ } catch (InterruptedException ie) {
+ if (!isSilent()) {
+ ie.printStackTrace();
+ }
+ }
+ }
+ // end properly
+ if (isAlive()) { // sets the exit value in case process is dead
+ destroy();
+ } else {
+ if (isDebug()) {
+ System.out.println("[ChildProcess] ended itself");
+ }
+ }
+ } catch (IOException ioe) {
+ if (!isSilent()) {
+ ioe.printStackTrace();
+ }
+ }
+ return getExitValue();
+ }
+
+ /**
+ * The exit value
+ */
+ public int getExitValue() {
+ return _exitValue;
+ }
+
+ private void setExitValue(int exitValue) {
+ _exitValue = exitValue;
+ }
+
+ /**
+ * Tests if the process is still alive
+ */
+ private boolean isAlive() {
+ try {
+ setExitValue(_process.exitValue());
+ return false;
+ } catch (IllegalThreadStateException itse) {
+ return true;
+ }
+ }
+
+ /**
+ * Destroy the child process
+ */
+ private void destroy() {
+ _process.destroy();
+ setExitValue(DESTROYED_AFTER_TIMEOUT);
+ if (isDebug()) {
+ System.out.println("[ChildProcess] destroying because of timeout !");
+ }
+ }
+
+ /**
+ * Lists the submitted command (if so indicated)
+ */
+ private void debugCommand() {
+ if (isDebug()) {
+ String[] command = getCommand();
+ if (command != null) {
+ System.out.print("[ChildProcess] command '");
+ for (int i = 0; i < command.length; i++) {
+ String commandPart = command[i];
+ if (i == 0) {
+ System.out.print(commandPart);
+ } else {
+ System.out.print(" " + commandPart);
+ }
+ }
+ System.out.println("' is now running...");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ConsoleInstaller.java b/installer/src/java/org/python/util/install/ConsoleInstaller.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ConsoleInstaller.java
@@ -0,0 +1,609 @@
+package org.python.util.install;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+import org.python.util.install.driver.Tunnel;
+
+public class ConsoleInstaller implements ProgressListener, TextKeys {
+
+ public static final String CURRENT_JRE = "=";
+
+ private static final String _CANCEL = "c";
+
+ private static final String _PROMPT = ">>>";
+
+ private static final String _BEGIN_ANSWERS = "[";
+
+ private static final String _END_ANSWERS = "]";
+
+
+ private InstallerCommandLine _commandLine;
+
+ private JarInstaller _jarInstaller;
+
+ private JarInfo _jarInfo;
+
+ private Tunnel _tunnel;
+
+ public ConsoleInstaller(InstallerCommandLine commandLine, JarInfo jarInfo) {
+ _commandLine = commandLine;
+ _jarInfo = jarInfo;
+ _jarInstaller = new JarInstaller(this, jarInfo);
+ }
+
+ public void setTunnel(Tunnel tunnel) {
+ _tunnel = tunnel;
+ }
+
+ public void install() {
+ File targetDirectory = null;
+ JavaHomeHandler javaHomeHandler = null;
+ if (_commandLine.hasConsoleOption()) {
+ welcome();
+ selectLanguage();
+ acceptLicense();
+ InstallationType installationType = selectInstallationType();
+ targetDirectory = determineTargetDirectory();
+ javaHomeHandler = checkVersion(determineJavaHome());
+ promptForCopying(targetDirectory, installationType, javaHomeHandler);
+ _jarInstaller.inflate(targetDirectory, installationType, javaHomeHandler);
+ showReadme(targetDirectory);
+ success(targetDirectory);
+ } else if (_commandLine.hasSilentOption()) {
+ message(getText(C_SILENT_INSTALLATION));
+ targetDirectory = _commandLine.getTargetDirectory();
+ checkTargetDirectorySilent(targetDirectory);
+ javaHomeHandler = checkVersionSilent(_commandLine.getJavaHomeHandler());
+ _jarInstaller.inflate(targetDirectory,
+ _commandLine.getInstallationType(),
+ javaHomeHandler);
+ success(targetDirectory);
+ }
+ }
+
+ protected final static void message(String message) {
+ System.out.println(message); // this System.out.println is intended
+ }
+
+ private void welcome() {
+ message(getText(C_WELCOME_TO_JYTHON));
+ message(getText(C_VERSION_INFO, _jarInfo.getVersion()));
+ message(getText(C_AT_ANY_TIME_CANCEL, _CANCEL));
+ }
+
+ private String question(String question) {
+ return question(question, null, false, null);
+ }
+
+ private String question(String question, boolean answerRequired) {
+ return question(question, null, answerRequired, null);
+ }
+
+ private String question(String question, List<String> answers, String defaultAnswer) {
+ return question(question, answers, true, defaultAnswer);
+ }
+
+ /**
+ * question and answer
+ *
+ * @param question
+ * @param answers
+ * Possible answers (may be null)
+ * @param answerRequired
+ * @param defaultAnswer
+ * (may be null)
+ *
+ * @return (chosen) answer
+ */
+ private String question(String question,
+ List<String> answers,
+ boolean answerRequired,
+ String defaultAnswer) {
+ try {
+ if (answers != null && answers.size() > 0) {
+ question = question + " " + _BEGIN_ANSWERS;
+ Iterator<String> answersAsIterator = answers.iterator();
+ while (answersAsIterator.hasNext()) {
+ if (!question.endsWith(_BEGIN_ANSWERS))
+ question = question + "/";
+ String possibleAnswer = answersAsIterator.next();
+ if (possibleAnswer.equalsIgnoreCase(defaultAnswer)) {
+ if (Character.isDigit(possibleAnswer.charAt(0))) {
+ question = question.concat(" ").concat(possibleAnswer).concat(" ");
+ } else {
+ question = question + possibleAnswer.toUpperCase();
+ }
+ } else {
+ question = question + possibleAnswer;
+ }
+ }
+ question = question + _END_ANSWERS;
+ }
+ question = question + " " + _PROMPT + " ";
+ boolean match = false;
+ String answer = "";
+ while (!match && !_CANCEL.equalsIgnoreCase(answer)) {
+ // output to normal System.out
+ System.out.print(question); // intended print, not println (!)
+ answer = readLine();
+ if ("".equals(answer) && answerRequired) {
+ // check default answer
+ if (defaultAnswer != null) {
+ match = true;
+ answer = defaultAnswer;
+ }
+ } else {
+ if (answers != null && answers.size() > 0) {
+ Iterator<String> answersAsIterator = answers.iterator();
+ while (answersAsIterator.hasNext()) {
+ if (answer.equalsIgnoreCase(answersAsIterator.next())) {
+ match = true;
+ }
+ }
+ } else {
+ match = true;
+ }
+ if (!match && !_CANCEL.equalsIgnoreCase(answer)) {
+ message(getText(C_INVALID_ANSWER, answer));
+ }
+ }
+ }
+ if (_CANCEL.equalsIgnoreCase(answer)) {
+ throw new InstallationCancelledException();
+ }
+ return answer;
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe);
+ }
+ }
+
+ /**
+ * Send a signal through the tunnel, and then wait for the answer from the other side.
+ *
+ * <pre>
+ * (2) [Driver] receives question [Tunnel] sends question [Console] (1)
+ * (3) [Driver] sends answer [Tunnel] receives answer [Console] (4)
+ * </pre>
+ */
+ private String readLine() throws IOException {
+ InputStream inputStream;
+ String line = "";
+ if (_tunnel == null) {
+ inputStream = System.in;
+ } else {
+ inputStream = _tunnel.getAnswerReceiverStream();
+ _tunnel.getQuestionSenderStream().write(Tunnel.NEW_LINE.getBytes());
+ _tunnel.getQuestionSenderStream().flush();
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ line = reader.readLine();
+ return line;
+ }
+
+ private void selectLanguage() {
+ List<String> availableLanguages = new ArrayList<String>(2);
+ availableLanguages.add(getText(C_ENGLISH));
+ availableLanguages.add(getText(C_GERMAN)); // 1 == German
+ List<String> answers = new ArrayList<String>(availableLanguages.size());
+ String languages = "";
+ String defaultAnswer = null;
+ for (Iterator<String> iterator = availableLanguages.iterator(); iterator.hasNext();) {
+ String language = iterator.next();
+ String possibleAnswer = language.substring(0, 1);
+ if (defaultAnswer == null) {
+ defaultAnswer = possibleAnswer;
+ }
+ languages = languages + language + ", ";
+ answers.add(possibleAnswer.toLowerCase());
+ }
+ languages = languages.substring(0, languages.length() - 2);
+ message(getText(C_AVAILABLE_LANGUAGES, languages));
+ String answer = question(getText(C_SELECT_LANGUAGE), answers, defaultAnswer);
+ if (answer.equalsIgnoreCase(answers.get(1))) {
+ Installation.setLanguage(Locale.GERMAN);
+ } else {
+ Installation.setLanguage(Locale.ENGLISH);
+ }
+ }
+
+ private InstallationType selectInstallationType() {
+ InstallationType installationType = new InstallationType();
+ String no = getText(C_NO);
+ String yes = getText(C_YES);
+ message(getText(C_INSTALL_TYPES));
+ message(" " + Installation.ALL + ". " + getText(C_ALL));
+ message(" " + Installation.STANDARD + ". " + getText(C_STANDARD));
+ message(" " + Installation.MINIMUM + ". " + getText(C_MINIMUM));
+ message(" " + Installation.STANDALONE + ". " + getText(C_STANDALONE));
+ String answer = question(getText(C_SELECT_INSTALL_TYPE), getTypeAnswers(), Installation.ALL);
+ if (Installation.ALL.equals(answer)) {
+ installationType.setAll();
+ } else if (Installation.STANDARD.equals(answer)) {
+ installationType.setStandard();
+ } else if (Installation.MINIMUM.equals(answer)) {
+ installationType.setMinimum();
+ } else if (Installation.STANDALONE.equals(answer)) {
+ installationType.setStandalone();
+ }
+ if (!installationType.isStandalone()) {
+ // include parts ?
+ if (!installationType.isAll()) {
+ answer = question(getText(C_INCLUDE), getYNAnswers(), no);
+ if (yes.equals(answer)) {
+ do {
+ answer = question(getText(C_INEXCLUDE_PARTS, no), getInExcludeAnswers(), no);
+ if (InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES.equals(answer)) {
+ installationType.addLibraryModules();
+ } else if (InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES.equals(answer)) {
+ installationType.addDemosAndExamples();
+ } else if (InstallerCommandLine.INEXCLUDE_DOCUMENTATION.equals(answer)) {
+ installationType.addDocumentation();
+ } else if (InstallerCommandLine.INEXCLUDE_SOURCES.equals(answer)) {
+ installationType.addSources();
+ }
+ if (!no.equals(answer)) {
+ message(getText(C_SCHEDULED, answer));
+ }
+ } while (!no.equals(answer));
+ }
+ }
+ // exclude parts ?
+ if (!installationType.isMinimum()) {
+ answer = question(getText(C_EXCLUDE), getYNAnswers(), no);
+ if (yes.equals(answer)) {
+ do {
+ answer = question(getText(C_INEXCLUDE_PARTS, no), getInExcludeAnswers(), no);
+ if (InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES.equals(answer)) {
+ installationType.removeLibraryModules();
+ } else if (InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES.equals(answer)) {
+ installationType.removeDemosAndExamples();
+ } else if (InstallerCommandLine.INEXCLUDE_DOCUMENTATION.equals(answer)) {
+ installationType.removeDocumentation();
+ } else if (InstallerCommandLine.INEXCLUDE_SOURCES.equals(answer)) {
+ installationType.removeSources();
+ }
+ if (!no.equals(answer)) {
+ message(getText(C_UNSCHEDULED, answer));
+ }
+ } while (!no.equals(answer));
+ }
+ }
+ }
+ return installationType;
+ }
+
+ private JavaHomeHandler checkVersion(JavaHomeHandler javaHomeHandler) {
+ // handle target java version
+ JavaInfo javaInfo = verifyTargetJava(javaHomeHandler);
+ message(getText(C_JAVA_VERSION,
+ javaInfo.getJavaVersionInfo().getVendor(),
+ javaInfo.getJavaVersionInfo().getVersion()));
+ if (!Installation.isValidJava(javaInfo.getJavaVersionInfo())) {
+ message(getText(C_UNSUPPORTED_JAVA));
+ question(getText(C_PROCEED_ANYWAY));
+ }
+ // handle OS
+ String osName = System.getProperty(Installation.OS_NAME);
+ String osVersion = System.getProperty(Installation.OS_VERSION);
+ message(getText(C_OS_VERSION, osName, osVersion));
+ if (!Installation.isValidOs()) {
+ message(getText(C_UNSUPPORTED_OS));
+ question(getText(C_PROCEED_ANYWAY));
+ }
+ return javaInfo.getJavaHomeHandler();
+ }
+
+ private JavaHomeHandler checkVersionSilent(JavaHomeHandler javaHomeHandler) {
+ // check target java version
+ JavaInfo javaInfo = verifyTargetJava(javaHomeHandler);
+ if (!Installation.isValidJava(javaInfo.getJavaVersionInfo())) {
+ message(getText(C_UNSUPPORTED_JAVA));
+ }
+ // check OS
+ if (!Installation.isValidOs()) {
+ message(getText(C_UNSUPPORTED_OS));
+ }
+ return javaInfo.getJavaHomeHandler();
+ }
+
+ private JavaInfo verifyTargetJava(JavaHomeHandler javaHomeHandler) {
+ JavaVersionInfo javaVersionInfo = new JavaVersionInfo();
+ Installation.fillJavaVersionInfo(javaVersionInfo, System.getProperties()); // a priori
+ if (javaHomeHandler.isDeviation()) {
+ javaVersionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ if (javaVersionInfo.getErrorCode() != Installation.NORMAL_RETURN) {
+ // switch back to current if an error occurred
+ message(getText(C_TO_CURRENT_JAVA, javaVersionInfo.getReason()));
+ javaHomeHandler = new JavaHomeHandler();
+ }
+ }
+ JavaInfo javaInfo = new JavaInfo();
+ javaInfo.setJavaHomeHandler(javaHomeHandler);
+ javaInfo.setJavaVersionInfo(javaVersionInfo);
+ return javaInfo;
+ }
+
+ private void acceptLicense() {
+ String no = getText(C_NO);
+ String yes = getText(C_YES);
+ String read = question(getText(C_READ_LICENSE), getYNAnswers(), no);
+ if (read.equalsIgnoreCase(getText(C_YES))) {
+ String licenseText = "n/a";
+ try {
+ licenseText = _jarInfo.getLicenseText();
+ message(licenseText);
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe);
+ }
+ }
+ String accept = question(getText(C_ACCEPT), getYNAnswers(), yes);
+ if (!accept.equalsIgnoreCase(getText(C_YES))) {
+ throw new InstallationCancelledException();
+ }
+ }
+
+ private File determineTargetDirectory() {
+ String no = getText(C_NO);
+ String yes = getText(C_YES);
+ File targetDirectory = null;
+ try {
+ do {
+ targetDirectory = new File(question(getText(C_ENTER_TARGET_DIRECTORY), true));
+ if (targetDirectory.exists()) {
+ if (!targetDirectory.isDirectory()) {
+ message(getText(C_NOT_A_DIRECTORY, targetDirectory.getCanonicalPath()));
+ } else {
+ if (targetDirectory.list().length > 0) {
+ String overwrite = question(getText(C_OVERWRITE_DIRECTORY,
+ targetDirectory.getCanonicalPath()),
+ getYNAnswers(),
+ no);
+ if (overwrite.equalsIgnoreCase(getText(C_YES))) {
+ String clear = question(getText(C_CLEAR_DIRECTORY,
+ targetDirectory.getCanonicalPath()),
+ getYNAnswers(),
+ yes);
+ if (clear.equalsIgnoreCase(getText(C_YES))) {
+ clearDirectory(targetDirectory);
+ }
+ }
+ }
+ }
+ } else {
+ String create = question(getText(C_CREATE_DIRECTORY,
+ targetDirectory.getCanonicalPath()),
+ getYNAnswers(),
+ yes);
+ if (create.equalsIgnoreCase(getText(C_YES))) {
+ if (!targetDirectory.mkdirs()) {
+ throw new InstallerException(getText(C_UNABLE_CREATE_DIRECTORY,
+ targetDirectory.getCanonicalPath()));
+ }
+ }
+ }
+ } while (!targetDirectory.exists() || !targetDirectory.isDirectory()
+ || targetDirectory.list().length > 0);
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe);
+ }
+ return targetDirectory;
+ }
+
+ private JavaHomeHandler determineJavaHome() {
+ JavaHomeHandler javaHomeHandler = null;
+ boolean javaFound = false;
+ while (!javaFound) {
+ String javaHomeName = question(getText(C_ENTER_JAVA_HOME), null, true, CURRENT_JRE);
+ // only validate deviations
+ if (CURRENT_JRE.equals(javaHomeName)) {
+ javaHomeHandler = new JavaHomeHandler();
+ javaFound = true;
+ } else {
+ javaHomeHandler = new JavaHomeHandler(javaHomeName);
+ if (javaHomeHandler.isDeviation()) {
+ if (!javaHomeHandler.isValidHome()) {
+ String binDirName = javaHomeName.concat("/bin");
+ message(getText(C_NO_JAVA_EXECUTABLE, binDirName));
+ } else {
+ javaFound = true;
+ }
+ } else {
+ javaFound = true;
+ }
+ }
+ }
+ return javaHomeHandler;
+ }
+
+ private void checkTargetDirectorySilent(File targetDirectory) {
+ try {
+ if (!targetDirectory.exists()) {
+ // create directory
+ if (!targetDirectory.mkdirs()) {
+ throw new InstallerException(getText(C_UNABLE_CREATE_DIRECTORY,
+ targetDirectory.getCanonicalPath()));
+ }
+ } else {
+ // assert it is an empty directory
+ if (!targetDirectory.isDirectory()) {
+ throw new InstallerException(getText(C_NOT_A_DIRECTORY,
+ targetDirectory.getCanonicalPath()));
+ } else {
+ if (targetDirectory.list().length > 0) {
+ throw new InstallerException(getText(C_NON_EMPTY_TARGET_DIRECTORY,
+ targetDirectory.getCanonicalPath()));
+ }
+ }
+ }
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe);
+ }
+ }
+
+ private void showReadme(final File targetDirectory) {
+ String no = getText(C_NO);
+ String read = question(getText(C_READ_README), getYNAnswers(), no);
+ if (read.equalsIgnoreCase(getText(C_YES))) {
+ try {
+ message(_jarInfo.getReadmeText());
+ question(getText(C_PROCEED));
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe);
+ }
+ }
+ }
+
+ private void clearDirectory(File targetDirectory) {
+ File files[] = targetDirectory.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ clearDirectory(files[i]);
+ }
+ if (!files[i].delete()) {
+ throw new InstallerException(getText(C_UNABLE_TO_DELETE, files[i].getAbsolutePath()));
+ }
+ }
+ }
+
+ private void promptForCopying(final File targetDirectory,
+ final InstallationType installationType,
+ final JavaHomeHandler javaHomeHandler) {
+ try {
+ message(getText(C_SUMMARY));
+ if (installationType.isStandalone()) {
+ message(" - " + InstallerCommandLine.TYPE_STANDALONE);
+ } else {
+ message(" - " + InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES + ": "
+ + installationType.installLibraryModules());
+ message(" - " + InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES + ": "
+ + installationType.installDemosAndExamples());
+ message(" - " + InstallerCommandLine.INEXCLUDE_DOCUMENTATION + ": "
+ + installationType.installDocumentation());
+ message(" - " + InstallerCommandLine.INEXCLUDE_SOURCES + ": "
+ + installationType.installSources());
+ if (javaHomeHandler.isValidHome()) {
+ message(" - JRE: " + javaHomeHandler.getHome().getAbsolutePath());
+ } else {
+ message(" - java");
+ }
+ }
+ String proceed = question(getText(C_CONFIRM_TARGET, targetDirectory.getCanonicalPath()),
+ getYNAnswers(), getText(C_YES));
+ if (!proceed.equalsIgnoreCase(getText(C_YES))) {
+ throw new InstallationCancelledException();
+ }
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe); // catch for the compiler
+ }
+ }
+
+ private void success(final File targetDirectory) {
+ try {
+ message(getText(C_CONGRATULATIONS) + " "
+ + getText(C_SUCCESS, _jarInfo.getVersion(), targetDirectory.getCanonicalPath()));
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe); // catch for the compiler
+ }
+ }
+
+ private List<String> getTypeAnswers() {
+ List<String> answers = new ArrayList<String>(4);
+ answers.add(Installation.ALL);
+ answers.add(Installation.STANDARD);
+ answers.add(Installation.MINIMUM);
+ answers.add(Installation.STANDALONE);
+ return answers;
+ }
+
+ private List<String> getYNAnswers() {
+ List<String> answers = new ArrayList<String>(2);
+ answers.add(getText(C_YES));
+ answers.add(getText(C_NO));
+ return answers;
+ }
+
+ private List<String> getInExcludeAnswers() {
+ List<String> answers = new ArrayList<String>(5);
+ answers.add(InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES);
+ answers.add(InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES);
+ answers.add(InstallerCommandLine.INEXCLUDE_DOCUMENTATION);
+ answers.add(InstallerCommandLine.INEXCLUDE_SOURCES);
+ answers.add(getText(C_NO));
+ return answers;
+ }
+
+ private void progressMessage(int percentage) {
+ message(" " + percentage + " %");
+ }
+
+ private String getText(String textKey) {
+ return Installation.getText(textKey);
+ }
+
+ private String getText(String textKey, String parameter0) {
+ return Installation.getText(textKey, parameter0);
+ }
+
+ private String getText(String textKey, String parameter0, String parameter1) {
+ return Installation.getText(textKey, parameter0, parameter1);
+ }
+
+ private static class JavaInfo {
+
+ private JavaVersionInfo _javaVersionInfo;
+
+ private JavaHomeHandler _javaHomeHandler;
+
+ void setJavaHomeHandler(JavaHomeHandler javaHomeHandler) {
+ _javaHomeHandler = javaHomeHandler;
+ }
+
+ JavaHomeHandler getJavaHomeHandler() {
+ return _javaHomeHandler;
+ }
+
+ void setJavaVersionInfo(JavaVersionInfo javaVersionInfo) {
+ _javaVersionInfo = javaVersionInfo;
+ }
+
+ JavaVersionInfo getJavaVersionInfo() {
+ return _javaVersionInfo;
+ }
+ }
+
+ //
+ // interface ProgressListener
+ //
+ public void progressChanged(int newPercentage) {
+ progressMessage(newPercentage);
+ }
+
+ public int getInterval() {
+ return 10; // fixed interval for console installer
+ }
+
+ public void progressFinished() {
+ progressMessage(100);
+ }
+
+ public void progressEntry(String entry) {
+ // ignore the single entries - only used in gui mode
+ }
+
+ public void progressStartScripts() {
+ message(getText(C_GENERATING_START_SCRIPTS));
+ }
+
+ public void progressStandalone() {
+ message(getText(C_PACKING_STANDALONE_JAR));
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/DirectoryFilter.java b/installer/src/java/org/python/util/install/DirectoryFilter.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/DirectoryFilter.java
@@ -0,0 +1,23 @@
+package org.python.util.install;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * Filters all directories, and sets the description in the file chooser
+ */
+public class DirectoryFilter extends FileFilter {
+
+ public boolean accept(File f) {
+ if (f.isDirectory()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public String getDescription() {
+ return Installation.getText(TextKeys.DIRECTORIES_ONLY);
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/DirectorySelectionPage.java b/installer/src/java/org/python/util/install/DirectorySelectionPage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/DirectorySelectionPage.java
@@ -0,0 +1,200 @@
+package org.python.util.install;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.File;
+import java.io.IOException;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public class DirectorySelectionPage extends AbstractWizardPage {
+
+ private static final long serialVersionUID = -3672273150338356549L;
+
+ private JLabel _label;
+ private JTextField _directory;
+ private JButton _browse;
+ private JarInfo _jarInfo;
+
+ public DirectorySelectionPage(JarInfo jarInfo) {
+ super();
+ _jarInfo = jarInfo;
+ initComponents();
+ }
+
+ private void initComponents() {
+ // label
+ _label = new JLabel();
+ // directory
+ _directory = new JTextField(40);
+ _directory.addFocusListener(new DirectoryFocusListener());
+ // browse button
+ _browse = new JButton();
+ _browse.addActionListener(new BrowseButtonListener());
+
+ JPanel panel = new JPanel();
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ panel.setLayout(gridBagLayout);
+ GridBagConstraints gridBagConstraints = newGridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ panel.add(_label, gridBagConstraints);
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ panel.add(_directory, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 1;
+ panel.add(_browse, gridBagConstraints);
+
+ add(panel);
+ }
+
+ JTextField getDirectory() {
+ return _directory;
+ }
+
+ protected String getTitle() {
+ return getText(TARGET_DIRECTORY_PROPERTY);
+ }
+
+ protected String getDescription() {
+ return getText(CHOOSE_LOCATION);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return true;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return _directory;
+ }
+
+ protected void activate() {
+ _label.setText(getText(SELECT_TARGET_DIRECTORY) + ": ");
+ _browse.setText(getText(BROWSE));
+ String directory = FrameInstaller.getTargetDirectory();
+ if (directory == null || directory.length() <= 0) {
+ File defaultDirectory = getDefaultDirectory();
+ try {
+ directory = defaultDirectory.getCanonicalPath();
+ } catch (IOException e) {
+ directory = "?";
+ }
+ FrameInstaller.setTargetDirectory(directory);
+ }
+ _directory.setText(FrameInstaller.getTargetDirectory());
+ _directory.setToolTipText(_directory.getText());
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+ private File getDefaultDirectory() {
+ String directory = "";
+ File defaultDirectory = null;
+ // 1st try (on windows): root
+ if (Installation.isWindows()) {
+ JavaHomeHandler handler = new JavaHomeHandler();
+ if (handler.isValidHome()) {
+ directory = handler.getHome().getAbsolutePath();
+ if (directory.length() > 2) {
+ directory = directory.substring(0, 2);
+ }
+ } else {
+ directory = "C:";
+ }
+ defaultDirectory = makeJythonSubDirectory(directory);
+ }
+ // 2st try: user.home
+ if (defaultDirectory == null) {
+ directory = System.getProperty("user.home", "");
+ if (directory.length() > 0) {
+ defaultDirectory = makeJythonSubDirectory(directory);
+ }
+ }
+ // 3rd try: user.dir
+ if (defaultDirectory == null) {
+ directory = System.getProperty("user.dir", "");
+ if (directory.length() > 0) {
+ defaultDirectory = makeJythonSubDirectory(directory);
+ }
+ }
+ // 4th try: current directory
+ if (defaultDirectory == null) {
+ defaultDirectory = makeJythonSubDirectory(new File(new File("dummy").getAbsolutePath()).getParent());
+ }
+ return defaultDirectory;
+ }
+
+ private File makeJythonSubDirectory(String directory) {
+ File defaultDirectory = null;
+ File parentDirectory = new File(directory);
+ if (parentDirectory.exists() && parentDirectory.isDirectory()) {
+ String jythonSubDirectoryName = "jython" + (_jarInfo.getVersion()).replaceAll("\\+", "");
+ defaultDirectory = new File(parentDirectory, jythonSubDirectoryName);
+ }
+ return defaultDirectory;
+ }
+
+ private class BrowseButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ String directoryName = _directory.getText();
+ File directory = new File(directoryName);
+ if (directory.exists()) {
+ if (!directory.isDirectory()) {
+ // switch to parent directory if user typed the name of a file
+ directory = directory.getParentFile();
+ }
+ }
+ JFileChooser fileChooser = new JFileChooser(directory);
+ fileChooser.setDialogTitle(getText(SELECT_TARGET_DIRECTORY));
+ // the filter is at the moment only used for the title of the dialog:
+ fileChooser.setFileFilter(new DirectoryFilter());
+ fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ if (fileChooser.isAcceptAllFileFilterUsed()) {
+ if (Installation.isMacintosh() && Installation.isJDK141()) {
+ // work around ArrayIndexOutOfBoundsExceptio on Mac OS X, java version 1.4.1
+ } else {
+ fileChooser.setAcceptAllFileFilterUsed(false);
+ }
+ }
+ int returnValue = fileChooser.showDialog(_browse, getText(SELECT));
+ if (returnValue == JFileChooser.APPROVE_OPTION) {
+ _directory.setText(fileChooser.getSelectedFile().getAbsolutePath());
+ _directory.setToolTipText(_directory.getText());
+ FrameInstaller.setTargetDirectory(_directory.getText());
+ }
+ }
+ }
+
+ private class DirectoryFocusListener implements FocusListener {
+ public void focusGained(FocusEvent e) {
+ }
+
+ public void focusLost(FocusEvent e) {
+ FrameInstaller.setTargetDirectory(_directory.getText());
+ _directory.setToolTipText(_directory.getText());
+ }
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/DirectorySelectionPageValidator.java b/installer/src/java/org/python/util/install/DirectorySelectionPageValidator.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/DirectorySelectionPageValidator.java
@@ -0,0 +1,36 @@
+package org.python.util.install;
+
+import java.io.File;
+
+public class DirectorySelectionPageValidator extends AbstractWizardValidator {
+
+ DirectorySelectionPage _page;
+
+ DirectorySelectionPageValidator(DirectorySelectionPage page) {
+ super();
+ _page = page;
+ }
+
+ protected void validate() throws ValidationException, ValidationInformationException {
+ String directory = _page.getDirectory().getText().trim(); // trim to be sure
+ if (directory != null && directory.length() > 0) {
+ File targetDirectory = new File(directory);
+ if (targetDirectory.exists()) {
+ if (targetDirectory.isDirectory()) {
+ if (targetDirectory.list().length > 0) {
+ throw new ValidationException(getText(NON_EMPTY_TARGET_DIRECTORY));
+ }
+ }
+ } else {
+ if (targetDirectory.mkdirs()) {
+ throw new ValidationInformationException(Installation.getText(CREATED_DIRECTORY, directory));
+ } else {
+ throw new ValidationException(getText(UNABLE_CREATE_DIRECTORY, directory));
+ }
+ }
+ } else {
+ throw new ValidationException(getText(EMPTY_TARGET_DIRECTORY));
+ }
+ FrameInstaller.setTargetDirectory(directory);
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/EmptyValidator.java b/installer/src/java/org/python/util/install/EmptyValidator.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/EmptyValidator.java
@@ -0,0 +1,8 @@
+package org.python.util.install;
+
+public class EmptyValidator extends AbstractWizardValidator {
+
+ protected void validate() {
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/FileHelper.java b/installer/src/java/org/python/util/install/FileHelper.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/FileHelper.java
@@ -0,0 +1,208 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Helper methods for file handling during installation / installation verification
+ */
+public final class FileHelper {
+
+ private final static String EXECUTABLE_MODE = "755";
+
+ /**
+ * create a temporary directory with the same name as the passed in File (which may exist as
+ * file, not directory)
+ *
+ * @param tempDirectory
+ * @return <code>true</code> only if the the directory was successfully created (or already
+ * existed)
+ */
+ public static boolean createTempDirectory(File tempDirectory) {
+ boolean success = true;
+ if (!tempDirectory.isDirectory()) {
+ if (tempDirectory.exists()) {
+ success = carryOnResult(tempDirectory.delete(), success);
+ }
+ if (success) {
+ success = tempDirectory.mkdirs();
+ }
+ }
+ return success;
+ }
+
+ /**
+ * completely remove a directory
+ *
+ * @param dir
+ * @return <code>true</code> if successful, <code>false</code> otherwise.
+ */
+ public static boolean rmdir(File dir) {
+ boolean success = true;
+ if (dir.exists()) {
+ File[] files = dir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ if (file.isFile()) {
+ success = carryOnResult(file.delete(), success);
+ } else {
+ if (file.isDirectory()) {
+ success = carryOnResult(rmdir(file), success);
+ }
+ }
+ }
+ success = carryOnResult(dir.delete(), success);
+ }
+ return success;
+ }
+
+ /**
+ * read the contents of a file into a String
+ *
+ * @param file
+ * The file has to exist
+ * @return The contents of the file as String
+ * @throws IOException
+ */
+ public static String readAll(File file) throws IOException {
+ FileReader fileReader = new FileReader(file);
+ try {
+ StringBuffer sb = new StringBuffer();
+ char[] b = new char[8192];
+ int n;
+ while ((n = fileReader.read(b)) > 0) {
+ sb.append(b, 0, n);
+ }
+ return sb.toString();
+ } finally {
+ fileReader.close();
+ }
+ }
+
+ /**
+ * read the contents of a stream into a String
+ * <p>
+ * ATTN: does not handle encodings
+ *
+ * @param inputStream
+ * The input stream
+ * @return A String representation of the file contents
+ * @throws IOException
+ */
+ public static String readAll(InputStream inputStream) throws IOException {
+ try {
+ StringBuffer sb = new StringBuffer();
+ byte[] b = new byte[8192];
+ int n;
+ while ((n = inputStream.read(b)) > 0) {
+ sb.append(new String(b, 0, n));
+ }
+ return sb.toString();
+ } finally {
+ inputStream.close();
+ }
+ }
+
+ /**
+ * Write contents to a file.
+ * <p>
+ * An existing file would be overwritten.
+ *
+ * @param file
+ * @param contents
+ *
+ * @throws IOException
+ */
+ public static void write(File file, String contents) throws IOException {
+ FileWriter writer = new FileWriter(file);
+ writer.write(contents);
+ writer.flush();
+ writer.close();
+ }
+
+ /**
+ * determine the url of a file relative to (in the same directory as) the specified .class file<br>
+ * can also be used if the .class file resides inside a .jar file
+ *
+ * @param clazz
+ * The class next to the file
+ * @param fileName
+ * The name of the file
+ *
+ * @return The url of the file, can be null
+ */
+ public static URL getRelativeURL(Class<?> clazz, String fileName) {
+ String filePath = getRelativePackagePath(clazz) + "/" + fileName;
+ return Thread.currentThread().getContextClassLoader().getResource(filePath);
+ }
+
+ /**
+ * get the input stream of a file relative to (in the same directory as) the specified .class
+ * file<br>
+ * can also be used if the .class file resides inside a .jar file
+ *
+ * @param clazz
+ * The class next to the file
+ * @param fileName
+ * The name of the file
+ *
+ * @return The input stream of the file, can be null
+ */
+ public static InputStream getRelativeURLAsStream(Class<?> clazz, String fileName) {
+ String filePath = getRelativePackagePath(clazz) + "/" + fileName;
+ return Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
+ }
+
+ /**
+ * do a chmod on the passed file
+ *
+ * @param scriptFile
+ */
+ public static void makeExecutable(File scriptFile) {
+ try {
+ String command[] = new String[3];
+ command[0] = "chmod";
+ command[1] = EXECUTABLE_MODE;
+ command[2] = scriptFile.getAbsolutePath();
+ long timeout = 3000;
+ ChildProcess childProcess = new ChildProcess(command, timeout);
+ childProcess.run();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ /**
+ * build the package path for the class loader<br>
+ * the class loader should be able to load a file appended to this path, if it is in the same
+ * directory.
+ *
+ * @param clazz
+ * The class
+ *
+ * @return The package path
+ */
+ private static String getRelativePackagePath(Class<?> clazz) {
+ String className = clazz.getName();
+ String packageName = className.substring(0, className.lastIndexOf("."));
+ return packageName.replace('.', '/');
+ }
+
+ /**
+ * @param newResult
+ * @param existingResult
+ * @return <code>false</code> if newResult or existingResult are false, <code>true</code>
+ * otherwise.
+ */
+ private static boolean carryOnResult(boolean newResult, boolean existingResult) {
+ if (existingResult) {
+ return newResult;
+ } else {
+ return existingResult;
+ }
+ }
+}
diff --git a/installer/src/java/org/python/util/install/FrameInstaller.java b/installer/src/java/org/python/util/install/FrameInstaller.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/FrameInstaller.java
@@ -0,0 +1,186 @@
+package org.python.util.install;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.Locale;
+import java.util.Properties;
+
+import javax.swing.UIManager;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+import org.python.util.install.driver.Autotest;
+
+public class FrameInstaller {
+ private static final String TRUE = "1";
+ private static final String FALSE = "0";
+
+ private static final String JAVA_VERSION_PROPERTY = "FrameInstaller.Version";
+ private static final String JAVA_VENDOR_PROPERTY = "FrameInstaller.Vendor";
+ private static final String JAVA_SPEC_VERSION_PROPERTY = "FrameInstaller.SpecVersion";
+
+ private static final String INEX_MOD_PROPERTY = "FrameInstaller.mod";
+ private static final String INEX_DEMO_PROPERTY = "FrameInstaller.demo";
+ private static final String INEX_DOC_PROPERTY = "FrameInstaller.doc";
+ private static final String INEX_SRC_PROPERTY = "FrameInstaller.src";
+ private static final String STANDALONE_PROPERTY = "FrameInstaller.standalone";
+
+ private static Properties _properties = new Properties();
+
+ private static JavaHomeHandler _javaHomeHandler;
+
+ protected FrameInstaller(InstallerCommandLine commandLine, JarInfo jarInfo, Autotest autotest) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e) {
+ }
+ // clear all properties
+ _properties.clear();
+ // set the default for the target directory
+ if (commandLine.hasDirectoryOption()) {
+ setTargetDirectory(commandLine.getTargetDirectory().getAbsolutePath());
+ }
+ if (commandLine.hasJavaHomeOption()) {
+ setJavaHomeHandler(commandLine.getJavaHomeHandler());
+ }
+ initDefaultJava();
+ Wizard wizard = new Wizard(jarInfo, autotest);
+ wizard.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent event) {
+ if (!Installation.isAutotesting()) {
+ System.exit(0);
+ }
+ }
+ });
+ wizard.addWizardListener(new SimpleWizardListener());
+ wizard.setVisible(true);
+ }
+
+ protected static void setProperty(String key, String value) {
+ _properties.setProperty(key, value);
+ }
+
+ protected static String getProperty(String key) {
+ return _properties.getProperty(key);
+ }
+
+ protected static String getProperty(String key, String defaultValue) {
+ return _properties.getProperty(key, defaultValue);
+ }
+
+ protected static void setTargetDirectory(String targetDirectory) {
+ setProperty(TextKeys.TARGET_DIRECTORY_PROPERTY, targetDirectory.trim());
+ }
+
+ protected static String getTargetDirectory() {
+ return getProperty(TextKeys.TARGET_DIRECTORY_PROPERTY);
+ }
+
+ protected static void setJavaHomeHandler(JavaHomeHandler javaHomeHandler) {
+ _javaHomeHandler = javaHomeHandler;
+ }
+
+ protected static JavaHomeHandler getJavaHomeHandler() {
+ if (_javaHomeHandler == null) {
+ _javaHomeHandler = new JavaHomeHandler();
+ }
+ return _javaHomeHandler;
+ }
+
+ protected static void setLanguage(Locale locale) {
+ setProperty(TextKeys.LANGUAGE_PROPERTY, locale.toString());
+ Installation.setLanguage(locale);
+ }
+
+ protected static Locale getLanguage() {
+ return new Locale(getProperty(TextKeys.LANGUAGE_PROPERTY));
+ }
+
+ protected static InstallationType getInstallationType() {
+ InstallationType installationType = new InstallationType();
+ if (Boolean.valueOf(getProperty(STANDALONE_PROPERTY)).booleanValue()) {
+ installationType.setStandalone();
+ }
+ if (Boolean.valueOf(getProperty(INEX_MOD_PROPERTY)).booleanValue()) {
+ installationType.addLibraryModules();
+ } else {
+ installationType.removeLibraryModules();
+ }
+ if (Boolean.valueOf(getProperty(INEX_DEMO_PROPERTY)).booleanValue()) {
+ installationType.addDemosAndExamples();
+ } else {
+ installationType.removeDemosAndExamples();
+ }
+ if (Boolean.valueOf(getProperty(INEX_DOC_PROPERTY)).booleanValue()) {
+ installationType.addDocumentation();
+ } else {
+ installationType.removeDocumentation();
+ }
+ if (Boolean.valueOf(getProperty(INEX_SRC_PROPERTY)).booleanValue()) {
+ installationType.addSources();
+ } else {
+ installationType.removeSources();
+ }
+ return installationType;
+ }
+
+ protected static void setInstallationType(InstallationType installationType) {
+ setProperty(STANDALONE_PROPERTY, Boolean.toString(installationType.isStandalone()));
+ setProperty(INEX_MOD_PROPERTY, Boolean.toString(installationType.installLibraryModules()));
+ setProperty(INEX_DEMO_PROPERTY, Boolean.toString(installationType.installDemosAndExamples()));
+ setProperty(INEX_DOC_PROPERTY, Boolean.toString(installationType.installDocumentation()));
+ setProperty(INEX_SRC_PROPERTY, Boolean.toString(installationType.installSources()));
+ }
+
+ protected static JavaVersionInfo getJavaVersionInfo() {
+ JavaVersionInfo javaVersionInfo = new JavaVersionInfo();
+ javaVersionInfo.setVersion(getProperty(JAVA_VERSION_PROPERTY));
+ javaVersionInfo.setVendor(getProperty(JAVA_VENDOR_PROPERTY));
+ javaVersionInfo.setSpecificationVersion(getProperty(JAVA_SPEC_VERSION_PROPERTY));
+ return javaVersionInfo;
+ }
+
+ protected static void setJavaVersionInfo(JavaVersionInfo javaVersionInfo) {
+ setProperty(JAVA_VERSION_PROPERTY, javaVersionInfo.getVersion());
+ setProperty(JAVA_VENDOR_PROPERTY, javaVersionInfo.getVendor());
+ setProperty(JAVA_SPEC_VERSION_PROPERTY, javaVersionInfo.getSpecificationVersion());
+ }
+
+ protected static void setAccept(boolean accept) {
+ if (accept) {
+ setProperty(TextKeys.ACCEPT_PROPERTY, TRUE);
+ } else {
+ setProperty(TextKeys.ACCEPT_PROPERTY, FALSE);
+ }
+ }
+
+ protected static boolean isAccept() {
+ return TRUE.equals(getProperty(TextKeys.ACCEPT_PROPERTY, FALSE));
+ }
+
+ protected static void initDefaultJava() {
+ JavaVersionInfo javaVersionInfo = new JavaVersionInfo();
+ Installation.fillJavaVersionInfo(javaVersionInfo, System.getProperties());
+ FrameInstaller.setJavaVersionInfo(javaVersionInfo);
+ }
+
+ private class SimpleWizardListener implements WizardListener {
+ public void wizardStarted(WizardEvent event) {
+ }
+
+ public void wizardFinished(WizardEvent event) {
+ if (!Installation.isAutotesting()) {
+ System.exit(0);
+ }
+ }
+
+ public void wizardCancelled(WizardEvent event) {
+ System.exit(1);
+ }
+
+ public void wizardNext(WizardEvent event) {
+ }
+
+ public void wizardPrevious(WizardEvent event) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/Installation.java b/installer/src/java/org/python/util/install/Installation.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/Installation.java
@@ -0,0 +1,439 @@
+package org.python.util.install;
+
+import java.awt.GraphicsEnvironment; // should be allowed on headless systems
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+import org.python.util.install.driver.Autotest;
+import org.python.util.install.driver.InstallationDriver;
+import org.python.util.install.driver.Tunnel;
+
+public class Installation {
+ public final static int NORMAL_RETURN = 0;
+ public final static int ERROR_RETURN = 1;
+
+ protected static final String ALL = "1";
+ protected static final String STANDARD = "2";
+ protected static final String MINIMUM = "3";
+ protected static final String STANDALONE = "9";
+
+ protected static final String OS_NAME = "os.name";
+ protected static final String OS_VERSION = "os.version";
+ protected static final String JAVA_VM_NAME = "java.vm.name";
+ protected static final String EMPTY = "";
+
+ protected static final String HEADLESS_PROPERTY_NAME = "java.awt.headless";
+
+ private static final String RESOURCE_CLASS = "org.python.util.install.TextConstants";
+
+ private static ResourceBundle _textConstants = ResourceBundle.getBundle(RESOURCE_CLASS, Locale.getDefault());
+
+ private static boolean _verbose = false;
+ private static boolean _isAutotesting = false;
+
+ public static void main(String args[]) {
+ internalMain(args, null, null);
+ }
+
+ public static void driverMain(String args[], Autotest autotest, Tunnel tunnel) {
+ internalMain(args, autotest, tunnel);
+ }
+
+ protected static boolean isVerbose() {
+ return _verbose;
+ }
+
+ protected static void setVerbose(boolean verbose) {
+ _verbose = verbose;
+ }
+
+ protected static boolean isAutotesting() {
+ return _isAutotesting;
+ }
+
+ protected static String getText(String key) {
+ return _textConstants.getString(key);
+ }
+
+ protected static String getText(String key, String... parameters) {
+ return MessageFormat.format(_textConstants.getString(key), (Object[])parameters);
+ }
+
+ protected static void setLanguage(Locale locale) {
+ _textConstants = ResourceBundle.getBundle(RESOURCE_CLASS, locale);
+ }
+
+ public static boolean isValidOs() {
+ String osName = System.getProperty(OS_NAME, "");
+ String lowerOs = osName.toLowerCase();
+ if (isWindows()) {
+ return true;
+ }
+ if (lowerOs.indexOf("linux") >= 0) {
+ return true;
+ }
+ if (lowerOs.indexOf("mac") >= 0) {
+ return true;
+ }
+ if (lowerOs.indexOf("unix") >= 0) {
+ return true;
+ }
+ return false;
+ }
+
+ protected static boolean isValidJava(JavaVersionInfo javaVersionInfo) {
+ String specificationVersion = javaVersionInfo.getSpecificationVersion();
+ verboseOutput("specification version: '" + specificationVersion + "'");
+ boolean valid = true;
+ if (getJavaSpecificationVersion(specificationVersion) < 15) {
+ valid = false;
+ }
+ return valid;
+ }
+
+ /**
+ * @return specification version as an int, e.g. 15 or 16 (the micro part is ignored)
+ * @param specificationVersion
+ * as system property
+ */
+ public static int getJavaSpecificationVersion(String specificationVersion) {
+ // major.minor.micro
+ // according to http://java.sun.com/j2se/1.5.0/docs/guide/versioning/spec/versioning2.html
+ String major = "1";
+ String minor = "0";
+ StringTokenizer tokenizer = new StringTokenizer(specificationVersion, ".");
+ if (tokenizer.hasMoreTokens()) {
+ major = tokenizer.nextToken();
+ }
+ if (tokenizer.hasMoreTokens()) {
+ minor = tokenizer.nextToken();
+ }
+ return Integer.valueOf(major.concat(minor)).intValue();
+ }
+
+ public static boolean isWindows() {
+ boolean isWindows = false;
+ String osName = System.getProperty(OS_NAME, "");
+ if (osName.toLowerCase().indexOf("windows") >= 0) {
+ isWindows = true;
+ }
+ return isWindows;
+ }
+
+ protected static boolean isMacintosh() {
+ boolean isMacintosh = false;
+ String osName = System.getProperty(OS_NAME, "");
+ if (osName.toLowerCase().indexOf("mac") >= 0) {
+ isMacintosh = true;
+ }
+ return isMacintosh;
+ }
+
+ protected static boolean isGNUJava() {
+ boolean isGNUJava = false;
+ String javaVmName = System.getProperty(JAVA_VM_NAME, "");
+ String lowerVmName = javaVmName.toLowerCase();
+ if (lowerVmName.indexOf("gnu") >= 0 && lowerVmName.indexOf("libgcj") >= 0) {
+ isGNUJava = true;
+ }
+ return isGNUJava;
+ }
+
+ protected static boolean isJDK141() {
+ boolean isJDK141 = false;
+ String javaVersion = System.getProperty(JavaVersionTester.JAVA_VERSION, "");
+ if (javaVersion.toLowerCase().startsWith("1.4.1")) {
+ isJDK141 = true;
+ }
+ return isJDK141;
+ }
+
+ /**
+ * Get the version info of an external (maybe other) jvm.
+ *
+ * @param javaHomeHandler
+ * The java home handler pointing to the java home of the external jvm.<br>
+ * The /bin directory is assumed to be a direct child directory.
+ *
+ * @return The versionInfo
+ */
+ protected static JavaVersionInfo getExternalJavaVersion(JavaHomeHandler javaHomeHandler) {
+ JavaVersionInfo versionInfo = new JavaVersionInfo();
+ if (javaHomeHandler.isValidHome()) {
+ try {
+ ConsoleInstaller.message(getText(TextKeys.C_CHECK_JAVA_VERSION));
+ // launch the java command - temporary file will be written by the child process
+ File tempFile = File.createTempFile("jython_installation", ".properties");
+ if (tempFile.exists() && tempFile.canWrite()) {
+ String command[] = new String[5];
+ command[0] = javaHomeHandler.getExecutableName();
+ command[1] = "-cp";
+ // our own class path should be ok here
+ command[2] = System.getProperty("java.class.path");
+ command[3] = JavaVersionTester.class.getName();
+ command[4] = tempFile.getAbsolutePath();
+ verboseOutput("executing: " + command[0] + " " + command[1] + " " + command[2]
+ + " " + command[3] + " " + command[4]);
+ ChildProcess childProcess = new ChildProcess(command, 10000); // 10 seconds
+ childProcess.setDebug(Installation.isVerbose());
+ int errorCode = childProcess.run();
+ if (errorCode != NORMAL_RETURN) {
+ versionInfo.setErrorCode(errorCode);
+ versionInfo.setReason(getText(TextKeys.C_NO_VALID_JAVA, javaHomeHandler.toString()));
+ } else {
+ Properties tempProperties = new Properties();
+ tempProperties.load(new FileInputStream(tempFile));
+ fillJavaVersionInfo(versionInfo, tempProperties);
+ }
+ } else {
+ versionInfo.setErrorCode(ERROR_RETURN);
+ versionInfo.setReason(getText(TextKeys.C_UNABLE_CREATE_TMPFILE, tempFile.getAbsolutePath()));
+ }
+ } catch (IOException e) {
+ versionInfo.setErrorCode(ERROR_RETURN);
+ versionInfo.setReason(getText(TextKeys.C_NO_VALID_JAVA, javaHomeHandler.toString()));
+ }
+ } else {
+ versionInfo.setErrorCode(ERROR_RETURN);
+ versionInfo.setReason(getText(TextKeys.C_NO_VALID_JAVA, javaHomeHandler.toString()));
+ }
+
+ return versionInfo;
+ }
+
+ /**
+ * @return The system default java version
+ */
+ public static JavaVersionInfo getDefaultJavaVersion() {
+ JavaVersionInfo versionInfo = new JavaVersionInfo();
+ String executableName = "java";
+ try {
+ // launch the java command - temporary file will be written by the child process
+ File tempFile = File.createTempFile("jython_installation", ".properties");
+ if (tempFile.exists() && tempFile.canWrite()) {
+ String command[] = new String[5];
+ command[0] = executableName;
+ command[1] = "-cp";
+ // our own class path should be ok here
+ command[2] = System.getProperty("java.class.path");
+ command[3] = JavaVersionTester.class.getName();
+ command[4] = tempFile.getAbsolutePath();
+ ChildProcess childProcess = new ChildProcess(command, 10000); // 10 seconds
+ childProcess.setDebug(false);
+ int errorCode = childProcess.run();
+ if (errorCode != NORMAL_RETURN) {
+ versionInfo.setErrorCode(errorCode);
+ versionInfo.setReason(getText(TextKeys.C_NO_VALID_JAVA, executableName));
+ } else {
+ Properties tempProperties = new Properties();
+ tempProperties.load(new FileInputStream(tempFile));
+ fillJavaVersionInfo(versionInfo, tempProperties);
+ }
+ } else {
+ versionInfo.setErrorCode(ERROR_RETURN);
+ versionInfo.setReason(getText(TextKeys.C_UNABLE_CREATE_TMPFILE,
+ tempFile.getAbsolutePath()));
+ }
+ } catch (IOException e) {
+ versionInfo.setErrorCode(ERROR_RETURN);
+ versionInfo.setReason(getText(TextKeys.C_NO_VALID_JAVA, executableName));
+ }
+ return versionInfo;
+ }
+
+ protected static void fillJavaVersionInfo(JavaVersionInfo versionInfo, Properties properties) {
+ versionInfo.setVersion(properties.getProperty(JavaVersionTester.JAVA_VERSION));
+ versionInfo.setSpecificationVersion(properties.getProperty(JavaVersionTester.JAVA_SPECIFICATION_VERSION));
+ versionInfo.setVendor(properties.getProperty(JavaVersionTester.JAVA_VENDOR));
+ }
+
+ public static class JavaVersionInfo {
+ private String _version;
+ private String _specificationVersion;
+ private String _vendor;
+ private int _errorCode;
+ private String _reason;
+
+ protected JavaVersionInfo() {
+ _version = EMPTY;
+ _specificationVersion = EMPTY;
+ _errorCode = NORMAL_RETURN;
+ _reason = EMPTY;
+ }
+
+ protected void setVersion(String version) {
+ _version = version;
+ }
+
+ protected void setSpecificationVersion(String specificationVersion) {
+ _specificationVersion = specificationVersion;
+ }
+
+ protected void setVendor(String vendor) {
+ _vendor = vendor;
+ }
+
+ protected void setErrorCode(int errorCode) {
+ _errorCode = errorCode;
+ }
+
+ protected void setReason(String reason) {
+ _reason = reason;
+ }
+
+ protected String getVersion() {
+ return _version;
+ }
+
+ public String getSpecificationVersion() {
+ return _specificationVersion;
+ }
+
+ protected String getVendor() {
+ return _vendor;
+ }
+
+ public int getErrorCode() {
+ return _errorCode;
+ }
+
+ protected String getReason() {
+ return _reason;
+ }
+ }
+
+ protected static class JavaFilenameFilter implements FilenameFilter {
+ public boolean accept(File dir, String name) {
+ if (name.toLowerCase().startsWith("java")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static boolean isGuiAllowed() {
+ verboseOutput("checking gui availability");
+ if (Boolean.getBoolean(HEADLESS_PROPERTY_NAME)) {
+ verboseOutput(HEADLESS_PROPERTY_NAME + " is true");
+ return false;
+ } else if (GraphicsEnvironment.isHeadless()) {
+ verboseOutput("GraphicsEnvironment is headless");
+ return false;
+ } else {
+ try {
+ verboseOutput("trying to get the GraphicsEnvironment");
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ verboseOutput("got the GraphicsEnvironment!");
+ return true;
+ } catch (Throwable t) {
+ verboseOutput("got the following exception:");
+ verboseOutput(t);
+ return false;
+ }
+ }
+ }
+
+ //
+ // private methods
+ //
+
+ private static boolean useGui(InstallerCommandLine commandLine) {
+ if (commandLine.hasConsoleOption() || commandLine.hasSilentOption()) {
+ return false;
+ }
+ return isGuiAllowed();
+ }
+
+ /**
+ * In the normal case, this method is called with <code>(args, null, null)</code>, see <code>main(args)</code>.
+ * <p>
+ * However, in autotesting mode (<code>commandLine.hasAutotestOption()</code>), we pass in Autotest and Tunnel,
+ * see <code>driverMain(args, autotest, tunnel)</code>.
+ * <p>
+ * This means that in autotesting mode this method will call itself (via <code>InstallationDriver.drive()</code>),
+ * but with different arguments.
+ */
+ private static void internalMain(String[] args, Autotest autotest, Tunnel tunnel) {
+ try {
+ setVerbose(InstallerCommandLine.hasVerboseOptionInArgs(args));
+ dumpSystemProperties();
+ verboseOutput("reading jar info");
+ JarInfo jarInfo = new JarInfo();
+ InstallerCommandLine commandLine = new InstallerCommandLine(jarInfo);
+ if (!commandLine.setArgs(args) || commandLine.hasHelpOption()) {
+ commandLine.printHelp();
+ System.exit(1);
+ } else {
+ if (commandLine.hasAutotestOption()) {
+ verboseOutput("running autotests");
+ _isAutotesting = true;
+ InstallationDriver autotestDriver = new InstallationDriver(commandLine);
+ autotestDriver.drive(); // ! reentrant into internalMain()
+ _isAutotesting = false;
+ ConsoleInstaller.message("\ncongratulations - autotests complete !");
+ System.exit(0);
+ }
+ if (!useGui(commandLine)) {
+ verboseOutput("using the console installer");
+ ConsoleInstaller consoleInstaller = new ConsoleInstaller(commandLine, jarInfo);
+ consoleInstaller.setTunnel(tunnel);
+ consoleInstaller.install();
+ if (!isAutotesting()) {
+ System.exit(0);
+ }
+ } else {
+ verboseOutput("using the gui installer");
+ new FrameInstaller(commandLine, jarInfo, autotest);
+ }
+ }
+ } catch (InstallationCancelledException ice) {
+ ConsoleInstaller.message((getText(TextKeys.INSTALLATION_CANCELLED)));
+ System.exit(1);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void dumpSystemProperties() throws IOException {
+ if (isVerbose()) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> names = (Enumeration<String>)System.getProperties().propertyNames();
+ StringBuilder contents = new StringBuilder(400);
+ contents.append("Properties at the beginning of the Jython installation:\n\n");
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ String value = System.getProperty(name, "");
+ contents.append(name);
+ contents.append('=');
+ contents.append(value);
+ contents.append("\n");
+ }
+ File output = File.createTempFile("System", ".properties");
+ FileHelper.write(output, contents.toString());
+ ConsoleInstaller.message("system properties dumped to " + output.getAbsolutePath());
+ }
+ }
+
+ private static void verboseOutput(String message) {
+ if (isVerbose()) {
+ ConsoleInstaller.message(message);
+ }
+ }
+
+ private static void verboseOutput(Throwable t) {
+ if (isVerbose()) {
+ t.printStackTrace();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/InstallationCancelledException.java b/installer/src/java/org/python/util/install/InstallationCancelledException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/InstallationCancelledException.java
@@ -0,0 +1,9 @@
+package org.python.util.install;
+
+public class InstallationCancelledException extends InstallerException {
+
+ public InstallationCancelledException() {
+ super();
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/InstallationListener.java b/installer/src/java/org/python/util/install/InstallationListener.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/InstallationListener.java
@@ -0,0 +1,7 @@
+package org.python.util.install;
+
+public interface InstallationListener {
+
+ public void progressFinished();
+
+}
diff --git a/installer/src/java/org/python/util/install/InstallationType.java b/installer/src/java/org/python/util/install/InstallationType.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/InstallationType.java
@@ -0,0 +1,120 @@
+package org.python.util.install;
+
+public class InstallationType {
+
+ private boolean _installLibraryModules = true;
+ private boolean _installDemosAndExamples = true;
+ private boolean _installDocumentation = true;
+ private boolean _installSources = false;
+ private boolean _isStandalone = false;
+
+ public boolean installLibraryModules() {
+ return _installLibraryModules;
+ }
+
+ public boolean installDemosAndExamples() {
+ return _installDemosAndExamples;
+ }
+
+ public boolean installDocumentation() {
+ return _installDocumentation;
+ }
+
+ public boolean installSources() {
+ return _installSources;
+ }
+
+ public void addLibraryModules() {
+ _installLibraryModules = true;
+ }
+
+ public void removeLibraryModules() {
+ _installLibraryModules = false;
+ }
+
+ public void addDemosAndExamples() {
+ _installDemosAndExamples = true;
+ }
+
+ public void removeDemosAndExamples() {
+ _installDemosAndExamples = false;
+ }
+
+ public void addDocumentation() {
+ _installDocumentation = true;
+ }
+
+ public void removeDocumentation() {
+ _installDocumentation = false;
+ }
+
+ public void addSources() {
+ _installSources = true;
+ }
+
+ public void removeSources() {
+ _installSources = false;
+ }
+
+ public void setStandalone() {
+ _isStandalone = true;
+ addLibraryModules();
+ removeDemosAndExamples();
+ removeDocumentation();
+ removeSources();
+ }
+
+ public boolean isStandalone() {
+ return _isStandalone;
+ }
+
+ public void setAll() {
+ addLibraryModules();
+ addDemosAndExamples();
+ addDocumentation();
+ addSources();
+ _isStandalone = false;
+ }
+
+ public boolean isAll() {
+ return installLibraryModules() && installDemosAndExamples() && installDocumentation() && installSources();
+ }
+
+ public void setStandard() {
+ addLibraryModules();
+ addDemosAndExamples();
+ addDocumentation();
+ removeSources();
+ _isStandalone = false;
+ }
+
+ public boolean isStandard() {
+ return installLibraryModules() && installDemosAndExamples() && installDocumentation() && !installSources();
+ }
+
+ public void setMinimum() {
+ removeLibraryModules();
+ removeDemosAndExamples();
+ removeDocumentation();
+ removeSources();
+ _isStandalone = false;
+ }
+
+ public boolean isMinimum() {
+ return !installLibraryModules() && !installDemosAndExamples() && !installDocumentation() && !installSources();
+ }
+
+ /**
+ * @return <code>true</code> if current settings reflect one of the predefined settings
+ */
+ public boolean isPredefined() {
+ return isAll() || isStandard() || isMinimum() || isStandalone();
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer(30);
+ buf.append("mod: " + installDemosAndExamples() + ", demo: " + installDemosAndExamples() + ", doc: "
+ + installDocumentation() + ", src: " + installSources());
+ return buf.toString();
+ }
+}
diff --git a/installer/src/java/org/python/util/install/InstallerCommandLine.java b/installer/src/java/org/python/util/install/InstallerCommandLine.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/InstallerCommandLine.java
@@ -0,0 +1,456 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.MissingArgumentException;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+import org.apache.commons.cli.PosixParser;
+
+public class InstallerCommandLine {
+ protected static final String INEXCLUDE_LIBRARY_MODULES = "mod";
+ protected static final String INEXCLUDE_DEMOS_AND_EXAMPLES = "demo";
+ protected static final String INEXCLUDE_DOCUMENTATION = "doc";
+ protected static final String INEXCLUDE_SOURCES = "src";
+
+ protected static final String CONSOLE_SHORT = "c";
+ protected static final String CONSOLE_LONG = "console";
+ private static final String CONSOLE_DESC = "console based installation (user interaction)\n"
+ + "any other options will be ignored (except 'verbose')";
+
+ protected static final String SILENT_SHORT = "s";
+ protected static final String SILENT_LONG = "silent";
+ private static final String SILENT_DESC = "silent installation (without user interaction)";
+
+ protected static final String VERBOSE_SHORT = "v";
+ protected static final String VERBOSE_LONG = "verbose";
+ private static final String VERBOSE_DESC = "print more output during the installation\n"
+ + "(also valid in GUI and autotest mode)";
+
+ private static final String JRE_SHORT = "j";
+ private static final String JRE_LONG = "jre";
+ private static final String JRE_DESC = "home directory of the runtime jre or jdk\n"
+ + "(executables are assumed in the /bin subdirectory)\n" + "select this if you want to run Jython with a\n"
+ + "different java version than the installation";
+
+ private static final String AUTOTEST_SHORT = "A";
+ private static final String AUTOTEST_LONG = "autotest";
+ private static final String AUTOTEST_DESC = "automatic stress tests for the installer\n"
+ + "most of the other options are ignored\n" + "allowed additional options: '" + VERBOSE_LONG + "', '"
+ + JRE_LONG + "'";
+
+ private static final String DIRECTORY_SHORT = "d";
+ private static final String DIRECTORY_LONG = "directory";
+ private static final String DIRECTORY_DESC = "target directory to install to\n"
+ + "(required in silent mode,\nused as default in GUI mode)";
+
+ private static final String DIRECTORY_ARG = "dir";
+
+ private static final String TYPE_STANDARD = "standard";
+ private static final String TYPE_ALL = "all";
+ private static final String TYPE_MINIMUM = "minimum";
+ protected static final String TYPE_STANDALONE = "standalone";
+ private static final String STANDALONE_DOCUMENTATION = "install a single, executable .jar,\ncontaining all the modules";
+
+ private static final String INEXCLUDE_ARG = "part(s)";
+ private static final String INEXCLUDE_PARTS = "more than one of the following is possible:\n" + "- "
+ + INEXCLUDE_LIBRARY_MODULES + ": library modules\n" + "- " + INEXCLUDE_DEMOS_AND_EXAMPLES
+ + ": demos and examples\n" + "- " + INEXCLUDE_DOCUMENTATION + ": documentation\n" + "- "
+ + INEXCLUDE_SOURCES + ": java source code";
+
+ private static final String TYPE_SHORT = "t";
+ private static final String TYPE_LONG = "type";
+ private static final String TYPE_ARG = TYPE_LONG;
+ private static final String TYPE_DESC = "installation type\n" + "one of the following types is possible\n"
+ + "(see also include/exclude parts):\n" + "- " + TYPE_ALL + ": everything (including " + INEXCLUDE_SOURCES
+ + ")\n" + "- " + TYPE_STANDARD + ": core, " + INEXCLUDE_LIBRARY_MODULES + ", "
+ + INEXCLUDE_DEMOS_AND_EXAMPLES + ", " + INEXCLUDE_DOCUMENTATION + ",\n"+ TYPE_STANDARD+ " is the default\n" + "- " + TYPE_MINIMUM + ": core\n"
+ + "- " + TYPE_STANDALONE + ": " + STANDALONE_DOCUMENTATION;
+
+ private static final String INCLUDE_SHORT = "i";
+ private static final String INCLUDE_LONG = "include";
+ private static final String INCLUDE_DESC = "finer control over parts to install\n" + INEXCLUDE_PARTS;
+
+ private static final String EXCLUDE_SHORT = "e";
+ private static final String EXCLUDE_LONG = "exclude";
+ private static final String EXCLUDE_DESC = "finer control over parts not to install\n" + INEXCLUDE_PARTS
+ + "\n(excludes override includes)";
+
+ private static final String HELP_SHORT = "h";
+ private static final String HELP2_SHORT = "?";
+ private static final String HELP_LONG = "help";
+ private static final String HELP_DESC = "print this help (overrides any other options)";
+
+ private static final String SYNTAX = "\n\tjava -jar jython_version.jar";
+ private static final String HEADER = "\nNo option at all will start the interactive GUI installer, except:\n"
+ + "Options respected in GUI mode are '" + DIRECTORY_LONG + "' and '" + JRE_LONG
+ + "', which serve as default values in the wizard.\n"
+ + "In non-GUI mode the following options are available:\n.";
+ private static final String SYNTAX_WITHOUT_JAR = "\n\tjava -jar ";
+ private static final String FOOTER = "";
+ private static final String EXAMPLES = "\nexample of a GUI installation:{0}"
+ + "\n\nexample of a console installation:{0} -" + CONSOLE_SHORT
+ + "\n\nexample of a silent installation:{0} -" + SILENT_SHORT + " -" + DIRECTORY_SHORT + " targetDirectory"
+ + "\n\nexamples of a silent installation with more options:{0} -" + SILENT_SHORT + " -" + DIRECTORY_SHORT
+ + " targetDirectory -" + TYPE_SHORT + " " + TYPE_MINIMUM + " -" + INCLUDE_SHORT + " " + INEXCLUDE_SOURCES
+ + " -" + JRE_SHORT + " javaHome" + "{0} -" + SILENT_SHORT + " -" + DIRECTORY_SHORT + " targetDirectory -"
+ + TYPE_SHORT + " " + TYPE_STANDARD + " -" + EXCLUDE_SHORT + " " + INEXCLUDE_DEMOS_AND_EXAMPLES + " "
+ + INEXCLUDE_DOCUMENTATION + "\n\t\t -" + INCLUDE_SHORT + " " + INEXCLUDE_SOURCES + " -" + JRE_SHORT
+ + " javaHome -" + VERBOSE_SHORT
+ + "\n\nexample of an autotest installation into temporary directories:{0} -" + AUTOTEST_SHORT
+ + "\n\t(make sure you do NOT touch mouse NOR keyboard after hitting enter/return!)"
+ + "\n\nexample of an autotest installation, using a different jre for the start scripts:{0} -"
+ + AUTOTEST_SHORT + " -" + JRE_SHORT + " javaHome" + " -" + VERBOSE_SHORT
+ + "\n\t(make sure you do NOT touch mouse NOR keyboard after hitting enter/return!)";
+
+ private String[] _args;
+ private Options _options;
+ private CommandLine _commandLine;
+ private JarInfo _jarInfo;
+ private final Parser _parser = new PosixParser();
+
+ public InstallerCommandLine(JarInfo jarInfo) {
+ createOptions();
+ _jarInfo = jarInfo;
+ }
+
+ /**
+ * Pre-scan of the arguments to detect a verbose flag
+ * @param args
+ * @return <code>true</code> if there is a verbose option
+ */
+ public static final boolean hasVerboseOptionInArgs(String[] args) {
+ String shortVerbose = "-".concat(VERBOSE_SHORT);
+ String longVerbose = "--".concat(VERBOSE_LONG);
+ return hasOptionInArgs(args, shortVerbose, longVerbose);
+ }
+
+ /**
+ * constructor intended for JUnit tests only.
+ */
+ public InstallerCommandLine() {
+ this(null);
+ }
+
+ /**
+ * Set the arguments from the command line.
+ *
+ * @param args the arguments of the command line
+ * @return <code>true</code> if all arguments are valid, <code>false</code> otherwise. No help is printed if
+ * <code>false</code> is returned
+ */
+ public boolean setArgs(String args[]) {
+ // pre-process args to determine if we can (and should) switch to console mode
+ try {
+ CommandLine preCommandLine = _parser.parse(_options, args, false);
+ if (!hasConsoleOption(preCommandLine) && !hasSilentOption(preCommandLine)
+ && !hasAutotestOption(preCommandLine)) {
+ if (!Installation.isGuiAllowed() || Installation.isGNUJava()) {
+ // auto switch to console mode
+ if (hasVerboseOption(preCommandLine)) {
+ ConsoleInstaller.message("auto-switching to console mode");
+ }
+ String[] newArgs = new String[args.length + 1];
+ System.arraycopy(args, 0, newArgs, 0, args.length);
+ newArgs[args.length] = "-" + CONSOLE_SHORT;
+ args = newArgs;
+ }
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ _args = args;
+ try {
+ // throws for missing or unknown options / arguments
+ _commandLine = _parser.parse(_options, _args, false);
+ } catch (MissingArgumentException mae) {
+ System.err.println(mae.getMessage());
+ return false;
+ } catch (ParseException pe) {
+ System.err.println(pe.getMessage());
+ return false;
+ }
+ List unrecognized = _commandLine.getArgList();
+ if (unrecognized.size() > 0) {
+ System.err.println("unrecognized argument(s): " + unrecognized);
+ return false;
+ }
+ if (hasTypeOption()) {
+ String type = _commandLine.getOptionValue(TYPE_SHORT);
+ if (TYPE_ALL.equals(type) || TYPE_STANDARD.equals(type) || TYPE_MINIMUM.equals(type)
+ || TYPE_STANDALONE.equals(type)) {
+ } else {
+ System.err.println("unrecognized argument '" + type + "' to option: " + TYPE_SHORT + " / " + TYPE_LONG);
+ return false;
+ }
+ }
+ if (hasSilentOption()) {
+ if (!hasDirectoryOption()) {
+ System.err.println("option " + DIRECTORY_SHORT + " / " + DIRECTORY_LONG + " is required in "
+ + SILENT_LONG + " mode");
+ return false;
+ }
+ }
+ if (hasIncludeOption()) {
+ String[] includeParts = _commandLine.getOptionValues(INCLUDE_SHORT);
+ for (int i = 0; i < includeParts.length; i++) {
+ if (!isValidInExcludePart(includeParts[i])) {
+ System.err.println("unrecognized include part '" + includeParts[i] + "'");
+ return false;
+ }
+ }
+ }
+ if (hasExcludeOption()) {
+ String[] excludeParts = _commandLine.getOptionValues(EXCLUDE_SHORT);
+ for (int i = 0; i < excludeParts.length; i++) {
+ if (!isValidInExcludePart(excludeParts[i])) {
+ System.err.println("unrecognized exclude part '" + excludeParts[i] + "'");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean hasArguments() {
+ return _args.length > 0;
+ }
+
+ public boolean hasHelpOption() {
+ return _commandLine.hasOption(HELP_SHORT) || _commandLine.hasOption(HELP2_SHORT)
+ || _commandLine.hasOption(HELP_LONG);
+ }
+
+ public boolean hasSilentOption() {
+ return hasSilentOption(_commandLine);
+ }
+
+ private boolean hasSilentOption(CommandLine commandLine) {
+ return commandLine.hasOption(SILENT_SHORT) || commandLine.hasOption(SILENT_LONG);
+ }
+
+ public boolean hasConsoleOption() {
+ return hasConsoleOption(_commandLine);
+ }
+
+ private boolean hasConsoleOption(CommandLine commandLine) {
+ return commandLine.hasOption(CONSOLE_SHORT) || commandLine.hasOption(CONSOLE_LONG);
+ }
+
+ public boolean hasAutotestOption() {
+ return hasAutotestOption(_commandLine);
+ }
+
+ private boolean hasAutotestOption(CommandLine commandLine) {
+ return commandLine.hasOption(AUTOTEST_SHORT) || commandLine.hasOption(AUTOTEST_LONG);
+ }
+
+ public boolean hasDirectoryOption() {
+ return _commandLine.hasOption(DIRECTORY_SHORT) || _commandLine.hasOption(DIRECTORY_LONG);
+ }
+
+ public boolean hasTypeOption() {
+ return _commandLine.hasOption(TYPE_SHORT) || _commandLine.hasOption(TYPE_LONG);
+ }
+
+ public boolean hasIncludeOption() {
+ return _commandLine.hasOption(INCLUDE_SHORT) || _commandLine.hasOption(INCLUDE_LONG);
+ }
+
+ public boolean hasExcludeOption() {
+ return _commandLine.hasOption(EXCLUDE_SHORT) || _commandLine.hasOption(EXCLUDE_LONG);
+ }
+
+ public boolean hasJavaHomeOption() {
+ return _commandLine.hasOption(JRE_SHORT) || _commandLine.hasOption(JRE_LONG);
+ }
+
+ public boolean hasVerboseOption() {
+ return hasVerboseOption(_commandLine);
+ }
+
+ private boolean hasVerboseOption(CommandLine commandLine) {
+ return commandLine.hasOption(VERBOSE_SHORT) || commandLine.hasOption(VERBOSE_LONG);
+ }
+
+ public void printHelp() {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.defaultWidth = 76;
+ String syntax = SYNTAX;
+ if (_jarInfo != null) {
+ try {
+ syntax = SYNTAX_WITHOUT_JAR + _jarInfo.getJarFile().getName();
+ } catch (IOException ioe) {
+ }
+ }
+ formatter.printHelp(syntax, HEADER, _options, FOOTER, true);
+ String examples = MessageFormat.format(EXAMPLES, syntax);
+ System.out.println(examples);
+ }
+
+ /**
+ * @return the requested target directory, <code>null</code> if no directory specified
+ */
+ public File getTargetDirectory() {
+ if (hasDirectoryOption()) {
+ return new File(_commandLine.getOptionValue(DIRECTORY_SHORT));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @return a java home handler for the requested java home directory, or a default handler if no
+ * java home specified
+ */
+ public JavaHomeHandler getJavaHomeHandler() {
+ if (hasJavaHomeOption()) {
+ return new JavaHomeHandler(_commandLine.getOptionValue(JRE_SHORT));
+ } else {
+ return new JavaHomeHandler();
+ }
+ }
+
+ /**
+ * The Installation type is built out of the type, include and exclude option
+ *
+ * @return the installation type usable for the jar installer
+ */
+ public InstallationType getInstallationType() {
+ InstallationType installationType = new InstallationType(); // defaults to standard
+ // build a priori values out of the type option
+ if (hasTypeOption()) {
+ String typeName = _commandLine.getOptionValue(TYPE_SHORT);
+ if (TYPE_ALL.equals(typeName)) {
+ installationType.setAll();
+ } else if (TYPE_MINIMUM.equals(typeName)) {
+ installationType.setMinimum();
+ } else if (TYPE_STANDALONE.equals(typeName)) {
+ installationType.setStandalone();
+ }
+ }
+ // add parts to include
+ if (hasIncludeOption()) {
+ String[] includeParts = _commandLine.getOptionValues(INCLUDE_SHORT);
+ for (int i = 0; i < includeParts.length; i++) {
+ if (INEXCLUDE_DEMOS_AND_EXAMPLES.equals(includeParts[i])) {
+ installationType.addDemosAndExamples();
+ }
+ if (INEXCLUDE_DOCUMENTATION.equals(includeParts[i])) {
+ installationType.addDocumentation();
+ }
+ if (INEXCLUDE_LIBRARY_MODULES.equals(includeParts[i])) {
+ installationType.addLibraryModules();
+ }
+ if (INEXCLUDE_SOURCES.equals(includeParts[i])) {
+ installationType.addSources();
+ }
+ }
+ }
+ // remove parts to exclude
+ if (hasExcludeOption()) {
+ String[] excludeParts = _commandLine.getOptionValues(EXCLUDE_SHORT);
+ for (int i = 0; i < excludeParts.length; i++) {
+ if (INEXCLUDE_DEMOS_AND_EXAMPLES.equals(excludeParts[i])) {
+ installationType.removeDemosAndExamples();
+ }
+ if (INEXCLUDE_DOCUMENTATION.equals(excludeParts[i])) {
+ installationType.removeDocumentation();
+ }
+ if (INEXCLUDE_LIBRARY_MODULES.equals(excludeParts[i])) {
+ installationType.removeLibraryModules();
+ }
+ if (INEXCLUDE_SOURCES.equals(excludeParts[i])) {
+ installationType.removeSources();
+ }
+ }
+ }
+ return installationType;
+ }
+
+ //
+ // private methods
+ //
+
+ private static final boolean hasOptionInArgs(String[] args, String shortOption, String longOption) {
+ boolean hasOption = false;
+ int i = 0;
+ while (!hasOption && i < args.length) {
+ if (shortOption.equals(args[i]) || longOption.equals(args[i])) {
+ hasOption = true;
+ }
+ i++;
+ }
+ return hasOption;
+ }
+
+ private void createOptions() {
+ _options = new Options();
+ _options.setSortAsAdded(true);
+
+ // console or silent mode
+ Option consoleOption = new Option(CONSOLE_SHORT, CONSOLE_LONG, false, CONSOLE_DESC);
+ Option silentOption = new Option(SILENT_SHORT, SILENT_LONG, false, SILENT_DESC);
+ Option autotestOption = new Option(AUTOTEST_SHORT, AUTOTEST_LONG, false, AUTOTEST_DESC);
+ OptionGroup group1 = new OptionGroup();
+ group1.addOption(consoleOption);
+ group1.addOption(silentOption);
+ group1.addOption(autotestOption);
+ _options.addOptionGroup(group1);
+
+ // target directory
+ Option directoryOption = new Option(DIRECTORY_SHORT, DIRECTORY_LONG, true, DIRECTORY_DESC);
+ directoryOption.setArgName(DIRECTORY_ARG);
+ _options.addOption(directoryOption);
+
+ // installation type
+ Option typeOption = new Option(TYPE_SHORT, TYPE_LONG, true, TYPE_DESC);
+ typeOption.setArgName(TYPE_ARG);
+ _options.addOption(typeOption);
+
+ // additional parts to include
+ Option includeOption = new Option(INCLUDE_SHORT, INCLUDE_DESC);
+ includeOption.setArgs(4);
+ includeOption.setArgName(INEXCLUDE_ARG);
+ includeOption.setLongOpt(INCLUDE_LONG);
+ _options.addOption(includeOption);
+
+ // parts to exclude
+ Option excludeOption = new Option(EXCLUDE_SHORT, EXCLUDE_DESC);
+ excludeOption.setArgs(4);
+ excludeOption.setArgName(INEXCLUDE_ARG);
+ excludeOption.setLongOpt(EXCLUDE_LONG);
+ _options.addOption(excludeOption);
+
+ // runtime jre
+ Option jreOption = new Option(JRE_SHORT, JRE_LONG, true, JRE_DESC);
+ jreOption.setArgName(DIRECTORY_ARG);
+ _options.addOption(jreOption);
+
+ // verbose
+ Option verboseOption = new Option(VERBOSE_SHORT, VERBOSE_LONG, false, VERBOSE_DESC);
+ _options.addOption(verboseOption);
+
+ // different help options
+ Option helpHOption = new Option(HELP_SHORT, HELP_LONG, false, HELP_DESC);
+ Option helpQOption = new Option(HELP2_SHORT, HELP_DESC);
+ OptionGroup group2 = new OptionGroup();
+ group2.addOption(helpHOption);
+ group2.addOption(helpQOption);
+ _options.addOptionGroup(group2);
+ }
+
+ private boolean isValidInExcludePart(String part) {
+ return INEXCLUDE_DEMOS_AND_EXAMPLES.equals(part) || INEXCLUDE_DOCUMENTATION.equals(part)
+ || INEXCLUDE_LIBRARY_MODULES.equals(part) || INEXCLUDE_SOURCES.equals(part);
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/InstallerException.java b/installer/src/java/org/python/util/install/InstallerException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/InstallerException.java
@@ -0,0 +1,21 @@
+package org.python.util.install;
+
+public class InstallerException extends RuntimeException {
+
+ public InstallerException() {
+ super();
+ }
+
+ public InstallerException(String message) {
+ super(message);
+ }
+
+ public InstallerException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InstallerException(Throwable cause) {
+ super(cause);
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/JarInfo.java b/installer/src/java/org/python/util/install/JarInfo.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/JarInfo.java
@@ -0,0 +1,235 @@
+package org.python.util.install;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+public class JarInfo {
+ private static final String JAR_URL_PREFIX = "jar:file:";
+ private static final String JAR_SEPARATOR = "!";
+ private static final String JYTHON = "Jython";
+ private static final String VERSION_ATTRIBUTE = "version";
+ private static final String EXCLUDE_DIRS_ATTRIBUTE = "exclude-dirs";
+ private static final String EXCLUDE_DIRS_DELIM = ";";
+
+ private File _jarFile;
+ private int _numberOfEntries;
+ private Manifest _manifest;
+ private String _licenseText;
+ private String _readmeText;
+
+ public JarInfo() {
+ _jarFile = null;
+ _numberOfEntries = 0;
+ _manifest = null;
+
+ try {
+ readJarInfo();
+ } catch (IOException ioe) {
+ throw new InstallerException(Installation.getText(TextKeys.ERROR_ACCESS_JARFILE), ioe);
+ }
+ }
+
+ public String getVersion() {
+ String version = "<unknown>";
+ try {
+ Attributes jythonAttributes = getManifest().getAttributes(JYTHON);
+ if (jythonAttributes != null) {
+ version = jythonAttributes.getValue(VERSION_ATTRIBUTE); // do
+ // not
+ // use
+ // containsKey
+ }
+ } catch (IOException ioe) {
+ }
+ return version;
+ }
+
+ public File getJarFile() throws IOException {
+ if (_jarFile == null)
+ readJarInfo();
+ return _jarFile;
+ }
+
+ public Manifest getManifest() throws IOException {
+ if (_manifest == null)
+ readJarInfo();
+ return _manifest;
+ }
+
+ public int getNumberOfEntries() throws IOException {
+ if (_numberOfEntries == 0)
+ readJarInfo();
+ return _numberOfEntries;
+ }
+
+ public List<String> getExcludeDirs() throws IOException {
+ List<String> excludeDirs = new ArrayList<String>();
+ Attributes jythonAttributes = getManifest().getAttributes(JYTHON);
+ if (jythonAttributes != null) {
+ // do not use containsKey
+ String excludeDirsString = jythonAttributes.getValue(EXCLUDE_DIRS_ATTRIBUTE);
+ if (excludeDirsString != null && excludeDirsString.length() > 0) {
+ StringTokenizer tokenizer = new StringTokenizer(excludeDirsString, EXCLUDE_DIRS_DELIM);
+ while (tokenizer.hasMoreTokens()) {
+ excludeDirs.add(tokenizer.nextToken());
+ }
+ }
+ }
+ return excludeDirs;
+ }
+
+ public String getLicenseText() throws IOException {
+ if (_licenseText == null) {
+ readJarInfo();
+ }
+ return _licenseText;
+ }
+
+ public String getReadmeText() throws IOException {
+ if (_readmeText == null) {
+ readJarInfo();
+ }
+ return _readmeText;
+ }
+
+ private void readJarInfo() throws IOException {
+ String fullClassName = getClass().getName();
+ String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
+ URL url = getClass().getResource(className + ".class");
+ // we expect an URL like:
+ // jar:file:/C:/stuff/jython21i.jar!/org/python/util/install/JarInfo.class
+ // escape plus signs, since the URLDecoder would turn them into spaces
+ final String plus = "\\+";
+ final String escapedPlus = "__ppluss__";
+ String rawUrl = url.toString();
+ rawUrl = rawUrl.replaceAll(plus, escapedPlus);
+ String urlString = URLDecoder.decode(rawUrl, "UTF-8");
+ urlString = urlString.replaceAll(escapedPlus, plus);
+ int jarSeparatorIndex = urlString.lastIndexOf(JAR_SEPARATOR);
+ if (!urlString.startsWith(JAR_URL_PREFIX) || jarSeparatorIndex <= 0) {
+ throw new InstallerException(Installation.getText(TextKeys.UNEXPECTED_URL, urlString));
+ }
+ String jarFileName = urlString.substring(JAR_URL_PREFIX.length(), jarSeparatorIndex);
+ _jarFile = new File(jarFileName);
+ if (!_jarFile.exists()) {
+ throw new InstallerException(Installation.getText(TextKeys.JAR_NOT_FOUND, _jarFile.getAbsolutePath()));
+ }
+ JarFile jarFile = new JarFile(_jarFile);
+ Enumeration<JarEntry> entries = jarFile.entries();
+ _numberOfEntries = 0;
+ while (entries.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entries.nextElement();
+ if ("LICENSE.txt".equals(entry.getName())) {
+ _licenseText = readTextFile(entry, jarFile);
+ }
+ if ("README.txt".equals(entry.getName())) {
+ _readmeText = readTextFile(entry, jarFile);
+ }
+ _numberOfEntries++;
+ }
+ _manifest = jarFile.getManifest();
+ if (_manifest == null) {
+ throw new InstallerException(Installation.getText(TextKeys.NO_MANIFEST, _jarFile.getAbsolutePath()));
+ }
+ jarFile.close();
+ }
+
+ /**
+ * Read the text file with the most appropriate Charset.
+ *
+ * @param entry
+ * @param jarFile
+ *
+ * @return the contents of the text file
+ *
+ * @throws IOException
+ */
+ private String readTextFile(JarEntry entry, JarFile jarFile) throws IOException {
+ String contents = readTextFileWithCharset(jarFile, entry, "US-ASCII"); // expected to run on most platforms
+ if (contents == null) {
+ contents = readTextFileWithCharset(jarFile, entry, "ISO-8859-1");
+ }
+ if (contents == null) {
+ contents = readTextFileWithDefaultCharset(jarFile, entry);
+ }
+ return contents;
+ }
+
+ /**
+ * Try to read the text file (jarEntry) from the jarFile, using a given <code>charsetName</code>.
+ *
+ * @param jarFile
+ * @param entry
+ * @param charsetName the name of the Charset
+ *
+ * @return the contents of the text file as String (if reading was successful), <code>null</code> otherwise.<br>
+ * No exception is thrown
+ */
+ private String readTextFileWithCharset(JarFile jarFile, JarEntry entry, String charsetName) {
+ String contents = null;
+ if (Charset.isSupported(charsetName)) {
+ BufferedReader reader = null;
+ try {
+ StringBuffer buffer = new StringBuffer(1000);
+ reader = new BufferedReader(new InputStreamReader(jarFile.getInputStream(entry), Charset
+ .forName(charsetName)));
+ buffer = new StringBuffer(1000);
+ for (String s; (s = reader.readLine()) != null;) {
+ buffer.append(s);
+ buffer.append("\n");
+ }
+ contents = buffer.toString();
+ } catch (IOException ioe) {
+ } finally {
+ if (reader != null)
+ try {
+ reader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return contents;
+ }
+
+ /**
+ * Read the text file (jarEntry) from the jarFile, using the platform default Charset.
+ *
+ * @param jarFile
+ * @param entry
+ *
+ * @return the contents of the text file as String.
+ *
+ * @throws IOException if a problem occurs
+ */
+ private String readTextFileWithDefaultCharset(JarFile jarFile, JarEntry entry) throws IOException {
+ String contents = null;
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(jarFile.getInputStream(entry)));
+ StringBuffer buffer = new StringBuffer(1000);
+ for (String s; (s = reader.readLine()) != null;) {
+ buffer.append(s);
+ buffer.append("\n");
+ }
+ contents = buffer.toString();
+ } finally {
+ if (reader != null)
+ reader.close();
+ }
+ return contents;
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/JarInstaller.java b/installer/src/java/org/python/util/install/JarInstaller.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/JarInstaller.java
@@ -0,0 +1,283 @@
+package org.python.util.install;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * Working horse extracting the contents of the installation .jar to the file system. <br>
+ * The directory stucture is preserved, but there is the possibility to exclude some entries
+ * (directories at the moment).
+ */
+public class JarInstaller {
+
+ public static final String JYTHON_JAR = "jython.jar";
+
+ private static final String PATH_SEPARATOR = "/";
+
+ private static final String LIB_NAME_SEP = "Lib" + PATH_SEPARATOR;
+
+ private static final String LIB_PAWT_SEP = LIB_NAME_SEP + "pawt" + PATH_SEPARATOR;
+
+ private static final int BUFFER_SIZE = 1024;
+
+ private ProgressListener _progressListener;
+
+ private JarInfo _jarInfo;
+
+ private List<InstallationListener> _installationListeners;
+
+ public JarInstaller(ProgressListener progressListener, JarInfo jarInfo) {
+ _progressListener = progressListener;
+ _jarInfo = jarInfo;
+ _installationListeners = new ArrayList<InstallationListener>();
+ }
+
+ /**
+ * Do the pysical installation:
+ * <ul>
+ * <li>unzip the files
+ * <li>generate the start scripts
+ * </ul>
+ *
+ * @param targetDirectory
+ * @param installationType
+ */
+ public void inflate(final File targetDirectory, InstallationType installationType, JavaHomeHandler javaHomeHandler) {
+ try {
+ // has to correspond with build.xml
+ // has to correspond with build.Lib.include.properties
+ List<String> excludeDirs = _jarInfo.getExcludeDirs();
+ List<String> coreLibFiles = new ArrayList<String>();
+ if (!installationType.installSources()) {
+ excludeDirs.add("src");
+ excludeDirs.add("grammar");
+ excludeDirs.add("extlibs");
+ }
+ if (!installationType.installDocumentation()) {
+ excludeDirs.add("Doc");
+ }
+ if (!installationType.installDemosAndExamples()) {
+ excludeDirs.add("Demo");
+ }
+ if (!installationType.installLibraryModules()) {
+ excludeDirs.add(LIB_NAME_SEP + "email");
+ excludeDirs.add(LIB_NAME_SEP + "encodings");
+ excludeDirs.add(LIB_NAME_SEP + "test");
+ excludeDirs.add(LIB_NAME_SEP + "jxxload_help");
+ coreLibFiles = getCoreLibFiles();
+ }
+ if (installationType.isStandalone()) {
+ excludeDirs.add("Tools");
+ excludeDirs.add(LIB_NAME_SEP + "email/test");
+ excludeDirs.add(LIB_NAME_SEP + "test");
+ }
+ int count = 0;
+ int percent = 0;
+ int numberOfIntervals = 100 / _progressListener.getInterval();
+ int numberOfEntries = approximateNumberOfEntries(installationType);
+ int threshold = numberOfEntries / numberOfIntervals + 1; // +1 = pessimistic
+ boolean coreExclusionReported = false;
+ // unzip
+ ZipInputStream zipInput = new ZipInputStream(new BufferedInputStream(new FileInputStream(_jarInfo.getJarFile()),
+ BUFFER_SIZE));
+ ZipEntry zipEntry = zipInput.getNextEntry();
+ while (zipEntry != null) {
+ String zipEntryName = zipEntry.getName();
+ boolean exclude = false;
+ // handle exclusion of directories
+ Iterator<String> excludeDirsAsIterator = excludeDirs.iterator();
+ while (excludeDirsAsIterator.hasNext()) {
+ if (zipEntryName.startsWith(excludeDirsAsIterator.next()
+ + PATH_SEPARATOR)) {
+ exclude = true;
+ }
+ }
+ // exclude build.xml when not installing source
+ if (!installationType.installSources() && zipEntryName.equals("build.xml"))
+ exclude = true;
+ // handle exclusion of core Lib files
+ if (!exclude) {
+ exclude = shouldExcludeFile(installationType,
+ coreLibFiles,
+ zipEntry,
+ zipEntryName);
+ if (Installation.isVerbose() && !coreExclusionReported && exclude) {
+ ConsoleInstaller.message("excluding some .py files, like " + zipEntryName);
+ coreExclusionReported = true;
+ }
+ }
+ if (exclude) {
+ if (Installation.isVerbose() && zipEntry.isDirectory()) {
+ ConsoleInstaller.message("excluding directory " + zipEntryName);
+ }
+ } else {
+ count++;
+ if (count % threshold == 0) {
+ percent = percent + _progressListener.getInterval();
+ _progressListener.progressChanged(percent);
+ }
+ createDirectories(targetDirectory, zipEntryName);
+ if (!zipEntry.isDirectory()) {
+ File file = createFile(targetDirectory, zipEntryName);
+ _progressListener.progressEntry(file.getAbsolutePath());
+ FileOutputStream output = new FileOutputStream(file);
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int len;
+ while ((len = zipInput.read(buffer)) > 0) {
+ output.write(buffer, 0, len);
+ }
+ output.close();
+ file.setLastModified(zipEntry.getTime());
+ }
+ }
+ zipInput.closeEntry();
+ zipEntry = zipInput.getNextEntry();
+ }
+ if (!installationType.isStandalone()) {
+ // generate start scripts
+ _progressListener.progressStartScripts();
+ StartScriptGenerator generator = new StartScriptGenerator(targetDirectory, javaHomeHandler);
+ generator.generateStartScripts();
+ } else {
+ _progressListener.progressStandalone();
+ File jythonJar = new File(targetDirectory, JYTHON_JAR);
+ File jythonPlainJar = new File(targetDirectory, "plain_" + JYTHON_JAR);
+ jythonJar.renameTo(jythonPlainJar);
+ File libDir = new File(targetDirectory, "Lib");
+ StandalonePackager packager = new StandalonePackager(jythonJar);
+ packager.addJarFile(jythonPlainJar);
+ _progressListener.progressChanged(90); // approx
+ packager.addFullDirectory(libDir);
+ packager.close();
+ // TODO:Oti move to FileHelper
+ StandalonePackager.emptyDirectory(targetDirectory, jythonJar);
+ }
+ // finish: inform listeners
+ _progressListener.progressFinished();
+ Iterator<InstallationListener> installationListenersIterator = _installationListeners.iterator();
+ while (installationListenersIterator.hasNext()) {
+ installationListenersIterator.next().progressFinished();
+ }
+ } catch (IOException ioe) {
+ throw new InstallerException(Installation.getText(TextKeys.ERROR_ACCESS_JARFILE), ioe);
+ }
+ }
+
+ public void addInstallationListener(InstallationListener installationListener) {
+ if (installationListener != null) {
+ _installationListeners.add(installationListener);
+ }
+ }
+
+ private int approximateNumberOfEntries(InstallationType installationType) {
+ int numberOfEntries = 200; // core (minimum)
+ if (installationType.installLibraryModules()) {
+ if (installationType.isStandalone()) {
+ numberOfEntries += 450;
+ } else {
+ numberOfEntries += 1300;
+ }
+ }
+ if (installationType.installDemosAndExamples()) {
+ numberOfEntries += 70;
+ }
+ if (installationType.installDocumentation()) {
+ numberOfEntries += 500;
+ }
+ if (installationType.installSources()) {
+ numberOfEntries += 1000;
+ }
+ return numberOfEntries;
+ }
+
+ private void createDirectories(final File targetDirectory, final String zipEntryName) {
+ int lastSepIndex = zipEntryName.lastIndexOf(PATH_SEPARATOR);
+ if (lastSepIndex > 0) {
+ File directory = new File(targetDirectory, zipEntryName.substring(0, lastSepIndex));
+ if (directory.exists() && directory.isDirectory()) {} else {
+ if (!directory.mkdirs()) {
+ throw new InstallerException(Installation.getText(TextKeys.UNABLE_CREATE_DIRECTORY,
+ directory.getAbsolutePath()));
+ }
+ }
+ }
+ }
+
+ private File createFile(final File targetDirectory, final String zipEntryName)
+ throws IOException {
+ File file = new File(targetDirectory, zipEntryName);
+ if (file.exists() && file.isFile()) {} else {
+ if (!file.createNewFile()) {
+ throw new InstallerException(Installation.getText(TextKeys.UNABLE_CREATE_FILE,
+ file.getCanonicalPath()));
+ }
+ }
+ return file;
+ }
+
+ private List<String> getCoreLibFiles() {
+ List<String> coreLibFiles = new ArrayList<String>();
+ coreLibFiles.add("__future__.py");
+ coreLibFiles.add("copy.py");
+ coreLibFiles.add("dbexts.py");
+ coreLibFiles.add("imaplib.py");
+ coreLibFiles.add("isql.py");
+ coreLibFiles.add("javaos.py");
+ coreLibFiles.add("javapath.py");
+ coreLibFiles.add("jreload.py");
+ coreLibFiles.add("marshal.py");
+ coreLibFiles.add("ntpath.py");
+ coreLibFiles.add("os.py");
+ coreLibFiles.add("popen2.py");
+ coreLibFiles.add("posixpath.py");
+ coreLibFiles.add("random.py");
+ coreLibFiles.add("re.py");
+ coreLibFiles.add("site.py");
+ coreLibFiles.add("socket.py");
+ coreLibFiles.add("sre.py");
+ coreLibFiles.add("sre_compile.py");
+ coreLibFiles.add("sre_constants.py");
+ coreLibFiles.add("sre_parse.py");
+ coreLibFiles.add("stat.py");
+ coreLibFiles.add("string.py");
+ coreLibFiles.add("threading.py");
+ coreLibFiles.add("UserDict.py");
+ coreLibFiles.add("zipfile.py");
+ coreLibFiles.add("zlib.py");
+ return coreLibFiles;
+ }
+
+ private boolean shouldExcludeFile(InstallationType installationType,
+ List<String> coreLibFiles,
+ ZipEntry zipEntry,
+ String zipEntryName) {
+ boolean exclude = false;
+ if (!installationType.installLibraryModules()) {
+ // handle files in Lib
+ if (!zipEntry.isDirectory() && zipEntryName.startsWith(LIB_NAME_SEP)) {
+ // include all files in /pawt subdirectory
+ if (!zipEntryName.startsWith(LIB_PAWT_SEP)) {
+ if (zipEntryName.endsWith(".py")) { // only compare *.py files
+ exclude = true;
+ Iterator<String> coreLibFilesAsIterator = coreLibFiles.iterator();
+ while (coreLibFilesAsIterator.hasNext()) {
+ String coreFileName = coreLibFilesAsIterator.next();
+ if (zipEntryName.endsWith(PATH_SEPARATOR + coreFileName)) {
+ exclude = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ return exclude;
+ }
+}
diff --git a/installer/src/java/org/python/util/install/JavaHomeHandler.java b/installer/src/java/org/python/util/install/JavaHomeHandler.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/JavaHomeHandler.java
@@ -0,0 +1,209 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unified entry point for treatment of java.home
+ * <p>
+ * Note that the system property <code>java.home</code> is never changed
+ */
+public final class JavaHomeHandler {
+
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String JAVA = "java";
+
+ private static final String JAVA_EXE = "java.exe";
+
+ private static final String BIN = "bin";
+
+ private static final String DEFAULT = "_default_";
+
+ private static final String EMPTY = "";
+
+ /**
+ * A map for java home strings and their respective executable names
+ */
+ private static Map<String, String> _executableNames;
+
+ /**
+ * The current java home
+ */
+ private String _currentJavaHome;
+
+ /**
+ * create a java home handler for the default java home
+ */
+ public JavaHomeHandler() {
+ this(DEFAULT);
+ }
+
+ /**
+ * create a java home handler for a java home deviation
+ *
+ * @param currentJavaHome
+ * The deviated java home
+ */
+ public JavaHomeHandler(String currentJavaHome) {
+ setCurrentJavaHome(currentJavaHome);
+ check(getCurrentJavaHome());
+ }
+
+ /**
+ * get the name of the java executable
+ *
+ * @return A name of a java executable which can be passed to {@link ChildProcess}
+ */
+ public String getExecutableName() {
+ return getExecutableName(getCurrentJavaHome());
+ }
+
+ /**
+ * tell the validity of the current java home
+ * <p>
+ * Note: if the current java home is not valid, {@link JavaHomeHandler#getExecutableName()}
+ * still returns the name of a callable java
+ *
+ * @return <code>true</code> if we have a valid java home, <code>false</code> otherwise.
+ */
+ public boolean isValidHome() {
+ return !getFallbackExecutableName().equals(getExecutableName());
+ }
+
+ /**
+ * get the current java home, if it is valid
+ *
+ * @return The current java home
+ * @throws InstallerException
+ * if there is no valid java home
+ *
+ * @see JavaHomeHandler#isValidHome()
+ */
+ public File getHome() throws InstallerException {
+ if (!isValidHome()) {
+ throw new InstallerException("no valid java home");
+ } else {
+ return new File(getCurrentJavaHome());
+ }
+ }
+
+ /**
+ * @return <code>true</code> if the current java home is a deviation, <code>false</code>
+ * otherwise
+ */
+ public boolean isDeviation() {
+ // make sure the default java home is also known
+ if (!getExecutableNames().containsKey(DEFAULT)) {
+ check(DEFAULT);
+ }
+ return !getExecutableName(DEFAULT).equals(getExecutableName(getCurrentJavaHome()));
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder(80);
+ builder.append("[");
+ if(!isValidHome()) {
+ builder.append("in");
+ }
+ builder.append("valid java home: ");
+ builder.append(getCurrentJavaHome());
+ builder.append("; executable: ");
+ builder.append(getExecutableName());
+ builder.append("]");
+ return builder.toString();
+ }
+
+ /**
+ * reset the handler (clear all stored java homes)
+ */
+ static void reset() {
+ getExecutableNames().clear();
+ }
+
+ private String getExecutableName(String javaHome) {
+ Map<String, String> executableNames = getExecutableNames();
+ if (!executableNames.containsKey(javaHome)) {
+ check(javaHome);
+ }
+ return executableNames.get(javaHome);
+ }
+
+ private void check(String javaHome) {
+ boolean valid = false;
+ boolean isDefault = false;
+ File javaExecutableFile = null;
+ if (DEFAULT.equals(javaHome)) {
+ isDefault = true;
+ javaHome = System.getProperty(JAVA_HOME, EMPTY);
+ }
+ if (javaHome.length() > 0) {
+ File javaHomeDir = new File(javaHome);
+ if (javaHomeDir.exists() && javaHomeDir.isDirectory()) {
+ File binDir = new File(javaHomeDir, BIN);
+ if (binDir.exists() && binDir.isDirectory()) {
+ javaExecutableFile = getExecutableFile(binDir);
+ if (javaExecutableFile.exists()) {
+ valid = true;
+ }
+ }
+ }
+ }
+ if (valid) {
+ addExecutable(javaHome, javaExecutableFile);
+ if (isDefault) {
+ addExecutable(DEFAULT, javaExecutableFile);
+ if (DEFAULT.equals(getCurrentJavaHome())) {
+ // update the current home to the real one
+ setCurrentJavaHome(javaHome);
+ }
+ }
+ } else {
+ addFallbackExecutable(javaHome);
+ if (isDefault) {
+ addFallbackExecutable(DEFAULT);
+ }
+ }
+ }
+
+ private String getFallbackExecutableName() {
+ return JAVA;
+ }
+
+ private void addFallbackExecutable(String javaHome) {
+ getExecutableNames().put(javaHome, getFallbackExecutableName());
+ }
+
+ private void addExecutable(String javaHome, File javaExecutableFile) {
+ getExecutableNames().put(javaHome, javaExecutableFile.getAbsolutePath());
+ }
+
+ private File getExecutableFile(File binDir) {
+ if (Installation.isWindows()) {
+ return new File(binDir, JAVA_EXE);
+ } else {
+ return new File(binDir, JAVA);
+ }
+ }
+
+ private static Map<String, String> getExecutableNames() {
+ if (_executableNames == null) {
+ _executableNames = new HashMap<String, String>();
+ }
+ return _executableNames;
+ }
+
+ private String getCurrentJavaHome() {
+ if (_currentJavaHome == null) {
+ return DEFAULT;
+ } else {
+ return _currentJavaHome;
+ }
+ }
+
+ private void setCurrentJavaHome(String currentJavaHome) {
+ _currentJavaHome = currentJavaHome.trim();
+ }
+}
diff --git a/installer/src/java/org/python/util/install/JavaSelectionPage.java b/installer/src/java/org/python/util/install/JavaSelectionPage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/JavaSelectionPage.java
@@ -0,0 +1,199 @@
+package org.python.util.install;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.File;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+public class JavaSelectionPage extends AbstractWizardPage {
+
+ private static final long serialVersionUID = 2871052924519223110L;
+
+ private final static String _CURRENT_ACTION_COMMAND = "current";
+ private final static String _OTHER_ACTION_COMMAND = "other";
+
+ private JRadioButton _currentButton;
+ private JRadioButton _otherButton;
+
+ private JLabel _label;
+ private JTextField _javaHome;
+ private JButton _browse;
+
+ public JavaSelectionPage() {
+ super();
+ initComponents();
+ }
+
+ private void initComponents() {
+ // label for java home
+ _label = new JLabel();
+
+ // radio buttons
+ RadioButtonListener radioButtonListener = new RadioButtonListener();
+ _currentButton = new JRadioButton();
+ _currentButton.setActionCommand(_CURRENT_ACTION_COMMAND);
+ _currentButton.addActionListener(radioButtonListener);
+ _otherButton = new JRadioButton();
+ _otherButton.setActionCommand(_OTHER_ACTION_COMMAND);
+ _otherButton.addActionListener(radioButtonListener);
+ ButtonGroup radioButtonGroup = new ButtonGroup();
+ radioButtonGroup.add(_currentButton);
+ radioButtonGroup.add(_otherButton);
+ JPanel radioPanel = new JPanel(new GridLayout(0, 1));
+ radioPanel.add(_currentButton);
+ radioPanel.add(_otherButton);
+
+ // directory for java home
+ _javaHome = new JTextField(40);
+ _javaHome.addFocusListener(new JavaFocusListener());
+ // browse button
+ _browse = new JButton();
+ _browse.addActionListener(new BrowseButtonListener());
+
+ JPanel panel = new JPanel();
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ panel.setLayout(gridBagLayout);
+ GridBagConstraints gridBagConstraints = newGridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ panel.add(_label, gridBagConstraints);
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ panel.add(radioPanel, gridBagConstraints);
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ panel.add(_javaHome, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 2;
+ panel.add(_browse, gridBagConstraints);
+
+ add(panel);
+ }
+
+ JTextField getJavaHome() {
+ return _javaHome;
+ }
+
+ protected String getTitle() {
+ return getText(TARGET_JAVA_HOME_PROPERTY);
+ }
+
+ protected String getDescription() {
+ return getText(CHOOSE_JRE);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return true;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return _currentButton;
+ }
+
+ protected void activate() {
+ _label.setText(getText(SELECT_JAVA_HOME) + ": ");
+ _currentButton.setText(getText(CURRENT));
+ _otherButton.setText(getText(OTHER));
+ _browse.setText(getText(BROWSE));
+ setValues();
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+ private void setValues() {
+ boolean current = true;
+ JavaHomeHandler javaHomeHandler = FrameInstaller.getJavaHomeHandler();
+ if (javaHomeHandler.isDeviation()) {
+ current = false;
+ }
+ setCurrent(current);
+ }
+
+ private void setCurrent(boolean current) {
+ if (current) {
+ FrameInstaller.setJavaHomeHandler(new JavaHomeHandler());
+ _currentButton.setSelected(true);
+ _otherButton.setSelected(false);
+ _javaHome.setEnabled(false);
+ _browse.setEnabled(false);
+ } else {
+ _currentButton.setSelected(false);
+ _otherButton.setSelected(true);
+ _javaHome.setEnabled(true);
+ _browse.setEnabled(true);
+ }
+ JavaHomeHandler javaHomeHandler = FrameInstaller.getJavaHomeHandler();
+ if (javaHomeHandler.isValidHome()) {
+ _javaHome.setText(javaHomeHandler.getHome().getAbsolutePath());
+ } else {
+ _javaHome.setText("");
+ }
+ _javaHome.setToolTipText(_javaHome.getText());
+ }
+
+ private final class BrowseButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ JFileChooser fileChooser = new JFileChooser(new File(_javaHome.getText()));
+ fileChooser.setDialogTitle(getText(SELECT_JAVA_HOME));
+ // the filter is at the moment only used for the title of the dialog:
+ fileChooser.setFileFilter(new DirectoryFilter());
+ fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ if (fileChooser.isAcceptAllFileFilterUsed()) {
+ if (Installation.isMacintosh() && Installation.isJDK141()) {
+ // work around ArrayIndexOutOfBoundsExceptio on Mac OS X, java version 1.4.1
+ } else {
+ fileChooser.setAcceptAllFileFilterUsed(false);
+ }
+ }
+ int returnValue = fileChooser.showDialog(_browse, getText(SELECT));
+ if (returnValue == JFileChooser.APPROVE_OPTION) {
+ FrameInstaller.setJavaHomeHandler(new JavaHomeHandler(fileChooser.getSelectedFile().getAbsolutePath()));
+ setValues();
+ }
+ }
+ }
+
+ private final class RadioButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+ setCurrent(_CURRENT_ACTION_COMMAND.equals(actionCommand));
+ }
+ }
+
+ private final class JavaFocusListener implements FocusListener {
+ public void focusGained(FocusEvent e) {
+ }
+
+ public void focusLost(FocusEvent e) {
+ String javaHome = _javaHome.getText();
+ FrameInstaller.setJavaHomeHandler(new JavaHomeHandler(javaHome));
+ _javaHome.setToolTipText(javaHome);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/JavaSelectionPageValidator.java b/installer/src/java/org/python/util/install/JavaSelectionPageValidator.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/JavaSelectionPageValidator.java
@@ -0,0 +1,31 @@
+package org.python.util.install;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+
+public class JavaSelectionPageValidator extends AbstractWizardValidator {
+
+ JavaSelectionPage _page;
+
+ JavaSelectionPageValidator(JavaSelectionPage page) {
+ super();
+ _page = page;
+ }
+
+ protected void validate() throws ValidationException {
+ JavaVersionInfo javaVersionInfo = new JavaVersionInfo();
+ String directory = _page.getJavaHome().getText().trim(); // trim to be sure
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler(directory);
+ if(javaHomeHandler.isDeviation()) {
+ javaVersionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ if (javaVersionInfo.getErrorCode() != Installation.NORMAL_RETURN) {
+ throw new ValidationException(javaVersionInfo.getReason());
+ }
+ } else {
+ // no experiments if current java is selected
+ Installation.fillJavaVersionInfo(javaVersionInfo, System.getProperties());
+ }
+ FrameInstaller.setJavaHomeHandler(javaHomeHandler);
+ FrameInstaller.setJavaVersionInfo(javaVersionInfo);
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/JavaVersionTester.java b/installer/src/java/org/python/util/install/JavaVersionTester.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/JavaVersionTester.java
@@ -0,0 +1,61 @@
+package org.python.util.install;
+
+import java.io.File;
+
+/**
+ * Helper class to test a java version
+ */
+public class JavaVersionTester {
+
+ public static final String JAVA_HOME = "java.home";
+ protected static final String JAVA_VERSION = "java.version";
+ public static final String JAVA_SPECIFICATION_VERSION = "java.specification.version";
+ protected static final String JAVA_VENDOR = "java.vendor";
+ private static final String NEWLINE = "\n";
+
+ private static final String UNKNOWN = "<unknown>";
+
+ public static void main(String[] args) {
+ if (args.length > 0) {
+ String tempFilePath = args[0];
+ File tempFile = new File(tempFilePath);
+ if (tempFile.exists() && tempFile.canWrite()) {
+ try {
+ writeTempFile(tempFile);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ } else {
+ if (!tempFile.exists()) {
+ System.err.println("temp file " + tempFilePath + " does not exist");
+ } else {
+ System.err.println("cannot write to temp file " + tempFilePath);
+ }
+ System.exit(1);
+ }
+ } else {
+ System.err.println("no temp file given. usage: JavaVersionTester tempfile");
+ System.out.println("exiting with 1");
+ System.exit(1);
+ }
+ }
+
+ private static void writeTempFile(File file) throws Exception {
+ FileHelper.write(file, createFileContent());
+ }
+
+ private static String createFileContent() {
+ StringBuffer sb = new StringBuffer(500);
+ String java_home = new JavaHomeHandler().getExecutableName();
+ if (File.separatorChar != '/') {
+ java_home = java_home.replace(File.separatorChar, '/'); // backslash would be interpreted as escape char
+ }
+ sb.append(JAVA_HOME + "=" + java_home + NEWLINE);
+ sb.append(JAVA_VERSION + "=" + System.getProperty(JAVA_VERSION, UNKNOWN) + NEWLINE);
+ sb.append(JAVA_SPECIFICATION_VERSION + "=" + System.getProperty(JAVA_SPECIFICATION_VERSION, UNKNOWN) + NEWLINE);
+ sb.append(JAVA_VENDOR + "=" + System.getProperty(JAVA_VENDOR, UNKNOWN) + NEWLINE);
+ return sb.toString();
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/LanguagePage.java b/installer/src/java/org/python/util/install/LanguagePage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/LanguagePage.java
@@ -0,0 +1,121 @@
+package org.python.util.install;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+public class LanguagePage extends AbstractWizardPage {
+
+ private static Map _languageIndexes = new HashMap(2);
+ static {
+ _languageIndexes.put(Locale.ENGLISH, new Integer(0));
+ _languageIndexes.put(Locale.GERMAN, new Integer(1));
+ }
+
+ private JLabel _label;
+ private JComboBox _languageBox;
+ private JarInfo _jarInfo;
+ private boolean _activated;
+ private boolean _stopListening;
+
+ public LanguagePage(JarInfo jarInfo) {
+ super();
+ _jarInfo = jarInfo;
+ _activated = false;
+ _stopListening = false;
+ initComponents();
+ }
+
+ private void initComponents() {
+ _label = new JLabel();
+ add(_label);
+ _languageBox = new JComboBox();
+ _languageBox.addActionListener(new LanguageBoxListener());
+ add(_languageBox);
+ }
+
+ protected String getTitle() {
+ return getText(WELCOME_TO_JYTHON);
+ }
+
+ protected String getDescription() {
+ return getText(VERSION_INFO, _jarInfo.getVersion());
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return false;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return _languageBox;
+ }
+
+ protected void activate() {
+ _label.setText(getText(SELECT_LANGUAGE) + ": ");
+ // replace combo box items (localization)
+ int itemCount = _languageBox.getItemCount();
+ _stopListening = true; // adding and removing fires an action event
+ for (int i = 0; i < itemCount; i++) {
+ _languageBox.removeItemAt(0);
+ }
+ _languageBox.addItem(getText(ENGLISH)); // keep indexes here
+ _languageBox.addItem(getText(GERMAN));
+ _stopListening = false;
+ if (!_activated) {
+ // preselect German if default looks like German
+ if (Locale.getDefault().toString().startsWith(Locale.GERMAN.toString())) {
+ _languageBox.setSelectedIndex(getLanguageIndex(Locale.GERMAN));
+ FrameInstaller.setLanguage(Locale.GERMAN);
+ }
+ } else {
+ _languageBox.setSelectedIndex(getLanguageIndex(FrameInstaller.getLanguage()));
+ }
+ _activated = true;
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+ private int getLanguageIndex(Locale locale) {
+ return ((Integer) _languageIndexes.get(locale)).intValue();
+ }
+
+ private Locale getLanguageFromIndex(int index) {
+ Integer indexInteger = new Integer(index);
+ Iterator languages = _languageIndexes.entrySet().iterator();
+ while (languages.hasNext()) {
+ Map.Entry entry = (Map.Entry) languages.next();
+ if (entry.getValue().equals(indexInteger)) {
+ return (Locale) entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ private class LanguageBoxListener implements ActionListener {
+ public void actionPerformed(ActionEvent ae) {
+ if (!_stopListening) {
+ FrameInstaller.setLanguage(getLanguageFromIndex(_languageBox.getSelectedIndex()));
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/LicensePage.java b/installer/src/java/org/python/util/install/LicensePage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/LicensePage.java
@@ -0,0 +1,120 @@
+package org.python.util.install;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+public class LicensePage extends AbstractWizardPage {
+
+ private static final String _ACCEPT_ACTION_COMMAND = "1";
+ private static final String _DO_NOT_ACCEPT_ACTION_COMMAND = "0";
+
+ private JRadioButton _acceptButton;
+ private JRadioButton _doNotAcceptButton;
+
+ public LicensePage(JarInfo jarInfo) {
+ super();
+ initComponents(jarInfo);
+ }
+
+ private void initComponents(JarInfo jarInfo) {
+ String licenseText = "n/a";
+ try {
+ licenseText = jarInfo.getLicenseText();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ JPanel centerPanel = new JPanel();
+ centerPanel.setLayout(new GridLayout(1, 1, 10, 10));
+ JTextArea textArea = new JTextArea(13, 80);
+ JScrollPane scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ textArea.setEditable(false);
+ textArea.setText(licenseText);
+ centerPanel.add(scrollPane);
+
+ // radio buttons
+ JPanel southPanel = new JPanel();
+ RadioButtonListener radioButtonListener = new RadioButtonListener();
+ _acceptButton = new JRadioButton();
+ _acceptButton.setActionCommand(_ACCEPT_ACTION_COMMAND);
+ _acceptButton.addActionListener(radioButtonListener);
+ _doNotAcceptButton = new JRadioButton();
+ _doNotAcceptButton.setActionCommand(_DO_NOT_ACCEPT_ACTION_COMMAND);
+ _doNotAcceptButton.addActionListener(radioButtonListener);
+ ButtonGroup radioButtonGroup = new ButtonGroup();
+ radioButtonGroup.add(_acceptButton);
+ radioButtonGroup.add(_doNotAcceptButton);
+ JPanel radioPanel = new JPanel(new GridLayout(1, 0));
+ radioPanel.add(_acceptButton);
+ radioPanel.add(_doNotAcceptButton);
+ southPanel.add(radioPanel);
+
+ setLayout(new BorderLayout(0, 5));
+ add(centerPanel, BorderLayout.CENTER);
+ add(southPanel, BorderLayout.SOUTH);
+ }
+
+ protected String getTitle() {
+ return getText(LICENSE);
+ }
+
+ protected String getDescription() {
+ return getText(PLEASE_READ_LICENSE);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return true;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return _doNotAcceptButton;
+ }
+
+ protected void activate() {
+ _acceptButton.setText(getText(ACCEPT));
+ _doNotAcceptButton.setText(getText(DO_NOT_ACCEPT));
+ boolean accept = FrameInstaller.isAccept();
+ _acceptButton.setSelected(accept);
+ _doNotAcceptButton.setSelected(!accept);
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+ protected boolean isAccept() {
+ return _acceptButton.isSelected() && !_doNotAcceptButton.isSelected();
+ }
+
+ private final static class RadioButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+ if (actionCommand.equals(_ACCEPT_ACTION_COMMAND)) {
+ FrameInstaller.setAccept(true);
+ } else {
+ FrameInstaller.setAccept(false);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/LicensePageValidator.java b/installer/src/java/org/python/util/install/LicensePageValidator.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/LicensePageValidator.java
@@ -0,0 +1,17 @@
+package org.python.util.install;
+
+public class LicensePageValidator extends AbstractWizardValidator {
+
+ LicensePage _page;
+
+ LicensePageValidator(LicensePage page) {
+ super();
+ _page = page;
+ }
+
+ protected void validate() throws ValidationException {
+ if (!_page.isAccept()) {
+ throw new ValidationException(getText(PLEASE_ACCEPT_LICENSE));
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/OverviewPage.java b/installer/src/java/org/python/util/install/OverviewPage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/OverviewPage.java
@@ -0,0 +1,243 @@
+package org.python.util.install;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+
+public class OverviewPage extends AbstractWizardPage {
+
+ private final static int _LONGER_LENGTH = 25;
+ private final static int _SHORTER_LENGTH = 10;
+
+ private JLabel _directoryLabel;
+ private JLabel _typeLabel;
+ private JTextField _directory;
+ private JTextField _type;
+ private JLabel _message;
+
+ private JLabel _osLabel;
+ private JCheckBox _osBox;
+ private JLabel _javaLabel;
+ private JTextField _javaVendor;
+ private JTextField _javaVersion;
+ private JCheckBox _javaBox;
+
+ public OverviewPage() {
+ super();
+ initComponents();
+ }
+
+ private void initComponents() {
+ _directoryLabel = new JLabel();
+ _directory = new JTextField(_LONGER_LENGTH);
+ _directory.setEditable(false);
+ _directory.setFocusable(false);
+ _typeLabel = new JLabel();
+ _type = new JTextField(_LONGER_LENGTH);
+ _type.setEditable(false);
+ _type.setFocusable(false);
+
+ _osLabel = new JLabel();
+ JTextField osName = new JTextField(_LONGER_LENGTH);
+ osName.setText(System.getProperty(Installation.OS_NAME));
+ osName.setToolTipText(System.getProperty(Installation.OS_NAME));
+ osName.setEditable(false);
+ osName.setFocusable(false);
+ JTextField osVersion = new JTextField(_SHORTER_LENGTH);
+ osVersion.setText(System.getProperty(Installation.OS_VERSION));
+ osVersion.setToolTipText(System.getProperty(Installation.OS_VERSION));
+ osVersion.setEditable(false);
+ osVersion.setFocusable(false);
+ _osBox = new JCheckBox();
+ _osBox.setEnabled(false);
+ _osBox.setSelected(Installation.isValidOs());
+ _osBox.setFocusable(false);
+
+ _javaLabel = new JLabel();
+ _javaLabel.setFocusable(false);
+ _javaVendor = new JTextField(_LONGER_LENGTH);
+ _javaVendor.setEditable(false);
+ _javaVendor.setFocusable(false);
+ _javaVersion = new JTextField(_SHORTER_LENGTH);
+ _javaVersion.setEditable(false);
+ _javaVersion.setFocusable(false);
+ _javaBox = new JCheckBox();
+ _javaBox.setEnabled(false);
+ _javaBox.setFocusable(false);
+
+ _message = new JLabel();
+
+ JPanel panel = new JPanel();
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ panel.setLayout(gridBagLayout);
+ GridBagConstraints gridBagConstraints = newGridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ panel.add(_directoryLabel, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 0;
+ panel.add(_directory, gridBagConstraints);
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ panel.add(_typeLabel, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 1;
+ panel.add(_type, gridBagConstraints);
+
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ panel.add(_osLabel, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 2;
+ panel.add(osName, gridBagConstraints);
+ gridBagConstraints.gridx = 2;
+ gridBagConstraints.gridy = 2;
+ panel.add(osVersion, gridBagConstraints);
+ gridBagConstraints.gridx = 3;
+ gridBagConstraints.gridy = 2;
+ panel.add(_osBox, gridBagConstraints);
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 3;
+ panel.add(_javaLabel, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 3;
+ panel.add(_javaVendor, gridBagConstraints);
+ gridBagConstraints.gridx = 2;
+ gridBagConstraints.gridy = 3;
+ panel.add(_javaVersion, gridBagConstraints);
+ gridBagConstraints.gridx = 3;
+ gridBagConstraints.gridy = 3;
+ panel.add(_javaBox, gridBagConstraints);
+
+ // attn special constraints for message (should always be on last row)
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 4;
+ gridBagConstraints.gridwidth = 2;
+ panel.add(_message, gridBagConstraints);
+
+ add(panel);
+ }
+
+ protected String getTitle() {
+ return getText(OVERVIEW_TITLE);
+ }
+
+ protected String getDescription() {
+ return getText(OVERVIEW_DESCRIPTION);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return true;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return null;
+ }
+
+ protected void activate() {
+ // directory
+ _directoryLabel.setText(getText(TARGET_DIRECTORY_PROPERTY) + ": ");
+ _directory.setText(FrameInstaller.getTargetDirectory());
+ _directory.setToolTipText(FrameInstaller.getTargetDirectory());
+
+ // type
+ _typeLabel.setText(getText(INSTALLATION_TYPE) + ": ");
+ InstallationType installationType = FrameInstaller.getInstallationType();
+ String typeText;
+ if (installationType.isAll()) {
+ typeText = getText(ALL);
+ } else if (installationType.isStandard()) {
+ typeText = getText(STANDARD);
+ } else if (installationType.isMinimum()) {
+ typeText = getText(MINIMUM);
+ } else if (installationType.isStandalone()) {
+ typeText = getText(STANDALONE);
+ } else {
+ typeText = getText(CUSTOM);
+ typeText += " (";
+ boolean predecessor = false;
+ if (installationType.installLibraryModules()) {
+ if (predecessor) {
+ typeText += " ";
+ }
+ typeText += InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES;
+ predecessor = true;
+ }
+ if (installationType.installDemosAndExamples()) {
+ if (predecessor) {
+ typeText += " ";
+ }
+ typeText += InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES;
+ predecessor = true;
+ }
+ if (installationType.installDocumentation()) {
+ if (predecessor) {
+ typeText += " ";
+ }
+ typeText += InstallerCommandLine.INEXCLUDE_DOCUMENTATION;
+ predecessor = true;
+ }
+ if (installationType.installSources()) {
+ if (predecessor) {
+ typeText += " ";
+ }
+ typeText += InstallerCommandLine.INEXCLUDE_SOURCES;
+ predecessor = true;
+ }
+ typeText += ")";
+ }
+ _type.setText(typeText);
+ _type.setToolTipText(typeText);
+
+ // os
+ _osLabel.setText(getText(OS_INFO) + ": ");
+ String osText;
+ if (_osBox.isSelected()) {
+ osText = getText(OK);
+ } else {
+ osText = getText(MAYBE_NOT_SUPPORTED);
+ }
+ _osBox.setText(osText);
+
+ // java
+ _javaLabel.setText(getText(JAVA_INFO) + ": ");
+ JavaVersionInfo javaVersionInfo = FrameInstaller.getJavaVersionInfo();
+ _javaVendor.setText(javaVersionInfo.getVendor());
+ _javaVendor.setToolTipText(javaVersionInfo.getVendor());
+ _javaVersion.setText(javaVersionInfo.getVersion());
+ _javaVersion.setToolTipText(javaVersionInfo.getVersion());
+ _javaBox.setSelected(Installation.isValidJava(javaVersionInfo));
+ String javaText;
+ if (_javaBox.isSelected()) {
+ javaText = getText(OK);
+ } else {
+ javaText = getText(NOT_OK);
+ }
+ _javaBox.setText(javaText);
+
+ // message
+ _message.setText(getText(CONFIRM_START, getText(NEXT)));
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ProgressListener.java b/installer/src/java/org/python/util/install/ProgressListener.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ProgressListener.java
@@ -0,0 +1,15 @@
+package org.python.util.install;
+
+public interface ProgressListener extends InstallationListener {
+
+ public int getInterval();
+
+ public void progressChanged(int newPercentage);
+
+ public void progressEntry(String entry);
+
+ public void progressStartScripts();
+
+ public void progressStandalone();
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ProgressPage.java b/installer/src/java/org/python/util/install/ProgressPage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ProgressPage.java
@@ -0,0 +1,122 @@
+package org.python.util.install;
+
+import java.awt.BorderLayout;
+import java.io.File;
+import java.io.IOException;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+
+import org.python.util.install.driver.Autotest;
+
+public class ProgressPage extends AbstractWizardPage implements ProgressListener {
+
+ private static final long serialVersionUID = 9013748834030994976L;
+
+ private JarInfo _jarInfo;
+ private JLabel _label;
+ private JProgressBar _progressBar;
+ private JLabel _progressEntry;
+ private Autotest _autotest;
+
+ public ProgressPage(JarInfo jarInfo, Autotest autotest) {
+ super();
+ _jarInfo = jarInfo;
+ _autotest = autotest;
+ initComponents();
+ }
+
+ private void initComponents() {
+ JPanel northPanel = new JPanel();
+ _label = new JLabel();
+ northPanel.add(_label);
+ _progressBar = new JProgressBar();
+ northPanel.add(_progressBar);
+ JPanel centerPanel = new JPanel();
+ _progressEntry = new JLabel();
+ centerPanel.add(_progressEntry);
+ setLayout(new BorderLayout(0, 5));
+ add(northPanel, BorderLayout.NORTH);
+ add(centerPanel, BorderLayout.CENTER);
+ }
+
+ protected String getTitle() {
+ return getText(INSTALLATION_IN_PROGRESS);
+ }
+
+ protected String getDescription() {
+ return getText(PLEASE_WAIT);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return false;
+ }
+
+ protected boolean isNextVisible() {
+ return false;
+ }
+
+ protected JComponent getFocusField() {
+ return null;
+ }
+
+ protected void activate() {
+ _label.setText(getText(PROGRESS) + ": ");
+ _progressBar.setValue(0);
+ _progressBar.setStringPainted(true);
+ try {
+ _progressEntry.setText(getText(INFLATING, _jarInfo.getJarFile().getName()));
+ } catch (IOException e) {
+ // should not happen
+ }
+ JarInstaller jarInstaller = new JarInstaller(this, _jarInfo);
+ if (_autotest != null) {
+ jarInstaller.addInstallationListener(_autotest);
+ }
+ File targetDirectory = new File(FrameInstaller.getTargetDirectory());
+ JavaHomeHandler javaHomeHandler = FrameInstaller.getJavaHomeHandler();
+ jarInstaller.inflate(targetDirectory, FrameInstaller.getInstallationType(), javaHomeHandler);
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+ //
+ // interface ProgressListener
+ //
+
+ public void progressChanged(int newPercentage) {
+ _progressBar.setValue(newPercentage);
+ }
+
+ public int getInterval() {
+ return 1;
+ }
+
+ public void progressFinished() {
+ _progressBar.setValue(100);
+ getWizard().gotoNextPage();
+ }
+
+ public void progressEntry(String entry) {
+ _progressEntry.setText(getText(INFLATING, entry));
+ }
+
+ public void progressStartScripts() {
+ _progressEntry.setText(getText(GENERATING_START_SCRIPTS));
+ }
+
+ public void progressStandalone() {
+ _progressEntry.setText(getText(PACKING_STANDALONE_JAR));
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ReadmePage.java b/installer/src/java/org/python/util/install/ReadmePage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ReadmePage.java
@@ -0,0 +1,75 @@
+package org.python.util.install;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.io.IOException;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+public class ReadmePage extends AbstractWizardPage {
+
+ private JTextArea _textArea;
+ private JarInfo _jarInfo;
+
+ public ReadmePage(JarInfo jarInfo) {
+ super();
+ _jarInfo = jarInfo;
+ initComponents();
+ }
+
+ private void initComponents() {
+ JPanel centerPanel = new JPanel();
+ centerPanel.setLayout(new GridLayout(1, 1));
+ _textArea = new JTextArea(13, 80);
+ JScrollPane scrollPane = new JScrollPane(_textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ _textArea.setEditable(false);
+ _textArea.setText("n/a");
+ centerPanel.add(scrollPane);
+
+ setLayout(new BorderLayout(0, 5));
+ add(centerPanel, BorderLayout.CENTER);
+ }
+
+ protected String getTitle() {
+ return getText(README);
+ }
+
+ protected String getDescription() {
+ return getText(PLEASE_README);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return false;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return null;
+ }
+
+ protected void activate() {
+ try {
+ _textArea.setText(_jarInfo.getReadmeText());
+ } catch (IOException ioe) {
+ throw new InstallerException(ioe);
+ }
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/StandalonePackager.java b/installer/src/java/org/python/util/install/StandalonePackager.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/StandalonePackager.java
@@ -0,0 +1,184 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+public class StandalonePackager {
+
+ private final static int BUF_SIZE = 1024;
+
+ private File _jarFile;
+ private Manifest _manifest;
+ private JarOutputStream _jarOut;
+
+ /**
+ * Helper class to pack stuff into a single .jar file.
+ * <p>
+ * If a .jar file has to be added, this should be the first add (because of the MANIFEST).
+ */
+ public StandalonePackager(File jarFile) {
+ _jarFile = jarFile;
+ }
+
+ /**
+ * add a file, in given parent dir (<code>null</code> = top)
+ *
+ * @param file to write to jar
+ * @param parentDir as String
+ *
+ * @throws IOException
+ */
+ public void addFile(File file, String parentDir) throws IOException {
+ byte[] buffer = new byte[BUF_SIZE];
+ FileInputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(file);
+ String jarEntryName = null;
+ if (parentDir != null && parentDir.length() > 0) {
+ jarEntryName = parentDir + "/" + file.getName();
+ } else {
+ jarEntryName = file.getName();
+ }
+ getJarOutputStream().putNextEntry(new JarEntry(jarEntryName));
+ for (int read = 0; read != -1; read = inputStream.read(buffer)) {
+ getJarOutputStream().write(buffer, 0, read);
+ }
+ getJarOutputStream().closeEntry();
+ } finally {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ }
+ }
+
+ /**
+ * add a full directory
+ *
+ * @param directory
+ * @throws IOException
+ */
+ public void addFullDirectory(File directory) throws IOException {
+ addDirectory(directory, null);
+ }
+
+ /**
+ * add the contents of a given jar file
+ *
+ * @param jarFile to add
+ * @throws IOException
+ * @throws FileNotFoundException
+ */
+ public void addJarFile(File jarFile) throws FileNotFoundException, IOException {
+ JarFile jarJarFile = new JarFile(jarFile);
+ try {
+ _manifest = jarJarFile.getManifest();
+ } finally {
+ jarJarFile.close();
+ }
+
+ JarInputStream inputStr = null;
+ try {
+ inputStr = new JarInputStream(new FileInputStream(jarFile));
+ JarEntry entry = inputStr.getNextJarEntry();
+ while (entry != null) {
+ getJarOutputStream().putNextEntry(entry);
+ byte[] buffer = new byte[BUF_SIZE];
+ int len;
+ while ((len = inputStr.read(buffer)) > 0) {
+ getJarOutputStream().write(buffer, 0, len);
+ }
+ getJarOutputStream().closeEntry();
+ entry = inputStr.getNextJarEntry();
+ }
+ } finally {
+ if (inputStr != null) {
+ try {
+ inputStr.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void close() throws FileNotFoundException, IOException {
+ getJarOutputStream().close();
+ }
+
+ /**
+ * removes all files in directory dir (and subdirectories), except excludeFile.
+ *
+ * @param dir
+ * @param excludeFile
+ */
+ public static void emptyDirectory(File dir, File excludeFile) {
+ File[] files = dir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (!files[i].equals(excludeFile)) {
+ if (files[i].isDirectory()) {
+ emptyDirectory(files[i], excludeFile);
+ } else {
+ files[i].delete();
+ }
+ }
+ }
+ if (dir.listFiles().length == 0) {
+ dir.delete();
+ }
+ }
+
+ /**
+ * add the given directory to the jar, including all subdirectories, in given parent dir (<code>null</code> =
+ * top)
+ *
+ * @param dir to add to the jar
+ * @param parentDir to save in jar
+ * @throws IOException
+ */
+ private void addDirectory(File dir, String parentDir) throws IOException {
+ if (!dir.isDirectory())
+ return;
+ File[] filesInDir = dir.listFiles();
+ for (int i = 0; i < filesInDir.length; i++) {
+ File currentFile = filesInDir[i];
+ if (currentFile.isFile()) {
+ if (parentDir != null && parentDir.length() > 0) {
+ addFile(currentFile, parentDir + "/" + dir.getName());
+ } else {
+ addFile(currentFile, dir.getName());
+ }
+ } else {
+ String newParentDir = null;
+ if (parentDir != null && parentDir.length() > 0) {
+ newParentDir = parentDir + "/" + dir.getName();
+ } else {
+ newParentDir = dir.getName();
+ }
+ addDirectory(currentFile, newParentDir);
+ }
+ }
+ }
+
+ /**
+ * @return the jar output stream
+ */
+ private JarOutputStream getJarOutputStream() throws FileNotFoundException, IOException {
+ if (_jarOut == null) {
+ if (_manifest != null) {
+ _jarOut = new JarOutputStream(new FileOutputStream(_jarFile), _manifest);
+ } else {
+ _jarOut = new JarOutputStream(new FileOutputStream(_jarFile));
+ }
+ }
+ return _jarOut;
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/StartScriptGenerator.java b/installer/src/java/org/python/util/install/StartScriptGenerator.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/StartScriptGenerator.java
@@ -0,0 +1,240 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Date;
+
+public class StartScriptGenerator {
+
+ protected final static int UNIX_FLAVOUR = 10;
+
+ protected final static int WINDOWS_FLAVOUR = 30;
+
+ protected final static int BOTH_FLAVOUR = 50;
+
+ protected final static String WIN_CR_LF;
+
+ private final static String JAVA_HOME = "JAVA_HOME";
+
+ /** do not hard-wire JYTHON_HOME */
+ private final static String JYTHON_HOME_FALLBACK = "JYTHON_HOME_FALLBACK";
+
+ private final static String JYTHON = "jython";
+
+ private final static String JYTHON_BAT = "jython.bat";
+ static {
+ int dInt = Integer.parseInt("0d", 16);
+ int aInt = Integer.parseInt("0a", 16);
+ WIN_CR_LF = new String(new char[] {(char)dInt, (char)aInt});
+ }
+
+ private File _targetDirectory;
+
+ private JavaHomeHandler _javaHomeHandler;
+
+ private int _flavour;
+
+ public StartScriptGenerator(File targetDirectory, JavaHomeHandler javaHomeHandler) {
+ _targetDirectory = targetDirectory;
+ _javaHomeHandler = javaHomeHandler;
+ if (Installation.isWindows()) {
+ setFlavour(WINDOWS_FLAVOUR);
+ } else {
+ // everything else defaults to unix at the moment
+ setFlavour(UNIX_FLAVOUR);
+ }
+ }
+
+ protected void setFlavour(int flavour) {
+ _flavour = flavour;
+ if (flavour == WINDOWS_FLAVOUR) {
+ // check if we should create unix like scripts, too
+ if (hasUnixlikeShell()) {
+ _flavour = BOTH_FLAVOUR;
+ }
+ }
+ }
+
+ protected int getFlavour() {
+ return _flavour;
+ }
+
+ protected boolean hasUnixlikeShell() {
+ int errorCode = 0;
+ try {
+ String command[] = new String[] {"sh", "-c", "env"};
+ long timeout = 3000;
+ ChildProcess childProcess = new ChildProcess(command, timeout);
+ childProcess.setDebug(false);
+ childProcess.setSilent(true);
+ errorCode = childProcess.run();
+ } catch (Throwable t) {
+ errorCode = 1;
+ }
+ return errorCode == 0;
+ }
+
+ protected final void generateStartScripts() throws IOException {
+ File bin = new File(getTargetDirectory(), "bin");
+ File bin_jython = new File(bin, JYTHON);
+ switch(getFlavour()){
+ case BOTH_FLAVOUR:
+ writeToTargetDir(JYTHON_BAT, getJythonScript(WINDOWS_FLAVOUR));
+ FileHelper.makeExecutable(writeToTargetDir(JYTHON, getJythonScript(BOTH_FLAVOUR)));
+ FileHelper.makeExecutable(bin_jython);
+ break;
+ case WINDOWS_FLAVOUR:
+ writeToTargetDir(JYTHON_BAT, getJythonScript(WINDOWS_FLAVOUR));
+ // delete the *nix script in /bin dir
+ bin_jython.delete();
+ break;
+ default:
+ FileHelper.makeExecutable(writeToTargetDir(JYTHON, getJythonScript(UNIX_FLAVOUR)));
+ FileHelper.makeExecutable(bin_jython);
+ // delete the windows script in /bin dir
+ File bin_jython_bat = new File(bin, JYTHON_BAT);
+ bin_jython_bat.delete();
+ break;
+ }
+ }
+
+ /**
+ * only <code>protected</code> for unit test use
+ */
+ protected final String getJythonScript(int flavour) throws IOException {
+ if (flavour == WINDOWS_FLAVOUR) {
+ return getStartScript(getWindowsJythonTemplate()) + readFromFile(JYTHON_BAT);
+ } else {
+ return getStartScript(getUnixJythonTemplate()) + readFromFile(JYTHON);
+ }
+ }
+
+ /**
+ * These placeholders are valid for all private methods:
+ *
+ * {0} : current date <br>
+ * {1} : user.name <br>
+ * {2} : target directory <br>
+ */
+ private String getStartScript(String template) throws IOException {
+ String parameters[] = new String[4];
+ parameters[0] = new Date().toString();
+ parameters[1] = System.getProperty("user.name");
+ parameters[2] = getTargetDirectory().getCanonicalPath();
+ return MessageFormat.format(template, (Object[])parameters);
+ }
+
+ /**
+ * placeholders:
+ *
+ * @see getStartScript
+ */
+ private String getWindowsJythonTemplate() {
+ StringBuilder builder = getWindowsHeaderTemplate();
+ builder.append("set ");
+ builder.append(JAVA_HOME);
+ builder.append("=");
+ if (_javaHomeHandler.isValidHome()) {
+ builder.append("\"");
+ builder.append(_javaHomeHandler.getHome().getAbsolutePath());
+ builder.append("\"");
+ }
+ builder.append(WIN_CR_LF);
+ builder.append("set ");
+ builder.append(JYTHON_HOME_FALLBACK);
+ builder.append("=\"{2}\"");
+ builder.append(WIN_CR_LF);
+ builder.append(WIN_CR_LF);
+ return builder.toString();
+ }
+
+ /**
+ * placeholders:
+ *
+ * @see getStartScript
+ */
+ private StringBuilder getWindowsHeaderTemplate() {
+ StringBuilder builder = new StringBuilder(1000);
+ builder.append("@echo off");
+ builder.append(WIN_CR_LF);
+ builder.append("rem This file was generated by the Jython installer");
+ builder.append(WIN_CR_LF);
+ builder.append("rem Created on {0} by {1}");
+ builder.append(WIN_CR_LF);
+ builder.append(WIN_CR_LF);
+ return builder;
+ }
+
+ /**
+ * placeholders:
+ *
+ * @see getStartScript
+ */
+ private String getUnixJythonTemplate() {
+ StringBuilder builder = getUnixHeaderTemplate();
+ builder.append(JAVA_HOME);
+ builder.append("=");
+ if (_javaHomeHandler.isValidHome()) {
+ builder.append("\"");
+ builder.append(_javaHomeHandler.getHome().getAbsolutePath());
+ builder.append("\"");
+ }
+ builder.append("\n");
+ builder.append(JYTHON_HOME_FALLBACK);
+ builder.append("=\"{2}\"\n");
+ builder.append("\n");
+ return builder.toString();
+ }
+
+ /**
+ * placeholders:
+ *
+ * @see getStartScript
+ */
+ private StringBuilder getUnixHeaderTemplate() {
+ StringBuilder builder = new StringBuilder(1000);
+ builder.append("#!/usr/bin/env bash\n");
+ builder.append("\n");
+ builder.append("# This file was generated by the Jython installer\n");
+ builder.append("# Created on {0} by {1}\n");
+ builder.append("\n");
+ return builder;
+ }
+
+ /**
+ * @param fileName
+ * The short file name, e.g. JYTHON_BAT
+ *
+ * @throws IOException
+ */
+ private String readFromFile(String fileName) throws IOException {
+ // default runtime location
+ File targetDirectory = getTargetDirectory();
+ File file = new File(new File(targetDirectory, "bin"), fileName);
+ if (!file.exists()) {
+ // deviation: test time location
+ file = new File(targetDirectory, fileName);
+ }
+ return FileHelper.readAll(file);
+ }
+
+ /**
+ * Create (or overwrite) the specified file in the target directory
+ *
+ * @param fileName
+ * The short file name, e.g. JYTHON_BAT
+ * @param contents
+ *
+ * @throws IOException
+ */
+ private File writeToTargetDir(String fileName, String contents) throws IOException {
+ File file = new File(getTargetDirectory(), fileName);
+ FileHelper.write(file, contents);
+ return file;
+ }
+
+ private File getTargetDirectory() {
+ return _targetDirectory;
+ }
+}
diff --git a/installer/src/java/org/python/util/install/SuccessPage.java b/installer/src/java/org/python/util/install/SuccessPage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/SuccessPage.java
@@ -0,0 +1,55 @@
+package org.python.util.install;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+public class SuccessPage extends AbstractWizardPage {
+
+ private JarInfo _jarInfo;
+ private JLabel _label;
+
+ public SuccessPage(JarInfo jarInfo) {
+ super();
+ _jarInfo = jarInfo;
+ initComponents();
+ }
+
+ private void initComponents() {
+ _label = new JLabel();
+ add(_label);
+ }
+
+ protected String getTitle() {
+ return getText(CONGRATULATIONS);
+ }
+
+ protected String getDescription() {
+ return getText(SUCCESS, _jarInfo.getVersion(), FrameInstaller.getTargetDirectory());
+ }
+
+ protected boolean isCancelVisible() {
+ return false;
+ }
+
+ protected boolean isPreviousVisible() {
+ return false;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ return null;
+ }
+
+ protected void activate() {
+ _label.setText(getText(PRESS_FINISH, getWizard().getFinishString()));
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/TextConstants.java b/installer/src/java/org/python/util/install/TextConstants.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/TextConstants.java
@@ -0,0 +1,148 @@
+package org.python.util.install;
+
+import java.util.ListResourceBundle;
+
+public class TextConstants extends ListResourceBundle implements TextKeys {
+
+ static final Object[][] contents = {
+ // LOCALIZE THIS
+
+ { ACCEPT, "I accept" }, // license
+ { ALL, "All (everything, including sources)" }, // installation type
+ { BROWSE, "Browse..." }, // button (open the JFileChooser)
+ { CANCEL, "Cancel" }, // button
+ { CHOOSE_LOCATION, "Choose the location where you want Jython to be installed to" }, // selection
+ { CHOOSE_JRE, "Choose the java version (JRE/JDK) to run Jython with" }, // selection
+ { CONFIRM_START, "Please press {0} to start the installation" }, // overview
+ { CONGRATULATIONS, "Congratulations!" }, // congratulations
+ { CORE, "Core" }, // installation type
+ { CREATED_DIRECTORY, "Created directory {0}" }, // directory
+ { CURRENT, "Current" }, // directory
+ { CUSTOM, "Custom" }, // installation type
+ { DEMOS_EXAMPLES, "Demos and examples" }, // installation type
+ { DO_NOT_ACCEPT, "I do not accept" }, // license
+ { DIRECTORIES_ONLY, "Directories only" }, // file chooser
+ { DOCUMENTATION, "Documentation" }, // installation type
+ { EMPTY_TARGET_DIRECTORY, "Target directory must not be empty" }, // error
+ { ENGLISH, "English" }, // language
+ { ERROR, "Error" }, // error
+ { ERROR_ACCESS_JARFILE, "Error accessing jar file" }, // error
+ { FINISH, "Finish" }, // button
+ { GENERATING_START_SCRIPTS, "Generating start scripts ..." }, // progress
+ { GERMAN, "German" }, // language
+ { INFLATING, "Inflating {0}" }, // progress
+ { INFORMATION, "Information" }, // information
+ { INSTALLATION_CANCELLED, "Installation cancelled." }, // final
+ { INSTALLATION_IN_PROGRESS, "The installation is now in progress" }, // progress
+ { INSTALLATION_TYPE_DESCRIPTION, "The following installation types are available" }, // installation type
+ { INSTALLATION_TYPE, "Installation type" }, // installation type
+ { JAR_NOT_FOUND, "Unable to find jar file {0}." }, // error
+ { JAVA_INFO, "Java vendor / version" }, // version
+ { JYTHON_INSTALL, "Jython Installation" }, // title
+ { LANGUAGE_PROPERTY, "Language" }, // language
+ { LIBRARY_MODULES, "Library modules" }, // installation type
+ { LICENSE, "License agreement" }, // license
+ { MAYBE_NOT_SUPPORTED, "Maybe not supported" }, // version
+ { MINIMUM, "Minimum (core)" }, // installation type
+ { NEXT, "Next" }, // button
+ { NON_EMPTY_TARGET_DIRECTORY, "Target directory is not empty" }, // error
+ { NO_MANIFEST, "No manifest found in jar file {0}." }, // error
+ { NOT_OK, "Not ok !" }, // version
+ { OK, "Ok" }, // version
+ { OS_INFO, "OS name / version" }, // version
+ { OTHER, "Other" }, // directory
+ { OVERVIEW_DESCRIPTION, "The installation will be done using the following options" }, // overview
+ { OVERVIEW_TITLE, "Overview (summary of options)" }, // overview
+ { PACKING_STANDALONE_JAR, "Packing standalone " + JarInstaller.JYTHON_JAR + " ..." }, // progress
+ { PLEASE_ACCEPT_LICENSE, "Please read and accept the license agreement" }, // license
+ { PLEASE_README, "Please read the following information" }, // readme
+ { PLEASE_READ_LICENSE, "Please read the license agreement carefully" }, // license
+ { PLEASE_WAIT, "Please stand by, this may take a few seconds ..." }, // progress
+ { PRESS_FINISH, "Please press {0} to exit the installation." }, // finish
+ { PREVIOUS, "Previous" }, // button
+ { PROGRESS, "Progress" }, // progress
+ { README, "README" }, // readme
+ { SELECT, "Select" }, // button (approval in JFileChooser)
+ { SELECT_INSTALLATION_TYPE, "Please select the installation type" }, // installation type
+ { SELECT_JAVA_HOME, "Please select the java home directory" }, // directory
+ { SELECT_LANGUAGE, "Please select your language" }, // language
+ { SELECT_TARGET_DIRECTORY, "Please select the target directory" }, // directory
+ { SOURCES, "Sources" }, // installation type
+ { STANDARD, "Standard (core, library modules, demos, examples, documentation)" }, // installation type
+ { STANDALONE, "Standalone (a callable .jar file)" }, // installation type
+ { SUCCESS, "You successfully installed Jython {0} to directory {1}." }, // success
+ { TARGET_DIRECTORY_PROPERTY, "Target directory" }, // property as title
+ { TARGET_JAVA_HOME_PROPERTY, "Target java home" }, // property as title
+ { UNABLE_CREATE_DIRECTORY, "Unable to create directory {0}." }, // error
+ { UNABLE_CREATE_FILE, "Unable to create file {0}." }, // error
+ { UNABLE_TO_DELETE, "Unable to delete {0}" }, // error
+ { UNEXPECTED_URL, "Unexpected URL {0} found for installation jar file." }, // error
+ { VERSION_INFO, "You are about to install Jython version {0}" }, // version
+ { WELCOME_TO_JYTHON, "Welcome to Jython !" }, // welcome
+ { ZIP_ENTRY_SIZE, "Size of zip entry {0} unknown." }, // error
+ { ZIP_ENTRY_TOO_BIG, "Zip entry {0} too big." }, // error
+
+ // console texts (C_*) should not contain special characters (like e.g. ü)
+ { C_ACCEPT, "Do you accept the license agreement ?" }, // license
+ { C_ALL, "All (everything, including sources)" }, // installation type
+ { C_AT_ANY_TIME_CANCEL, "(at any time, answer {0} to cancel the installation)" }, // console
+ { C_AVAILABLE_LANGUAGES, "For the installation process, the following languages are available: {0}" }, // console
+ { C_CHECK_JAVA_VERSION, "Checking java version ..." }, // progress
+ { C_CLEAR_DIRECTORY, "Contents of directory {0} will be deleted now! Are you sure to proceed ?" }, //console
+ { C_CONFIRM_TARGET, "Please confirm copying of files to directory {0}" }, // console
+ { C_CONGRATULATIONS, "Congratulations!" }, // congratulations
+ { C_CREATE_DIRECTORY, "Unable to find directory {0}, create it ?" }, // console
+ { C_ENTER_TARGET_DIRECTORY, "Please enter the target directory" }, // console
+ { C_ENTER_JAVA_HOME, "Please enter the java home directory (empty for using the current java runtime)" }, // console
+ { C_ENGLISH, "English" }, // language
+ { C_EXCLUDE, "Do you want to exclude parts from the installation ?" }, // installation type
+ { C_GENERATING_START_SCRIPTS, "Generating start scripts ..." }, // progress
+ { C_GERMAN, "German" }, // language
+ { C_INCLUDE, "Do you want to install additional parts ?" }, // installation type
+ { C_INEXCLUDE_PARTS, "The following parts are selectable ({0} = no more)" }, // installation type
+ { C_INSTALL_TYPES, "The following installation types are available:" }, // installation type
+ { C_INVALID_ANSWER, "Answer {0} is not valid here" }, // error
+ { C_JAVA_VERSION, "Your java version to start Jython is: {0} / {1}" }, // version
+ { C_MINIMUM, "Minimum (core)" }, // installation type
+ { C_NO, "n" }, // answer
+ { C_NO_BIN_DIRECTORY, "There is no /bin directory below {0}." }, // error
+ { C_NO_JAVA_EXECUTABLE, "No java executable found in {0}." }, // error
+ { C_NO_VALID_JAVA, "No valid java found in {0}." }, // error
+ { C_NON_EMPTY_TARGET_DIRECTORY, "Target directory {0} is not empty" }, // error
+ { C_NOT_A_DIRECTORY, "{0} is not a directory. " }, // error
+ { C_NOT_FOUND, "{0} not found. " }, // error
+ { C_OS_VERSION, "Your operating system version is: {0} / {1}" }, // version
+ { C_OVERWRITE_DIRECTORY, "Directory {0} is not empty - ok to overwrite contents ?" }, // console
+ { C_PACKING_STANDALONE_JAR, "Packing standalone " + JarInstaller.JYTHON_JAR + " ..." }, // progress
+ { C_PROCEED, "Please press Enter to proceed" }, // console
+ { C_PROCEED_ANYWAY, "Please press Enter to proceed anyway" }, // console
+ { C_READ_LICENSE, "Do you want to read the license agreement now ?" }, // license
+ { C_READ_README, "Do you want to show the contents of README ?" }, // readme
+ { C_SCHEDULED, "{0} scheduled for installation" }, // installation type
+ { C_SELECT_INSTALL_TYPE, "Please select the installation type" }, // installation type
+ { C_SELECT_LANGUAGE, "Please select your language" }, // language
+ { C_SILENT_INSTALLATION, "Performing silent installation" }, // installation mode
+ { C_STANDALONE, "Standalone (a single, executable .jar)" }, //installation mode
+ { C_STANDARD, "Standard (core, library modules, demos and examples, documentation)" }, // installation type
+ { C_SUCCESS, "You successfully installed Jython {0} to directory {1}." }, // success
+ { C_SUMMARY, "Summary:" }, // summary
+ { C_TO_CURRENT_JAVA, "Warning: switching back to current JDK due to error: {0}." }, // warning
+ { C_UNABLE_CREATE_DIRECTORY, "Unable to create directory {0}." }, // error
+ { C_UNABLE_CREATE_TMPFILE, "Unable to create temp file {0}." }, // error
+ { C_UNSCHEDULED, "{0} excluded from installation" }, // installation type
+ { C_UNABLE_TO_DELETE, "Unable to delete {0}" }, // error
+ { C_UNSUPPORTED_JAVA, "This java version is not supported." }, // version
+ { C_UNSUPPORTED_OS, "This operating system might not be fully supported." }, // version
+ { C_USING_TYPE, "Using installation type {0}" }, // installation type
+ { C_VERSION_INFO, "You are about to install Jython version {0}" }, // version
+ { C_WELCOME_TO_JYTHON, "Welcome to Jython !" }, // welcome
+ { C_YES, "y" }, // answer
+
+ // END OF MATERIAL TO LOCALIZE
+ };
+
+ public Object[][] getContents() {
+ return contents;
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/TextConstants_de.java b/installer/src/java/org/python/util/install/TextConstants_de.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/TextConstants_de.java
@@ -0,0 +1,148 @@
+package org.python.util.install;
+
+import java.util.ListResourceBundle;
+
+public class TextConstants_de extends ListResourceBundle implements TextKeys, UnicodeSequences {
+
+ static final Object[][] contents = {
+ // Die folgenden Texte duerfen Umlaute und Sonderzeichen enthalten, aber nur als Unicode Escape Sequenzen aus UnicodeSequences
+ // The following texts may contain special characters, but only as unicode escape sequences from UnicodeSequences
+ { ACCEPT, "Ja, ich akzeptiere" }, // license
+ { ALL, "Alles (volle Installation, inklusive Quellcode)" }, // installation type
+ { BROWSE, "Suchen..." }, // button (open the JFileChooser)
+ { CANCEL, "Abbrechen" }, // button text
+ { CHOOSE_LOCATION, "W"+a2+"hlen Sie das Verzeichnis, in das Jython installiert werden soll" }, // selection
+ { CHOOSE_JRE, "Bestimmen Sie die Java Version (JRE/JDK), mit welcher Jython gestartet werden soll" }, // selection
+ { CONFIRM_START, "Bitte dr"+u2+"cken Sie {0}, um die Installation zu starten" }, // overview
+ { CONGRATULATIONS, "Gratulation!" }, // congratulations
+ { CORE, "Kern" }, // installation type
+ { CREATED_DIRECTORY, "Verzeichnis {0} wurde erstellt" }, // directory
+ { CURRENT, "Das aktuelle" }, // directory
+ { CUSTOM, "Benutzerdefiniert" }, // installation type
+ { DEMOS_EXAMPLES, "Demos und Beispiele" }, // installation type
+ { DIRECTORIES_ONLY, "Nur Verzeichnisse" }, // file chooser
+ { DOCUMENTATION, "Dokumentation" }, // installation type
+ { DO_NOT_ACCEPT, "Nein, ich akzeptiere nicht" }, // license
+ { EMPTY_TARGET_DIRECTORY, "Das Zielverzeichnis darf nicht leer sein" }, // error
+ { ENGLISH, "Englisch" }, // language
+ { ERROR, "Fehler" }, // error
+ { ERROR_ACCESS_JARFILE, "Problem beim Zugriff auf das jar File" }, // error
+ { FINISH, "Beenden" }, // button
+ { GENERATING_START_SCRIPTS, "Start Scripts werden generiert ..." }, // progress
+ { GERMAN, "Deutsch" }, // language
+ { INFLATING, "Entpacke {0}" }, // progress
+ { INFORMATION, "Information" }, // information
+ { INSTALLATION_CANCELLED, "Sie haben die Installation abgebrochen." }, // final
+ { INSTALLATION_IN_PROGRESS, "Die Installation l"+a2+"uft" }, // progress
+ { INSTALLATION_TYPE_DESCRIPTION, "Die folgenden Installationstypen sind verf"+u2+"gbar" }, // installation type
+ { INSTALLATION_TYPE, "Installationstyp" }, // installation type
+ { JAVA_INFO, "Java Hersteller / Version" }, // version
+ { JAR_NOT_FOUND, "Jar File {0} nicht gefunden." }, // error
+ { JYTHON_INSTALL, "Jython Installation" }, // title
+ { LANGUAGE_PROPERTY, "Sprache" }, // language
+ { LIBRARY_MODULES, "Bibliotheksmodule" }, // installation type
+ { LICENSE, "Lizenzvereinbarung" }, // license
+ { MAYBE_NOT_SUPPORTED, "Eventuell nicht unterst"+u2+"tzt" }, // version
+ { MINIMUM, "Minimum (Kern)" }, // installation type
+ { NEXT, "Weiter" }, // button
+ { NON_EMPTY_TARGET_DIRECTORY, "Das Zielverzeichnis enth"+a2+"lt bereits Daten." }, // error
+ { NO_MANIFEST, "Jar File {0} enth"+a2+"lt kein Manifest." }, // error
+ { NOT_OK, "Nicht ok !" }, // version
+ { OK, "Ok" }, // version
+ { OS_INFO, "Betriebssystem / Version" }, // version
+ { OTHER, "Ein abweichendes" }, // directory
+ { OVERVIEW_DESCRIPTION, "Sie haben folgende Einstellungen f"+u2+"r die Installation ausgew"+a2+"hlt" }, // overview
+ { OVERVIEW_TITLE, U2+"bersicht "+u2+"ber die gew"+a2+"hlten Einstellungen" }, // overview
+ { PACKING_STANDALONE_JAR, "Das standalone " + JarInstaller.JYTHON_JAR + " File wird erstellt ..." }, // progress
+ { PLEASE_ACCEPT_LICENSE, "Bitte lesen und akzeptieren Sie die Lizenzvereinbarung" }, // license
+ { PLEASE_README, "Bitte lesen Sie die folgenden Informationen" }, // readme
+ { PLEASE_READ_LICENSE, "Bitte lesen Sie die Lizenzvereinbarung sorf"+a2+"ltig durch" }, // license
+ { PLEASE_WAIT, "Bitte um etwas Geduld, die Installation kann einige Sekunden dauern ..." }, // progress
+ { PRESS_FINISH, "Bitte dr"+u2+"cken Sie {0}, um die Installation abzuschliessen." }, // finish
+ { PREVIOUS, "Zur"+u2+"ck" }, // button
+ { PROGRESS, "Fortschritt" }, // progress
+ { README, "README" }, // readme
+ { SELECT, "Ausw"+a2+"hlen" }, // button (approval in JFileChooser)
+ { SELECT_INSTALLATION_TYPE, "Bitte w"+a2+"hlen Sie den Installationstyp" }, // installation type
+ { SELECT_JAVA_HOME, "Bitte w"+a2+"hlen Sie das Java Home Verzeichnis" }, // directory
+ { SELECT_LANGUAGE, "Bitte w"+a2+"hlen Sie Ihre Sprache" }, // language
+ { SELECT_TARGET_DIRECTORY, "Bitte w"+a2+"hlen Sie das Zielverzeichnis" }, // directory
+ { SOURCES, "Quellcode" }, // installation type
+ { STANDARD, "Standard (Kern, Bibliotheksmodule, Demos, Beispiele, Dokumentation)" }, // installation type
+ { STANDALONE, "Standalone (ein ausf"+u2+"hrbares .jar File)" }, // installation type
+ { SUCCESS, "Sie haben Jython {0} erfolgreich im Verzeichnis {1} installiert." }, // final
+ { TARGET_DIRECTORY_PROPERTY, "Zielverzeichnis" }, // property als Titel
+ { TARGET_JAVA_HOME_PROPERTY, "Java Home Verzeichnis" }, // property als Titel
+ { UNABLE_CREATE_DIRECTORY, "Fehler beim Erstellen von Verzeichnis {0}." }, // error
+ { UNABLE_CREATE_FILE, "Fehler beim Erstellen von File {0}." }, // error
+ { UNABLE_TO_DELETE, "Fehler beim L"+o2+"schen von {0}" }, // console
+ { UNEXPECTED_URL, "Das Jar File f"+u2+"r die Installation weist eine unerwartete URL {0} auf." }, // error
+ { VERSION_INFO, "Sie sind im Begriff, Jython Version {0} zu installieren." }, // version
+ { WELCOME_TO_JYTHON, "Willkommen bei Jython !" }, // welcome
+ { ZIP_ENTRY_SIZE, "Der Zip Eintrag {0} hat eine unbekannte Gr"+o2+"sse." }, // error
+ { ZIP_ENTRY_TOO_BIG, "Der Zip Eintrag {0} ist zu gross." }, // error
+
+ // Konsole Texte (beginnend mit C_) duerfen keine Umlaute und andere Sonderzeichen enthalten:
+ // console texts (beginning with C_) must not contain special characters (use ASCII only):
+ { C_ACCEPT, "Akzeptieren Sie die Lizenzvereinbarung ?" }, // license
+ { C_ALL, "Alles (volle Installation, inklusive Quellcode)" }, // installation type
+ { C_AT_ANY_TIME_CANCEL, "(Sie koennen die Installation jederzeit durch Eingabe von {0} abbrechen)" }, // console
+ { C_AVAILABLE_LANGUAGES, "Die folgenden Sprachen sind fuer den Installationsvorgang verfuegbar: {0}" }, // languages
+ { C_CHECK_JAVA_VERSION, "Ueberpruefung der Java Version ..." }, // progress
+ { C_CLEAR_DIRECTORY, "Der Inhalt von Verzeichnis {0} wird anschliessend geloescht! Moechten Sie wirklich weiterfahren ?" }, //console
+ { C_CONFIRM_TARGET, "Bitte bestaetigen Sie den Start des Kopiervorgangs ins Verzeichnis {0}" }, // console
+ { C_CONGRATULATIONS, "Gratulation!" }, // congratulations
+ { C_CREATE_DIRECTORY, "Das Verzeichnis {0} gibt es nicht - soll es erstellt werden ?" }, // console
+ { C_ENTER_TARGET_DIRECTORY, "Bitte geben Sie das Zielverzeichnis ein" }, // console
+ { C_ENTER_JAVA_HOME, "Bitte geben Sie das gewuenschte Java Home Verzeichnis ein (Enter fuer das aktuelle)" }, // console
+ { C_ENGLISH, "Englisch" }, // language
+ { C_EXCLUDE, "Moechten Sie Teile von der Installation ausschliessen ?" }, // installation type
+ { C_GENERATING_START_SCRIPTS, "Start Scripts werden generiert ..." }, // progress
+ { C_GERMAN, "Deutsch" }, // language
+ { C_INCLUDE, "Moechten Sie weitere Teile installieren ?" }, // installation type
+ { C_INEXCLUDE_PARTS, "Folgende Teile stehen zur Auswahl ({0} = keine weiteren)" }, // installation type
+ { C_INSTALL_TYPES, "Die folgenden Installationstypen sind verfuegbar:" }, // installation type
+ { C_INVALID_ANSWER, "Die Antwort {0} ist hier nicht gueltig" }, // error
+ { C_JAVA_VERSION, "Ihre Java Version fuer den Start von Jython ist: {0} / {1}" }, // version
+ { C_MINIMUM, "Minimum (Kern)" }, // installation type
+ { C_NO, "n" }, // answer
+ { C_NO_BIN_DIRECTORY, "Es gibt kein /bin Verzeichnis unterhalb {0}." }, //error
+ { C_NO_JAVA_EXECUTABLE, "Es gibt kein ausfuehrbares java in {0}." }, // error
+ { C_NO_VALID_JAVA, "Keine gueltige Java Version gefunden in {0}." }, // error
+ { C_NON_EMPTY_TARGET_DIRECTORY, "Das Zielverzeichnis {0} enthaelt bereits Daten" }, // error
+ { C_NOT_A_DIRECTORY, "{0} ist kein Verzeichnis. " }, // error
+ { C_NOT_FOUND, "{0} nicht gefunden." }, // error
+ { C_OS_VERSION, "Ihre Betriebssystem Version ist: {0} / {1}" }, // version
+ { C_OVERWRITE_DIRECTORY, "Das Verzeichnis {0} enthaelt bereits Daten, und die Installation wuerde diese ueberschreiben - ok ?" }, // console
+ { C_PACKING_STANDALONE_JAR, "Das standalone " + JarInstaller.JYTHON_JAR + " File wird erstellt ..." }, // progress
+ { C_PROCEED, "Bitte druecken Sie Enter um weiterzufahren" }, // console
+ { C_PROCEED_ANYWAY, "Bitte druecken Sie Enter um trotzdem weiterzufahren" }, // console
+ { C_READ_LICENSE, "Moechten Sie die Lizenzvereinbarung jetzt lesen ?" }, // license
+ { C_READ_README, "Moechten Sie den Inhalt von README jetzt lesen ?" }, // readme
+ { C_SCHEDULED, "{0} zur Installation vorgemerkt" }, // installation type
+ { C_SELECT_INSTALL_TYPE, "Bitte waehlen Sie den Installationstyp" }, // installation type
+ { C_SELECT_LANGUAGE, "Bitte waehlen Sie Ihre Sprache" }, // language
+ { C_SILENT_INSTALLATION, "Die Installation wird ohne Benutzerinteraktion ausgefuehrt" }, // installation mode
+ { C_STANDALONE, "Standalone (ein ausfuehrbares .jar File)" }, //installation mode
+ { C_STANDARD, "Standard (Kern, Bibliotheksmodule, Demos und Beispiele, Dokumentation)" }, // installation type
+ { C_SUCCESS, "Sie haben Jython {0} erfolgreich im Verzeichnis {1} installiert." }, // final
+ { C_SUMMARY, "Zusammenfassung:" }, // summary
+ { C_TO_CURRENT_JAVA, "Warnung: Wechsel zum aktuellen JDK wegen Fehler: {0}." }, // warning
+ { C_UNABLE_CREATE_DIRECTORY, "Fehler beim Erstellen von Verzeichnis {0}." }, // error
+ { C_UNABLE_CREATE_TMPFILE, "Fehler beim Erstellen der temporaeren Datei {0}." }, // error
+ { C_UNABLE_TO_DELETE, "Fehler beim Loeschen von {0}" }, // console
+ { C_UNSCHEDULED, "{0} von der Installation ausgeschlossen" }, // installation type
+ { C_UNSUPPORTED_JAVA, "Diese Java Version ist nicht unterstuetzt." }, // version
+ { C_UNSUPPORTED_OS, "Dieses Betriebssystem ist eventuell nicht vollstaendig unterstuetzt." }, // version
+ { C_USING_TYPE, "Installationstyp ist {0}" }, // installation type
+ { C_VERSION_INFO, "Sie sind im Begriff, Jython Version {0} zu installieren." }, // version
+ { C_WELCOME_TO_JYTHON, "Willkommen bei Jython !" }, // welcome
+ { C_YES, "j" }, // answer
+
+ };
+
+ public Object[][] getContents() {
+ return contents;
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/TextConstants_en.java b/installer/src/java/org/python/util/install/TextConstants_en.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/TextConstants_en.java
@@ -0,0 +1,5 @@
+package org.python.util.install;
+
+public class TextConstants_en extends TextConstants {
+ // need this as placeholder
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/TextKeys.java b/installer/src/java/org/python/util/install/TextKeys.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/TextKeys.java
@@ -0,0 +1,135 @@
+package org.python.util.install;
+
+public interface TextKeys {
+ public static final String ACCEPT = "ACCEPT";
+ public static final String ACCEPT_PROPERTY = "ACCEPT_PROPERTY";
+ public static final String ALL = "ALL";
+ public static final String BROWSE = "BROWSE";
+ public static final String CANCEL = "CANCEL";
+ public static final String CHOOSE_LOCATION = "CHOOSE_LOCATION";
+ public static final String CHOOSE_JRE = "CHOOSE_JRE";
+ public static final String CONFIRM_START = "CONFIRM_START";
+ public static final String CONGRATULATIONS = "CONGRATULATIONS";
+ public static final String CORE = "CORE";
+ public static final String CREATED_DIRECTORY = "CREATED_DIRECTORY";
+ public static final String CURRENT = "CURRENT";
+ public static final String CUSTOM = "CUSTOM";
+ public static final String DEMOS_EXAMPLES = "DEMOS_EXAMPLES";
+ public static final String DIRECTORIES_ONLY = "DIRECTORIES_ONLY";
+ public static final String DOCUMENTATION = "DOCUMENTATION";
+ public static final String DO_NOT_ACCEPT = "DO_NOT_ACCEPT";
+ public static final String EMPTY_TARGET_DIRECTORY = "EMPTY_TARGET_DIRECTORY";
+ public static final String ENGLISH = "ENGLISH";
+ public static final String ERROR = "ERROR";
+ public static final String ERROR_ACCESS_JARFILE = "ERROR_ACCESS_JARFILE";
+ public static final String FINISH = "FINISH";
+ public static final String GENERATING_START_SCRIPTS = "GENERATE_START_SCRIPTS";
+ public static final String GERMAN = "GERMAN";
+ public static final String INFLATING = "INFLATING";
+ public static final String INFORMATION = "INFORMATION";
+ public static final String INSTALLATION_CANCELLED = "INSTALLATION_CANCELLED";
+ public static final String INSTALLATION_IN_PROGRESS = "INSTALLATION_IN_PROGRESS";
+ public static final String INSTALLATION_TYPE_DESCRIPTION = "INSTALLATION_TYPE_DESCRIPTION";
+ public static final String INSTALLATION_TYPE = "INSTALLATION_TYPE";
+ public static final String JAR_NOT_FOUND = "JAR_NOT_FOUND";
+ public static final String JAVA_INFO = "JAVA_INFO";
+ public static final String JYTHON_INSTALL = "JYTHON_INSTALL";
+ public static final String LANGUAGE_PROPERTY = "LANGUAGE_PROPERTY";
+ public static final String LIBRARY_MODULES = "LIBRARY_MODULES";
+ public static final String LICENSE = "LICENSE";
+ public static final String MAYBE_NOT_SUPPORTED = "MAYBE_NOT_SUPPORTED";
+ public static final String MINIMUM = "MINIMUM";
+ public static final String NEXT = "NEXT";
+ public static final String NON_EMPTY_TARGET_DIRECTORY = "NON_EMPTY_TARGET_DIRECTORY";
+ public static final String NO_MANIFEST = "NO_MANIFEST";
+ public static final String NOT_OK = "NOT_OK";
+ public static final String OK = "OK";
+ public static final String OS_INFO = "OS_INFO";
+ public static final String OTHER = "OTHER";
+ public static final String OVERVIEW_DESCRIPTION = "OVERVIEW_DESCRIPTION";
+ public static final String OVERVIEW_TITLE = "OVERVIEW_TITLE";
+ public static final String PACKING_STANDALONE_JAR = "PACKING_STANDALONE_JAR";
+ public static final String PLEASE_ACCEPT_LICENSE = "PLEASE_ACCEPT_LICENSE";
+ public static final String PLEASE_README = "PLEASE_README";
+ public static final String PLEASE_READ_LICENSE = "PLEASE_READ_LICENSE";
+ public static final String PLEASE_WAIT = "PLEASE_WAIT";
+ public static final String PRESS_FINISH = "PRESS_FINISH";
+ public static final String PREVIOUS = "PREVIOUS";
+ public static final String PROGRESS = "PROGRESS";
+ public static final String README = "README";
+ public static final String SELECT = "SELECT";
+ public static final String SELECT_INSTALLATION_TYPE = "SELECT_INSTALLATION_TYPE";
+ public static final String SELECT_JAVA_HOME = "SELECT_JAVA_HOME";
+ public static final String SELECT_LANGUAGE = "SELECT_LANGUAGE";
+ public static final String SELECT_TARGET_DIRECTORY = "SELECT_TARGET_DIRECTORY";
+ public static final String SOURCES = "SOURCES";
+ public static final String STANDARD = "STANDARD";
+ public static final String STANDALONE = "STANDALONE";
+ public static final String SUCCESS = "SUCCESS";
+ public static final String TARGET_DIRECTORY_PROPERTY = "TARGET_DIRECTORY_PROPERTY";
+ public static final String TARGET_JAVA_HOME_PROPERTY = "TARGET_JAVA_HOME_PROPERTY";
+ public static final String UNABLE_CREATE_DIRECTORY = "UNABLE_CREATE_DIRECTORY";
+ public static final String UNABLE_CREATE_FILE = "UNABLE_CREATE_FILE";
+ public static final String UNABLE_TO_DELETE = "UNABLE_TO_DELETE";
+ public static final String UNEXPECTED_URL = "UNEXPECTED_URL";
+ public static final String VERSION_INFO = "VERSION_INFO";
+ public static final String WELCOME_TO_JYTHON = "WELCOME_TO_JYTHON";
+ public static final String ZIP_ENTRY_SIZE = "ZIP_ENTRY_SIZE";
+ public static final String ZIP_ENTRY_TOO_BIG = "ZIP_ENTRY_TOO_BIG";
+
+ // console texts
+ public static final String C_ACCEPT = "C_ACCEPT";
+ public static final String C_ALL = "C_ALL";
+ public static final String C_AT_ANY_TIME_CANCEL = "C_AT_ANY_TIME_CANCEL";
+ public static final String C_AVAILABLE_LANGUAGES = "C_AVAILABLE_LANGUAGES";
+ public static final String C_CHECK_JAVA_VERSION = "C_CHECK_JAVA_VERSION";
+ public static final String C_CLEAR_DIRECTORY = "C_CLEAR_DIRECTORY";
+ public static final String C_CONFIRM_TARGET = "C_CONFIRM_TARGET";
+ public static final String C_CONGRATULATIONS = "C_CONGRATULATIONS";
+ public static final String C_CREATE_DIRECTORY = "C_CREATE_DIRECTORY";
+ public static final String C_ENGLISH = "C_ENGLISH";
+ public static final String C_ENTER_TARGET_DIRECTORY = "C_ENTER_TARGET_DIRECTORY";
+ public static final String C_ENTER_JAVA_HOME = "C_ENTER_JAVA_HOME";
+ public static final String C_EXCLUDE = "C_EXCLUDE";
+ public static final String C_GENERATING_START_SCRIPTS = "C_GENERATE_START_SCRIPTS";
+ public static final String C_GERMAN = "C_GERMAN";
+ public static final String C_INCLUDE = "C_INCLUDE";
+ public static final String C_INEXCLUDE_PARTS = "C_INEXCLUDE_PARTS";
+ public static final String C_INSTALL_TYPES = "C_INSTALL_TYPES";
+ public static final String C_INVALID_ANSWER = "C_INVALID_ANSWER";
+ public static final String C_JAVA_VERSION = "C_JAVA_VERSION";
+ public static final String C_MINIMUM = "C_MINIMUM";
+ public static final String C_NO = "C_NO";
+ public static final String C_NO_BIN_DIRECTORY = "C_NO_BIN_DIRECTORY";
+ public static final String C_NO_JAVA_EXECUTABLE = "C_NO_JAVA_EXECUTABLE";
+ public static final String C_NO_VALID_JAVA = "C_NO_VALID_JAVA";
+ public static final String C_NON_EMPTY_TARGET_DIRECTORY = "C_NON_EMPTY_TARGET_DIRECTORY";
+ public static final String C_NOT_A_DIRECTORY = "C_NOT_A_DIRECTORY";
+ public static final String C_NOT_FOUND = "C_NOT_FOUND";
+ public static final String C_OS_VERSION = "C_OS_VERSION";
+ public static final String C_OVERWRITE_DIRECTORY = "C_OVERWRITE_DIRECTORY";
+ public static final String C_PACKING_STANDALONE_JAR = "C_PACKING_STANDALONE_JAR";
+ public static final String C_PROCEED = "C_PROCEED";
+ public static final String C_PROCEED_ANYWAY = "C_PROCEED_ANYWAY";
+ public static final String C_READ_LICENSE = "C_READ_LICENSE";
+ public static final String C_READ_README = "C_READ_README";
+ public static final String C_SCHEDULED = "C_SCHEDULED";
+ public static final String C_SELECT_INSTALL_TYPE = "C_SELECT_INSTALL_TYPE";
+ public static final String C_SELECT_LANGUAGE = "C_SELECT_LANGUAGE";
+ public static final String C_SILENT_INSTALLATION = "C_SILENT_INSTALLATION";
+ public static final String C_STANDALONE = "C_STANDALONE";
+ public static final String C_STANDARD = "C_STANDARD";
+ public static final String C_SUCCESS = "C_SUCCESS";
+ public static final String C_SUMMARY = "C_SUMMARY";
+ public static final String C_UNABLE_CREATE_TMPFILE = "C_UNABLE_CREATE_TMPFILE";
+ public static final String C_TO_CURRENT_JAVA = "C_TO_CURRENT_JAVA";
+ public static final String C_UNABLE_CREATE_DIRECTORY = "C_UNABLE_CREATE_DIRECTORY";
+ public static final String C_UNABLE_TO_DELETE = "C_UNABLE_TO_DELETE";
+ public static final String C_UNSCHEDULED = "C_UNSCHEDULED";
+ public static final String C_UNSUPPORTED_JAVA = "C_UNSUPPORTED_JAVA";
+ public static final String C_UNSUPPORTED_OS = "C_UNSUPPORTED_OS";
+ public static final String C_USING_TYPE = "C_USING_TYPE";
+ public static final String C_VERSION_INFO = "C_VERSION_INFO";
+ public static final String C_WELCOME_TO_JYTHON = "C_WELCOME_TO_JYTHON";
+ public static final String C_YES = "C_YES";
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/TypePage.java b/installer/src/java/org/python/util/install/TypePage.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/TypePage.java
@@ -0,0 +1,268 @@
+package org.python.util.install;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+
+public class TypePage extends AbstractWizardPage {
+
+ private static final String _CUSTOM_ACTION_COMMAND = "custom";
+
+ private JLabel _label;
+ private JRadioButton _allButton;
+ private JRadioButton _standardButton;
+ private JRadioButton _minimumButton;
+ private JRadioButton _standaloneButton;
+ private JRadioButton _customButton;
+
+ private JCheckBox _core;
+ private JCheckBox _mod;
+ private JCheckBox _demo;
+ private JCheckBox _doc;
+ private JCheckBox _src;
+
+ private boolean _firstTime = true;
+
+ public TypePage() {
+ super();
+ initComponents();
+ }
+
+ private void initComponents() {
+ TypeChangeListener typeChangeListener = new TypeChangeListener();
+
+ _label = new JLabel();
+
+ // radio buttons
+ _allButton = new JRadioButton();
+ _allButton.setActionCommand(Installation.ALL);
+ _allButton.addActionListener(typeChangeListener);
+ _standardButton = new JRadioButton();
+ _standardButton.setActionCommand(Installation.STANDARD);
+ _standardButton.addActionListener(typeChangeListener);
+ _minimumButton = new JRadioButton();
+ _minimumButton.setActionCommand(Installation.MINIMUM);
+ _minimumButton.addActionListener(typeChangeListener);
+ _standaloneButton = new JRadioButton();
+ _standaloneButton.setActionCommand(Installation.STANDALONE);
+ _standaloneButton.addActionListener(typeChangeListener);
+ _customButton = new JRadioButton();
+ _customButton.setActionCommand(_CUSTOM_ACTION_COMMAND);
+ _customButton.addActionListener(typeChangeListener);
+ ButtonGroup radioButtonGroup = new ButtonGroup();
+ radioButtonGroup.add(_allButton);
+ radioButtonGroup.add(_standardButton);
+ radioButtonGroup.add(_minimumButton);
+ radioButtonGroup.add(_standaloneButton);
+ radioButtonGroup.add(_customButton);
+ JPanel radioPanel = new JPanel(new GridLayout(0, 1));
+ radioPanel.add(_allButton);
+ radioPanel.add(_standardButton);
+ radioPanel.add(_minimumButton);
+ radioPanel.add(_standaloneButton);
+ radioPanel.add(_customButton);
+
+ // check boxes
+ _core = new JCheckBox();
+ _core.setEnabled(false);
+ _mod = new JCheckBox();
+ _mod.setEnabled(true);
+ _mod.setActionCommand(InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES);
+ _mod.addActionListener(typeChangeListener);
+ _demo = new JCheckBox();
+ _demo.setEnabled(true);
+ _demo.setActionCommand(InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES);
+ _demo.addActionListener(typeChangeListener);
+ _doc = new JCheckBox();
+ _doc.setEnabled(true);
+ _doc.setActionCommand(InstallerCommandLine.INEXCLUDE_DOCUMENTATION);
+ _doc.addActionListener(typeChangeListener);
+ _src = new JCheckBox();
+ _src.setEnabled(true);
+ _src.setActionCommand(InstallerCommandLine.INEXCLUDE_SOURCES);
+ _src.addActionListener(typeChangeListener);
+
+ JPanel checkboxPanel = new JPanel();
+ GridLayout gridLayout = new GridLayout(5, 1);
+ checkboxPanel.setLayout(gridLayout);
+ checkboxPanel.add(_core);
+ checkboxPanel.add(_mod);
+ checkboxPanel.add(_demo);
+ checkboxPanel.add(_doc);
+ checkboxPanel.add(_src);
+
+ JPanel panel = new JPanel();
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ panel.setLayout(gridBagLayout);
+ GridBagConstraints gridBagConstraints = newGridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridwidth = 2;
+ panel.add(_label, gridBagConstraints);
+ gridBagConstraints.gridwidth = 1;
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ panel.add(radioPanel, gridBagConstraints);
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 1;
+ panel.add(checkboxPanel, gridBagConstraints);
+
+ add(panel);
+ }
+
+ protected String getTitle() {
+ return getText(INSTALLATION_TYPE);
+ }
+
+ protected String getDescription() {
+ return getText(INSTALLATION_TYPE_DESCRIPTION);
+ }
+
+ protected boolean isCancelVisible() {
+ return true;
+ }
+
+ protected boolean isPreviousVisible() {
+ return true;
+ }
+
+ protected boolean isNextVisible() {
+ return true;
+ }
+
+ protected JComponent getFocusField() {
+ InstallationType installationType = getInstallationType();
+ if (installationType.isAll()) {
+ return _allButton;
+ } else if (installationType.isMinimum()) {
+ return _minimumButton;
+ } else if (installationType.isStandalone()) {
+ return _standaloneButton;
+ } else if (installationType.isStandard()) {
+ return _standardButton;
+ } else {
+ return _customButton;
+ }
+ }
+
+ protected void activate() {
+ _label.setText(getText(SELECT_INSTALLATION_TYPE) + ": ");
+ _allButton.setText(getText(ALL));
+ _standardButton.setText(getText(STANDARD));
+ _minimumButton.setText(getText(MINIMUM));
+ _standaloneButton.setText(getText(STANDALONE));
+ _customButton.setText(getText(CUSTOM));
+ InstallationType installationType = getInstallationType();
+ if (installationType.isAll()) {
+ _allButton.setSelected(true);
+ } else if (installationType.isMinimum()) {
+ _minimumButton.setSelected(true);
+ } else if (installationType.isStandalone()) {
+ _standaloneButton.setSelected(true);
+ } else if (installationType.isStandard()) {
+ _standardButton.setSelected(true);
+ } else {
+ _customButton.setSelected(true);
+ }
+ _core.setText(getText(CORE));
+ _mod.setText(getText(LIBRARY_MODULES));
+ _demo.setText(getText(DEMOS_EXAMPLES));
+ _doc.setText(getText(DOCUMENTATION));
+ _src.setText(getText(SOURCES));
+ setCheckboxes(installationType);
+ }
+
+ protected void passivate() {
+ }
+
+ protected void beforeValidate() {
+ }
+
+ private InstallationType getInstallationType() {
+ InstallationType installationType;
+ if (_firstTime) {
+ _firstTime = false;
+ installationType = new InstallationType();
+ installationType.setStandard();
+ FrameInstaller.setInstallationType(installationType);
+ }
+ installationType = FrameInstaller.getInstallationType();
+ return installationType;
+ }
+
+ private final class TypeChangeListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ InstallationType installationType = FrameInstaller.getInstallationType();
+ String actionCommand = e.getActionCommand();
+ if (Installation.ALL.equals(actionCommand)) {
+ installationType.setAll();
+ setCheckboxes(installationType);
+ } else if (Installation.STANDARD.equals(actionCommand)) {
+ installationType.setStandard();
+ setCheckboxes(installationType);
+ } else if (Installation.MINIMUM.equals(actionCommand)) {
+ installationType.setMinimum();
+ setCheckboxes(installationType);
+ } else if (Installation.STANDALONE.equals(actionCommand)) {
+ installationType.setStandalone();
+ setCheckboxes(installationType);
+ } else if (_CUSTOM_ACTION_COMMAND.equals(actionCommand)) {
+ _mod.setEnabled(true);
+ _demo.setEnabled(true);
+ _doc.setEnabled(true);
+ _src.setEnabled(true);
+ } else {
+ boolean selected = ((JCheckBox) e.getSource()).isSelected();
+ if (InstallerCommandLine.INEXCLUDE_LIBRARY_MODULES.equals(actionCommand)) {
+ if (selected) {
+ installationType.addLibraryModules();
+ } else {
+ installationType.removeLibraryModules();
+ }
+ } else if (InstallerCommandLine.INEXCLUDE_DEMOS_AND_EXAMPLES.equals(actionCommand)) {
+ if (selected) {
+ installationType.addDemosAndExamples();
+ } else {
+ installationType.removeDemosAndExamples();
+ }
+ } else if (InstallerCommandLine.INEXCLUDE_DOCUMENTATION.equals(actionCommand)) {
+ if (selected) {
+ installationType.addDocumentation();
+ } else {
+ installationType.removeDocumentation();
+ }
+ } else if (InstallerCommandLine.INEXCLUDE_SOURCES.equals(actionCommand)) {
+ if (selected) {
+ installationType.addSources();
+ } else {
+ installationType.removeSources();
+ }
+ }
+ }
+ FrameInstaller.setInstallationType(installationType);
+ }
+ }
+
+ void setCheckboxes(InstallationType installationType) {
+ _core.setSelected(true);
+ _mod.setSelected(installationType.installLibraryModules());
+ _demo.setSelected(installationType.installDemosAndExamples());
+ _doc.setSelected(installationType.installDocumentation());
+ _src.setSelected(installationType.installSources());
+ _standaloneButton.setSelected(installationType.isStandalone());
+ _mod.setEnabled(!installationType.isPredefined());
+ _demo.setEnabled(!installationType.isPredefined());
+ _doc.setEnabled(!installationType.isPredefined());
+ _src.setEnabled(!installationType.isPredefined());
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/UnicodeSequences.java b/installer/src/java/org/python/util/install/UnicodeSequences.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/UnicodeSequences.java
@@ -0,0 +1,19 @@
+package org.python.util.install;
+
+/**
+ * Some unicode special characters
+ *
+ * @see http://www.unicode.org/charts/PDF/U0080.pdf
+ */
+public interface UnicodeSequences {
+
+ public static final String A2 = "\u00C4"; // German A umlaut: A with two dots above
+ public static final String a2 = "\u00E4"; // German a umlaut: a with two dots above
+
+ public static final String O2 = "\u00D6"; // German O umlaut: O with two dots above
+ public static final String o2 = "\u00F6"; // German o umlaut: o with two dots above
+
+ public static final String U2 = "\u00DC"; // German U umlaut: U with two dots above
+ public static final String u2 = "\u00FC"; // German u umlaut: u with two dots above
+
+}
diff --git a/installer/src/java/org/python/util/install/ValidationEvent.java b/installer/src/java/org/python/util/install/ValidationEvent.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ValidationEvent.java
@@ -0,0 +1,14 @@
+package org.python.util.install;
+
+import java.util.EventObject;
+
+public class ValidationEvent extends EventObject {
+
+ public ValidationEvent(AbstractWizardPage source) {
+ super(source);
+ }
+
+ public AbstractWizardPage getWizardPage() {
+ return (AbstractWizardPage) source;
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ValidationException.java b/installer/src/java/org/python/util/install/ValidationException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ValidationException.java
@@ -0,0 +1,19 @@
+package org.python.util.install;
+
+public class ValidationException extends Exception {
+ public ValidationException() {
+ super();
+ }
+
+ public ValidationException(String message) {
+ super(message);
+ }
+
+ public ValidationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ValidationException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ValidationInformationException.java b/installer/src/java/org/python/util/install/ValidationInformationException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ValidationInformationException.java
@@ -0,0 +1,21 @@
+package org.python.util.install;
+
+public class ValidationInformationException extends Exception {
+
+ public ValidationInformationException() {
+ super();
+ }
+
+ public ValidationInformationException(String message) {
+ super(message);
+ }
+
+ public ValidationInformationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ValidationInformationException(Throwable cause) {
+ super(cause);
+ }
+
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/ValidationListener.java b/installer/src/java/org/python/util/install/ValidationListener.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/ValidationListener.java
@@ -0,0 +1,11 @@
+package org.python.util.install;
+
+public interface ValidationListener {
+ public void validationFailed(ValidationEvent event, ValidationException exception);
+
+ public void validationInformationRequired(ValidationEvent event, ValidationInformationException exception);
+
+ public void validationStarted(ValidationEvent event);
+
+ public void validationSucceeded(ValidationEvent event);
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/Wizard.java b/installer/src/java/org/python/util/install/Wizard.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/Wizard.java
@@ -0,0 +1,90 @@
+package org.python.util.install;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+
+import javax.swing.JOptionPane;
+
+import org.python.util.install.driver.Autotest;
+
+public class Wizard extends AbstractWizard implements TextKeys {
+
+ public Wizard(JarInfo jarInfo, Autotest autotest) {
+ super();
+
+ setTitle(getText(JYTHON_INSTALL));
+
+ LanguagePage languagePage = new LanguagePage(jarInfo);
+ LicensePage licensePage = new LicensePage(jarInfo);
+ licensePage.setValidator(new LicensePageValidator(licensePage));
+ TypePage typePage = new TypePage();
+ DirectorySelectionPage directoryPage = new DirectorySelectionPage(jarInfo);
+ directoryPage.setValidator(new DirectorySelectionPageValidator(directoryPage));
+ JavaSelectionPage javaPage = new JavaSelectionPage();
+ javaPage.setValidator(new JavaSelectionPageValidator(javaPage));
+ OverviewPage overviewPage = new OverviewPage();
+ ProgressPage progressPage = new ProgressPage(jarInfo, autotest);
+ ReadmePage readmePage = new ReadmePage(jarInfo);
+ SuccessPage successPage = new SuccessPage(jarInfo);
+
+ this.addPage(languagePage);
+ this.addPage(licensePage);
+ this.addPage(typePage);
+ this.addPage(directoryPage);
+ this.addPage(javaPage);
+ this.addPage(overviewPage);
+ this.addPage(progressPage);
+ this.addPage(readmePage);
+ this.addPage(successPage);
+
+ setSize(720, 330);
+ centerOnScreen();
+ validate();
+ }
+
+ protected boolean finish() {
+ return true;
+ }
+
+ protected String getCancelString() {
+ return getText(CANCEL);
+ }
+
+ protected String getFinishString() {
+ return getText(FINISH);
+ }
+
+ protected String getNextString() {
+ return getText(NEXT);
+ }
+
+ protected String getPreviousString() {
+ return getText(PREVIOUS);
+ }
+
+ public void validationStarted(ValidationEvent event) {
+ }
+
+ public void validationFailed(ValidationEvent event, ValidationException exception) {
+ JOptionPane.showMessageDialog(this, exception.getMessage(), getText(TextKeys.ERROR), JOptionPane.ERROR_MESSAGE);
+ }
+
+ public void validationInformationRequired(ValidationEvent event, ValidationInformationException exception) {
+ JOptionPane.showMessageDialog(this, exception.getMessage(), getText(INFORMATION),
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ public void validationSucceeded(ValidationEvent event) {
+ }
+
+ private final String getText(String textKey) {
+ return Installation.getText(textKey);
+ }
+
+ private void centerOnScreen() {
+ Dimension dim = getToolkit().getScreenSize();
+ Rectangle rectBounds = getBounds();
+ setLocation((dim.width - rectBounds.width) / 2, (dim.height - rectBounds.height) / 2);
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/WizardEvent.java b/installer/src/java/org/python/util/install/WizardEvent.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/WizardEvent.java
@@ -0,0 +1,13 @@
+package org.python.util.install;
+
+import java.util.EventObject;
+
+public class WizardEvent extends EventObject {
+ public WizardEvent(AbstractWizard source) {
+ super(source);
+ }
+
+ public AbstractWizard getWizard() {
+ return (AbstractWizard) source;
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/WizardHeader.java b/installer/src/java/org/python/util/install/WizardHeader.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/WizardHeader.java
@@ -0,0 +1,89 @@
+package org.python.util.install;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JSeparator;
+
+public class WizardHeader extends AbstractWizardHeader {
+ private static final Dimension _iconSize = new Dimension(100, 60);
+
+ private JLabel _descriptionLabel;
+ private JSeparator _headerSeparator;
+ private JLabel _iconLabel;
+ private JLabel _titleLabel;
+
+ WizardHeader() {
+ super();
+ initComponents();
+ }
+
+ private void initComponents() {
+ GridBagConstraints gridBagConstraints;
+
+ _titleLabel = new JLabel();
+ _descriptionLabel = new JLabel();
+ _iconLabel = new JLabel();
+ _headerSeparator = new JSeparator();
+
+ setLayout(new GridBagLayout());
+
+ setBackground(new Color(255, 255, 255));
+ _titleLabel.setFont(_titleLabel.getFont().deriveFont(Font.BOLD, 14f));
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.insets = new Insets(2, 2, 2, 2);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ add(_titleLabel, gridBagConstraints);
+
+ _descriptionLabel.setFont(_descriptionLabel.getFont().deriveFont(Font.PLAIN));
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.insets = new Insets(2, 7, 2, 2);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.weighty = 1.0;
+ add(_descriptionLabel, gridBagConstraints);
+
+ _iconLabel.setMinimumSize(_iconSize);
+ _iconLabel.setMaximumSize(_iconSize);
+ _iconLabel.setPreferredSize(_iconSize);
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridheight = 2;
+ gridBagConstraints.insets = new Insets(2, 2, 2, 2);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHEAST;
+ add(_iconLabel, gridBagConstraints);
+
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ add(_headerSeparator, gridBagConstraints);
+ }
+
+ protected void setDescription(String description) {
+ _descriptionLabel.setText(description);
+ }
+
+ protected void setIcon(ImageIcon icon) {
+ _iconLabel.setIcon(icon);
+ }
+
+ protected void setTitle(String title) {
+ _titleLabel.setText(title);
+ }
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/WizardListener.java b/installer/src/java/org/python/util/install/WizardListener.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/WizardListener.java
@@ -0,0 +1,13 @@
+package org.python.util.install;
+
+public interface WizardListener {
+ public void wizardCancelled(WizardEvent event);
+
+ public void wizardFinished(WizardEvent event);
+
+ public void wizardNext(WizardEvent event);
+
+ public void wizardPrevious(WizardEvent event);
+
+ public void wizardStarted(WizardEvent event);
+}
\ No newline at end of file
diff --git a/installer/src/java/org/python/util/install/driver/Autotest.java b/installer/src/java/org/python/util/install/driver/Autotest.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/Autotest.java
@@ -0,0 +1,274 @@
+package org.python.util.install.driver;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.python.util.install.FileHelper;
+import org.python.util.install.Installation;
+import org.python.util.install.InstallationListener;
+import org.python.util.install.InstallerCommandLine;
+import org.python.util.install.JavaHomeHandler;
+import org.python.util.install.JavaVersionTester;
+import org.python.util.install.Installation.JavaVersionInfo;
+
+public abstract class Autotest implements InstallationListener {
+
+ private static final String _DIR_SUFFIX = "_dir";
+
+ private static int _count = 0; // unique test number
+ private static File _rootDirectory = null;
+ private static JavaVersionInfo _systemDefaultJavaVersion;
+
+ private String _name;
+ private File _targetDir;
+ private JavaHomeHandler _javaHomeHandler;
+ private boolean _verbose;
+ private String[] _commandLineArgs;
+ private Verifier _verifier;
+
+ /**
+ * constructor
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ protected Autotest(InstallerCommandLine commandLine) throws IOException, DriverException {
+ _count++;
+ buildName();
+ if (_rootDirectory == null) {
+ createRootDirectory();
+ }
+ createTargetDirectory();
+ setCommandLineArgs(new String[0]); // a priori value
+ _verbose = commandLine.hasVerboseOption();
+ _javaHomeHandler = commandLine.getJavaHomeHandler();
+ }
+
+ /**
+ * @return the root directory for all test installations
+ */
+ protected static File getRootDir() {
+ return _rootDirectory;
+ }
+
+ /**
+ * @return the target directory of this test
+ */
+ protected File getTargetDir() {
+ return _targetDir;
+ }
+
+ /**
+ * @return the name of this test
+ */
+ protected String getName() {
+ return _name;
+ }
+
+ /**
+ * @return the array of command line arguments
+ */
+ protected String[] getCommandLineArgs() {
+ return _commandLineArgs;
+ }
+
+ /**
+ * set the array of command line arguments
+ *
+ * @param commandLineArgs
+ */
+ protected void setCommandLineArgs(String[] commandLineArgs) {
+ _commandLineArgs = commandLineArgs;
+ }
+
+ /**
+ * @return the java home handler, can be asked for deviation using <code>isDeviation()</code>.
+ */
+ protected JavaHomeHandler getJavaHomeHandler() {
+ return _javaHomeHandler;
+ }
+
+ /**
+ * @return <code>true</code> if this test should be verbose
+ */
+ protected boolean isVerbose() {
+ return _verbose;
+ }
+
+ /**
+ * @return the name suffix for this test
+ */
+ protected abstract String getNameSuffix();
+
+ /**
+ * @throws DriverException if the target directory does not exist or is empty (installation failed)
+ */
+ protected void assertTargetDirNotEmpty() throws DriverException {
+ File targetDir = getTargetDir();
+ if (targetDir != null) {
+ if (targetDir.exists() && targetDir.isDirectory()) {
+ if (targetDir.listFiles().length > 0) {
+ return;
+ }
+ }
+ }
+ throw new DriverException("installation failed for " + targetDir.getAbsolutePath());
+ }
+
+ /**
+ * Convenience method to add the additional arguments, if specified behind the -A option
+ * <p>
+ * This adds (if present):
+ * <ul>
+ * <li> target directory (should always be present)
+ * <li> verbose
+ * <li> jre
+ * </ul>
+ */
+ protected void addAdditionalArguments() {
+ if (getTargetDir() != null) {
+ addArgument("-d");
+ addArgument(getTargetDir().getAbsolutePath());
+ }
+ if (isVerbose()) {
+ addArgument("-v");
+ }
+ JavaHomeHandler javaHomeHandler = getJavaHomeHandler();
+ if (javaHomeHandler.isDeviation() && javaHomeHandler.isValidHome()) {
+ addArgument("-j");
+ addArgument(javaHomeHandler.getHome().getAbsolutePath());
+ }
+ }
+
+ /**
+ * Add an additional String argument to the command line arguments
+ *
+ * @param newArgument
+ */
+ protected void addArgument(String newArgument) {
+ setCommandLineArgs(addArgument(newArgument, getCommandLineArgs()));
+ }
+
+ /**
+ * set the verifier
+ */
+ protected void setVerifier(Verifier verifier) {
+ _verifier = verifier;
+ _verifier.setTargetDir(getTargetDir());
+ }
+
+ protected Verifier getVerifier() {
+ return _verifier;
+ }
+
+ //
+ // private stuff
+ //
+
+ /**
+ * build a test name containing some special characters (which will be used to create the target
+ * directory), and store it into <code>_name</code>.
+ */
+ private void buildName() {
+ StringBuilder b = new StringBuilder(24);
+ if (_count <= 99) {
+ b.append('0');
+ }
+ if (_count <= 9) {
+ b.append('0');
+ }
+ b.append(_count);
+ // explicitly use a blank, to nail down some platform specific problems
+ b.append(' ');
+ // add an exclamation mark if possible (see issue #1208)
+ if(canHandleExclamationMarks()) {
+ b.append('!');
+ }
+ b.append(getNameSuffix());
+ b.append('_');
+ _name = b.toString();
+ }
+
+ /**
+ * Add the new argument to the args array
+ *
+ * @param newArgument
+ * @param args
+ *
+ * @return the new String array, with size increased by 1
+ */
+ private String[] addArgument(String newArgument, String[] args) {
+ String[] newArgs = new String[args.length + 1];
+ for (int i = 0; i < args.length; i++) {
+ newArgs[i] = args[i];
+ }
+ newArgs[args.length] = newArgument;
+ return newArgs;
+ }
+
+ /**
+ * create the root directory for all automatic installations
+ * <p>
+ * assumed to be a subdirectory of java.io.tmpdir
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ private void createRootDirectory() throws IOException, DriverException {
+ File tmpFile = File.createTempFile("jython.autoinstall.root_", _DIR_SUFFIX);
+ if (FileHelper.createTempDirectory(tmpFile)) {
+ _rootDirectory = tmpFile;
+ } else {
+ throw new DriverException("unable to create root temporary directory");
+ }
+ }
+
+ /**
+ * create a target directory for a test installation
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ private void createTargetDirectory() throws IOException, DriverException {
+ File tmpFile = File.createTempFile(getName(), _DIR_SUFFIX, _rootDirectory);
+ if (FileHelper.createTempDirectory(tmpFile)) {
+ _targetDir = tmpFile;
+ } else {
+ throw new DriverException("unable to create temporary target directory");
+ }
+ }
+
+ /**
+ * Determine if the target directory may contain an exclamation mark (see also issue #1208).
+ * <p>
+ * Autotests can handle exclamation marks, if both the running and the system default java
+ * specification versions are 1.6 or higher. Class.getResource() was fixed for JDK 1.6, but only if the directory name does not end with '!'...
+ * <p>
+ * Currently there is no way on windows, because the enabledelayedexpansion in jython.bat cannot
+ * handle exclamation marks in variable names.
+ *
+ * @return <code>true</code> if we can handle exclamation marks, <code>false</code> otherwise
+ */
+ private boolean canHandleExclamationMarks() {
+ boolean exclamation = false;
+ if (!Installation.isWindows()) {
+ // get the running java specification version
+ String specificationVersion = System.getProperty(JavaVersionTester.JAVA_SPECIFICATION_VERSION,
+ "");
+ if (Installation.getJavaSpecificationVersion(specificationVersion) > 15) {
+ // get the system default java version
+ if (_systemDefaultJavaVersion == null) {
+ _systemDefaultJavaVersion = Installation.getDefaultJavaVersion();
+ }
+ if (_systemDefaultJavaVersion.getErrorCode() == Installation.NORMAL_RETURN) {
+ specificationVersion = _systemDefaultJavaVersion.getSpecificationVersion();
+ if (Installation.getJavaSpecificationVersion(specificationVersion) > 15) {
+ exclamation = true;
+ }
+ }
+ }
+ }
+ return exclamation;
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/ConsoleAutotest.java b/installer/src/java/org/python/util/install/driver/ConsoleAutotest.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/ConsoleAutotest.java
@@ -0,0 +1,30 @@
+package org.python.util.install.driver;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.python.util.install.InstallerCommandLine;
+
+public class ConsoleAutotest extends SilentAutotest {
+
+ private Collection _answers;
+
+ protected ConsoleAutotest(InstallerCommandLine commandLine) throws IOException, DriverException {
+ super(commandLine);
+ _answers = new ArrayList(50);
+ }
+
+ protected void addAnswer(String answer) {
+ _answers.add(answer);
+ }
+
+ protected Collection getAnswers() {
+ return _answers;
+ }
+
+ protected String getNameSuffix() {
+ return "consoleTest";
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/ConsoleDriver.java b/installer/src/java/org/python/util/install/driver/ConsoleDriver.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/ConsoleDriver.java
@@ -0,0 +1,58 @@
+package org.python.util.install.driver;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A class driving another class, while the other class is performing console I/O.
+ *
+ * <pre>
+ * (2) [Driver] receives question [Tunnel] sends question [Console] (1)
+ * (3) [Driver] sends answer [Tunnel] receives answer [Console] (4)
+ * </pre>
+ */
+public class ConsoleDriver extends Thread {
+
+ private Tunnel _tunnel;
+ private Collection _answers;
+
+ public ConsoleDriver(Tunnel tunnel, Collection answers) {
+ _tunnel = tunnel;
+ _answers = answers;
+ }
+
+ /**
+ * Send answers in the correct sequence, as soon as the question is asked.
+ */
+ public void run() {
+ Iterator answersIterator = _answers.iterator();
+ while (answersIterator.hasNext()) {
+ String answer = (String) answersIterator.next();
+ try {
+ readLine();
+ sendAnswer(answer);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void sendAnswer(String answer) throws IOException, InterruptedException {
+ Thread.sleep(100); // wait to be sure the question is really issued on the other end of the tunnel
+ System.out.println(" -> driving: '" + answer + "'");
+ answer += Tunnel.NEW_LINE;
+ _tunnel.getAnswerSenderStream().write(answer.getBytes());
+ _tunnel.getAnswerSenderStream().flush();
+ }
+
+ private void readLine() throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(_tunnel.getQuestionReceiverStream()));
+ reader.readLine();
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/DriverException.java b/installer/src/java/org/python/util/install/driver/DriverException.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/DriverException.java
@@ -0,0 +1,17 @@
+package org.python.util.install.driver;
+
+public class DriverException extends Exception {
+
+ public DriverException() {
+ super();
+ }
+
+ public DriverException(String message) {
+ super(message);
+ }
+
+ public DriverException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/GuiAutotest.java b/installer/src/java/org/python/util/install/driver/GuiAutotest.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/GuiAutotest.java
@@ -0,0 +1,188 @@
+package org.python.util.install.driver;
+
+import java.awt.AWTException;
+import java.awt.Robot;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.python.util.install.InstallerCommandLine;
+
+public class GuiAutotest extends Autotest {
+
+ private static final int _DEFAULT_DELAY = 500; // ms
+
+ private Robot _robot;
+ private List _keyActions;
+ private boolean _waiting = false;
+
+ protected GuiAutotest(InstallerCommandLine commandLine) throws IOException, DriverException {
+ super(commandLine);
+ _keyActions = new ArrayList();
+ // pass in the target directory, verbositiy
+ String[] args = new String[] { "-d", getTargetDir().getAbsolutePath() };
+ setCommandLineArgs(args);
+ addAdditionalArguments();
+ }
+
+ protected String getNameSuffix() {
+ return "guiTest";
+ }
+
+ /**
+ * add a normal key action (press and release)
+ *
+ * @param keyCode
+ */
+ protected void addKeyAction(int keyCode) {
+ KeyAction keyAction = new KeyAction(keyCode);
+ addKeyAction(keyAction);
+ }
+
+ /**
+ * add a normal key action (press and release), with a specific delay
+ *
+ * @param keyCode
+ * @param delay
+ */
+ protected void addKeyAction(int keyCode, int delay) {
+ KeyAction keyAction = new KeyAction(keyCode, delay);
+ addKeyAction(keyAction);
+ }
+
+ /**
+ * add a key action (press and release) which waits before executing
+ *
+ * @param keyCode
+ */
+ protected void addWaitingKeyAction(int keyCode) {
+ KeyAction keyAction = new KeyAction(keyCode, true);
+ addKeyAction(keyAction);
+ }
+
+ protected void setWaiting(boolean waiting) {
+ _waiting = waiting;
+ }
+
+ /**
+ * execute a single gui auto test
+ *
+ * @throws DriverException
+ */
+ protected void execute() throws DriverException {
+ try {
+ _robot = new Robot();
+
+ System.out.println("waiting 2 seconds for the first gui ... please do not change focus");
+ _robot.delay(2000); // initial gui load
+
+ Iterator actionsIterator = _keyActions.iterator();
+ while (actionsIterator.hasNext()) {
+ KeyAction keyAction = (KeyAction) actionsIterator.next();
+ setWaiting(keyAction.isWait());
+ if (isWaiting()) {
+ System.out.println("waiting for the installation to finish ...");
+ }
+ while (isWaiting()) {
+ try {
+ Thread.sleep(_DEFAULT_DELAY);
+ } catch (InterruptedException e) {
+ throw new DriverException(e);
+ }
+ }
+ executeKeyAction(keyAction);
+ }
+ } catch (AWTException ae) {
+ throw new DriverException(ae);
+ }
+
+ }
+
+ /**
+ * General KeyAction
+ */
+ protected static class KeyAction {
+ private int _keyCode;
+ private int _delay;
+ private boolean _wait;
+
+ /**
+ * @param keyCode
+ */
+ protected KeyAction(int keyCode) {
+ this(keyCode, _DEFAULT_DELAY);
+ }
+
+ /**
+ * @param keyCode
+ * @param delay in ms
+ */
+ protected KeyAction(int keyCode, int delay) {
+ super();
+ setKeyCode(keyCode);
+ setDelay(delay);
+ }
+
+ /**
+ * @param keyCode
+ * @param wait true if we should wait before executing this key action
+ */
+ protected KeyAction(int keyCode, boolean wait) {
+ this(keyCode, _DEFAULT_DELAY);
+ setWait(wait);
+ }
+
+ protected void setKeyCode(int keyCode) {
+ _keyCode = keyCode;
+ }
+
+ protected void setDelay(int delay) {
+ _delay = delay;
+ }
+
+ protected int getDelay() {
+ return _delay;
+ }
+
+ protected int getKeyCode() {
+ return _keyCode;
+ }
+
+ protected void setWait(boolean wait) {
+ _wait = wait;
+ }
+
+ protected boolean isWait() {
+ return _wait;
+ }
+ }
+
+ //
+ // interface InstallationListener
+ //
+
+ public void progressFinished() {
+ setWaiting(false);
+ }
+
+ //
+ // private stuff
+ //
+
+ private boolean isWaiting() {
+ return _waiting;
+ }
+
+ private void addKeyAction(KeyAction keyAction) {
+ _keyActions.add(keyAction);
+ }
+
+ private void executeKeyAction(KeyAction keyAction) {
+ _robot.delay(keyAction.getDelay());
+ _robot.keyPress(keyAction.getKeyCode());
+ _robot.delay(20); // delay was handled before press
+ _robot.keyRelease(keyAction.getKeyCode());
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/InstallationDriver.java b/installer/src/java/org/python/util/install/driver/InstallationDriver.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/InstallationDriver.java
@@ -0,0 +1,416 @@
+package org.python.util.install.driver;
+
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.python.util.install.ConsoleInstaller;
+import org.python.util.install.Installation;
+import org.python.util.install.InstallerCommandLine;
+import org.python.util.install.JavaHomeHandler;
+
+public class InstallationDriver {
+ private SilentAutotest[] _silentTests;
+ private ConsoleAutotest[] _consoleTests;
+ private GuiAutotest[] _guiTests;
+ private InstallerCommandLine _commandLine;
+
+ /**
+ * construct the driver
+ *
+ * @param commandLine the console arguments
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ public InstallationDriver(InstallerCommandLine commandLine) throws DriverException {
+ _commandLine = commandLine;
+ try {
+ buildSilentTests();
+ buildConsoleTests();
+ buildGuiTests();
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ }
+
+ /**
+ * execute all the automatic tests
+ *
+ * @throws DriverException
+ */
+ public void drive() throws DriverException {
+ try {
+ // silent tests
+ for (int i = 0; i < _silentTests.length; i++) {
+ driveSilentTest(_silentTests[i]);
+ }
+ // console tests
+ for (int i = 0; i < _consoleTests.length; i++) {
+ driveConsoleTest(_consoleTests[i]);
+ }
+ // gui tests
+ for (int i = 0; i < _guiTests.length; i++) {
+ driveGuiTest(_guiTests[i]);
+ }
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ }
+
+ /**
+ * execute a single console test
+ *
+ * @param consoleTest
+ * @throws DriverException
+ * @throws IOException
+ * @throws IOException
+ */
+ private void driveConsoleTest(ConsoleAutotest consoleTest) throws DriverException, IOException {
+ Tunnel _tunnel;
+ _tunnel = new Tunnel();
+ // have to fork off the driver thread first
+ ConsoleDriver driver = new ConsoleDriver(_tunnel, consoleTest.getAnswers());
+ driver.start();
+ // now do the installation
+ Installation.driverMain(consoleTest.getCommandLineArgs(), consoleTest, _tunnel);
+ _tunnel.close();
+ validate(consoleTest);
+ }
+
+ /**
+ * execute a single silent test
+ *
+ * @param silentTest
+ * @throws DriverException
+ */
+ private void driveSilentTest(SilentAutotest silentTest) throws DriverException {
+ Installation.driverMain(silentTest.getCommandLineArgs(), silentTest, null); // only a thin wrapper
+ validate(silentTest);
+ }
+
+ /**
+ * execute a single gui test
+ *
+ * @param guiTest
+ * @throws DriverException
+ */
+ private void driveGuiTest(GuiAutotest guiTest) throws DriverException {
+ Installation.driverMain(guiTest.getCommandLineArgs(), guiTest, null); // only a thin wrapper
+ guiTest.execute();
+ validate(guiTest);
+ }
+
+ /**
+ * perform validations after the test was run
+ *
+ * @param autoTest
+ * @throws DriverException
+ */
+ private void validate(Autotest autoTest) throws DriverException {
+ autoTest.assertTargetDirNotEmpty();
+ if (autoTest.getVerifier() != null) {
+ System.out.println("verifying installation - this can take a while ...");
+ autoTest.getVerifier().verify();
+ System.out.println("... installation ok.\n");
+ }
+ }
+
+ /**
+ * @return the command line the autotest session was started with
+ */
+ private InstallerCommandLine getOriginalCommandLine() {
+ return _commandLine;
+ }
+
+ /**
+ * build all the silent tests
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ private void buildSilentTests() throws IOException, DriverException {
+ List<SilentAutotest> silentTests = new ArrayList<SilentAutotest>(50);
+
+ SilentAutotest test1 = new SilentAutotest(getOriginalCommandLine());
+ String[] arguments = new String[] { "-s" };
+ test1.setCommandLineArgs(arguments);
+ test1.addAdditionalArguments(); // this also adds target directory
+ test1.setVerifier(new NormalVerifier());
+ silentTests.add(test1);
+
+ SilentAutotest test2 = new SilentAutotest(getOriginalCommandLine());
+ arguments = new String[] { "-s", "-t", "minimum" };
+ test2.setCommandLineArgs(arguments);
+ test2.addAdditionalArguments();
+ test2.setVerifier(new NormalVerifier());
+ silentTests.add(test2);
+
+ SilentAutotest test3 = new SilentAutotest(getOriginalCommandLine());
+ arguments = new String[] { "-s", "-t", "standalone" };
+ test3.setCommandLineArgs(arguments);
+ test3.addAdditionalArguments();
+ test3.setVerifier(new StandaloneVerifier());
+ silentTests.add(test3);
+
+ // build array
+ int size = silentTests.size();
+ _silentTests = new SilentAutotest[size];
+ Iterator<SilentAutotest> silentIterator = silentTests.iterator();
+ for (int i = 0; i < size; i++) {
+ _silentTests[i] = silentIterator.next();
+ }
+ }
+
+ /**
+ * build all the console tests
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ private void buildConsoleTests() throws IOException, DriverException {
+ List<ConsoleAutotest> consoleTests = new ArrayList<ConsoleAutotest>(5);
+ final String[] arguments;
+ if (getOriginalCommandLine().hasVerboseOption()) {
+ arguments = new String[] { "-c", "-v" };
+ } else {
+ arguments = new String[] { "-c" };
+ }
+ // do NOT call addAdditionalArguments()
+
+ ConsoleAutotest test1 = new ConsoleAutotest(getOriginalCommandLine());
+ test1.setCommandLineArgs(arguments);
+ test1.addAnswer("e"); // language
+ test1.addAnswer("n"); // no read of license
+ test1.addAnswer("y"); // accept license
+ test1.addAnswer("3"); // type: minimum
+ test1.addAnswer("n"); // include: nothing
+ test1.addAnswer(test1.getTargetDir().getAbsolutePath()); // target directory
+ addJavaAndOSAnswers(test1);
+ test1.addAnswer("y"); // confirm copying
+ test1.addAnswer("n"); // no readme
+ test1.setVerifier(new NormalVerifier());
+ consoleTests.add(test1);
+
+ ConsoleAutotest test2 = new ConsoleAutotest(getOriginalCommandLine());
+ test2.setCommandLineArgs(arguments);
+ test2.addAnswer("e"); // language
+ test2.addAnswer("n"); // no read of license
+ test2.addAnswer("y"); // accept license
+ test2.addAnswer("3"); // type: minimum
+ test2.addAnswer("y"); // include
+ test2.addAnswer("mod"); // include
+ test2.addAnswer("demo"); // include
+ test2.addAnswer("src"); // include
+ test2.addAnswer("n"); // no further includes
+ test2.addAnswer("y"); // exclude
+ test2.addAnswer("demo"); // exclude
+ test2.addAnswer("wrongAnswer"); // wrong answer
+ test2.addAnswer("n"); // no further excludes
+ test2.addAnswer(test2.getTargetDir().getAbsolutePath()); // target directory
+ addJavaAndOSAnswers(test2);
+ test2.addAnswer("y"); // confirm copying
+ test2.addAnswer("n"); // no readme
+ test2.setVerifier(new NormalVerifier());
+ consoleTests.add(test2);
+
+ ConsoleAutotest test3 = new ConsoleAutotest(getOriginalCommandLine());
+ test3.setCommandLineArgs(arguments);
+ test3.addAnswer("e"); // language
+ test3.addAnswer("n"); // no read of license
+ test3.addAnswer("y"); // accept license
+ test3.addAnswer("9"); // type: standalone
+ test3.addAnswer(test3.getTargetDir().getAbsolutePath()); // target directory
+ addJavaAndOSAnswers(test3);
+ test3.addAnswer("y"); // confirm copying
+ test3.addAnswer("n"); // no readme
+ test3.setVerifier(new StandaloneVerifier());
+ consoleTests.add(test3);
+
+ // test for bug 1783960
+ ConsoleAutotest test4 = new ConsoleAutotest(getOriginalCommandLine());
+ test4.setCommandLineArgs(arguments);
+ test4.addAnswer("e"); // language
+ test4.addAnswer("n"); // no read of license
+ test4.addAnswer("y"); // accept license
+ test4.addAnswer("2"); // type: standard
+ test4.addAnswer("n"); // no includes
+ test4.addAnswer("y"); // exclude
+ test4.addAnswer("n"); // no further excludes
+ test4.addAnswer(test4.getTargetDir().getAbsolutePath()); // target directory
+ addJavaAndOSAnswers(test4);
+ test4.addAnswer("y"); // confirm copying
+ test4.addAnswer("n"); // no readme
+ test4.setVerifier(new NormalVerifier());
+ consoleTests.add(test4);
+
+ // build array
+ int size = consoleTests.size();
+ _consoleTests = new ConsoleAutotest[size];
+ Iterator<ConsoleAutotest> consoleIterator = consoleTests.iterator();
+ for (int i = 0; i < size; i++) {
+ _consoleTests[i] = consoleIterator.next();
+ }
+ }
+
+ private void addJavaAndOSAnswers(ConsoleAutotest test) {
+ JavaHomeHandler javaHomeHandler = test.getJavaHomeHandler();
+ if (javaHomeHandler.isDeviation() && javaHomeHandler.isValidHome()) {
+ test.addAnswer(javaHomeHandler.getHome().getAbsolutePath()); // different jre
+ } else {
+ test.addAnswer(ConsoleInstaller.CURRENT_JRE);
+ }
+ if (!Installation.isValidOs()) {
+ test.addAnswer(""); // enter to proceed anyway
+ }
+ }
+
+ /**
+ * build all the gui tests
+ *
+ * @throws IOException
+ * @throws DriverException
+ */
+ private void buildGuiTests() throws IOException, DriverException {
+ List<GuiAutotest> guiTests = new ArrayList<GuiAutotest>(50);
+
+ if (Installation.isGuiAllowed()) {
+ GuiAutotest guiTest1 = new GuiAutotest(getOriginalCommandLine());
+ buildLanguageAndLicensePage(guiTest1);
+ // type page - use 'Standard'
+ guiTest1.addKeyAction(KeyEvent.VK_TAB);
+ guiTest1.addKeyAction(KeyEvent.VK_TAB);
+ guiTest1.addKeyAction(KeyEvent.VK_TAB);
+ guiTest1.addKeyAction(KeyEvent.VK_TAB);
+ guiTest1.addKeyAction(KeyEvent.VK_TAB);
+ guiTest1.addKeyAction(KeyEvent.VK_TAB);
+ guiTest1.addKeyAction(KeyEvent.VK_SPACE);
+ buildRestOfGuiPages(guiTest1);
+ guiTest1.setVerifier(new NormalVerifier());
+ guiTests.add(guiTest1);
+
+ GuiAutotest guiTest2 = new GuiAutotest(getOriginalCommandLine());
+ buildLanguageAndLicensePage(guiTest2);
+ // type page - use 'All'
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_SPACE); // select 'All'
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_TAB);
+ guiTest2.addKeyAction(KeyEvent.VK_SPACE);
+ buildRestOfGuiPages(guiTest2);
+ guiTest2.setVerifier(new NormalVerifier());
+ guiTests.add(guiTest2);
+
+ GuiAutotest guiTest3 = new GuiAutotest(getOriginalCommandLine());
+ buildLanguageAndLicensePage(guiTest3);
+ // type page - use 'Custom'
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_SPACE); // select 'Custom'
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_SPACE); // deselect 'Demos and Examples'
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_SPACE); // deselect 'Documentation'
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_SPACE); // select 'Sources'
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_TAB);
+ guiTest3.addKeyAction(KeyEvent.VK_SPACE);
+ buildRestOfGuiPages(guiTest3);
+ guiTest3.setVerifier(new NormalVerifier());
+ guiTests.add(guiTest3);
+
+ GuiAutotest guiTest4 = new GuiAutotest(getOriginalCommandLine());
+ buildLanguageAndLicensePage(guiTest4);
+ // type page - use 'Standalone'
+ guiTest4.addKeyAction(KeyEvent.VK_TAB);
+ guiTest4.addKeyAction(KeyEvent.VK_TAB);
+ guiTest4.addKeyAction(KeyEvent.VK_SPACE); // select 'Standalone'
+ guiTest4.addKeyAction(KeyEvent.VK_TAB);
+ guiTest4.addKeyAction(KeyEvent.VK_TAB);
+ guiTest4.addKeyAction(KeyEvent.VK_TAB);
+ guiTest4.addKeyAction(KeyEvent.VK_TAB);
+ guiTest4.addKeyAction(KeyEvent.VK_SPACE);
+ buildRestOfGuiPages(guiTest4);
+ guiTest4.setVerifier(new StandaloneVerifier());
+ guiTests.add(guiTest4);
+ }
+
+ // build array
+ int size = guiTests.size();
+ _guiTests = new GuiAutotest[size];
+ Iterator<GuiAutotest> guiIterator = guiTests.iterator();
+ for (int i = 0; i < size; i++) {
+ _guiTests[i] = guiIterator.next();
+ }
+ }
+
+ private void buildLanguageAndLicensePage(GuiAutotest guiTest) {
+ // language page
+ guiTest.addKeyAction(KeyEvent.VK_E);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ // license page
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_SPACE); // select "i accept"
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ }
+
+ private void buildRestOfGuiPages(GuiAutotest guiTest) {
+ // directory page
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ // java selection page
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ JavaHomeHandler javaHomeHandler = guiTest.getJavaHomeHandler();
+ boolean isValidDeviation = javaHomeHandler.isDeviation() && javaHomeHandler.isValidHome();
+ if (isValidDeviation) { // need 2 more tabs
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ guiTest.addKeyAction(KeyEvent.VK_TAB);
+ }
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ // overview page
+ if (isValidDeviation) {
+ guiTest.addKeyAction(KeyEvent.VK_SPACE, 3000); // enough time to check the java version
+ } else {
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ }
+ // installation page (skipped)
+ // readme page
+ guiTest.addWaitingKeyAction(KeyEvent.VK_TAB); // wait for the installation to finish
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ // success page
+ guiTest.addKeyAction(KeyEvent.VK_SPACE);
+ }
+}
diff --git a/installer/src/java/org/python/util/install/driver/NormalVerifier.java b/installer/src/java/org/python/util/install/driver/NormalVerifier.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/NormalVerifier.java
@@ -0,0 +1,287 @@
+package org.python.util.install.driver;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.text.MessageFormat;
+import java.util.StringTokenizer;
+
+import org.python.util.install.ChildProcess;
+import org.python.util.install.FileHelper;
+import org.python.util.install.Installation;
+import org.python.util.install.JavaHomeHandler;
+
+public class NormalVerifier implements Verifier {
+
+ protected static final String AUTOTEST_PY = "autotest.py";
+
+ protected static final String JYTHON_TEST = "jython_test";
+
+ private static final String BIN = "bin";
+
+ private static final String BAT_EXTENSION = ".bat";
+
+ private static final String JYTHON_UP = "jython up and running!";
+
+ private static final String JYTHON = "jython";
+
+ private static final String TEMPLATE_SUFFIX = ".template";
+
+ private static final String VERIFYING = "verifying";
+
+ private File _targetDir;
+
+ public void setTargetDir(File targetDir) {
+ _targetDir = targetDir;
+ }
+
+ public File getTargetDir() {
+ return _targetDir;
+ }
+
+ public void verify() throws DriverException {
+ createTestScriptFile(); // create the test .py script
+ // verify the most simple start of jython works
+ verifyStart(getSimpleCommand());
+ if (doShellScriptTests()) {
+ // verify more complex versions of starting jython
+ verifyStart(getShellScriptTestCommand());
+ }
+ }
+
+ /**
+ * Will be overridden in subclass StandaloneVerifier
+ *
+ * @return the command array to start jython with
+ * @throws DriverException
+ * if there was a problem getting the target directory path
+ */
+ protected String[] getSimpleCommand() throws DriverException {
+ String parentDirName = null;
+ try {
+ parentDirName = getTargetDir().getCanonicalPath() + File.separator;
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ String[] command = new String[2];
+ if (Installation.isWindows()) {
+ command[0] = parentDirName + JYTHON + BAT_EXTENSION;
+ } else {
+ command[0] = parentDirName + JYTHON;
+ }
+ command[1] = parentDirName + AUTOTEST_PY;
+ return command;
+ }
+
+ /**
+ * @return The command to test the shell script more deeply
+ * @throws DriverException
+ */
+ protected final String[] getShellScriptTestCommand() throws DriverException {
+ // first we have to create the shell script
+ File testCommandDir = getShellScriptTestCommandDir();
+ if (!testCommandDir.exists()) {
+ if (!testCommandDir.mkdirs()) {
+ throw new DriverException("unable to create directory "
+ + testCommandDir.getAbsolutePath());
+ }
+ }
+ String commandName = JYTHON_TEST;
+ boolean isWindows = Installation.isWindows();
+ if (isWindows) {
+ commandName = commandName.concat(BAT_EXTENSION);
+ }
+ File command = new File(testCommandDir, commandName);
+ try {
+ if (!command.exists()) {
+ command.createNewFile();
+ }
+ FileHelper.write(command, getShellScriptTestContents());
+ if (!isWindows) {
+ FileHelper.makeExecutable(command);
+ }
+ return new String[] {command.getCanonicalPath()};
+ } catch (Exception e) {
+ throw new DriverException(e);
+ }
+ }
+
+ /**
+ * @return The contents of the shell test script
+ * @throws DriverException
+ */
+ protected final String getShellScriptTestContents() throws DriverException {
+ String contents = "";
+ String templateName = JYTHON_TEST;
+ if (Installation.isWindows()) {
+ templateName = templateName.concat(BAT_EXTENSION);
+ }
+ templateName = templateName.concat(TEMPLATE_SUFFIX);
+ InputStream inputStream = FileHelper.getRelativeURLAsStream(getClass(), templateName);
+ if (inputStream != null) {
+ try {
+ String template = FileHelper.readAll(inputStream);
+ String targetDirPath = getTargetDir().getCanonicalPath();
+ String upScriptPath = getSimpleCommand()[1];
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler();
+ String javaHomeString = "";
+ if (javaHomeHandler.isValidHome()) {
+ javaHomeString = javaHomeHandler.getHome().getAbsolutePath();
+ }
+ contents = MessageFormat.format(template,
+ targetDirPath,
+ upScriptPath,
+ javaHomeString,
+ VERIFYING);
+ } catch (Exception e) {
+ throw new DriverException(e);
+ }
+ }
+ return contents;
+ }
+
+ /**
+ * @return The directory where to create the shell script test command in.
+ *
+ * @throws DriverException
+ */
+ protected final File getShellScriptTestCommandDir() throws DriverException {
+ String dirName;
+ try {
+ dirName = getTargetDir().getCanonicalPath().concat(File.separator).concat(BIN);
+ return new File(dirName);
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ }
+
+ /**
+ * Internal method verifying a jython-starting command by capturing the ouptut
+ *
+ * @param command
+ *
+ * @throws DriverException
+ */
+ private void verifyStart(String[] command) throws DriverException {
+ ChildProcess childProcess = new ChildProcess(command);
+ childProcess.setDebug(true);
+ ByteArrayOutputStream redirectedErr = new ByteArrayOutputStream();
+ ByteArrayOutputStream redirectedOut = new ByteArrayOutputStream();
+ int exitValue = 0;
+ PrintStream oldErr = System.err;
+ PrintStream oldOut = System.out;
+ try {
+ System.setErr(new PrintStream(redirectedErr));
+ System.setOut(new PrintStream(redirectedOut));
+ exitValue = childProcess.run();
+ } finally {
+ System.setErr(oldErr);
+ System.setOut(oldOut);
+ }
+ // verify the output
+ String output = null;
+ String error = null;
+ try {
+ redirectedErr.flush();
+ redirectedOut.flush();
+ String encoding = "US-ASCII";
+ output = redirectedOut.toString(encoding);
+ error = redirectedErr.toString(encoding);
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ if (exitValue != 0) {
+ throw new DriverException("start of jython failed, output:\n" + output + "\nerror:\n"
+ + error);
+ }
+ verifyError(error);
+ verifyOutput(output);
+ }
+
+ /**
+ * Will be overridden in subclass StandaloneVerifier
+ *
+ * @return <code>true</code> if the jython start shell script should be verified (using
+ * different options)
+ */
+ protected boolean doShellScriptTests() {
+ return true;
+ }
+
+ private void verifyError(String error) throws DriverException {
+ StringTokenizer tokenizer = new StringTokenizer(error, "\n");
+ while (tokenizer.hasMoreTokens()) {
+ String line = tokenizer.nextToken();
+ if (isExpectedError(line)) {
+ feedback(line);
+ } else {
+ throw new DriverException(error);
+ }
+ }
+ }
+
+ private boolean isExpectedError(String line) {
+ boolean expected = false;
+ if (line.startsWith("*sys-package-mgr*")) {
+ expected = true;
+ } else if (line.indexOf("32 bit") >= 0 && line.indexOf("64 bit") >= 0) {
+ // OS X incompatibility message when using -A -j java1.6.0 from java1.5.0
+ expected = true;
+ }
+ return expected;
+ }
+
+ private void verifyOutput(String output) throws DriverException {
+ boolean started = false;
+ StringTokenizer tokenizer = new StringTokenizer(output, "\n");
+ while (tokenizer.hasMoreTokens()) {
+ String line = tokenizer.nextToken();
+ if (isExpectedOutput(line)) {
+ feedback(line);
+ if (line.startsWith(JYTHON_UP)) {
+ started = true;
+ }
+ } else {
+ throw new DriverException(output);
+ }
+ }
+ if (!started) {
+ throw new DriverException("start of jython failed:\n" + output);
+ }
+ }
+
+ private boolean isExpectedOutput(String line) {
+ boolean expected = false;
+ if (line.startsWith("[ChildProcess]") || line.startsWith(VERIFYING)) {
+ expected = true;
+ } else if (line.startsWith(JYTHON_UP)) {
+ expected = true;
+ }
+ return expected;
+ }
+
+ private String getTestScript() {
+ StringBuilder b = new StringBuilder(80);
+ b.append("import sys\n");
+ b.append("import os\n");
+ b.append("print '");
+ b.append(JYTHON_UP);
+ b.append("'\n");
+ return b.toString();
+ }
+
+ private void createTestScriptFile() throws DriverException {
+ File file = new File(getTargetDir(), AUTOTEST_PY);
+ try {
+ FileHelper.write(file, getTestScript());
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ }
+
+ private void feedback(String line) {
+ System.out.println(line);
+ }
+}
diff --git a/installer/src/java/org/python/util/install/driver/SilentAutotest.java b/installer/src/java/org/python/util/install/driver/SilentAutotest.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/SilentAutotest.java
@@ -0,0 +1,25 @@
+package org.python.util.install.driver;
+
+import java.io.IOException;
+
+import org.python.util.install.InstallerCommandLine;
+
+public class SilentAutotest extends Autotest {
+
+ protected SilentAutotest(InstallerCommandLine commandLine) throws IOException, DriverException {
+ super(commandLine);
+ }
+
+ protected String getNameSuffix() {
+ return "silentTest";
+ }
+
+ //
+ // interface InstallationListener
+ //
+
+ public void progressFinished() {
+ // ignored
+ }
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/StandaloneVerifier.java b/installer/src/java/org/python/util/install/driver/StandaloneVerifier.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/StandaloneVerifier.java
@@ -0,0 +1,74 @@
+package org.python.util.install.driver;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.python.util.install.JavaHomeHandler;
+
+public class StandaloneVerifier extends NormalVerifier {
+
+ public void verify() throws DriverException {
+ // make sure only JYTHON_JAR is in the target directory
+ if (getTargetDir().listFiles().length > 1) {
+ throw new DriverException("more than " + JYTHON_JAR + " installed");
+ }
+ // make sure JYTHON_JAR contains a MANIFEST and a /Lib directory
+ verifyJythonJar();
+ // do the jython startup verification from the superclass
+ super.verify();
+ }
+
+ @Override
+ protected String[] getSimpleCommand() throws DriverException {
+ String parentDirName = null;
+ try {
+ parentDirName = getTargetDir().getCanonicalPath() + File.separator;
+ } catch (IOException ioe) {
+ throw new DriverException(ioe);
+ }
+ String command[] = new String[4];
+ command[0] = new JavaHomeHandler().getExecutableName();
+ command[1] = "-jar";
+ command[2] = parentDirName + JYTHON_JAR;
+ command[3] = parentDirName + AUTOTEST_PY;
+ return command;
+ }
+
+ @Override
+ protected boolean doShellScriptTests() {
+ return false;
+ }
+
+ private void verifyJythonJar() throws DriverException {
+ File jythonJar = getTargetDir().listFiles()[0];
+ JarFile jar = null;
+ try {
+ jar = new JarFile(jythonJar);
+ if (jar.getManifest() == null) {
+ throw new DriverException(JYTHON_JAR + " contains no MANIFEST");
+ }
+ boolean hasLibDir = false;
+ Enumeration<JarEntry> entries = jar.entries();
+ while (!hasLibDir && entries.hasMoreElements()) {
+ JarEntry entry = (JarEntry)entries.nextElement();
+ if (entry.getName().startsWith("Lib/")) {
+ hasLibDir = true;
+ }
+ }
+ if (!hasLibDir) {
+ throw new DriverException(JYTHON_JAR + " contains no /Lib directory");
+ }
+ } catch (IOException e) {
+ throw new DriverException(e);
+ } finally {
+ if (jar != null) {
+ try {
+ jar.close();
+ } catch (IOException ioe) {}
+ }
+ }
+ }
+}
diff --git a/installer/src/java/org/python/util/install/driver/Tunnel.java b/installer/src/java/org/python/util/install/driver/Tunnel.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/Tunnel.java
@@ -0,0 +1,61 @@
+package org.python.util.install.driver;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+/**
+ * A communication tunnel between a console driver and a console.
+ *
+ * <pre>
+ * (2) [Driver] receives question [Tunnel] sends question [Console] (1)
+ * (3) [Driver] sends answer [Tunnel] receives answer [Console] (4)
+ * </pre>
+ */
+public class Tunnel {
+
+ public static final String NEW_LINE = "\n";
+
+ private PipedOutputStream _questionSenderStream;
+ private PipedInputStream _questionReceiverStream;
+ private PipedOutputStream _answerSenderStream;
+ private PipedInputStream _answerReceiverStream;
+
+ public Tunnel() throws IOException {
+ _questionSenderStream = new PipedOutputStream();
+ _questionReceiverStream = new PipedInputStream();
+ _questionSenderStream.connect(_questionReceiverStream);
+
+ _answerSenderStream = new PipedOutputStream();
+ _answerReceiverStream = new PipedInputStream();
+ _answerSenderStream.connect(_answerReceiverStream);
+ }
+
+ public PipedOutputStream getQuestionSenderStream() {
+ return _questionSenderStream;
+ }
+
+ public PipedInputStream getQuestionReceiverStream() {
+ return _questionReceiverStream;
+ }
+
+ public PipedOutputStream getAnswerSenderStream() {
+ return _answerSenderStream;
+ }
+
+ public PipedInputStream getAnswerReceiverStream() {
+ return _answerReceiverStream;
+ }
+
+ public void close() throws IOException {
+ _questionReceiverStream.close();
+ _questionSenderStream.close();
+ _answerReceiverStream.close();
+ _answerSenderStream.close();
+
+ _questionReceiverStream = null;
+ _questionSenderStream = null;
+ _answerReceiverStream = null;
+ _answerSenderStream = null;
+ }
+}
diff --git a/installer/src/java/org/python/util/install/driver/Verifier.java b/installer/src/java/org/python/util/install/driver/Verifier.java
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/Verifier.java
@@ -0,0 +1,17 @@
+package org.python.util.install.driver;
+
+import java.io.File;
+
+import org.python.util.install.JarInstaller;
+
+public interface Verifier {
+
+ public static final String JYTHON_JAR = JarInstaller.JYTHON_JAR;
+
+ public void setTargetDir(File targetDir);
+
+ public File getTargetDir();
+
+ public void verify() throws DriverException;
+
+}
diff --git a/installer/src/java/org/python/util/install/driver/jython_test.bat.template b/installer/src/java/org/python/util/install/driver/jython_test.bat.template
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/jython_test.bat.template
@@ -0,0 +1,73 @@
+ at echo off
+
+rem 3 variables to be set from the caller, UNquoted:
+set _INSTALL_DIR={0}
+set _SCRIPT={1}
+set _JAVA_HOME={2}
+
+rem save old home env vars and classpath:
+set _OLD_JAVA_HOME=%JAVA_HOME%
+set _OLD_JYTHON_HOME=%JYTHON_HOME%
+set _OLD_CLASSPATH=%CLASSPATH%
+
+cd /d "%_INSTALL_DIR%\bin"
+
+echo {3}: only JAVA_HOME, quoted:
+set JAVA_HOME="%_JAVA_HOME%"
+set JYTHON_HOME=
+call jython.bat "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+echo {3}: only JAVA_HOME, UNquoted:
+set JAVA_HOME=%_JAVA_HOME%
+set JYTHON_HOME=
+call jython.bat "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+echo {3}: both homes quoted:
+set JAVA_HOME="%_JAVA_HOME%"
+set JYTHON_HOME="%_INSTALL_DIR%"
+call jython.bat "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+echo {3}: both homes UNquoted:
+set JAVA_HOME=%_JAVA_HOME%
+set JYTHON_HOME=%_INSTALL_DIR%
+call jython.bat "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+cd ..
+
+echo {3}: no home, calling in home dir:
+set JAVA_HOME=
+set JYTHON_HOME=
+call jython.bat "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+cd ..
+
+echo {3}: no home, calling /jython.bat from another working dir:"
+set JAVA_HOME=
+set JYTHON_HOME=
+call "%_INSTALL_DIR%\jython.bat" "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+echo {3}: no home, calling bin/jython.bat from another working dir:"
+set JAVA_HOME=
+set JYTHON_HOME=
+call "%_INSTALL_DIR%\bin\jython.bat" "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+echo {3}: no home, setting CLASSPATH, calling /jython.bat from another working dir:"
+set JAVA_HOME=
+set JYTHON_HOME=
+set CLASSPATH=.;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip
+call "%_INSTALL_DIR%\jython.bat" "%_SCRIPT%"
+set E=%ERRORLEVEL%
+
+rem cleanup:
+set JAVA_HOME=%_OLD_JAVA_HOME%
+set JYTHON_HOME=%_OLD_JYTHON_HOME%
+set CLASSPATH=%_OLD_CLASSPATH%
+cd /d "%~dp0%"
+exit /b %E%
diff --git a/installer/src/java/org/python/util/install/driver/jython_test.template b/installer/src/java/org/python/util/install/driver/jython_test.template
new file mode 100644
--- /dev/null
+++ b/installer/src/java/org/python/util/install/driver/jython_test.template
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+# 3 variables to be set from the caller (unquoted) -> quoted in here:
+_INSTALL_DIR="{0}"
+_SCRIPT="{1}"
+_JAVA_HOME="{2}"
+
+# save old home env vars:
+_OLD_JAVA_HOME=$JAVA_HOME
+_OLD_JYTHON_HOME=$JYTHON_HOME
+# save current dir
+_CURDIR=`pwd`
+
+cd "$_INSTALL_DIR/bin"
+
+echo "{3}: no home:"
+export JAVA_HOME=
+export JYTHON_HOME=
+./jython "$_SCRIPT"
+
+echo "{3}: only JAVA_HOME:"
+export JAVA_HOME="$_JAVA_HOME"
+export JYTHON_HOME=
+./jython "$_SCRIPT"
+
+echo "{3}: only JYTHON_HOME:"
+export JAVA_HOME=
+export JYTHON_HOME="$_INSTALL_DIR"
+./jython "$_SCRIPT"
+
+echo "{3}: both homes:"
+export JAVA_HOME="$_JAVA_HOME"
+export JYTHON_HOME="$_INSTALL_DIR"
+./jython "$_SCRIPT"
+
+cd ..
+
+echo "{3}: no home, calling in home dir:"
+export JAVA_HOME=
+export JYTHON_HOME=
+./jython "$_SCRIPT"
+
+cd ~
+
+echo "{3}: no home, calling /jython from another working dir:"
+export JAVA_HOME=
+export JYTHON_HOME=
+"$_INSTALL_DIR/jython" "$_SCRIPT"
+
+echo "{3}: no home, calling /bin/jython from another working dir:"
+export JAVA_HOME=
+export JYTHON_HOME=
+"$_INSTALL_DIR/bin/jython" "$_SCRIPT"
+
+# cleanup:
+cd "$_CURDIR"
+export JAVA_HOME=$_OLD_JAVA_HOME
+export JYTHON_HOME=$_OLD_JYTHON_HOME
diff --git a/installer/src/java/org/python/util/install/jython_small_c.png b/installer/src/java/org/python/util/install/jython_small_c.png
new file mode 100644
index 0000000000000000000000000000000000000000..e65a7f18e5ecad694dd2093cf01256a2eb93aada
GIT binary patch
[stripped]
diff --git a/installer/test/java/org/AllTests.java b/installer/test/java/org/AllTests.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/AllTests.java
@@ -0,0 +1,101 @@
+package org;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * A package recursive test suite.
+ * <p>
+ * All classes ending with 'Test' are added to the suite.
+ *
+ * @see AllTests.TestClassFilter
+ */
+public class AllTests extends TestSuite {
+
+ /**
+ * @return Test suite at the directory where this class resists
+ *
+ * @throws Exception
+ */
+ public static Test suite() throws Exception {
+ Class<AllTests> suiteClass = AllTests.class;
+ String testSuiteClassName = suiteClass.getName();
+ File suiteFile = new File(suiteClass.getClassLoader().getResource(
+ testSuiteClassName.replace('.', '/').concat(".class")).getFile());
+ String basePackage = suiteClass.getPackage().getName();
+ File baseDir = suiteFile.getParentFile();
+ TestSuite suite = new TestSuite("Test " + basePackage + " recursive.");
+ buildSuite(baseDir.getAbsolutePath().length(), basePackage, baseDir, new TestClassFilter(), suite);
+ return suite;
+ }
+
+ //
+ // private methods
+ //
+
+ private static void buildSuite(int prefixLength, String basePackage, File currentDir, FilenameFilter filter,
+ TestSuite currentSuite) throws Exception {
+ List<File> potentialDirectories = Arrays.asList(currentDir.listFiles(filter));
+ if (potentialDirectories.size() == 0) {
+ return;
+ }
+ StringBuffer currentPackageName = new StringBuffer(200);
+ currentPackageName.append(basePackage);
+ currentPackageName.append(currentDir.getAbsolutePath().substring(prefixLength).replace('\\', '.').replace('/',
+ '.'));
+
+ List<File> classFiles = new ArrayList<File>(potentialDirectories.size());
+ Collections.sort(potentialDirectories, new FileComparator());
+ Iterator<File> directoryIterator = potentialDirectories.iterator();
+ while (directoryIterator.hasNext()) {
+ File potentialDirectory = (File) directoryIterator.next();
+ if (potentialDirectory.isDirectory()) {
+ TestSuite subTestSuite = new TestSuite(potentialDirectory.getName());
+ buildSuite(prefixLength, basePackage, potentialDirectory, filter, subTestSuite);
+ // only if suite contains tests
+ if (subTestSuite.countTestCases() > 0) {
+ currentSuite.addTest(subTestSuite);
+ }
+ } else {
+ classFiles.add(potentialDirectory);
+ }
+ }
+ Iterator<File> fileIterator = classFiles.iterator();
+ while (fileIterator.hasNext()) {
+ File file = (File) fileIterator.next();
+ StringBuffer className = new StringBuffer(200);
+ className.append(currentPackageName);
+ className.append('.');
+ String fileName = file.getName();
+ className.append(fileName);
+ className.setLength(className.length() - 6);
+ currentSuite.addTest(new TestSuite(Class.forName(className.toString()), fileName.substring(0, fileName
+ .length() - 6)));
+ }
+ }
+
+ private static class TestClassFilter implements FilenameFilter {
+ public boolean accept(File dir, String name) {
+ if (name.endsWith("Test.class")) {
+ return true;
+ }
+ return new File(dir, name).isDirectory();
+ }
+ }
+
+ private static class FileComparator implements Comparator<File> {
+ public int compare(File f1, File f2) {
+ return f1.getAbsolutePath().compareTo(f2.getAbsolutePath());
+ }
+ }
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/ApplicationTest.java b/installer/test/java/org/apache/commons/cli/ApplicationTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/ApplicationTest.java
@@ -0,0 +1,120 @@
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * <p>
+ * This is a collection of tests that test real world
+ * applications command lines.
+ * </p>
+ *
+ * <p>
+ * The following are the applications that are tested:
+ * <ul>
+ * <li>Ant</li>
+ * </ul>
+ * </p>
+ *
+ * @author John Keyes (john at integralsource.com)
+ */
+public class ApplicationTest extends TestCase {
+
+ public static Test suite() {
+ return new TestSuite(ApplicationTest.class);
+ }
+
+ public ApplicationTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ *
+ */
+ public void testLs() {
+ // create the command line parser
+ CommandLineParser parser = new PosixParser();
+ Options options = new Options();
+ options.addOption( "a", "all", false, "do not hide entries starting with ." );
+ options.addOption( "A", "almost-all", false, "do not list implied . and .." );
+ options.addOption( "b", "escape", false, "print octal escapes for nongraphic characters" );
+ OptionBuilder.withLongOpt( "block-size" );
+ OptionBuilder.withDescription( "use SIZE-byte blocks" );
+ OptionBuilder.withValueSeparator( '=' );
+ OptionBuilder.hasArg();
+ options.addOption(OptionBuilder.create());
+// options.addOption( OptionBuilder.withLongOpt( "block-size" )
+// .withDescription( "use SIZE-byte blocks" )
+// .withValueSeparator( '=' )
+// .hasArg()
+// .create() );
+ options.addOption( "B", "ignore-backups", false, "do not list implied entried ending with ~");
+ options.addOption( "c", false, "with -lt: sort by, and show, ctime (time of last modification of file status information) with -l:show ctime and sort by name otherwise: sort by ctime" );
+ options.addOption( "C", false, "list entries by columns" );
+
+ String[] args = new String[]{ "--block-size=10" };
+
+ try {
+ CommandLine line = parser.parse( options, args );
+ assertTrue( line.hasOption( "block-size" ) );
+ assertEquals( line.getOptionValue( "block-size" ), "10" );
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected exception:" + exp.getMessage() );
+ }
+ }
+
+ /**
+ * Ant test
+ */
+ public void testAnt() {
+ // use the GNU parser
+ CommandLineParser parser = new GnuParser( );
+ Options options = new Options();
+ options.addOption( "help", false, "print this message" );
+ options.addOption( "projecthelp", false, "print project help information" );
+ options.addOption( "version", false, "print the version information and exit" );
+ options.addOption( "quiet", false, "be extra quiet" );
+ options.addOption( "verbose", false, "be extra verbose" );
+ options.addOption( "debug", false, "print debug information" );
+ options.addOption( "version", false, "produce logging information without adornments" );
+ options.addOption( "logfile", true, "use given file for log" );
+ options.addOption( "logger", true, "the class which is to perform the logging" );
+ options.addOption( "listener", true, "add an instance of a class as a project listener" );
+ options.addOption( "buildfile", true, "use given buildfile" );
+ OptionBuilder.withDescription( "use value for given property" );
+ OptionBuilder.hasArgs();
+ OptionBuilder.withValueSeparator();
+ options.addOption( OptionBuilder.create( 'D' ) );
+ //, null, true, , false, true );
+ options.addOption( "find", true, "search for buildfile towards the root of the filesystem and use it" );
+
+ String[] args = new String[]{ "-buildfile", "mybuild.xml",
+ "-Dproperty=value", "-Dproperty1=value1",
+ "-projecthelp" };
+
+ try {
+ CommandLine line = parser.parse( options, args );
+
+ // check multiple values
+ String[] opts = line.getOptionValues( "D" );
+ assertEquals( "property", opts[0] );
+ assertEquals( "value", opts[1] );
+ assertEquals( "property1", opts[2] );
+ assertEquals( "value1", opts[3] );
+
+ // check single value
+ assertEquals( line.getOptionValue( "buildfile"), "mybuild.xml" );
+
+ // check option
+ assertTrue( line.hasOption( "projecthelp") );
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected exception:" + exp.getMessage() );
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/installer/test/java/org/apache/commons/cli/BugsTest.java b/installer/test/java/org/apache/commons/cli/BugsTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/BugsTest.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: BugsTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class BugsTest extends TestCase
+{
+
+ public static Test suite() {
+ return new TestSuite( BugsTest.class );
+ }
+
+ public BugsTest( String name )
+ {
+ super( name );
+ }
+
+ public void setUp()
+ {
+ }
+
+ public void tearDown()
+ {
+ }
+
+ public void test11457() {
+ Options options = new Options();
+ OptionBuilder.withLongOpt( "verbose" );
+ options.addOption( OptionBuilder.create() );
+ String[] args = new String[] { "--verbose" };
+
+ CommandLineParser parser = new PosixParser();
+
+ try {
+ CommandLine cmd = parser.parse( options, args );
+ assertTrue( cmd.hasOption( "verbose" ) );
+ }
+ catch( ParseException exp ) {
+ exp.printStackTrace();
+ fail( "Unexpected Exception: " + exp.getMessage() );
+ }
+ }
+
+ public void test11458()
+ {
+ Options options = new Options();
+ OptionBuilder.withValueSeparator( '=' );
+ OptionBuilder.hasArgs();
+ options.addOption(OptionBuilder.create( 'D' ) );
+ OptionBuilder.withValueSeparator( ':' );
+ OptionBuilder.hasArgs();
+ options.addOption( OptionBuilder.create( 'p' ) );
+ String[] args = new String[] { "-DJAVA_HOME=/opt/java" ,
+ "-pfile1:file2:file3" };
+
+ CommandLineParser parser = new PosixParser();
+
+ try {
+ CommandLine cmd = parser.parse( options, args );
+
+ String[] values = cmd.getOptionValues( 'D' );
+
+ assertEquals( values[0], "JAVA_HOME" );
+ assertEquals( values[1], "/opt/java" );
+
+ values = cmd.getOptionValues( 'p' );
+
+ assertEquals( values[0], "file1" );
+ assertEquals( values[1], "file2" );
+ assertEquals( values[2], "file3" );
+
+ java.util.Iterator iter = cmd.iterator();
+ while( iter.hasNext() ) {
+ Option opt = (Option)iter.next();
+ switch( opt.getId() ) {
+ case 'D':
+ assertEquals( opt.getValue( 0 ), "JAVA_HOME" );
+ assertEquals( opt.getValue( 1 ), "/opt/java" );
+ break;
+ case 'p':
+ assertEquals( opt.getValue( 0 ), "file1" );
+ assertEquals( opt.getValue( 1 ), "file2" );
+ assertEquals( opt.getValue( 2 ), "file3" );
+ break;
+ default:
+ fail( "-D option not found" );
+ }
+ }
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected Exception:\nMessage:" + exp.getMessage()
+ + "Type: " + exp.getClass().getName() );
+ }
+ }
+
+ public void test11680()
+ {
+ Options options = new Options();
+ options.addOption("f", true, "foobar");
+ options.addOption("m", true, "missing");
+ String[] args = new String[] { "-f" , "foo" };
+
+ CommandLineParser parser = new PosixParser();
+
+ try {
+ CommandLine cmd = parser.parse( options, args );
+
+ try {
+ cmd.getOptionValue( "f", "default f");
+ cmd.getOptionValue( "m", "default m");
+ }
+ catch( NullPointerException exp ) {
+ fail( "NullPointer caught: " + exp.getMessage() );
+ }
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected Exception: " + exp.getMessage() );
+ }
+ }
+
+ public void test11456()
+ {
+ // Posix
+ Options options = new Options();
+ OptionBuilder.hasOptionalArg();
+ options.addOption( OptionBuilder.create( 'a' ) );
+ OptionBuilder.hasArg();
+ options.addOption( OptionBuilder.create( 'b' ) );
+ String[] args = new String[] { "-a", "-bvalue" };
+
+ CommandLineParser parser = new PosixParser();
+
+ try {
+ CommandLine cmd = parser.parse( options, args );
+ assertEquals( cmd.getOptionValue( 'b' ), "value" );
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected Exception: " + exp.getMessage() );
+ }
+
+ // GNU
+ options = new Options();
+ OptionBuilder.hasOptionalArg();
+ options.addOption( OptionBuilder.create( 'a' ) );
+ OptionBuilder.hasArg();
+ options.addOption( OptionBuilder.create( 'b' ) );
+ args = new String[] { "-a", "-b", "value" };
+
+ parser = new GnuParser();
+
+ try {
+ CommandLine cmd = parser.parse( options, args );
+ assertEquals( cmd.getOptionValue( 'b' ), "value" );
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected Exception: " + exp.getMessage() );
+ }
+
+ }
+
+ public void test12210() {
+ // create the main options object which will handle the first parameter
+ Options mainOptions = new Options();
+ // There can be 2 main exclusive options: -exec|-rep
+
+ // Therefore, place them in an option group
+
+ String[] argv = new String[] { "-exec", "-exec_opt1", "-exec_opt2" };
+ OptionGroup grp = new OptionGroup();
+
+ grp.addOption(new Option("exec",false,"description for this option"));
+
+ grp.addOption(new Option("rep",false,"description for this option"));
+
+ mainOptions.addOptionGroup(grp);
+
+ // for the exec option, there are 2 options...
+ Options execOptions = new Options();
+ execOptions.addOption("exec_opt1",false," desc");
+ execOptions.addOption("exec_opt2",false," desc");
+
+ // similarly, for rep there are 2 options...
+ Options repOptions = new Options();
+ repOptions.addOption("repopto",false,"desc");
+ repOptions.addOption("repoptt",false,"desc");
+
+ // create the parser
+ GnuParser parser = new GnuParser();
+
+ // finally, parse the arguments:
+
+ // first parse the main options to see what the user has specified
+ // We set stopAtNonOption to true so it does not touch the remaining
+ // options
+ try {
+ CommandLine cmd = parser.parse(mainOptions,argv,true);
+ // get the remaining options...
+ argv = cmd.getArgs();
+
+ if(cmd.hasOption("exec")){
+ cmd = parser.parse(execOptions,argv,false);
+ // process the exec_op1 and exec_opt2...
+ assertTrue( cmd.hasOption("exec_opt1") );
+ assertTrue( cmd.hasOption("exec_opt2") );
+ }
+ else if(cmd.hasOption("rep")){
+ cmd = parser.parse(repOptions,argv,false);
+ // process the rep_op1 and rep_opt2...
+ }
+ else {
+ fail( "exec option not found" );
+ }
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected exception: " + exp.getMessage() );
+ }
+ }
+
+ public void test13425() {
+ Options options = new Options();
+ OptionBuilder.withLongOpt( "old-password" );
+ OptionBuilder.withDescription( "Use this option to specify the old password" );
+ OptionBuilder.hasArg();
+ Option oldpass = OptionBuilder.create( 'o' );
+ OptionBuilder.withLongOpt( "new-password" );
+ OptionBuilder.withDescription( "Use this option to specify the new password" );
+ OptionBuilder.hasArg();
+ Option newpass = OptionBuilder.create( 'n' );
+
+ String[] args = {
+ "-o",
+ "-n",
+ "newpassword"
+ };
+
+ options.addOption( oldpass );
+ options.addOption( newpass );
+
+ Parser parser = new PosixParser();
+
+ CommandLine line = null;
+ try {
+ line = parser.parse( options, args );
+ }
+ // catch the exception and leave the method
+ catch( Exception exp ) {
+ assertTrue( exp != null );
+ return;
+ }
+ fail( "MissingArgumentException not caught." + line);
+ }
+
+ public void test13666() {
+ Options options = new Options();
+ OptionBuilder.withDescription( "dir" );
+ OptionBuilder.hasArg();
+ Option dir = OptionBuilder.create( 'd' );
+ options.addOption( dir );
+ try {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp( "dir", options );
+ }
+ catch( Exception exp ) {
+ fail( "Unexpected Exception: " + exp.getMessage() );
+ }
+ }
+
+ public void test13935() {
+ OptionGroup directions = new OptionGroup();
+
+ Option left = new Option( "l", "left", false, "go left" );
+ Option right = new Option( "r", "right", false, "go right" );
+ Option straight = new Option( "s", "straight", false, "go straight" );
+ Option forward = new Option( "f", "forward", false, "go forward" );
+ forward.setRequired( true );
+
+ directions.addOption( left );
+ directions.addOption( right );
+ directions.setRequired( true );
+
+ Options opts = new Options();
+ opts.addOptionGroup( directions );
+ opts.addOption( straight );
+
+ CommandLineParser parser = new PosixParser();
+ boolean exception = false;
+
+ CommandLine line = null;
+ String[] args = new String[] { };
+ try {
+ line = parser.parse( opts, args );
+ }
+ catch( ParseException exp ) {
+ exception = true;
+ }
+
+ if( !exception ) {
+ fail( "Expected exception not caught.");
+ }
+
+ exception = false;
+
+ args = new String[] { "-s" };
+ try {
+ line = parser.parse( opts, args );
+ }
+ catch( ParseException exp ) {
+ exception = true;
+ }
+
+ if( !exception ) {
+ fail( "Expected exception not caught.");
+ }
+
+ exception = false;
+
+ args = new String[] { "-s", "-l" };
+ try {
+ line = parser.parse( opts, args );
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected exception: " + exp.getMessage() );
+ }
+
+ opts.addOption( forward );
+ args = new String[] { "-s", "-l", "-f" };
+ try {
+ line = parser.parse( opts, args );
+ }
+ catch( ParseException exp ) {
+ fail( "Unexpected exception: " + exp.getMessage() );
+ }
+ if(line != null) {
+ line = null;
+ }
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/BuildTest.java b/installer/test/java/org/apache/commons/cli/BuildTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/BuildTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: BuildTest.java 2662 2006-02-18 14:20:33Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class BuildTest extends TestCase
+{
+
+ public static Test suite() {
+ return new TestSuite(BuildTest.class);
+ }
+
+ public BuildTest(String name)
+ {
+ super(name);
+ }
+
+ public void setUp()
+ {
+
+ }
+
+ public void tearDown()
+ {
+
+ }
+
+ public void testSimple()
+ {
+ Options opts = new Options();
+
+ opts.addOption("a",
+ false,
+ "toggle -a");
+
+ opts.addOption("b",
+ true,
+ "toggle -b");
+ }
+
+ public void testDuplicateSimple()
+ {
+ Options opts = new Options();
+ opts.addOption("a",
+ false,
+ "toggle -a");
+
+ opts.addOption("a",
+ true,
+ "toggle -a*");
+
+ assertEquals( "last one in wins", "toggle -a*", opts.getOption("a").getDescription() );
+ }
+
+ public void testLong()
+ {
+ Options opts = new Options();
+
+ opts.addOption("a",
+ "--a",
+ false,
+ "toggle -a");
+
+ opts.addOption("b",
+ "--b",
+ true,
+ "set -b");
+
+ }
+
+ public void testDuplicateLong()
+ {
+ Options opts = new Options();
+ opts.addOption("a",
+ "--a",
+ false,
+ "toggle -a");
+
+ opts.addOption("a",
+ "--a",
+ false,
+ "toggle -a*");
+ assertEquals( "last one in wins", "toggle -a*", opts.getOption("a").getDescription() );
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/GnuParseTest.java b/installer/test/java/org/apache/commons/cli/GnuParseTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/GnuParseTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: GnuParseTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class GnuParseTest extends TestCase
+{
+ private Options _options = null;
+ private CommandLineParser _parser = null;
+
+ public static Test suite() {
+ return new TestSuite( GnuParseTest.class );
+ }
+
+ public GnuParseTest( String name )
+ {
+ super( name );
+ }
+
+ public void setUp()
+ {
+ _options = new Options()
+ .addOption("a",
+ "enable-a",
+ false,
+ "turn [a] on or off")
+ .addOption("b",
+ "bfile",
+ true,
+ "set the value of [b]")
+ .addOption("c",
+ "copt",
+ false,
+ "turn [c] on or off");
+
+ _parser = new GnuParser( );
+ }
+
+ public void tearDown()
+ {
+
+ }
+
+ public void testSimpleShort()
+ {
+ String[] args = new String[] { "-a",
+ "-b", "toast",
+ "foo", "bar" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testSimpleLong()
+ {
+ String[] args = new String[] { "--enable-a",
+ "--bfile", "toast",
+ "foo", "bar" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testExtraOption()
+ {
+ String[] args = new String[] { "-a", "-d", "-b", "toast",
+ "foo", "bar" };
+
+ boolean caught = false;
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 3);
+ }
+ catch (UnrecognizedOptionException e)
+ {
+ caught = true;
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ assertTrue( "Confirm UnrecognizedOptionException caught", caught );
+ }
+
+ public void testMissingArg()
+ {
+
+ String[] args = new String[] { "-b" };
+
+ boolean caught = false;
+
+ CommandLine cl = null;
+ try
+ {
+ cl = _parser.parse(_options, args);
+ }
+ catch (MissingArgumentException e)
+ {
+ caught = true;
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+
+ assertTrue( "Confirm MissingArgumentException caught " + cl, caught );
+ }
+
+ public void testStop()
+ {
+ String[] args = new String[] { "-c",
+ "foober",
+ "-b",
+ "toast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args, true);
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm 3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testMultiple()
+ {
+ String[] args = new String[] { "-c",
+ "foobar",
+ "-b",
+ "toast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args, true);
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm 3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+
+ cl = _parser.parse(_options, cl.getArgs() );
+
+ assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+ assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testMultipleWithLong()
+ {
+ String[] args = new String[] { "--copt",
+ "foobar",
+ "--bfile", "toast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options,args,
+ true);
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm 3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+
+ cl = _parser.parse(_options, cl.getArgs() );
+
+ assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+ assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testDoubleDash()
+ {
+ String[] args = new String[] { "--copt",
+ "--",
+ "-b", "toast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm -b is not set", ! cl.hasOption("b") );
+ assertTrue( "Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
+
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testSingleDash()
+ {
+ String[] args = new String[] { "--copt",
+ "-b", "-",
+ "-a",
+ "-" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("-") );
+ assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+ assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("-") );
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/HelpFormatterExamples.java b/installer/test/java/org/apache/commons/cli/HelpFormatterExamples.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/HelpFormatterExamples.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: HelpFormatterExamples.java 2662 2006-02-18 14:20:33Z otmarhumbel $
+ */
+package org.apache.commons.cli;
+
+/**
+ * A sample program shpwing the use of Options and the HelpFormatter class
+ *
+ * @author Slawek Zachcial
+ **/
+public class HelpFormatterExamples
+{
+ // --------------------------------------------------------------- Constants
+
+ // ------------------------------------------------------------------ Static
+
+ public static void main( String[] args )
+ {
+ System.out.println("\n#\n# 'man' example\n#");
+ manExample();
+/*
+ System.out.println("\n#\n# 'bzip2' example\n#");
+ bzip2Example();
+ System.out.println("\n#\n# 'ls' example\n#");
+ lsExample();
+*/
+ }
+
+ static void manExample()
+ {
+ String cmdLine =
+ "man [-c|-f|-k|-w|-tZT device] [-adlhu7V] [-Mpath] [-Ppager] [-Slist] " +
+ "[-msystem] [-pstring] [-Llocale] [-eextension] [section] page ...";
+ Options opts =
+ new Options().
+ addOption("a", "all", false, "find all matching manual pages.").
+ addOption("d", "debug", false, "emit debugging messages.").
+ addOption("e", "extension", false, "limit search to extension type 'extension'.").
+ addOption("f", "whatis", false, "equivalent to whatis.").
+ addOption("k", "apropos", false, "equivalent to apropos.").
+ addOption("w", "location", false, "print physical location of man page(s).").
+ addOption("l", "local-file", false, "interpret 'page' argument(s) as local filename(s)").
+ addOption("u", "update", false, "force a cache consistency check.").
+ //FIXME - should generate -r,--prompt string
+ addOption("r", "prompt", true, "provide 'less' pager with prompt.").
+ addOption("c", "catman", false, "used by catman to reformat out of date cat pages.").
+ addOption("7", "ascii", false, "display ASCII translation or certain latin1 chars.").
+ addOption("t", "troff", false, "use troff format pages.").
+ //FIXME - should generate -T,--troff-device device
+ addOption("T", "troff-device", true, "use groff with selected device.").
+ addOption("Z", "ditroff", false, "use groff with selected device.").
+ addOption("D", "default", false, "reset all options to their default values.").
+ //FIXME - should generate -M,--manpath path
+ addOption("M", "manpath", true, "set search path for manual pages to 'path'.").
+ //FIXME - should generate -P,--pager pager
+ addOption("P", "pager", true, "use program 'pager' to display output.").
+ //FIXME - should generate -S,--sections list
+ addOption("S", "sections", true, "use colon separated section list.").
+ //FIXME - should generate -m,--systems system
+ addOption("m", "systems", true, "search for man pages from other unix system(s).").
+ //FIXME - should generate -L,--locale locale
+ addOption("L", "locale", true, "defaine the locale for this particular man search.").
+ //FIXME - should generate -p,--preprocessor string
+ addOption("p", "preprocessor", true, "string indicates which preprocessor to run.\n" +
+ " e - [n]eqn p - pic t - tbl\n" +
+ " g - grap r - refer v - vgrind").
+ addOption("V", "version", false, "show version.").
+ addOption("h", "help", false, "show this usage message.");
+
+ HelpFormatter hf = new HelpFormatter();
+ //hf.printHelp(cmdLine, opts);
+ hf.printHelp(60, cmdLine, null, opts, null);
+ }
+
+ static void bzip2Example()
+ {
+ System.out.println( "Coming soon" );
+ }
+
+ static void lsExample()
+ {
+ System.out.println( "Coming soon" );
+ }
+
+
+ // -------------------------------------------------------------- Attributes
+
+ // ------------------------------------------------------------ Constructors
+
+ // ------------------------------------------------------------------ Public
+
+ // --------------------------------------------------------------- Protected
+
+ // ------------------------------------------------------- Package protected
+
+ // ----------------------------------------------------------------- Private
+
+ // ----------------------------------------------------------- Inner classes
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/HelpFormatterTest.java b/installer/test/java/org/apache/commons/cli/HelpFormatterTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/HelpFormatterTest.java
@@ -0,0 +1,82 @@
+package org.apache.commons.cli;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+import junit.framework.TestCase;
+
+public class HelpFormatterTest extends TestCase {
+
+ private Options _options;
+
+ protected void setUp() {
+ _options = new Options();
+ Option aOption = new Option("a", "Aa", false, "option A");
+ Option bOption = new Option("b", "Bb", false, "option B");
+ OptionGroup group1 = new OptionGroup();
+ group1.addOption(aOption);
+ group1.addOption(bOption);
+ _options.addOptionGroup(group1);
+ }
+
+ /**
+ * the setUp above used to print [-a | -b] [-a] [-b]
+ */
+ public void testOptionGroupDuplication() {
+ String help = unifyNewLines(getFormattedHelp());
+ String expectedHelp = unifyNewLines(new String("usage: syntax [-a | -b]\n-a,--Aa option A\n-b,--Bb option B\n"));
+ assertEquals("expected usage to be '" + expectedHelp + "' instead of '" + help + "'",
+ expectedHelp,
+ help);
+ }
+
+ /**
+ * Options following an option group used to be non blank separated: [-b | -a][-o] instead of
+ * [-b | -a] [-o]
+ */
+ public void testOptionGroupSubsequentOptions() {
+ _options.addOption(new Option("o", "Option O"));
+ String help = getFormattedHelp();
+ assertTrue(help.indexOf("][") < 0);
+ assertTrue(help.indexOf("[-a | -b] [-o]") >= 0);
+ }
+
+ //
+ // private methods
+ //
+ private String getFormattedHelp() {
+ HelpFormatter formatter = new HelpFormatter();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ formatter.printHelp(pw, 60, "syntax", null, _options, 0, 1, null, true);
+ pw.flush();
+ String usage = baos.toString();
+ return usage;
+ }
+
+ /**
+ * replace the windows specific \r\n line endings with java like \n line endings
+ *
+ * @param in
+ * The string to be transformed
+ * @return The string with unified line endings
+ */
+ private String unifyNewLines(String in) {
+ char[] inChars = in.toCharArray();
+ StringBuilder b = new StringBuilder(inChars.length);
+ for (int i = 0; i < inChars.length; i++) {
+ char current = inChars[i];
+ if (current == '\r') {
+ if (i < inChars.length) {
+ char next = inChars[i + 1];
+ if (next == '\n') {
+ i++;
+ current = next;
+ }
+ }
+ }
+ b.append(current);
+ }
+ return b.toString();
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/OptionBuilderTest.java b/installer/test/java/org/apache/commons/cli/OptionBuilderTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/OptionBuilderTest.java
@@ -0,0 +1,160 @@
+package org.apache.commons.cli;
+
+import java.math.BigDecimal;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import junit.textui.TestRunner;
+
+public class OptionBuilderTest extends TestCase {
+
+ public OptionBuilderTest( String name ) {
+ super( name );
+ }
+
+ public static Test suite() {
+ return new TestSuite( OptionBuilderTest.class );
+ }
+
+ public static void main( String args[] ) {
+ TestRunner.run( suite() );
+ }
+
+ public void testCompleteOption( ) {
+ OptionBuilder.withLongOpt( "simple option");
+ OptionBuilder.hasArg( );
+ OptionBuilder.isRequired( );
+ OptionBuilder.hasArgs( );
+ OptionBuilder.withType( new BigDecimal( "10" ) );
+ OptionBuilder.withDescription( "this is a simple option" );
+ Option simple = OptionBuilder.create( 's' );
+
+ assertEquals( "s", simple.getOpt() );
+ assertEquals( "simple option", simple.getLongOpt() );
+ assertEquals( "this is a simple option", simple.getDescription() );
+ assertEquals( simple.getType().getClass(), BigDecimal.class );
+ assertTrue( simple.hasArg() );
+ assertTrue( simple.isRequired() );
+ assertTrue( simple.hasArgs() );
+ }
+
+ public void testTwoCompleteOptions( ) {
+ OptionBuilder.withLongOpt( "simple option");
+ OptionBuilder.hasArg( );
+ OptionBuilder.isRequired( );
+ OptionBuilder.hasArgs( );
+ OptionBuilder.withType( new BigDecimal( "10" ) );
+ OptionBuilder.withDescription( "this is a simple option" );
+ Option simple = OptionBuilder.create( 's' );
+
+ assertEquals( "s", simple.getOpt() );
+ assertEquals( "simple option", simple.getLongOpt() );
+ assertEquals( "this is a simple option", simple.getDescription() );
+ assertEquals( simple.getType().getClass(), BigDecimal.class );
+ assertTrue( simple.hasArg() );
+ assertTrue( simple.isRequired() );
+ assertTrue( simple.hasArgs() );
+
+ OptionBuilder.withLongOpt( "dimple option");
+ OptionBuilder.hasArg( );
+ OptionBuilder.withDescription( "this is a dimple option" );
+ simple = OptionBuilder.create( 'd' );
+
+ assertEquals( "d", simple.getOpt() );
+ assertEquals( "dimple option", simple.getLongOpt() );
+ assertEquals( "this is a dimple option", simple.getDescription() );
+ assertNull( simple.getType() );
+ assertTrue( simple.hasArg() );
+ assertTrue( !simple.isRequired() );
+ assertTrue( !simple.hasArgs() );
+ }
+
+ public void testBaseOptionCharOpt() {
+ OptionBuilder.withDescription( "option description");
+ Option base = OptionBuilder.create( 'o' );
+
+ assertEquals( "o", base.getOpt() );
+ assertEquals( "option description", base.getDescription() );
+ assertTrue( !base.hasArg() );
+ }
+
+ public void testBaseOptionStringOpt() {
+ OptionBuilder.withDescription( "option description");
+ Option base = OptionBuilder.create( "o" );
+
+ assertEquals( "o", base.getOpt() );
+ assertEquals( "option description", base.getDescription() );
+ assertTrue( !base.hasArg() );
+ }
+
+ public void testSpecialOptChars() {
+
+ // '?'
+ try {
+ OptionBuilder.withDescription( "help options" );
+ Option opt = OptionBuilder.create( '?' );
+ assertEquals( "?", opt.getOpt() );
+ }
+ catch( IllegalArgumentException arg ) {
+ fail( "IllegalArgumentException caught" );
+ }
+
+ // '@'
+ try {
+ OptionBuilder.withDescription( "read from stdin" );
+ Option opt = OptionBuilder.create( '@' );
+ assertEquals( "@", opt.getOpt() );
+ }
+ catch( IllegalArgumentException arg ) {
+ fail( "IllegalArgumentException caught" );
+ }
+ }
+
+ public void testOptionArgNumbers() {
+ OptionBuilder.withDescription( "option description" );
+ OptionBuilder.hasArgs( 2 );
+ Option opt = OptionBuilder.create( 'o' );
+ assertEquals( 2, opt.getArgs() );
+ }
+
+ public void testIllegalOptions() {
+ // bad single character option
+ try {
+ OptionBuilder.withDescription( "option description" );
+ OptionBuilder.create( '"' );
+ fail( "IllegalArgumentException not caught" );
+ }
+ catch( IllegalArgumentException exp ) {
+ // success
+ }
+
+ // bad character in option string
+ try {
+ OptionBuilder.create( "opt`" );
+ fail( "IllegalArgumentException not caught" );
+ }
+ catch( IllegalArgumentException exp ) {
+ // success
+ }
+
+ // null option
+ try {
+ OptionBuilder.create( null );
+ fail( "IllegalArgumentException not caught" );
+ }
+ catch( IllegalArgumentException exp ) {
+ // success
+ }
+
+ // valid option
+ try {
+ OptionBuilder.create( "opt" );
+ // success
+ }
+ catch( IllegalArgumentException exp ) {
+ fail( "IllegalArgumentException caught" );
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/test/java/org/apache/commons/cli/OptionGroupSortTest.java b/installer/test/java/org/apache/commons/cli/OptionGroupSortTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/OptionGroupSortTest.java
@@ -0,0 +1,43 @@
+package org.apache.commons.cli;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+public class OptionGroupSortTest extends TestCase {
+
+ private OptionGroup _optionGroup;
+
+ protected void setUp() {
+ _optionGroup = new OptionGroup();
+ _optionGroup.addOption(new Option("f", "first", false, "first"));
+ _optionGroup.addOption(new Option("s", "second", false, "second"));
+ _optionGroup.addOption(new Option("t", "third", false, "third"));
+ }
+
+ public void testSortNames() {
+ Collection names = _optionGroup.getNames();
+ Iterator namesIterator = names.iterator();
+ assertTrue(namesIterator.hasNext());
+ assertEquals("-f", (String) namesIterator.next());
+ assertTrue(namesIterator.hasNext());
+ assertEquals("-s", (String) namesIterator.next());
+ assertTrue(namesIterator.hasNext());
+ assertEquals("-t", (String) namesIterator.next());
+ assertFalse(namesIterator.hasNext());
+ }
+
+ public void testSortOptions() {
+ Collection options = _optionGroup.getOptions();
+ Iterator optionIterator = options.iterator();
+ assertTrue(optionIterator.hasNext());
+ assertEquals("first", ((Option) optionIterator.next()).getLongOpt());
+ assertTrue(optionIterator.hasNext());
+ assertEquals("second", ((Option) optionIterator.next()).getLongOpt());
+ assertTrue(optionIterator.hasNext());
+ assertEquals("third", ((Option) optionIterator.next()).getLongOpt());
+ assertFalse(optionIterator.hasNext());
+ }
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/OptionGroupTest.java b/installer/test/java/org/apache/commons/cli/OptionGroupTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/OptionGroupTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: OptionGroupTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author John Keyes (john at integralsource.com)
+ * @version $Revision: 3134 $
+ */
+public class OptionGroupTest extends TestCase
+{
+
+ private Options _options = null;
+ private CommandLineParser parser = new PosixParser();
+
+
+ public static Test suite()
+ {
+ return new TestSuite ( OptionGroupTest.class );
+ }
+
+ public OptionGroupTest( String name )
+ {
+ super( name );
+ }
+
+ public void setUp()
+ {
+ Option file = new Option( "f", "file", false, "file to process" );
+ Option dir = new Option( "d", "directory", false, "directory to process" );
+ OptionGroup group = new OptionGroup();
+ group.addOption( file );
+ group.addOption( dir );
+ _options = new Options().addOptionGroup( group );
+
+ Option section = new Option( "s", "section", false, "section to process" );
+ Option chapter = new Option( "c", "chapter", false, "chapter to process" );
+ OptionGroup group2 = new OptionGroup();
+ group2.addOption( section );
+ group2.addOption( chapter );
+
+ _options.addOptionGroup( group2 );
+ _options.addOption( "r", "revision", false, "revision number" );
+ }
+
+ public void tearDown()
+ {
+ }
+
+ public void testSingleOptionFromGroup()
+ {
+ String[] args = new String[] { "-f" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+
+ assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+ assertTrue( "Confirm -f is set", cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testSingleOption()
+ {
+ String[] args = new String[] { "-r" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+
+ assertTrue( "Confirm -r is set", cl.hasOption("r") );
+ assertTrue( "Confirm -f is NOT set", !cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testTwoValidOptions()
+ {
+ String[] args = new String[] { "-r", "-f" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+
+ assertTrue( "Confirm -r is set", cl.hasOption("r") );
+ assertTrue( "Confirm -f is set", cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testSingleLongOption()
+ {
+ String[] args = new String[] { "--file" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+
+ assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+ assertTrue( "Confirm -f is set", cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testTwoValidLongOptions()
+ {
+ String[] args = new String[] { "--revision", "--file" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+
+ assertTrue( "Confirm -r is set", cl.hasOption("r") );
+ assertTrue( "Confirm -f is set", cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testNoOptionsExtraArgs()
+ {
+ String[] args = new String[] { "arg1", "arg2" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+
+ assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+ assertTrue( "Confirm -f is NOT set", !cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm TWO extra args", cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testTwoOptionsFromGroup()
+ {
+ String[] args = new String[] { "-f", "-d" };
+
+ CommandLine cl = null;
+ try
+ {
+ cl = parser.parse( _options, args);
+ fail( "two arguments from group not allowed" );
+ }
+ catch (ParseException e)
+ {
+ if( !( e instanceof AlreadySelectedException ) )
+ {
+ fail( "incorrect exception caught:" + e.getMessage() + " in " + cl );
+ }
+ }
+ }
+
+ public void testTwoLongOptionsFromGroup()
+ {
+ String[] args = new String[] { "--file", "--directory" };
+
+ CommandLine cl = null;
+ try
+ {
+ cl = parser.parse( _options, args);
+ fail( "two arguments from group not allowed" );
+ }
+ catch (ParseException e)
+ {
+ if( !( e instanceof AlreadySelectedException ) )
+ {
+ fail( "incorrect exception caught:" + e.getMessage() + " in " + cl );
+ }
+ }
+ }
+
+ public void testTwoOptionsFromDifferentGroup()
+ {
+ String[] args = new String[] { "-f", "-s" };
+
+ try
+ {
+ CommandLine cl = parser.parse( _options, args);
+ assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+ assertTrue( "Confirm -f is set", cl.hasOption("f") );
+ assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+ assertTrue( "Confirm -s is set", cl.hasOption("s") );
+ assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+ assertTrue( "Confirm NO extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/OptionsTest.java b/installer/test/java/org/apache/commons/cli/OptionsTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/OptionsTest.java
@@ -0,0 +1,28 @@
+package org.apache.commons.cli;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+public class OptionsTest extends TestCase {
+
+ private Options _options;
+
+ public void testSortAsAdded() {
+ _options = new Options();
+ _options.setSortAsAdded(true);
+ _options.addOption("f", "first", false, "first");
+ _options.addOption("s", "second", false, "second");
+ _options.addOption("t", "third", false, "third");
+ Collection optionCollection = _options.getOptions();
+ Iterator optionIterator = optionCollection.iterator();
+ assertTrue(optionIterator.hasNext());
+ assertEquals("first", ((Option) optionIterator.next()).getLongOpt());
+ assertTrue(optionIterator.hasNext());
+ assertEquals("second", ((Option) optionIterator.next()).getLongOpt());
+ assertTrue(optionIterator.hasNext());
+ assertEquals("third", ((Option) optionIterator.next()).getLongOpt());
+ assertFalse(optionIterator.hasNext());
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/ParseRequiredTest.java b/installer/test/java/org/apache/commons/cli/ParseRequiredTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/ParseRequiredTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: ParseRequiredTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author John Keyes (john at integralsource.com)
+ * @version $Revision: 3134 $
+ */
+public class ParseRequiredTest extends TestCase
+{
+
+ private Options _options = null;
+ private CommandLineParser parser = new PosixParser();
+
+ public static Test suite() {
+ return new TestSuite(ParseRequiredTest.class);
+ }
+
+ public ParseRequiredTest(String name)
+ {
+ super(name);
+ }
+
+ public void setUp()
+ {
+ OptionBuilder.withLongOpt( "bfile" );
+ OptionBuilder.hasArg();
+ OptionBuilder.isRequired();
+ OptionBuilder.withDescription( "set the value of [b]" );
+ Option opt2 = OptionBuilder.create( 'b' );
+ _options = new Options()
+ .addOption("a",
+ "enable-a",
+ false,
+ "turn [a] on or off")
+ .addOption( opt2 );
+ }
+
+ public void tearDown()
+ {
+
+ }
+
+ public void testWithRequiredOption()
+ {
+ String[] args = new String[] { "-b", "file" };
+
+ try
+ {
+ CommandLine cl = parser.parse(_options,args);
+
+ assertTrue( "Confirm -a is NOT set", !cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("file") );
+ assertTrue( "Confirm NO of extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testOptionAndRequiredOption()
+ {
+ String[] args = new String[] { "-a", "-b", "file" };
+
+ try
+ {
+ CommandLine cl = parser.parse(_options,args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("file") );
+ assertTrue( "Confirm NO of extra args", cl.getArgList().size() == 0);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testMissingRequiredOption()
+ {
+ String[] args = new String[] { "-a" };
+
+ CommandLine cl = null;
+ try
+ {
+ cl = parser.parse(_options,args);
+ fail( "exception should have been thrown" );
+ }
+ catch (ParseException e)
+ {
+ if( !( e instanceof MissingOptionException ) )
+ {
+ fail( "expected to catch MissingOptionException in " + cl );
+ }
+ }
+ }
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/ParseTest.java b/installer/test/java/org/apache/commons/cli/ParseTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/ParseTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: ParseTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class ParseTest extends TestCase
+{
+
+ private Options _options = null;
+ private CommandLineParser _parser = null;
+
+ public static Test suite() {
+ return new TestSuite(ParseTest.class);
+ }
+
+ public ParseTest(String name)
+ {
+ super(name);
+ }
+
+ public void setUp()
+ {
+ _options = new Options()
+ .addOption("a",
+ "enable-a",
+ false,
+ "turn [a] on or off")
+ .addOption("b",
+ "bfile",
+ true,
+ "set the value of [b]")
+ .addOption("c",
+ "copt",
+ false,
+ "turn [c] on or off");
+
+ _parser = new PosixParser();
+ }
+
+ public void tearDown()
+ {
+
+ }
+
+ public void testSimpleShort()
+ {
+ String[] args = new String[] { "-a",
+ "-b", "toast",
+ "foo", "bar" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testSimpleLong()
+ {
+ String[] args = new String[] { "--enable-a",
+ "--bfile", "toast",
+ "foo", "bar" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testComplexShort()
+ {
+ String[] args = new String[] { "-acbtoast",
+ "foo", "bar" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testExtraOption()
+ {
+ String[] args = new String[] { "-adbtoast",
+ "foo", "bar" };
+
+ boolean caught = false;
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm size of extra args", cl.getArgList().size() == 3);
+ }
+ catch (UnrecognizedOptionException e)
+ {
+ caught = true;
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ assertTrue( "Confirm UnrecognizedOptionException caught", caught );
+ }
+
+ public void testMissingArg()
+ {
+
+ String[] args = new String[] { "-acb" };
+
+ boolean caught = false;
+
+ CommandLine cl = null;
+ try
+ {
+ cl = _parser.parse(_options, args);
+ }
+ catch (MissingArgumentException e)
+ {
+ caught = true;
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+
+ assertTrue( "Confirm MissingArgumentException caught " + cl, caught );
+ }
+
+ public void testStop()
+ {
+ String[] args = new String[] { "-c",
+ "foober",
+ "-btoast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args, true);
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testMultiple()
+ {
+ String[] args = new String[] { "-c",
+ "foobar",
+ "-btoast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args, true);
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
+
+ cl = _parser.parse(_options, cl.getArgs() );
+
+ assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+ assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testMultipleWithLong()
+ {
+ String[] args = new String[] { "--copt",
+ "foobar",
+ "--bfile", "toast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options,args,
+ true);
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm 3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+
+ cl = _parser.parse(_options, cl.getArgs() );
+
+ assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+ assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+ assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testDoubleDash()
+ {
+ String[] args = new String[] { "--copt",
+ "--",
+ "-b", "toast" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -c is set", cl.hasOption("c") );
+ assertTrue( "Confirm -b is not set", ! cl.hasOption("b") );
+ assertTrue( "Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
+
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+ }
+
+ public void testSingleDash()
+ {
+ String[] args = new String[] { "--copt",
+ "-b", "-",
+ "-a",
+ "-" };
+
+ try
+ {
+ CommandLine cl = _parser.parse(_options, args);
+
+ assertTrue( "Confirm -a is set", cl.hasOption("a") );
+ assertTrue( "Confirm -b is set", cl.hasOption("b") );
+ assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("-") );
+ assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+ assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("-") );
+ }
+ catch (ParseException e)
+ {
+ fail( e.toString() );
+ }
+
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java b/installer/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: PatternOptionBuilderTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+package org.apache.commons.cli;
+
+import java.math.BigDecimal;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test case for the PatternOptionBuilder class
+ *
+ * @author Henri Yandell
+ **/
+public class PatternOptionBuilderTest
+extends TestCase
+{
+ public static void main( String[] args )
+ {
+ String[] testName = { PatternOptionBuilderTest.class.getName() };
+ junit.textui.TestRunner.main(testName);
+ }
+
+ public static TestSuite suite()
+ {
+ return new TestSuite(PatternOptionBuilderTest.class);
+ }
+
+ public PatternOptionBuilderTest( String s )
+ {
+ super( s );
+ }
+
+ public void testSimplePattern()
+ {
+ try {
+ Options options = PatternOptionBuilder.parsePattern("a:b at cde>f+n%t/");
+ String[] args = new String[] { "-c", "-a", "foo", "-b", "java.util.Vector", "-e", "build.xml", "-f", "java.util.Calendar", "-n", "4.5", "-t", "http://jakarta.apache.org/" };
+
+ CommandLineParser parser = new PosixParser();
+ CommandLine line = parser.parse(options,args);
+
+ // tests the char methods of CommandLine that delegate to
+ // the String methods
+ assertEquals("flag a", "foo", line.getOptionValue("a"));
+ assertEquals("flag a", "foo", line.getOptionValue('a'));
+ assertEquals("string flag a", "foo", line.getOptionObject("a"));
+ assertEquals("string flag a", "foo", line.getOptionObject('a'));
+ assertEquals("object flag b", new java.util.Vector(), line.getOptionObject("b"));
+ assertEquals("object flag b", new java.util.Vector(), line.getOptionObject('b'));
+ assertEquals("boolean true flag c", true, line.hasOption("c"));
+ assertEquals("boolean true flag c", true, line.hasOption('c'));
+ assertEquals("boolean false flag d", false, line.hasOption("d"));
+ assertEquals("boolean false flag d", false, line.hasOption('d'));
+ assertEquals("file flag e", new java.io.File("build.xml"), line.getOptionObject("e"));
+ assertEquals("file flag e", new java.io.File("build.xml"), line.getOptionObject('e'));
+ assertEquals("class flag f", java.util.Calendar.class, line.getOptionObject("f"));
+ assertEquals("class flag f", java.util.Calendar.class, line.getOptionObject('f'));
+ assertEquals("number flag n", new BigDecimal("4.5"), line.getOptionObject("n"));
+ assertEquals("number flag n", new BigDecimal("4.5"), line.getOptionObject('n'));
+ assertEquals("url flag t", new java.net.URL("http://jakarta.apache.org/"), line.getOptionObject("t"));
+ assertEquals("url flag t", new java.net.URL("http://jakarta.apache.org/"), line.getOptionObject('t'));
+ /// DATES NOT SUPPORTED YET.
+ // assertEquals("number flag t", new java.util.Date(1023400137276L), line.getOptionObject('z'));
+ // input is: "Thu Jun 06 17:48:57 EDT 2002"
+ }
+ catch( ParseException exp ) {
+ fail( exp.getMessage() );
+ }
+ catch( java.net.MalformedURLException exp ) {
+ fail( exp.getMessage() );
+ }
+ }
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/PosixParserTest.java b/installer/test/java/org/apache/commons/cli/PosixParserTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/PosixParserTest.java
@@ -0,0 +1,138 @@
+package org.apache.commons.cli;
+
+import junit.framework.TestCase;
+
+public class PosixParserTest extends TestCase {
+
+ private static final String TEST_SHORT = "t";
+ private static final String TEST_LONG = "test";
+ private static final String TEST_DESC = "test option";
+
+ private static final String TEST_SHORT_OPTION = "-t";
+ private static final String TEST_LONG_OPTION = "--test";
+
+ private static final String ARGUMENT = "argument";
+
+ private Options _options;
+ private Parser _parser;
+
+ protected void setUp() {
+ _parser = new PosixParser();
+
+ _options = new Options();
+ Option testOption = new Option(TEST_SHORT, TEST_LONG, false, TEST_DESC);
+ _options.addOption(testOption);
+ }
+
+ /**
+ * test that an unknown single option and a double hyphen option (with or without argument) are treated the same
+ */
+ public void testFlattenStop() {
+ boolean stopAtNonOption = true; // means unallowed tokens should not be added
+ String[] args;
+ String[] expectedFlattened;
+
+ // unknown single dash option
+ args = new String[] { "-u" };
+ expectedFlattened = new String[0];
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "-u", TEST_SHORT_OPTION };
+ expectedFlattened = new String[] { TEST_SHORT_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+
+ // unknown double dash option
+ args = new String[] { "--unknown" };
+ expectedFlattened = new String[0];
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "--unknown", TEST_LONG_OPTION };
+ expectedFlattened = new String[] { TEST_LONG_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+
+ // unknown double dash option with argument after =
+ args = new String[] { "--unknown=" + ARGUMENT };
+ expectedFlattened = new String[0];
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "--unknown="+ARGUMENT, TEST_LONG_OPTION };
+ expectedFlattened = new String[] { TEST_LONG_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+
+ // unknown double dash option with argument after ' '
+ args = new String[] { "--unknown", ARGUMENT };
+ expectedFlattened = new String[] { ARGUMENT };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "--unknown", ARGUMENT, TEST_LONG_OPTION };
+ expectedFlattened = new String[] { ARGUMENT, TEST_LONG_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ }
+
+ /**
+ * test that an unknown single option and a double hyphen option (with or without argument) are treated the same
+ */
+ public void testFlattenNoStop() {
+ boolean stopAtNonOption = false; // means every token should be added
+ String[] args;
+ String[] expectedFlattened;
+
+ // unknown single dash option
+ args = new String[] { "-u" };
+ expectedFlattened = new String[] { "-u" };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "-u", TEST_SHORT_OPTION };
+ expectedFlattened = new String[] { "-u", TEST_SHORT_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+
+ // unknown double dash option
+ args = new String[] { "--unknown" };
+ expectedFlattened = new String[] { "--unknown" };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "--unknown", TEST_LONG_OPTION };
+ expectedFlattened = new String[] { "--unknown", TEST_LONG_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+
+ // unknown double dash option with argument after =
+ args = new String[] { "--unknown=" + ARGUMENT };
+ expectedFlattened = new String[] { "--unknown", ARGUMENT };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "--unknown="+ ARGUMENT, TEST_LONG_OPTION };
+ expectedFlattened = new String[] { "--unknown", ARGUMENT, TEST_LONG_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+
+ // unknown double dash option with argument after ' '
+ args = new String[] { "--unknown", ARGUMENT };
+ expectedFlattened = new String[] { "--unknown", ARGUMENT };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ args = new String[] { "--unknown", ARGUMENT, TEST_LONG_OPTION };
+ expectedFlattened = new String[] { "--unknown", ARGUMENT, TEST_LONG_OPTION };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ }
+
+ /**
+ * test that a misspelled long option (-test instead of --test) is not interpreted as -t est
+ */
+ public void testMisspelledLongOption() {
+ boolean stopAtNonOption = false; // means every token should be added
+ String[] args;
+ String[] expectedFlattened;
+
+ // unknown single dash long option
+ String singleDashLongOption = "-" + TEST_LONG;
+ args = new String[] { singleDashLongOption };
+ expectedFlattened = new String[] { singleDashLongOption };
+ assertEquals(expectedFlattened, _parser.flatten(_options, args, stopAtNonOption));
+ }
+
+ //
+ // private stuff
+ //
+
+ /**
+ * Assert that the content of the specified object arrays is equal
+ */
+ private void assertEquals(Object[] correct, Object[] tested) {
+ assertEquals("different array lengths:", correct.length, tested.length);
+ for (int i = 0; i < correct.length; i++) {
+ assertEquals("position " + i + " of array differs", correct[i], tested[i]);
+ }
+ }
+
+}
diff --git a/installer/test/java/org/apache/commons/cli/TestHelpFormatter.java b/installer/test/java/org/apache/commons/cli/TestHelpFormatter.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/TestHelpFormatter.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: TestHelpFormatter.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+package org.apache.commons.cli;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test case for the HelpFormatter class
+ *
+ * @author Slawek Zachcial
+ * @author John Keyes ( john at integralsource.com )
+ **/
+public class TestHelpFormatter extends TestCase
+{
+ public static void main( String[] args )
+ {
+ String[] testName = { TestHelpFormatter.class.getName() };
+ junit.textui.TestRunner.main(testName);
+ }
+
+ public static TestSuite suite()
+ {
+ return new TestSuite(TestHelpFormatter.class);
+ }
+
+ public TestHelpFormatter( String s )
+ {
+ super( s );
+ }
+
+ public void testFindWrapPos()
+ throws Exception
+ {
+ HelpFormatter hf = new HelpFormatter();
+
+ String text = "This is a test.";
+ //text width should be max 8; the wrap postition is 7
+ assertEquals("wrap position", 7, hf.findWrapPos(text, 8, 0));
+ //starting from 8 must give -1 - the wrap pos is after end
+ assertEquals("wrap position 2", -1, hf.findWrapPos(text, 8, 8));
+ //if there is no a good position before width to make a wrapping look for the next one
+ text = "aaaa aa";
+ assertEquals("wrap position 3", 4, hf.findWrapPos(text, 3, 0));
+ }
+
+ public void testPrintWrapped()
+ throws Exception
+ {
+ StringBuffer sb = new StringBuffer();
+ HelpFormatter hf = new HelpFormatter();
+
+ String text = "This is a test.";
+ String expected;
+
+ expected = "This is a" + hf.defaultNewLine + "test.";
+ hf.renderWrappedText(sb, 12, 0, text);
+ assertEquals("single line text", expected, sb.toString());
+
+ sb.setLength(0);
+ expected = "This is a" + hf.defaultNewLine + " test.";
+ hf.renderWrappedText(sb, 12, 4, text);
+ assertEquals("single line padded text", expected, sb.toString());
+
+ text =
+ "aaaa aaaa aaaa" + hf.defaultNewLine +
+ "aaaaaa" + hf.defaultNewLine +
+ "aaaaa";
+
+ expected = text;
+ sb.setLength(0);
+ hf.renderWrappedText(sb, 16, 0, text);
+ assertEquals("multi line text", expected, sb.toString());
+
+ expected =
+ "aaaa aaaa aaaa" + hf.defaultNewLine +
+ " aaaaaa" + hf.defaultNewLine +
+ " aaaaa";
+ sb.setLength(0);
+ hf.renderWrappedText(sb, 16, 4, text);
+ assertEquals("multi-line padded text", expected, sb.toString());
+ }
+
+ public void testPrintOptions()
+ throws Exception
+ {
+ StringBuffer sb = new StringBuffer();
+ HelpFormatter hf = new HelpFormatter();
+ final int leftPad = 1;
+ final int descPad = 3;
+ final String lpad = hf.createPadding(leftPad);
+ final String dpad = hf.createPadding(descPad);
+ Options options = null;
+ String expected = null;
+
+ options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
+ expected = lpad + "-a" + dpad + "aaaa aaaa aaaa aaaa aaaa";
+ hf.renderOptions(sb, 60, options, leftPad, descPad);
+ assertEquals("simple non-wrapped option", expected, sb.toString());
+
+ int nextLineTabStop = leftPad+descPad+"-a".length();
+ expected =
+ lpad + "-a" + dpad + "aaaa aaaa aaaa" + hf.defaultNewLine +
+ hf.createPadding(nextLineTabStop) + "aaaa aaaa";
+ sb.setLength(0);
+ hf.renderOptions(sb, nextLineTabStop+17, options, leftPad, descPad);
+ assertEquals("simple wrapped option", expected, sb.toString());
+
+
+ options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd");
+ expected = lpad + "-a,--aaa" + dpad + "dddd dddd dddd dddd";
+ sb.setLength(0);
+ hf.renderOptions(sb, 60, options, leftPad, descPad);
+ assertEquals("long non-wrapped option", expected, sb.toString());
+
+ nextLineTabStop = leftPad+descPad+"-a,--aaa".length();
+ expected =
+ lpad + "-a,--aaa" + dpad + "dddd dddd" + hf.defaultNewLine +
+ hf.createPadding(nextLineTabStop) + "dddd dddd";
+ sb.setLength(0);
+ hf.renderOptions(sb, 25, options, leftPad, descPad);
+ assertEquals("long wrapped option", expected, sb.toString());
+
+ options = new Options().
+ addOption("a", "aaa", false, "dddd dddd dddd dddd").
+ addOption("b", false, "feeee eeee eeee eeee");
+ expected =
+ lpad + "-a,--aaa" + dpad + "dddd dddd" + hf.defaultNewLine +
+ hf.createPadding(nextLineTabStop) + "dddd dddd" + hf.defaultNewLine +
+ lpad + "-b " + dpad + "feeee eeee" + hf.defaultNewLine +
+ hf.createPadding(nextLineTabStop) + "eeee eeee";
+ sb.setLength(0);
+ hf.renderOptions(sb, 25, options, leftPad, descPad);
+ assertEquals("multiple wrapped options", expected, sb.toString());
+ }
+
+ public void testAutomaticUsage()
+ throws Exception
+ {
+ HelpFormatter hf = new HelpFormatter();
+ Options options = null;
+ String expected = "usage: app [-a]";
+ ByteArrayOutputStream out = new ByteArrayOutputStream( );
+ PrintWriter pw = new PrintWriter( out );
+
+ options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
+ hf.printUsage( pw, 60, "app", options );
+ pw.flush();
+ assertEquals("simple auto usage", expected, out.toString().trim());
+ out.reset();
+
+ expected = "usage: app [-b] [-a]";
+ options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa")
+ .addOption("b", false, "bbb" );
+ hf.printUsage( pw, 60, "app", options );
+ pw.flush();
+ assertEquals("simple auto usage", expected, out.toString().trim());
+ out.reset();
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/ValueTest.java b/installer/test/java/org/apache/commons/cli/ValueTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/ValueTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: ValueTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class ValueTest extends TestCase
+{
+
+ public static Test suite() {
+ return new TestSuite(ValueTest.class);
+ }
+
+ private CommandLine _cl = null;
+ private Options opts = new Options();
+
+ public ValueTest(String name)
+ {
+ super(name);
+ }
+
+ public void setUp()
+ {
+ opts.addOption("a",
+ false,
+ "toggle -a");
+
+ opts.addOption("b",
+ true,
+ "set -b");
+
+ opts.addOption("c",
+ "c",
+ false,
+ "toggle -c");
+
+ opts.addOption("d",
+ "d",
+ true,
+ "set -d");
+
+ OptionBuilder.hasOptionalArg();
+ opts.addOption( OptionBuilder.create( 'e') );
+
+ OptionBuilder.hasOptionalArg();
+ OptionBuilder.withLongOpt( "fish" );
+ opts.addOption( OptionBuilder.create( ) );
+
+ OptionBuilder.hasOptionalArgs();
+ OptionBuilder.withLongOpt( "gravy" );
+ opts.addOption( OptionBuilder.create( ) );
+
+ OptionBuilder.hasOptionalArgs( 2 );
+ OptionBuilder.withLongOpt( "hide" );
+ opts.addOption( OptionBuilder.create( ) );
+
+ OptionBuilder.hasOptionalArgs( 2 );
+ opts.addOption( OptionBuilder.create( 'i' ) );
+
+ OptionBuilder.hasOptionalArgs( );
+ opts.addOption( OptionBuilder.create( 'j' ) );
+
+ String[] args = new String[] { "-a",
+ "-b", "foo",
+ "--c",
+ "--d", "bar"
+ };
+
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ _cl = parser.parse(opts,args);
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void tearDown()
+ {
+
+ }
+
+ public void testShortNoArg()
+ {
+ assertTrue( _cl.hasOption("a") );
+ assertNull( _cl.getOptionValue("a") );
+ }
+
+ public void testShortWithArg()
+ {
+ assertTrue( _cl.hasOption("b") );
+ assertNotNull( _cl.getOptionValue("b") );
+ assertEquals( _cl.getOptionValue("b"), "foo");
+ }
+
+ public void testLongNoArg()
+ {
+ assertTrue( _cl.hasOption("c") );
+ assertNull( _cl.getOptionValue("c") );
+ }
+
+ public void testLongWithArg()
+ {
+ assertTrue( _cl.hasOption("d") );
+ assertNotNull( _cl.getOptionValue("d") );
+ assertEquals( _cl.getOptionValue("d"), "bar");
+ }
+
+ public void testShortOptionalArgNoValue()
+ {
+ String[] args = new String[] { "-e"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("e") );
+ assertNull( cmd.getOptionValue("e") );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testShortOptionalArgValue()
+ {
+ String[] args = new String[] { "-e", "everything"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("e") );
+ assertEquals( "everything", cmd.getOptionValue("e") );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testLongOptionalNoValue()
+ {
+ String[] args = new String[] { "--fish"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("fish") );
+ assertNull( cmd.getOptionValue("fish") );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testLongOptionalArgValue()
+ {
+ String[] args = new String[] { "--fish", "face"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("fish") );
+ assertEquals( "face", cmd.getOptionValue("fish") );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testShortOptionalArgValues()
+ {
+ String[] args = new String[] { "-j", "ink", "idea"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("j") );
+ assertEquals( "ink", cmd.getOptionValue("j") );
+ assertEquals( "ink", cmd.getOptionValues("j")[0] );
+ assertEquals( "idea", cmd.getOptionValues("j")[1] );
+ assertEquals( cmd.getArgs().length, 0 );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testLongOptionalArgValues()
+ {
+ String[] args = new String[] { "--gravy", "gold", "garden"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("gravy") );
+ assertEquals( "gold", cmd.getOptionValue("gravy") );
+ assertEquals( "gold", cmd.getOptionValues("gravy")[0] );
+ assertEquals( "garden", cmd.getOptionValues("gravy")[1] );
+ assertEquals( cmd.getArgs().length, 0 );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testShortOptionalNArgValues()
+ {
+ String[] args = new String[] { "-i", "ink", "idea", "isotope", "ice"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("i") );
+ assertEquals( "ink", cmd.getOptionValue("i") );
+ assertEquals( "ink", cmd.getOptionValues("i")[0] );
+ assertEquals( "idea", cmd.getOptionValues("i")[1] );
+ assertEquals( cmd.getArgs().length, 2 );
+ assertEquals( "isotope", cmd.getArgs()[0] );
+ assertEquals( "ice", cmd.getArgs()[1] );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void testLongOptionalNArgValues()
+ {
+ String[] args = new String[] { "--hide", "house", "hair", "head"
+ };
+ try
+ {
+ CommandLineParser parser = new PosixParser();
+ CommandLine cmd = parser.parse(opts,args);
+ assertTrue( cmd.hasOption("hide") );
+ assertEquals( "house", cmd.getOptionValue("hide") );
+ assertEquals( "house", cmd.getOptionValues("hide")[0] );
+ assertEquals( "hair", cmd.getOptionValues("hide")[1] );
+ assertEquals( cmd.getArgs().length, 1 );
+ assertEquals( "head", cmd.getArgs()[0] );
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+}
diff --git a/installer/test/java/org/apache/commons/cli/ValuesTest.java b/installer/test/java/org/apache/commons/cli/ValuesTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/apache/commons/cli/ValuesTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ *
+ * $Id: ValuesTest.java 3134 2007-03-02 07:20:08Z otmarhumbel $
+ */
+
+package org.apache.commons.cli;
+
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class ValuesTest extends TestCase
+{
+ /** CommandLine instance */
+ private CommandLine _cmdline = null;
+ private Option _option = null;
+
+ public static Test suite() {
+ return new TestSuite( ValuesTest.class );
+ }
+
+ public ValuesTest( String name )
+ {
+ super( name );
+ }
+
+ public void setUp()
+ {
+ Options opts = new Options();
+
+ opts.addOption("a",
+ false,
+ "toggle -a");
+
+ opts.addOption("b",
+ true,
+ "set -b");
+
+ opts.addOption("c",
+ "c",
+ false,
+ "toggle -c");
+
+ opts.addOption("d",
+ "d",
+ true,
+ "set -d");
+
+ OptionBuilder.withLongOpt( "e" );
+ OptionBuilder.hasArgs();
+ OptionBuilder.withDescription( "set -e ");
+ opts.addOption( OptionBuilder.create( 'e' ) );
+
+ opts.addOption("f",
+ "f",
+ false,
+ "jk");
+
+ OptionBuilder.withLongOpt( "g" );
+ OptionBuilder.hasArgs( 2 );
+ OptionBuilder.withDescription( "set -g");
+ opts.addOption( OptionBuilder.create( 'g' ) );
+
+ OptionBuilder.withLongOpt( "h" );
+ OptionBuilder.hasArgs( 2 );
+ OptionBuilder.withDescription( "set -h");
+ opts.addOption( OptionBuilder.create( 'h' ) );
+
+ OptionBuilder.withLongOpt( "i" );
+ OptionBuilder.withDescription( "set -i");
+ opts.addOption( OptionBuilder.create( 'i' ) );
+
+ OptionBuilder.withLongOpt( "j" );
+ OptionBuilder.hasArgs( );
+ OptionBuilder.withDescription( "set -j");
+ OptionBuilder.withValueSeparator( '=' );
+ opts.addOption( OptionBuilder.create( 'j' ) );
+
+ OptionBuilder.withLongOpt( "k" );
+ OptionBuilder.hasArgs( );
+ OptionBuilder.withDescription( "set -k");
+ OptionBuilder.withValueSeparator( '=' );
+ opts.addOption( OptionBuilder.create( 'k' ) );
+
+ OptionBuilder.withLongOpt( "m" );
+ OptionBuilder.hasArgs( );
+ OptionBuilder.withDescription( "set -m");
+ OptionBuilder.withValueSeparator( );
+ _option = OptionBuilder.create( 'm' );
+
+ opts.addOption( _option );
+
+ String[] args = new String[] { "-a",
+ "-b", "foo",
+ "--c",
+ "--d", "bar",
+ "-e", "one", "two",
+ "-f",
+ "arg1", "arg2",
+ "-g", "val1", "val2" , "arg3",
+ "-h", "val1", "-i",
+ "-h", "val2",
+ "-jkey=value",
+ "-j", "key=value",
+ "-kkey1=value1",
+ "-kkey2=value2",
+ "-mkey=value"};
+
+ CommandLineParser parser = new PosixParser();
+
+ try
+ {
+ _cmdline = parser.parse(opts,args);
+ }
+ catch (ParseException e)
+ {
+ fail("Cannot setUp() CommandLine: " + e.toString());
+ }
+ }
+
+ public void tearDown()
+ {
+
+ }
+
+ public void testShortArgs()
+ {
+ assertTrue( _cmdline.hasOption("a") );
+ assertTrue( _cmdline.hasOption("c") );
+
+ assertNull( _cmdline.getOptionValues("a") );
+ assertNull( _cmdline.getOptionValues("c") );
+ }
+
+ public void testShortArgsWithValue()
+ {
+ assertTrue( _cmdline.hasOption("b") );
+ assertTrue( _cmdline.getOptionValue("b").equals("foo"));
+ assertTrue( _cmdline.getOptionValues("b").length == 1);
+
+ assertTrue( _cmdline.hasOption("d") );
+ assertTrue( _cmdline.getOptionValue("d").equals("bar"));
+ assertTrue( _cmdline.getOptionValues("d").length == 1);
+ }
+
+ public void testMultipleArgValues()
+ {
+ _cmdline.getOptionValues("e");
+ String[] values = new String[] { "one", "two" };
+ assertTrue( _cmdline.hasOption("e") );
+ assertTrue( _cmdline.getOptionValues("e").length == 2);
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues("e") ) );
+ }
+
+ public void testTwoArgValues()
+ {
+ _cmdline.getOptionValues("g");
+ String[] values = new String[] { "val1", "val2" };
+ assertTrue( _cmdline.hasOption("g") );
+ assertTrue( _cmdline.getOptionValues("g").length == 2);
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues("g") ) );
+ }
+
+ public void testComplexValues()
+ {
+ _cmdline.getOptionValues("h");
+ String[] values = new String[] { "val1", "val2" };
+ assertTrue( _cmdline.hasOption("i") );
+ assertTrue( _cmdline.hasOption("h") );
+ assertTrue( _cmdline.getOptionValues("h").length == 2);
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues("h") ) );
+ }
+
+ public void testExtraArgs()
+ {
+ String[] args = new String[] { "arg1", "arg2", "arg3" };
+ assertTrue( _cmdline.getArgs().length == 3 );
+ assertTrue( Arrays.equals( args, _cmdline.getArgs() ) );
+ }
+
+ public void testCharSeparator()
+ {
+ // tests the char methods of CommandLine that delegate to
+ // the String methods
+ String[] values = new String[] { "key", "value", "key", "value" };
+ assertTrue( _cmdline.hasOption( "j" ) );
+ assertTrue( _cmdline.hasOption( 'j' ) );
+ assertTrue( _cmdline.getOptionValues( "j" ).length == 4);
+ assertTrue( _cmdline.getOptionValues( 'j' ).length == 4);
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "j" ) ) );
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'j' ) ) );
+
+ values = new String[] { "key1", "value1", "key2", "value2" };
+ assertTrue( _cmdline.hasOption( "k" ) );
+ assertTrue( _cmdline.hasOption( 'k' ) );
+ assertTrue( _cmdline.getOptionValues( "k" ).length == 4 );
+ assertTrue( _cmdline.getOptionValues( 'k' ).length == 4 );
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "k" ) ) );
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'k' ) ) );
+
+ values = new String[] { "key", "value" };
+ assertTrue( _cmdline.hasOption( "m" ) );
+ assertTrue( _cmdline.hasOption( 'm' ) );
+ assertTrue( _cmdline.getOptionValues( "m" ).length == 2);
+ assertTrue( _cmdline.getOptionValues( 'm' ).length == 2);
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "m" ) ) );
+ assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'm' ) ) );
+ }
+
+ /**
+ * jkeyes - commented out this test as the new architecture
+ * breaks this type of functionality. I have left the test
+ * here in case I get a brainwave on how to resolve this.
+ */
+ /*
+ public void testGetValue()
+ {
+ // the 'm' option
+ assertTrue( _option.getValues().length == 2 );
+ assertEquals( _option.getValue(), "key" );
+ assertEquals( _option.getValue( 0 ), "key" );
+ assertEquals( _option.getValue( 1 ), "value" );
+
+ try {
+ assertEquals( _option.getValue( 2 ), "key" );
+ fail( "IndexOutOfBounds not caught" );
+ }
+ catch( IndexOutOfBoundsException exp ) {
+
+ }
+
+ try {
+ assertEquals( _option.getValue( -1 ), "key" );
+ fail( "IndexOutOfBounds not caught" );
+ }
+ catch( IndexOutOfBoundsException exp ) {
+
+ }
+ }
+ */
+}
diff --git a/installer/test/java/org/python/util/install/ChildProcessExample.java b/installer/test/java/org/python/util/install/ChildProcessExample.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/ChildProcessExample.java
@@ -0,0 +1,32 @@
+
+package org.python.util.install;
+
+/**
+ * An example child process that generates some output.
+ */
+public class ChildProcessExample {
+
+ public ChildProcessExample() {
+ System.out.println("[ChildProcessExample] is now here.");
+ }
+
+ public static void main(String args[]) {
+ int i = 0;
+ new ChildProcessExample();
+ for (i = 0; i < 10; i++) {
+ System.out.println("[ChildProcessExample] printing to stdout " + i);
+ // occasionally print to stderr, too
+ if (i % 3 == 0) {
+ System.err.println("[ChildProcessExample] printing to stderr " + i);
+ }
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ }
+ System.out.println("[ChildProcessExample] Exiting");
+ System.exit(0);
+ }
+
+}
\ No newline at end of file
diff --git a/installer/test/java/org/python/util/install/ChildProcessTest.java b/installer/test/java/org/python/util/install/ChildProcessTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/ChildProcessTest.java
@@ -0,0 +1,80 @@
+package org.python.util.install;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import junit.framework.TestCase;
+
+public class ChildProcessTest extends TestCase {
+
+ private final static String CLASS_NAME = "org.python.util.install.ChildProcessExample";
+
+ /**
+ * test a default child process
+ */
+ public void testDefault() {
+ ChildProcess childProcess = new ChildProcess();
+ String command[] = buildJavaCommand(CLASS_NAME);
+ childProcess.setCommand(command);
+ childProcess.setDebug(true);
+ int exitValue = childProcess.run();
+ assertEquals("Expected child process to end normally instead of " + exitValue, 0, exitValue);
+ }
+
+ /**
+ * test the child process with a timeout
+ */
+ public void testTimeout() {
+ ChildProcess childProcess = new ChildProcess();
+ String command[] = buildJavaCommand(CLASS_NAME);
+ childProcess.setCommand(command);
+ childProcess.setDebug(true);
+ childProcess.setTimeout(2000); // timeout to 2 seconds
+ int exitValue = childProcess.run();
+ assertEquals("Expected child process to be destroyed instead of " + exitValue,
+ ChildProcess.DESTROYED_AFTER_TIMEOUT,
+ exitValue);
+ }
+
+ /**
+ * test silent mode
+ */
+ public void testSilent() throws IOException {
+ ChildProcess childProcess = new ChildProcess();
+ String command[] = new String[] {"lwiklsl", "-siwK"};
+ childProcess.setCommand(command);
+ childProcess.setDebug(false);
+ childProcess.setSilent(true);
+ ByteArrayOutputStream redirectedErr = new ByteArrayOutputStream();
+ ByteArrayOutputStream redirectedOut = new ByteArrayOutputStream();
+ int exitValue = 0;
+ PrintStream oldErr = System.err;
+ PrintStream oldOut = System.out;
+ try {
+ System.setErr(new PrintStream(redirectedErr));
+ System.setOut(new PrintStream(redirectedOut));
+ exitValue = childProcess.run();
+ } finally {
+ System.setErr(oldErr);
+ System.setOut(oldOut);
+ }
+ assertTrue(0 != exitValue);
+ redirectedErr.flush();
+ redirectedOut.flush();
+ assertEquals(0, redirectedErr.size());
+ assertEquals(0, redirectedOut.size());
+ }
+
+ //
+ // private methods
+ //
+ private String[] buildJavaCommand(String classAndArguments) {
+ String quote = "";
+ if (System.getProperty("os.name", "unknown").toLowerCase().indexOf("windows") >= 0) {
+ quote = "\"";
+ }
+ String classpath = System.getProperty("java.class.path");
+ return new String[] {"java", "-classpath", quote.concat(classpath).concat(quote), classAndArguments};
+ }
+}
\ No newline at end of file
diff --git a/installer/test/java/org/python/util/install/ChmodTest_Standalone.java b/installer/test/java/org/python/util/install/ChmodTest_Standalone.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/ChmodTest_Standalone.java
@@ -0,0 +1,57 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Helper class to test of 'chmod' on different platforms
+ */
+public class ChmodTest_Standalone {
+
+ private static String _mode = "755"; // default mode
+
+ public static void main(String[] args) {
+ // get mode from first argument, if present
+ if (args.length > 0) {
+ _mode = args[0];
+ }
+
+ // create an empty test file in the current directory
+ String curdir = System.getProperty("user.dir");
+ File testFile = new File(curdir, "chmod.test");
+ String path = testFile.getAbsolutePath();
+ if (!testFile.exists()) {
+ try {
+ if (!testFile.createNewFile()) {
+ System.err.println(getPrefix() + "unable to create file " + path);
+ System.exit(1);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ // apply the chmod command on the test file
+ if (!testFile.exists()) {
+ System.err.println(getPrefix() + "unable to create file " + path);
+ System.exit(1);
+ } else {
+ String command[] = new String[] {"chmod", _mode, path};
+ ChildProcess childProcess = new ChildProcess(command, 3000);
+ childProcess.setDebug(true);
+ int exitValue = childProcess.run();
+ if (exitValue != 0) {
+ System.err.println(getPrefix() + "error during chmod");
+ } else {
+ System.out.println(getPrefix() + "chmod command executed on " + path);
+ }
+ System.exit(exitValue);
+ }
+ }
+
+ private static String getPrefix() {
+ return "[ChmodTest_Standalone] ";
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/FileHelperTest.java b/installer/test/java/org/python/util/install/FileHelperTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/FileHelperTest.java
@@ -0,0 +1,271 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+import junit.framework.TestCase;
+import junit.runner.TestSuiteLoader;
+
+import org.python.util.install.driver.Autotest;
+
+public class FileHelperTest extends TestCase {
+
+ private static final String JYTHON_TEST_TEMPLATE = "jython_test.template";
+
+ private static final String LOGO_GIF = "logo.gif";
+
+ private static final String JYTHON_SMALL_C_PNG = "jython_small_c.png";
+
+ public void testCreateTempDirectory_WasFile() throws IOException {
+ File file = File.createTempFile("some_prefix", "");
+ assertTrue(file.exists());
+ assertTrue(file.isFile());
+ assertTrue(FileHelper.createTempDirectory(file));
+ assertTrue(file.exists());
+ assertTrue(file.isDirectory());
+ }
+
+ public void testCreateTempDirectory_AlreadyPresent() throws IOException {
+ File dir = new File(System.getProperty("user.dir"));
+ assertTrue(dir.exists());
+ assertTrue(dir.isDirectory());
+ assertTrue(FileHelper.createTempDirectory(dir));
+ assertTrue(dir.exists());
+ assertTrue(dir.isDirectory());
+ }
+
+ public void testCreateTempDirectory() throws IOException {
+ File dir = new File(System.getProperty("user.dir"));
+ assertTrue(dir.exists());
+ assertTrue(dir.isDirectory());
+ File tmpDir = new File(dir, "tmp");
+ assertFalse(tmpDir.exists());
+ try {
+ assertTrue(FileHelper.createTempDirectory(tmpDir));
+ assertTrue(tmpDir.exists());
+ assertTrue(dir.isDirectory());
+ } finally {
+ if (tmpDir.exists()) {
+ assertTrue(tmpDir.delete());
+ }
+ }
+ }
+
+ public void testCreateTempDirectory_Failure() throws Exception {
+ File dir = new File(System.getProperty("user.dir"));
+ assertTrue(dir.exists());
+ assertTrue(dir.isDirectory());
+ File tmpFile = new File(dir, "tmpFailure");
+ assertFalse(tmpFile.exists());
+ try {
+ tmpFile.createNewFile();
+ assertTrue(tmpFile.exists());
+ assertTrue(tmpFile.isFile());
+ Lock lock = null;
+ try {
+ lock = new Lock(tmpFile);
+ boolean created = FileHelper.createTempDirectory(tmpFile);
+ if (Installation.isWindows()) {
+ // locking currently only effective on windows
+ assertFalse(created);
+ } else {
+ // change if there is a locking mechanism
+ assertTrue(created);
+ }
+ } finally {
+ if (lock != null) {
+ lock.release();
+ }
+ }
+ } finally {
+ if (tmpFile.exists()) {
+ assertTrue(tmpFile.delete());
+ }
+ }
+ }
+
+ public void testRmdir() throws IOException {
+ File dir = new File(System.getProperty("java.io.tmpdir"), "StartScriptGeneratorTest");
+ if (!dir.exists()) {
+ assertTrue(dir.mkdirs());
+ }
+ File bin = new File(dir, "bin");
+ if (!bin.exists()) {
+ assertTrue(bin.mkdirs());
+ }
+ File jython = new File(bin, "jython");
+ if (!jython.exists()) {
+ assertTrue(jython.createNewFile());
+ }
+ File jython_bat = new File(bin, "jython.bat");
+ if (!jython_bat.exists()) {
+ assertTrue(jython_bat.createNewFile());
+ }
+ assertTrue(FileHelper.rmdir(dir));
+ }
+
+ public void testRmdir_Failure() throws Exception {
+ File dir = new File(System.getProperty("java.io.tmpdir"), "StartScriptGeneratorTest");
+ if (!dir.exists()) {
+ assertTrue(dir.mkdirs());
+ }
+ File bin = new File(dir, "bin");
+ if (!bin.exists()) {
+ assertTrue(bin.mkdirs());
+ }
+ File jython = new File(bin, "jython");
+ if (!jython.exists()) {
+ assertTrue(jython.createNewFile());
+ }
+ File jython_bat = new File(bin, "jython.bat");
+ if (!jython_bat.exists()) {
+ assertTrue(jython_bat.createNewFile());
+ }
+ Lock lock = null;
+ try {
+ lock = new Lock(jython_bat);
+ boolean removed = FileHelper.rmdir(dir);
+ if (Installation.isWindows()) {
+ // locking currently only effective on windows
+ assertFalse(removed);
+ } else {
+ // change if there is a locking mechanism
+ assertTrue(removed);
+ }
+ } finally {
+ if (lock != null) {
+ lock.release();
+ }
+ assertTrue(FileHelper.rmdir(dir));
+ }
+ }
+
+ public void testReadAll() throws Exception {
+ File file = File.createTempFile("testReadAll", "");
+ final String contents = new String("line1 \n line2 \n");
+ FileHelper.write(file, contents);
+ String readContents = FileHelper.readAll(file);
+ assertEquals(contents, readContents);
+ }
+
+ public void testReadAll_InputStream() throws Exception {
+ URL url = FileHelper.getRelativeURL(Autotest.class, JYTHON_TEST_TEMPLATE);
+ assertNotNull(url);
+ URI uri = new URI(url.toString());
+ File file = new File(uri);
+ assertNotNull(file);
+ assertTrue(file.exists());
+ String expectedContents = FileHelper.readAll(file);
+ InputStream is = FileHelper.getRelativeURLAsStream(Autotest.class, JYTHON_TEST_TEMPLATE);
+ assertNotNull(is);
+ String contents = FileHelper.readAll(is);
+ assertEquals(expectedContents, contents);
+ // now from a .jar
+ is = FileHelper.getRelativeURLAsStream(TestSuiteLoader.class, LOGO_GIF);
+ assertNotNull(is);
+ contents = FileHelper.readAll(is);
+ assertNotNull(contents);
+ assertEquals(964, contents.length());
+ assertTrue(contents.startsWith("GIF89a&"));
+ }
+
+ public void testReadAll_NonExisting() {
+ String readContents = null;
+ try {
+ readContents = FileHelper.readAll(new File("_non_existing"));
+ fail("FileNotFoundException expected");
+ } catch (IOException e) {
+ assertNull(readContents);
+ }
+ }
+
+ public void testGetRelativeURL() {
+ URL url = FileHelper.getRelativeURL(Installation.class, JYTHON_SMALL_C_PNG);
+ assertNotNull(url);
+ assertTrue(url.getPath().endsWith("org/python/util/install/".concat(JYTHON_SMALL_C_PNG)));
+ // now from a .jar
+ url = FileHelper.getRelativeURL(TestSuiteLoader.class, LOGO_GIF);
+ assertNotNull(url);
+ assertTrue(url.getPath().endsWith("!/junit/runner/".concat(LOGO_GIF)));
+ }
+
+ public void testGetRelativeURLAsStream() throws IOException {
+ InputStream is = FileHelper.getRelativeURLAsStream(Installation.class, JYTHON_SMALL_C_PNG);
+ assertNotNull(is);
+ try {
+ assertTrue(is.read() >= 0);
+ } finally {
+ is.close();
+ }
+ // now from a .jar
+ is = FileHelper.getRelativeURLAsStream(TestSuiteLoader.class, LOGO_GIF);
+ assertNotNull(is);
+ try {
+ assertTrue(is.read() >= 0);
+ } finally {
+ is.close();
+ }
+ }
+
+ public void testWrite() throws IOException {
+ File file = new File("testWrite");
+ assertFalse(file.exists());
+ try {
+ final String contents = new String("line1 \n line2 \n");
+ FileHelper.write(file, contents);
+ assertTrue(file.exists());
+ String readContents = FileHelper.readAll(file);
+ assertEquals(contents, readContents);
+ } finally {
+ if (file.exists()) {
+ assertTrue(file.delete());
+ }
+ }
+ }
+
+ public void testWrite_Existing() throws IOException {
+ File file = File.createTempFile("testWrite", "");
+ assertTrue(file.exists());
+ final String firstContents = "first dummy contents";
+ FileHelper.write(file, firstContents);
+ assertEquals(firstContents, FileHelper.readAll(file));
+ final String realContents = new String("line1 \n line2 \n");
+ FileHelper.write(file, realContents);
+ assertEquals(realContents, FileHelper.readAll(file));
+ }
+
+ /**
+ * A poor man's file lock (does work on windows only)
+ */
+ public static class Lock {
+
+ private final FileOutputStream _fos;
+
+ /**
+ * acquire a file lock
+ *
+ * @param file
+ * The file to be locked
+ * @throws FileNotFoundException
+ */
+ public Lock(File file) throws FileNotFoundException {
+ _fos = new FileOutputStream(file);
+ }
+
+ /**
+ * release the file lock
+ *
+ * @throws IOException
+ */
+ public void release() throws IOException {
+ if (_fos != null) {
+ _fos.close();
+ }
+ }
+ }
+}
diff --git a/installer/test/java/org/python/util/install/FrameInstallerTest.java b/installer/test/java/org/python/util/install/FrameInstallerTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/FrameInstallerTest.java
@@ -0,0 +1,88 @@
+package org.python.util.install;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+
+import junit.framework.TestCase;
+
+public class FrameInstallerTest extends TestCase {
+
+ public void testInitDefaultJava() {
+ FrameInstaller.initDefaultJava();
+ JavaVersionInfo vInfo = FrameInstaller.getJavaVersionInfo();
+ assertNotNull(vInfo);
+ String version = vInfo.getVersion();
+ assertNotNull(version);
+ assertTrue(version.length() > 0);
+ String specificationVersion = vInfo.getSpecificationVersion();
+ assertNotNull(specificationVersion);
+ assertTrue(specificationVersion.length() > 0);
+ String vendor = vInfo.getVendor();
+ assertNotNull(vendor);
+ assertTrue(vendor.length() > 0);
+ }
+
+ public void testJavaVersionInfo() {
+ String version = "1;2;3";
+ String vendor = "jython [macrosystems]";
+ String specificationVersion = "@spec 1,4";
+
+ JavaVersionInfo vInfo = new JavaVersionInfo();
+ vInfo.setVersion(version);
+ vInfo.setVendor(vendor);
+ vInfo.setSpecificationVersion(specificationVersion);
+
+ FrameInstaller.setJavaVersionInfo(vInfo);
+ JavaVersionInfo returnedInfo = FrameInstaller.getJavaVersionInfo();
+
+ assertNotNull(returnedInfo);
+ assertEquals(version, returnedInfo.getVersion());
+ assertEquals(vendor, returnedInfo.getVendor());
+ assertEquals(specificationVersion, returnedInfo.getSpecificationVersion());
+ }
+
+ public void testInstallationType() {
+ InstallationType installationType = new InstallationType();
+ installationType.addLibraryModules();
+ installationType.removeDemosAndExamples();
+ installationType.removeDocumentation();
+ installationType.addSources();
+
+ FrameInstaller.setInstallationType(installationType);
+ InstallationType returnedType = FrameInstaller.getInstallationType();
+
+ assertNotNull(returnedType);
+ assertTrue(returnedType.installLibraryModules());
+ assertFalse(returnedType.installDemosAndExamples());
+ assertFalse(returnedType.installDocumentation());
+ assertTrue(returnedType.installSources());
+ }
+
+ public void testStandalone() {
+ InstallationType installationType = new InstallationType();
+ installationType.setStandalone();
+ assertTrue(installationType.installLibraryModules());
+ assertFalse(installationType.installDemosAndExamples());
+ assertFalse(installationType.installDocumentation());
+ assertFalse(installationType.installSources());
+
+ FrameInstaller.setInstallationType(installationType);
+ InstallationType returnedType = FrameInstaller.getInstallationType();
+
+ assertNotNull(returnedType);
+ assertTrue(returnedType.isStandalone());
+ assertTrue(returnedType.installLibraryModules());
+ assertFalse(returnedType.installDemosAndExamples());
+ assertFalse(returnedType.installDocumentation());
+ assertFalse(returnedType.installSources());
+ }
+
+ public void testSetGetJavaHomeHandler() {
+ assertNotNull(FrameInstaller.getJavaHomeHandler());
+ JavaHomeHandler handler1 = new JavaHomeHandler();
+ JavaHomeHandler handler2 = new JavaHomeHandler("some/dir");
+ FrameInstaller.setJavaHomeHandler(handler1);
+ assertEquals(handler1, FrameInstaller.getJavaHomeHandler());
+ FrameInstaller.setJavaHomeHandler(handler2);
+ assertEquals(handler2, FrameInstaller.getJavaHomeHandler());
+ }
+}
diff --git a/installer/test/java/org/python/util/install/InstallationTest.java b/installer/test/java/org/python/util/install/InstallationTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/InstallationTest.java
@@ -0,0 +1,107 @@
+package org.python.util.install;
+
+import java.io.File;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+
+import junit.framework.TestCase;
+
+public class InstallationTest extends TestCase {
+
+ public void testGetExternalJavaVersion() {
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler();
+ JavaVersionInfo versionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ assertEquals(Installation.NORMAL_RETURN, versionInfo.getErrorCode());
+ assertEquals("", versionInfo.getReason());
+ assertTrue(versionInfo.getVersion().length() > 0);
+ assertTrue(versionInfo.getSpecificationVersion().length() > 0);
+ assertTrue(versionInfo.getVersion().startsWith(versionInfo.getSpecificationVersion()));
+ assertNotNull(versionInfo.getVendor());
+ assertNotSame("", versionInfo.getVendor());
+ }
+
+ public void testGetExternalJavaVersionWithError() {
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler("non_existing/home");
+ JavaVersionInfo versionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ assertEquals(Installation.ERROR_RETURN, versionInfo.getErrorCode());
+ String reason = versionInfo.getReason();
+ assertTrue(reason.indexOf("invalid") >= 0);
+ }
+
+ public void testGetExternalJavaVersionNoBinDirectory() {
+ File wrongHome = new File(System.getProperty("user.home"));
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler(wrongHome.getAbsolutePath());
+ JavaVersionInfo versionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ assertEquals(Installation.ERROR_RETURN, versionInfo.getErrorCode());
+ String reason = versionInfo.getReason();
+ assertTrue(reason.indexOf("invalid") >= 0);
+ }
+
+ public void testGetExternalJavaVersionNoJavaInBinDirectory() {
+ File wrongHome = new File(System.getProperty("user.home"));
+ File binDir = new File(wrongHome, "bin");
+ assertFalse(binDir.exists());
+ try {
+ assertTrue(binDir.mkdirs());
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler(wrongHome.getAbsolutePath());
+ JavaVersionInfo versionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ assertEquals(Installation.ERROR_RETURN, versionInfo.getErrorCode());
+ assertTrue(versionInfo.getReason().indexOf("invalid") >= 0);
+ } finally {
+ if (binDir.exists()) {
+ binDir.delete();
+ }
+ }
+ }
+
+ public void testIsValidJavaVersion() {
+ JavaVersionInfo javaVersionInfo = new JavaVersionInfo();
+
+ javaVersionInfo.setSpecificationVersion("1.1.9");
+ assertFalse(Installation.isValidJava(javaVersionInfo));
+ javaVersionInfo.setSpecificationVersion("1.2");
+ assertFalse(Installation.isValidJava(javaVersionInfo));
+ javaVersionInfo.setSpecificationVersion("1.3");
+ assertFalse(Installation.isValidJava(javaVersionInfo));
+ javaVersionInfo.setSpecificationVersion("1.4");
+ assertFalse(Installation.isValidJava(javaVersionInfo));
+ javaVersionInfo.setSpecificationVersion("1.5");
+ assertTrue(Installation.isValidJava(javaVersionInfo));
+ javaVersionInfo.setSpecificationVersion("1.6");
+ assertTrue(Installation.isValidJava(javaVersionInfo));
+ javaVersionInfo.setSpecificationVersion("1.7");
+ assertTrue(Installation.isValidJava(javaVersionInfo));
+ }
+
+ public void testGetJavaSpecificationVersion() {
+ String specificationVersion = "1.4.2";
+ assertEquals(14, Installation.getJavaSpecificationVersion(specificationVersion));
+ specificationVersion = "1.5.0";
+ assertEquals(15, Installation.getJavaSpecificationVersion(specificationVersion));
+ specificationVersion = "1.6.0";
+ assertEquals(16, Installation.getJavaSpecificationVersion(specificationVersion));
+ }
+
+ public void testIsGNUJava() {
+ assertFalse(Installation.isGNUJava());
+ String originalVmName = System.getProperty(Installation.JAVA_VM_NAME);
+ try {
+ // fake GNU java
+ System.setProperty(Installation.JAVA_VM_NAME, "GNU libgcj");
+ assertTrue(Installation.isGNUJava());
+ } finally {
+ System.setProperty(Installation.JAVA_VM_NAME, originalVmName);
+ assertFalse(Installation.isGNUJava());
+ }
+ }
+
+ public void testGetDefaultJavaVersion() {
+ JavaVersionInfo info = Installation.getDefaultJavaVersion();
+ assertNotNull(info);
+ assertEquals(Installation.NORMAL_RETURN, info.getErrorCode());
+ String specVersion = info.getSpecificationVersion();
+ assertNotNull(specVersion);
+ assertTrue(specVersion.length() >= 3);
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/InstallationTypeTest.java b/installer/test/java/org/python/util/install/InstallationTypeTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/InstallationTypeTest.java
@@ -0,0 +1,119 @@
+package org.python.util.install;
+
+import junit.framework.TestCase;
+
+// test checkin
+public class InstallationTypeTest extends TestCase {
+
+ private InstallationType _type;
+
+ protected void setUp() {
+ _type = new InstallationType();
+ }
+
+ public void testConstruction() {
+ assertTrue(_type.isStandard());
+ assertFalse(_type.isMinimum());
+ assertFalse(_type.isAll());
+ assertFalse(_type.isStandalone());
+ assertTrue(_type.isPredefined());
+ }
+
+ public void testStandard() {
+ _type.setStandard();
+ assertTrue(_type.isStandard());
+ assertTrue(_type.installLibraryModules());
+ assertTrue(_type.installDemosAndExamples());
+ assertTrue(_type.installDocumentation());
+ assertFalse(_type.installSources());
+ assertFalse(_type.isStandalone());
+ assertTrue(_type.isPredefined());
+ }
+
+ public void testMinimum() {
+ assertFalse(_type.isMinimum());
+ _type.setMinimum();
+ assertTrue(_type.isMinimum());
+ assertFalse(_type.installLibraryModules());
+ assertFalse(_type.installDemosAndExamples());
+ assertFalse(_type.installDocumentation());
+ assertFalse(_type.installSources());
+ assertFalse(_type.isStandalone());
+ assertTrue(_type.isPredefined());
+ }
+
+ public void testAll() {
+ assertFalse(_type.isAll());
+ _type.setAll();
+ assertTrue(_type.isAll());
+ assertTrue(_type.installLibraryModules());
+ assertTrue(_type.installDemosAndExamples());
+ assertTrue(_type.installDocumentation());
+ assertTrue(_type.installSources());
+ assertFalse(_type.isStandalone());
+ assertTrue(_type.isPredefined());
+ }
+
+ public void testStandalone() {
+ assertFalse(_type.isStandalone());
+ _type.setStandalone();
+ assertTrue(_type.isStandalone());
+ assertFalse(_type.isMinimum());
+ assertFalse(_type.isStandard());
+ assertFalse(_type.isAll());
+ assertTrue(_type.isPredefined());
+
+ // sure to handle this as follows?
+ assertTrue(_type.installLibraryModules());
+ assertFalse(_type.installDemosAndExamples());
+ assertFalse(_type.installDocumentation());
+ assertFalse(_type.installSources());
+ }
+
+ public void testAddRemove() {
+ _type.removeDocumentation();
+ assertTrue(_type.installLibraryModules());
+ assertTrue(_type.installDemosAndExamples());
+ assertFalse(_type.installDocumentation());
+ assertFalse(_type.installSources());
+ assertFalse(_type.isMinimum());
+ assertFalse(_type.isStandard());
+ assertFalse(_type.isAll());
+ assertFalse(_type.isStandalone());
+ assertFalse(_type.isPredefined());
+
+ _type.removeDemosAndExamples();
+ assertTrue(_type.installLibraryModules());
+ assertFalse(_type.installDemosAndExamples());
+ assertFalse(_type.installDocumentation());
+ assertFalse(_type.installSources());
+ assertFalse(_type.isMinimum());
+ assertFalse(_type.isStandard());
+ assertFalse(_type.isAll());
+ assertFalse(_type.isStandalone());
+ assertFalse(_type.isPredefined());
+
+ _type.addSources();
+ assertTrue(_type.installLibraryModules());
+ assertFalse(_type.installDemosAndExamples());
+ assertFalse(_type.installDocumentation());
+ assertTrue(_type.installSources());
+ assertFalse(_type.isMinimum());
+ assertFalse(_type.isStandard());
+ assertFalse(_type.isAll());
+ assertFalse(_type.isStandalone());
+ assertFalse(_type.isPredefined());
+
+ _type.addDocumentation();
+ assertTrue(_type.installLibraryModules());
+ assertFalse(_type.installDemosAndExamples());
+ assertTrue(_type.installDocumentation());
+ assertTrue(_type.installSources());
+ assertFalse(_type.isMinimum());
+ assertFalse(_type.isStandard());
+ assertFalse(_type.isAll());
+ assertFalse(_type.isStandalone());
+ assertFalse(_type.isPredefined());
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/InstallerCommandLineTest.java b/installer/test/java/org/python/util/install/InstallerCommandLineTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/InstallerCommandLineTest.java
@@ -0,0 +1,637 @@
+package org.python.util.install;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+public class InstallerCommandLineTest extends TestCase {
+
+ public void testValidArguments() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[0];
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertFalse(commandLine.hasArguments());
+
+ args = new String[0];
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertFalse(commandLine.hasArguments());
+
+ args = new String[] { "-c" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "--directory", "c:/temp" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "--type", "all" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-t", "minimum" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-type", "standard" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-v" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "--verbose" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-A" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "--autotest" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[0];
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertFalse(commandLine.hasArguments());
+ }
+
+ public void testInvalidArguments() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "--one" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "--one argOne" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "--one", "--two", "--three" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-o" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-type" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-type", "weird" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ assertTrue(commandLine.hasArguments());
+
+ args = new String[] { "-" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ }
+
+ public void testMissingArgument() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "--directory" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--type" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ }
+
+ public void testUnknownArgument() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "yeah" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--silent", "yeah" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--silent", "yeah", "yoyo" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--type", "takatuka" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ }
+
+ public void testOptionGroups() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "-s", "-c" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "-s", "-A" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "-c", "-A" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--silent", "--console" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--silent", "--autotest" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "--console", "--autotest" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "-?", "-h" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+
+ args = new String[] { "-?", "--help" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ }
+
+ public void testSilent() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "-s" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args)); // expect required directory in silent mode
+
+ args = new String[] { "-s", "-d", "/tmp" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasSilentOption());
+ }
+
+ public void testConsole() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "-c" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasConsoleOption());
+ }
+
+ public void testGui() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ // normal gui startup without any arguments
+ assertTrue(Installation.isGuiAllowed());
+ args = new String[0];
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertFalse(commandLine.hasConsoleOption());
+ assertFalse(commandLine.hasSilentOption());
+ }
+
+ /**
+ * simulate startup on a headless system (auto-switch to console mode)
+ */
+ public void testHeadless() {
+ String[] args;
+ InstallerCommandLine commandLine;
+ boolean originalHeadless = Boolean.getBoolean(Installation.HEADLESS_PROPERTY_NAME);
+ try {
+ if (!originalHeadless) {
+ System.setProperty(Installation.HEADLESS_PROPERTY_NAME, "true");
+ }
+ assertFalse(Installation.isGuiAllowed());
+
+ // without any arguments
+ args = new String[0];
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasConsoleOption()); // auto switch
+ assertFalse(commandLine.hasSilentOption());
+
+ // with one argument
+ args = new String[] {"-v"};
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasVerboseOption());
+ assertTrue(commandLine.hasConsoleOption()); // auto switch
+ assertFalse(commandLine.hasSilentOption());
+
+ // with more arguments
+ args = new String[] {"-v", "-t", "minimum" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasVerboseOption());
+ assertTrue(commandLine.hasConsoleOption()); // auto switch
+ assertFalse(commandLine.hasSilentOption());
+ assertTrue(commandLine.hasTypeOption());
+ InstallationType type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertTrue(type.isMinimum());
+
+ // silent should override!
+ args = new String[] {"-v", "-s", "-d", "some_dir"};
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasVerboseOption());
+ assertFalse(commandLine.hasConsoleOption()); // no auto switch
+ assertTrue(commandLine.hasSilentOption());
+ assertTrue(commandLine.hasDirectoryOption());
+ File dir = commandLine.getTargetDirectory();
+ assertNotNull(dir);
+ assertEquals("some_dir", dir.getName());
+
+ // -A (autotest) should override as well
+ args = new String[] {"-A"};
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertFalse(commandLine.hasVerboseOption());
+ assertFalse(commandLine.hasConsoleOption()); // no auto switch
+ assertFalse(commandLine.hasSilentOption());
+
+ // console aready present should be no problem
+ args = new String[] {"-c", "-v"};
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasVerboseOption());
+ assertTrue(commandLine.hasConsoleOption());
+ assertFalse(commandLine.hasSilentOption());
+ } finally {
+ if (!originalHeadless) {
+ System.setProperty(Installation.HEADLESS_PROPERTY_NAME, "false");
+ assertTrue(Installation.isGuiAllowed());
+ }
+ }
+ }
+
+ public void testGNUSwitchToConsole() {
+ String originalVmName = System.getProperty(Installation.JAVA_VM_NAME);
+ try {
+ // fake GNU java
+ System.setProperty(Installation.JAVA_VM_NAME, "GNU libgcj");
+ assertTrue(Installation.isGNUJava());
+ String[] args;
+ InstallerCommandLine commandLine;
+ // expect auto switch
+ args = new String[] {"-v"};
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasVerboseOption());
+ assertTrue(commandLine.hasConsoleOption()); // auto switch
+ // expect no auto switch
+ args = new String[] {"-s", "-d", "some_dir"};
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasSilentOption());
+ assertFalse(commandLine.hasVerboseOption());
+ assertFalse(commandLine.hasConsoleOption()); // no auto switch
+ assertTrue(commandLine.hasDirectoryOption());
+ File dir = commandLine.getTargetDirectory();
+ assertNotNull(dir);
+ assertEquals("some_dir", dir.getName());
+ } finally {
+ System.setProperty(Installation.JAVA_VM_NAME, originalVmName);
+ assertFalse(Installation.isGNUJava());
+ }
+ }
+
+
+ public void testDirectory() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[] { "-d", "dir" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasDirectoryOption());
+ assertNotNull(commandLine.getTargetDirectory());
+ assertEquals("dir", commandLine.getTargetDirectory().getName());
+
+ args = new String[] { "-s", "--directory", "dir" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasDirectoryOption());
+ assertNotNull(commandLine.getTargetDirectory());
+ assertEquals("dir", commandLine.getTargetDirectory().getName());
+ }
+
+ public void testType() {
+ String[] args;
+ InstallerCommandLine commandLine;
+ InstallationType type;
+
+ args = new String[] { "-t", "all" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasTypeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertTrue(type.isAll());
+
+ args = new String[] { "--type", "standard" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasTypeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertTrue(type.isStandard());
+
+ args = new String[] { "--type", "minimum" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasTypeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertTrue(type.isMinimum());
+
+ args = new String[] { "--type", "standalone" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasTypeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertTrue(type.isStandalone());
+
+ assertFalse(commandLine.getJavaHomeHandler().isDeviation());
+ }
+
+ public void testInclude() {
+ String[] args;
+ InstallerCommandLine commandLine;
+ InstallationType type;
+
+ args = new String[] { "-t", "minimum", "-i", "mod" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasIncludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertTrue(type.installLibraryModules());
+ assertFalse(type.installDemosAndExamples());
+ assertFalse(type.installDocumentation());
+ assertFalse(type.installSources());
+
+ args = new String[] { "-t", "minimum", "-i", "mod", "demo" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasIncludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertTrue(type.installLibraryModules());
+ assertTrue(type.installDemosAndExamples());
+ assertFalse(type.installDocumentation());
+ assertFalse(type.installSources());
+
+ args = new String[] { "-t", "minimum", "-i", "mod", "demo", "doc" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasIncludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertTrue(type.installLibraryModules());
+ assertTrue(type.installDemosAndExamples());
+ assertTrue(type.installDocumentation());
+ assertFalse(type.installSources());
+
+ args = new String[] { "-t", "minimum", "--include", "mod", "demo", "doc", "src" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasIncludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertTrue(type.installLibraryModules());
+ assertTrue(type.installDemosAndExamples());
+ assertTrue(type.installDocumentation());
+ assertTrue(type.installSources());
+
+ args = new String[] { "-i", "modulo" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ }
+
+ public void testExclude() {
+ String[] args;
+ InstallerCommandLine commandLine;
+ InstallationType type;
+
+ args = new String[] { "-t", "all", "-e", "mod" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasExcludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertFalse(type.installLibraryModules());
+ assertTrue(type.installDemosAndExamples());
+ assertTrue(type.installDocumentation());
+ assertTrue(type.installSources());
+
+ args = new String[] { "-t", "all", "-e", "mod", "demo" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasExcludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertFalse(type.installLibraryModules());
+ assertFalse(type.installDemosAndExamples());
+ assertTrue(type.installDocumentation());
+ assertTrue(type.installSources());
+
+ args = new String[] { "-t", "all", "-e", "mod", "demo", "doc" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasExcludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertFalse(type.installLibraryModules());
+ assertFalse(type.installDemosAndExamples());
+ assertFalse(type.installDocumentation());
+ assertTrue(type.installSources());
+
+ args = new String[] { "-t", "all", "--exclude", "mod", "demo", "doc", "src" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasExcludeOption());
+ type = commandLine.getInstallationType();
+ assertNotNull(type);
+ assertFalse(type.isStandalone());
+ assertFalse(type.installLibraryModules());
+ assertFalse(type.installDemosAndExamples());
+ assertFalse(type.installDocumentation());
+ assertFalse(type.installSources());
+
+ args = new String[] { "--exclude", "sources" };
+ commandLine = new InstallerCommandLine();
+ assertFalse(commandLine.setArgs(args));
+ }
+
+ public void testJavaHomeHandler() {
+ String[] args;
+ InstallerCommandLine commandLine;
+ final String javaHomeName = "java/home/dir";
+
+ args = new String[] { "-j", javaHomeName };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasJavaHomeOption());
+ JavaHomeHandler javaHomeHandler = commandLine.getJavaHomeHandler();
+ assertNotNull(javaHomeHandler);
+ assertTrue(javaHomeHandler.toString().indexOf(javaHomeName) >= 0);
+ assertTrue(javaHomeHandler.isDeviation());
+
+ args = new String[] { "--jre", javaHomeName };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasJavaHomeOption());
+ javaHomeHandler = commandLine.getJavaHomeHandler();
+ assertNotNull(javaHomeHandler);
+ assertTrue(javaHomeHandler.toString().indexOf(javaHomeName) >= 0);
+ assertTrue(javaHomeHandler.isDeviation());
+
+ assertNull(commandLine.getTargetDirectory());
+ }
+
+ public void testExamples() {
+ String[] args;
+ InstallerCommandLine commandLine;
+ final String javaHomeName = "java/home/dir";
+
+ args = new String[] { "-c" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasConsoleOption());
+
+ args = new String[] { "-s", "-d", "dir" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasSilentOption());
+ assertTrue(commandLine.hasDirectoryOption());
+ assertNotNull(commandLine.getTargetDirectory());
+ assertEquals("dir", commandLine.getTargetDirectory().getName());
+
+ args = new String[] { "-s", "-d", "dir", "-t", "standard", "-j", javaHomeName, "-v" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasSilentOption());
+ assertTrue(commandLine.hasDirectoryOption());
+ assertNotNull(commandLine.getTargetDirectory());
+ assertEquals("dir", commandLine.getTargetDirectory().getName());
+ assertTrue(commandLine.hasTypeOption());
+ assertNotNull(commandLine.getInstallationType());
+ assertTrue(commandLine.getInstallationType().installDemosAndExamples());
+ assertTrue(commandLine.getInstallationType().installDocumentation());
+ assertTrue(commandLine.getInstallationType().installLibraryModules());
+ assertFalse(commandLine.getInstallationType().installSources());
+ assertTrue(commandLine.hasJavaHomeOption());
+ JavaHomeHandler javaHomeHandler = commandLine.getJavaHomeHandler();
+ assertTrue(javaHomeHandler.toString().indexOf(javaHomeName) >= 0);
+ assertTrue(javaHomeHandler.isDeviation());
+ assertTrue(commandLine.hasVerboseOption());
+
+ args = new String[] { "-s", "-d", "dir", "-t", "standard", "-e", "doc", "demo", "-i", "src", "-j", javaHomeName, "-v" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasSilentOption());
+ assertTrue(commandLine.hasDirectoryOption());
+ assertNotNull(commandLine.getTargetDirectory());
+ assertEquals("dir", commandLine.getTargetDirectory().getName());
+ assertTrue(commandLine.hasTypeOption());
+ assertNotNull(commandLine.getInstallationType());
+ assertFalse(commandLine.getInstallationType().installDemosAndExamples());
+ assertFalse(commandLine.getInstallationType().installDocumentation());
+ assertTrue(commandLine.getInstallationType().installLibraryModules());
+ assertTrue(commandLine.getInstallationType().installSources());
+ assertTrue(commandLine.hasJavaHomeOption());
+ javaHomeHandler = commandLine.getJavaHomeHandler();
+ assertTrue(javaHomeHandler.toString().indexOf(javaHomeName) >= 0);
+ assertTrue(javaHomeHandler.isDeviation());
+ assertTrue(commandLine.hasVerboseOption());
+ }
+
+ public void testHelp() {
+ String[] args;
+ InstallerCommandLine commandLine;
+
+ args = new String[0];
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertFalse(commandLine.hasHelpOption());
+
+ args = new String[] { "--help" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasHelpOption());
+
+ args = new String[] { "-h" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasHelpOption());
+
+ args = new String[] { "-?" };
+ commandLine = new InstallerCommandLine();
+ assertTrue(commandLine.setArgs(args));
+ assertTrue(commandLine.hasHelpOption());
+
+ // now print the help
+ commandLine.printHelp();
+ }
+
+ public void testHasVerboseOptionInArgs() {
+ String[] args = new String[0];
+ assertFalse(InstallerCommandLine.hasVerboseOptionInArgs(args));
+
+ args = new String[] {"a", "b", "c"};
+ assertFalse(InstallerCommandLine.hasVerboseOptionInArgs(args));
+
+ args = new String[] {"a", InstallerCommandLine.VERBOSE_SHORT, "c"};
+ assertFalse(InstallerCommandLine.hasVerboseOptionInArgs(args));
+
+ args = new String[] {"a", "-" + InstallerCommandLine.VERBOSE_SHORT, "c"};
+ assertTrue(InstallerCommandLine.hasVerboseOptionInArgs(args));
+
+ args = new String[] {"a", InstallerCommandLine.VERBOSE_LONG, "c"};
+ assertFalse(InstallerCommandLine.hasVerboseOptionInArgs(args));
+
+ args = new String[] {"a", "-" + InstallerCommandLine.VERBOSE_LONG, "c"};
+ assertFalse(InstallerCommandLine.hasVerboseOptionInArgs(args));
+
+ args = new String[] {"a", "--" + InstallerCommandLine.VERBOSE_LONG, "c"};
+ assertTrue(InstallerCommandLine.hasVerboseOptionInArgs(args));
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/JavaHomeHandlerTest.java b/installer/test/java/org/python/util/install/JavaHomeHandlerTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/JavaHomeHandlerTest.java
@@ -0,0 +1,114 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+public class JavaHomeHandlerTest extends TestCase {
+
+ private static final String JAVA_HOME = JavaHomeHandler.JAVA_HOME;
+
+ private static final String JAVA = "java";
+
+ private static final String SOME_WEIRD_HOME = "some/weird/home";
+
+ private String _originalJavaHome;
+
+ @Override
+ protected void setUp() throws Exception {
+ JavaHomeHandler.reset();
+ _originalJavaHome = System.getProperty(JAVA_HOME);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ System.setProperty(JAVA_HOME, _originalJavaHome);
+ }
+
+ public void testGetExecutableName() throws IOException {
+ String executable = new JavaHomeHandler().getExecutableName();
+ assertNotNull(executable);
+ assertTrue(executable.length() > JAVA.length());
+ String homePath = createTempHome().getAbsolutePath();
+ executable = new JavaHomeHandler(homePath).getExecutableName();
+ assertTrue(executable.length() > JAVA.length());
+ assertTrue(executable.indexOf(homePath) >= 0);
+ System.setProperty(JAVA_HOME, homePath);
+ executable = new JavaHomeHandler().getExecutableName();
+ assertTrue(executable.length() > JAVA.length());
+ assertTrue(executable.indexOf(homePath) >= 0);
+ }
+
+ public void testGetExecutableName_NonExisting() {
+ String executable = new JavaHomeHandler(SOME_WEIRD_HOME).getExecutableName();
+ assertEquals(JAVA, executable); // fallback
+ System.setProperty(JAVA_HOME, SOME_WEIRD_HOME);
+ executable = new JavaHomeHandler().getExecutableName();
+ assertEquals(JAVA, executable); // fallback
+ }
+
+ public void testCreateJavaHomeHandler() throws IOException {
+ JavaHomeHandler handler = new JavaHomeHandler();
+ assertNotNull(handler);
+ System.setProperty(JAVA_HOME, SOME_WEIRD_HOME);
+ handler = new JavaHomeHandler();
+ assertNotNull(handler);
+ System.setProperty(JAVA_HOME, createTempHome().getAbsolutePath());
+ handler = new JavaHomeHandler();
+ assertNotNull(handler);
+ }
+
+ public void testCreateHandler_Deviation() throws IOException {
+ JavaHomeHandler handler = new JavaHomeHandler(SOME_WEIRD_HOME);
+ assertNotNull(handler);
+ handler = new JavaHomeHandler(createTempHome().getAbsolutePath());
+ assertNotNull(handler);
+ }
+
+ public void testIsDeviation() throws IOException {
+ JavaHomeHandler handler = new JavaHomeHandler(createTempHome().getAbsolutePath());
+ assertTrue(handler.isDeviation());
+ handler = new JavaHomeHandler();
+ assertFalse(handler.isDeviation());
+ handler = new JavaHomeHandler(System.getProperty(JAVA_HOME));
+ assertFalse(handler.isDeviation());
+ }
+
+ public void testGetJavaHome() throws IOException {
+ String tempHome = createTempHome().getAbsolutePath();
+ JavaHomeHandler handler = new JavaHomeHandler(tempHome);
+ String home = handler.getHome().getAbsolutePath();
+ assertEquals(tempHome, home);
+ try {
+ handler = new JavaHomeHandler(SOME_WEIRD_HOME);
+ } catch (InstallerException ie) {
+ assertEquals("no valid java home", ie.getMessage());
+ }
+ }
+
+ public void testIsValidJavaHome() throws IOException {
+ JavaHomeHandler handler = new JavaHomeHandler(SOME_WEIRD_HOME);
+ assertFalse(handler.isValidHome());
+ handler = new JavaHomeHandler();
+ assertTrue(handler.isValidHome());
+ handler = new JavaHomeHandler(createTempHome().getAbsolutePath());
+ assertTrue(handler.isValidHome());
+ }
+
+ private File createTempHome() throws IOException {
+ File home = File.createTempFile("JavaHomeHandler", "Test");
+ assertTrue(FileHelper.createTempDirectory(home));
+ File binDir = new File(home, "bin");
+ assertTrue(binDir.mkdirs());
+ String executableName = JAVA;
+ if (Installation.isWindows()) {
+ executableName = executableName.concat(".exe");
+ }
+ File java = new File(binDir, executableName);
+ FileHelper.write(java, "dummy");
+ assertTrue(java.exists());
+ assertTrue(java.isFile());
+ return home;
+ }
+}
diff --git a/installer/test/java/org/python/util/install/JavaTest_Standalone.java b/installer/test/java/org/python/util/install/JavaTest_Standalone.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/JavaTest_Standalone.java
@@ -0,0 +1,32 @@
+package org.python.util.install;
+
+import org.python.util.install.Installation.JavaVersionInfo;
+
+/**
+ * Helper class to test an external java version
+ */
+public class JavaTest_Standalone {
+
+ public static void main(String[] args) {
+ if (args.length > 0) {
+ JavaHomeHandler javaHomeHandler = new JavaHomeHandler(args[0]);
+ JavaVersionInfo versionInfo = Installation.getExternalJavaVersion(javaHomeHandler);
+ if (versionInfo.getErrorCode() != Installation.NORMAL_RETURN) {
+ System.err.println(versionInfo.getReason());
+ } else {
+ System.out.println(getPrefix() + "java version:" + versionInfo.getVersion());
+ System.out.println(getPrefix() + "java spec version:" + versionInfo.getSpecificationVersion());
+ }
+ System.exit(versionInfo.getErrorCode());
+ } else {
+ System.err.println(getPrefix() + "missing argument: please specify the java home directory "
+ + "(/bin directory assumed below)");
+ System.exit(1);
+ }
+ }
+
+ private static String getPrefix() {
+ return "[JavaTest_Standalone] ";
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/StandalonePackagerTest.java b/installer/test/java/org/python/util/install/StandalonePackagerTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/StandalonePackagerTest.java
@@ -0,0 +1,183 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import junit.framework.TestCase;
+
+public class StandalonePackagerTest extends TestCase {
+ private File _sourceJarFile;
+ private File _targetJarFile;
+
+ private File _contentFile;
+ private File _nextContentFile;
+ private File _additionalFile;
+
+ private File _contentDir;
+ private File _additionalDir;
+
+ private File _jarDir;
+
+ protected void setUp() throws Exception {
+ _jarDir = File.createTempFile("jarDir", "");
+ assertTrue(FileHelper.createTempDirectory(_jarDir));
+ _targetJarFile = new File(_jarDir, "target.jar");
+ _sourceJarFile = new File(_jarDir, "source.jar");
+
+ _contentDir = File.createTempFile("content", "");
+ assertTrue(FileHelper.createTempDirectory(_contentDir));
+ _contentFile = new File(_contentDir, "content.file");
+ _contentFile.createNewFile();
+ assertTrue(_contentFile.exists());
+
+ createSourceJar();
+ }
+
+ protected void tearDown() throws Exception {
+ if (_sourceJarFile != null) {
+ _sourceJarFile.delete();
+ }
+ if (_targetJarFile != null) {
+ _targetJarFile.delete();
+ }
+ if (_contentFile != null) {
+ _contentFile.delete();
+ }
+ if (_nextContentFile != null) {
+ _nextContentFile.delete();
+ }
+ if (_additionalFile != null) {
+ _additionalFile.delete();
+ }
+ if (_contentDir != null) {
+ _contentDir.delete();
+ }
+ if (_additionalDir != null) {
+ _additionalDir.delete();
+ }
+ if (_jarDir != null) {
+ _jarDir.delete();
+ }
+ }
+
+ /**
+ * test the static method emptyDir()
+ */
+ public void testEmptyDir() throws Exception {
+ File tempContentFile = new File(_contentDir, "temp");
+ tempContentFile.createNewFile();
+ assertTrue(tempContentFile.exists());
+ File tempDir = new File(_contentDir, "tempDir");
+ assertTrue(FileHelper.createTempDirectory(tempDir));
+
+ StandalonePackager.emptyDirectory(_contentDir, _contentFile);
+ assertTrue(_contentFile.exists());
+ assertFalse(tempContentFile.exists());
+ assertFalse(tempDir.exists());
+ assertEquals(1, _contentDir.list().length);
+ }
+
+ /**
+ * test adding a jar file, a directory, and another single file
+ */
+ public void testAdd_Jar_Directory_File() throws IOException {
+ createAdditionalDirectory();
+ _nextContentFile = File.createTempFile("nextContent.file", "");
+ _nextContentFile.createNewFile();
+ assertTrue(_nextContentFile.exists());
+
+ StandalonePackager packager = new StandalonePackager(_targetJarFile);
+ try {
+ packager.addJarFile(_sourceJarFile);
+ packager.addFullDirectory(_additionalDir);
+ packager.addFile(_nextContentFile, null);
+ } finally {
+ packager.close();
+ }
+
+ assertTrue(_targetJarFile.exists());
+
+ Map<String, String> mandatoryEntries = new HashMap<String, String>(8);
+ mandatoryEntries.put(_contentDir.getName(), "dir");
+ mandatoryEntries.put(_contentFile.getName(), "file");
+ mandatoryEntries.put(_nextContentFile.getName(), "file");
+ mandatoryEntries.put(_additionalDir.getName(), "dir");
+ mandatoryEntries.put(_additionalFile.getName(), "file");
+ mandatoryEntries.put("META-INF", "dir");
+ mandatoryEntries.put("MANIFEST.MF", "file");
+
+ JarFile targetJarFile = new JarFile(_targetJarFile);
+ try {
+ Enumeration<JarEntry> entries = targetJarFile.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entries.nextElement();
+ String name;
+ String entryName = entry.getName();
+ int slashIndex = entryName.indexOf("/");
+ if (slashIndex >= 0) {
+ // handle directory
+ name = entryName.substring(slashIndex + 1);
+ String dirName = entryName.substring(0, slashIndex);
+ assertTrue(mandatoryEntries.containsKey(dirName));
+ assertEquals("dir", mandatoryEntries.get(dirName));
+ mandatoryEntries.remove(dirName);
+ } else {
+ name = entryName;
+ }
+ if (mandatoryEntries.containsKey(name)) {
+ assertEquals("file", (String) mandatoryEntries.get(name));
+ assertFalse(entry.isDirectory());
+ mandatoryEntries.remove(name);
+ }
+ }
+ assertTrue(mandatoryEntries.size() == 0);
+ assertNotNull(targetJarFile.getManifest());
+ } finally {
+ targetJarFile.close();
+ }
+ }
+
+ private void createSourceJar() throws FileNotFoundException, IOException {
+ Manifest manifest = new Manifest();
+ JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(_sourceJarFile), manifest);
+ addFile(_contentFile, _contentDir, jarOut);
+ jarOut.close();
+ }
+
+ private void createAdditionalDirectory() throws IOException {
+ _additionalDir = File.createTempFile("additional", "");
+ assertTrue(FileHelper.createTempDirectory(_additionalDir));
+
+ _additionalFile = new File(_additionalDir, "additional.file");
+ _additionalFile.createNewFile();
+ assertTrue(_additionalFile.exists());
+ }
+
+ private void addFile(File file, File parentDir, JarOutputStream jarOut) throws IOException {
+ byte[] buffer = new byte[1024];
+ FileInputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(file);
+ String jarEntryName = parentDir.getName() + "/" + file.getName();
+ jarOut.putNextEntry(new JarEntry(jarEntryName));
+ for (int read = 0; read != -1; read = inputStream.read(buffer))
+ jarOut.write(buffer, 0, read);
+ jarOut.closeEntry();
+ } finally {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ }
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/StartScriptGeneratorTest.java b/installer/test/java/org/python/util/install/StartScriptGeneratorTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/StartScriptGeneratorTest.java
@@ -0,0 +1,277 @@
+package org.python.util.install;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+public class StartScriptGeneratorTest extends TestCase {
+
+ private static final String AT_DATE = "@DATE";
+
+ private static final String WIN_CR_LF = StartScriptGenerator.WIN_CR_LF;
+
+ private StartScriptGenerator _generator;
+
+ private File _targetDir;
+
+ protected void setUp() throws Exception {
+ String userDirName = System.getProperty("user.dir"); // only true in eclipse ?
+ File userDir = new File(userDirName);
+ File parentDir = userDir.getParentFile();
+ assertTrue(parentDir.exists());
+ _targetDir = new File(parentDir, "jython");
+ if (!_targetDir.exists()) {
+ _targetDir = new File(parentDir, "jython-trunk");
+ }
+ assertTrue(_targetDir.exists());
+ assertTrue(_targetDir.isDirectory());
+ _targetDir = new File(_targetDir, "src");
+ _targetDir = new File(_targetDir, "shell");
+ assertTrue(_targetDir.exists());
+ assertTrue(_targetDir.isDirectory());
+ _generator = new StartScriptGenerator(_targetDir, new JavaHomeHandler());
+ }
+
+ // TODO: test on Solaris
+ public void testUnix() throws IOException {
+ _generator.setFlavour(StartScriptGenerator.UNIX_FLAVOUR);
+ StringBuffer buf = new StringBuffer(100);
+ buf.append("#!/usr/bin/env bash\n");
+ buf.append("\n");
+ buf.append("# This file was generated by the Jython installer\n");
+ buf.append("# Created on " + AT_DATE + " by " + System.getProperty("user.name") + "\n");
+ buf.append("\n");
+ buf.append("JAVA_HOME=\"");
+ buf.append(System.getProperty("java.home"));
+ buf.append("\"\n");
+ buf.append("JYTHON_HOME_FALLBACK=\"");
+ buf.append(_targetDir.getAbsolutePath());
+ buf.append("\"\n");
+ // some rudimentary tests - feel free to do more
+ String start = buf.toString().replaceAll(AT_DATE, new Date().toString());
+ String unixScript = _generator.getJythonScript(StartScriptGenerator.UNIX_FLAVOUR);
+ assertTrue(unixScript.startsWith(start));
+ assertTrue(unixScript.length() > 3500);
+ assertTrue(unixScript.indexOf("-Dpython.home=") > start.length());
+ assertTrue(unixScript.indexOf("-Dpython.executable=") > start.length());
+ // no hard coding of JYTHON_HOME
+ int jythonHomeIndex = unixScript.indexOf("if [ -z \"$JYTHON_HOME\" ] ; then");
+ assertTrue(jythonHomeIndex >= 0);
+ int definitionIndex = unixScript.indexOf("JYTHON_HOME=");
+ assertTrue(definitionIndex > jythonHomeIndex || definitionIndex < 0);
+ }
+
+ public void testWindows() throws IOException {
+ StringBuffer winBuf = new StringBuffer(100);
+ winBuf.append("@echo off" + WIN_CR_LF);
+ winBuf.append("rem This file was generated by the Jython installer" + WIN_CR_LF);
+ winBuf.append("rem Created on " + AT_DATE + " by " + System.getProperty("user.name") + ""
+ + WIN_CR_LF);
+ winBuf.append(WIN_CR_LF);
+ winBuf.append("set JAVA_HOME=\"");
+ winBuf.append(System.getProperty("java.home"));
+ winBuf.append("\"");
+ winBuf.append(WIN_CR_LF);
+ winBuf.append("set JYTHON_HOME_FALLBACK=\"");
+ winBuf.append(_targetDir.getAbsolutePath());
+ winBuf.append("\"");
+ winBuf.append(WIN_CR_LF);
+ // some rudimentary tests - feel free to do more
+ String start = winBuf.toString().replaceAll(AT_DATE, new Date().toString());
+ String winScript = _generator.getJythonScript(StartScriptGenerator.WINDOWS_FLAVOUR);
+ assertTrue(winScript.startsWith(start));
+ assertTrue(winScript.length() > 3500);
+ assertTrue(winScript.indexOf("if not \"%_TRIMMED_JAVA_HOME%\"==\"\"") > start.length());
+ assertTrue(winScript.indexOf("-Dpython.home=") > start.length());
+ assertTrue(winScript.indexOf("-Dpython.executable=") > start.length());
+ // no hard coding of JYTHON_HOME
+ int jythonHomeIndex = winScript.indexOf("if not \"%_TRIMMED_JYTHON_HOME%\"==\"\"");
+ assertTrue(jythonHomeIndex >= 0);
+ int definitionIndex = winScript.indexOf("set JYTHON_HOME=");
+ assertTrue(definitionIndex > jythonHomeIndex || definitionIndex < 0);
+ }
+
+ public void testFlavour() {
+ int expectedFlavour;
+ expectedFlavour = StartScriptGenerator.UNIX_FLAVOUR;
+ _generator.setFlavour(expectedFlavour);
+ assertEquals(expectedFlavour, _generator.getFlavour());
+ expectedFlavour = StartScriptGenerator.BOTH_FLAVOUR;
+ _generator.setFlavour(expectedFlavour);
+ assertEquals(expectedFlavour, _generator.getFlavour());
+ TestStartScriptGenerator testGenerator = new TestStartScriptGenerator(new File("dummy"),
+ new JavaHomeHandler("dummy"),
+ false);
+ expectedFlavour = StartScriptGenerator.WINDOWS_FLAVOUR;
+ testGenerator.setFlavour(expectedFlavour);
+ assertEquals(expectedFlavour, testGenerator.getFlavour());
+ expectedFlavour = StartScriptGenerator.UNIX_FLAVOUR;
+ testGenerator.setFlavour(expectedFlavour);
+ assertEquals(expectedFlavour, testGenerator.getFlavour());
+ testGenerator = new TestStartScriptGenerator(new File("dummy"),
+ new JavaHomeHandler("dummy"),
+ true);
+ testGenerator.setFlavour(StartScriptGenerator.WINDOWS_FLAVOUR);
+ assertEquals(StartScriptGenerator.BOTH_FLAVOUR, testGenerator.getFlavour());
+ }
+
+ public void testWindowsFlavour() throws IOException {
+ File dir = new File(System.getProperty("java.io.tmpdir"), "StartScriptGeneratorTest");
+ try {
+ if (!dir.exists()) {
+ assertTrue(dir.mkdirs());
+ }
+ File bin = new File(dir, "bin");
+ if (!bin.exists()) {
+ assertTrue(bin.mkdirs());
+ }
+ File jython = new File(bin, "jython");
+ if (!jython.exists()) {
+ assertTrue(jython.createNewFile());
+ }
+ File jython_bat = new File(bin, "jython.bat");
+ if (!jython_bat.exists()) {
+ assertTrue(jython_bat.createNewFile());
+ }
+ // windows flavour
+ TestStartScriptGenerator testGenerator = new TestStartScriptGenerator(dir,
+ new JavaHomeHandler(),
+ false);
+ testGenerator.setFlavour(StartScriptGenerator.WINDOWS_FLAVOUR);
+ testGenerator.generateStartScripts();
+ String[] fileNames = dir.list();
+ int fileNamesLength = fileNames.length;
+ assertEquals(2, fileNamesLength); // 1 file plus the /bin subdirectory
+ HashSet<String> fileNamesSet = new HashSet<String>(2);
+ for (int i = 0; i < fileNamesLength; i++) {
+ fileNamesSet.add(fileNames[i]);
+ }
+ assertTrue(fileNamesSet.contains("bin"));
+ assertTrue(fileNamesSet.contains("jython.bat"));
+ fileNames = bin.list();
+ assertEquals(1, fileNames.length);
+ assertEquals("jython.bat", fileNames[0]);
+ } finally {
+ if (dir.exists()) {
+ assertTrue("unable to delete directory ".concat(dir.getAbsolutePath()),
+ FileHelper.rmdir(dir));
+ }
+ }
+ }
+
+ public void testUnixFlavour() throws IOException {
+ File dir = new File(System.getProperty("java.io.tmpdir"), "StartScriptGeneratorTest");
+ try {
+ if (!dir.exists()) {
+ assertTrue(dir.mkdirs());
+ }
+ File bin = new File(dir, "bin");
+ if (!bin.exists()) {
+ assertTrue(bin.mkdirs());
+ }
+ File jython = new File(bin, "jython");
+ if (!jython.exists()) {
+ assertTrue(jython.createNewFile());
+ }
+ File jython_bat = new File(bin, "jython.bat");
+ if (!jython_bat.exists()) {
+ assertTrue(jython_bat.createNewFile());
+ }
+ // unix flavour
+ TestStartScriptGenerator testGenerator = new TestStartScriptGenerator(dir,
+ new JavaHomeHandler(),
+ false);
+ testGenerator.setFlavour(StartScriptGenerator.UNIX_FLAVOUR);
+ testGenerator.generateStartScripts();
+ String[] fileNames = dir.list();
+ int fileNamesLength = fileNames.length;
+ assertEquals(2, fileNamesLength); // 1 file plus the /bin subdirectory
+ HashSet<String> fileNamesSet = new HashSet<String>(2);
+ for (int i = 0; i < fileNamesLength; i++) {
+ fileNamesSet.add(fileNames[i]);
+ }
+ assertTrue(fileNamesSet.contains("bin"));
+ assertTrue(fileNamesSet.contains("jython"));
+ fileNames = bin.list();
+ assertEquals(1, fileNames.length);
+ assertEquals("jython", fileNames[0]);
+ } finally {
+ if (dir.exists()) {
+ assertTrue("unable to delete directory ".concat(dir.getAbsolutePath()),
+ FileHelper.rmdir(dir));
+ }
+ }
+ }
+
+ public void testBothFlavours() throws IOException {
+ File dir = new File(System.getProperty("java.io.tmpdir"), "StartScriptGeneratorTest");
+ try {
+ if (!dir.exists()) {
+ assertTrue(dir.mkdirs());
+ }
+ File bin = new File(dir, "bin");
+ if (!bin.exists()) {
+ assertTrue(bin.mkdirs());
+ }
+ File jython = new File(bin, "jython");
+ if (!jython.exists()) {
+ assertTrue(jython.createNewFile());
+ }
+ File jython_bat = new File(bin, "jython.bat");
+ if (!jython_bat.exists()) {
+ assertTrue(jython_bat.createNewFile());
+ }
+ // both flavours
+ TestStartScriptGenerator testGenerator = new TestStartScriptGenerator(dir,
+ new JavaHomeHandler(),
+ true);
+ // test generator constructor timing problem: do set the flavour once again
+ testGenerator.setFlavour(StartScriptGenerator.WINDOWS_FLAVOUR);
+ testGenerator.generateStartScripts();
+ String[] fileNames = dir.list();
+ int fileNamesLength = fileNames.length;
+ assertEquals(3, fileNamesLength); // 2 files plus the /bin subdirectory
+ Set<String> fileNamesSet = new HashSet<String>(4);
+ for (int i = 0; i < fileNamesLength; i++) {
+ fileNamesSet.add(fileNames[i]);
+ }
+ assertTrue(fileNamesSet.contains("bin"));
+ assertTrue(fileNamesSet.contains("jython"));
+ assertTrue(fileNamesSet.contains("jython.bat"));
+ fileNames = bin.list();
+ fileNamesLength = fileNames.length;
+ assertEquals(2, fileNamesLength);
+ fileNamesSet = new HashSet<String>(4);
+ for (int i = 0; i < fileNamesLength; i++) {
+ fileNamesSet.add(fileNames[i]);
+ }
+ assertTrue(fileNamesSet.contains("jython"));
+ assertTrue(fileNamesSet.contains("jython.bat"));
+ } finally {
+ if (dir.exists()) {
+ assertTrue("unable to delete directory ".concat(dir.getAbsolutePath()),
+ FileHelper.rmdir(dir));
+ }
+ }
+ }
+
+ class TestStartScriptGenerator extends StartScriptGenerator {
+
+ private boolean _hasBothFlavours;
+
+ public TestStartScriptGenerator(File targetDirectory,
+ JavaHomeHandler javaHomeHandler,
+ boolean hasBothFlavours) {
+ super(targetDirectory, javaHomeHandler);
+ _hasBothFlavours = hasBothFlavours;
+ }
+
+ protected boolean hasUnixlikeShell() {
+ return _hasBothFlavours;
+ }
+ }
+}
diff --git a/installer/test/java/org/python/util/install/UnicodeSequencesTest.java b/installer/test/java/org/python/util/install/UnicodeSequencesTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/UnicodeSequencesTest.java
@@ -0,0 +1,34 @@
+package org.python.util.install;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+public class UnicodeSequencesTest extends TestCase {
+
+ private static Set _latin1Encodings;
+
+ public void testUmlaute() {
+ String fileEncoding = System.getProperty("file.encoding", "unknown");
+ if (getLatin1Encodings().contains(fileEncoding)) {
+ assertEquals("ä", UnicodeSequences.a2);
+ assertEquals("Ä", UnicodeSequences.A2);
+ assertEquals("ö", UnicodeSequences.o2);
+ assertEquals("Ö", UnicodeSequences.O2);
+ assertEquals("ü", UnicodeSequences.u2);
+ assertEquals("Ü", UnicodeSequences.U2);
+ }
+ }
+
+ private static Set getLatin1Encodings() {
+ if (_latin1Encodings == null) {
+ _latin1Encodings = new HashSet(3);
+ _latin1Encodings.add("ISO-LATIN-1");
+ _latin1Encodings.add("ISO-8859-1");
+ _latin1Encodings.add("Cp1252");
+ }
+ return _latin1Encodings;
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/driver/AutotestTest.java b/installer/test/java/org/python/util/install/driver/AutotestTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/driver/AutotestTest.java
@@ -0,0 +1,78 @@
+package org.python.util.install.driver;
+
+import java.io.File;
+
+import org.python.util.install.InstallerCommandLine;
+
+import junit.framework.TestCase;
+
+public class AutotestTest extends TestCase {
+
+ private Autotest _autotest;
+
+ protected void setUp() throws Exception {
+ InstallerCommandLine commandLine = new InstallerCommandLine();
+ commandLine.setArgs(new String[0]);
+ _autotest = new SilentAutotest(commandLine);
+ }
+
+ public void testCreateDirectories() {
+ File rootDir = Autotest.getRootDir();
+ File targetDir = _autotest.getTargetDir();
+ assertNotNull(rootDir);
+ verifyDir(rootDir, false);
+ assertNotNull(targetDir);
+ verifyDir(targetDir, true);
+ assertEquals(rootDir, targetDir.getParentFile());
+ }
+
+ public void testCommandLineArgs() {
+ String[] args = new String[] { "-x", "-y", "-z" };
+ _autotest.setCommandLineArgs(args);
+ int len = _autotest.getCommandLineArgs().length;
+ assertEquals(args.length, len);
+ for (int i = 0; i < args.length; i++) {
+ assertEquals(args[i], _autotest.getCommandLineArgs()[i]);
+ }
+ }
+
+ public void testAddArgument() {
+ String[] args = new String[] { "-x", "-y", "-z" };
+ _autotest.setCommandLineArgs(args);
+ _autotest.addArgument("-u");
+ assertEquals(args.length + 1, _autotest.getCommandLineArgs().length);
+ for (int i = 0; i < args.length; i++) {
+ assertEquals(args[i], _autotest.getCommandLineArgs()[i]);
+ }
+ assertEquals("-u", _autotest.getCommandLineArgs()[args.length]);
+ }
+
+ public void testVerify() throws Exception {
+ TestVerifier testVerifier = new TestVerifier();
+ _autotest.setVerifier(testVerifier);
+ assertNotNull(_autotest.getVerifier());
+ assertNotNull(_autotest.getVerifier().getTargetDir());
+ assertEquals(_autotest.getTargetDir(), testVerifier.getTargetDir());
+ try {
+ _autotest.getVerifier().verify();
+ fail("should have thrown");
+ } catch (DriverException de) {
+ }
+
+ }
+
+ private void verifyDir(File dir, boolean ensureEmpty) {
+ assertTrue(dir.exists());
+ assertTrue(dir.isDirectory());
+ if (ensureEmpty) {
+ assertTrue(dir.listFiles().length <= 0);
+ }
+ }
+
+ private static class TestVerifier extends NormalVerifier {
+ public void verify() throws DriverException {
+ throw new DriverException("test verification failure");
+ }
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/driver/DrivableConsole.java b/installer/test/java/org/python/util/install/driver/DrivableConsole.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/driver/DrivableConsole.java
@@ -0,0 +1,82 @@
+package org.python.util.install.driver;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.python.util.install.driver.Tunnel;
+
+/**
+ * A simple class performing console I/O, easy to test.
+ */
+public class DrivableConsole {
+
+ private static final String _PROMPT = ">>>";
+ private Tunnel _tunnel;
+
+ public DrivableConsole(Tunnel tunnel) {
+ _tunnel = tunnel;
+ }
+
+ /**
+ * The console logic.
+ */
+ public void handleConsoleIO() throws Exception {
+ String answer;
+ answer = question("first question");
+ if ("1".equals(answer)) {
+ System.out.println("answer1 is " + answer);
+ answer = question("second question");
+ if ("2".equals(answer)) {
+ System.out.println("answer2 is " + answer);
+ answer = question("third question");
+ if ("3".equals(answer)) {
+ System.out.println("answer3 is " + answer);
+ } else {
+ throw new Exception("wrong answer3: " + answer);
+ }
+ } else {
+ throw new Exception("wrong answer2: " + answer);
+ }
+ } else {
+ throw new Exception("wrong answer1: " + answer);
+ }
+ }
+
+ /**
+ * Write a question (to normal <code>System.out</code>)
+ */
+ private String question(String question) throws IOException {
+ question = question + " " + _PROMPT + " ";
+ String answer = "";
+ // output to normal System.out
+ System.out.print(question); // intended print, not println (!)
+ answer = readLine();
+ return answer;
+ }
+
+ /**
+ * Send a signal through the tunnel, and then wait for the answer from the other side.
+ *
+ * <pre>
+ * (2) [Driver] receives question [Tunnel] sends question [Console] (1)
+ * (3) [Driver] sends answer [Tunnel] receives answer [Console] (4)
+ * </pre>
+ */
+ private String readLine() throws IOException {
+ InputStream inputStream;
+ String line = "";
+ if (_tunnel == null) {
+ inputStream = System.in;
+ } else {
+ inputStream = _tunnel.getAnswerReceiverStream();
+ _tunnel.getQuestionSenderStream().write(Tunnel.NEW_LINE.getBytes());
+ _tunnel.getQuestionSenderStream().flush();
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ line = reader.readLine();
+ return line;
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/driver/DrivableConsoleTest.java b/installer/test/java/org/python/util/install/driver/DrivableConsoleTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/driver/DrivableConsoleTest.java
@@ -0,0 +1,37 @@
+package org.python.util.install.driver;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.python.util.install.driver.ConsoleDriver;
+import org.python.util.install.driver.Tunnel;
+
+import junit.framework.TestCase;
+
+public class DrivableConsoleTest extends TestCase {
+
+ private DrivableConsole _console;
+ private Tunnel _tunnel;
+
+ protected void setUp() throws IOException {
+ _tunnel = new Tunnel();
+ _console = new DrivableConsole(_tunnel);
+ }
+
+ public void testDrive() throws Exception {
+ // sequence matters here (have to fork off the driver thread first
+ ConsoleDriver driver = new ConsoleDriver(_tunnel, getAnswers());
+ driver.start();
+ _console.handleConsoleIO();
+ }
+
+ private Collection getAnswers() {
+ Collection answers = new ArrayList();
+ answers.add("1");
+ answers.add("2");
+ answers.add("3");
+ return answers;
+ }
+
+}
diff --git a/installer/test/java/org/python/util/install/driver/NormalVerifierTest.java b/installer/test/java/org/python/util/install/driver/NormalVerifierTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/driver/NormalVerifierTest.java
@@ -0,0 +1,131 @@
+package org.python.util.install.driver;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.python.util.install.FileHelper;
+import org.python.util.install.Installation;
+import org.python.util.install.JavaVersionTester;
+
+public class NormalVerifierTest extends TestCase {
+
+ private static final String DQ = "\"";
+
+ private NormalVerifier _verifier;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ _verifier = new NormalVerifier();
+ // use a directory containing spaces as target directory
+ File targetDir = createTargetDirectory();
+ assertTrue(targetDir.exists());
+ assertTrue(targetDir.isDirectory());
+ _verifier.setTargetDir(targetDir);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (_verifier.getTargetDir() != null) {
+ File autotestFile = new File(_verifier.getTargetDir().getCanonicalPath(),
+ NormalVerifier.AUTOTEST_PY);
+ if (autotestFile.exists()) {
+ assertTrue(autotestFile.delete());
+ }
+ }
+ }
+
+ // have to install jython first in order to activate this test
+ public void testVerify() throws Exception {}
+
+ public void testGetSimpleCommand() throws Exception {
+ String prefix = _verifier.getTargetDir().getCanonicalPath().concat(File.separator);
+ String expectedCommand = prefix.concat("jython");
+ if (Installation.isWindows()) {
+ expectedCommand = expectedCommand.concat(".bat");
+ }
+ String expectedArgument = prefix.concat("autotest.py");
+ String[] command = _verifier.getSimpleCommand();
+ assertNotNull(command);
+ assertEquals(2, command.length);
+ assertEquals(expectedCommand, command[0]);
+ assertEquals(expectedArgument, command[1]);
+ }
+
+ public void testDoShellScriptTests() {
+ assertTrue(_verifier.doShellScriptTests());
+ }
+
+ public void testGetShellScriptTestCommandDir() throws DriverException, IOException {
+ String expectedDir = _verifier.getTargetDir()
+ .getCanonicalPath()
+ .concat(File.separator)
+ .concat("bin");
+ assertEquals(expectedDir, _verifier.getShellScriptTestCommandDir().getCanonicalPath());
+ }
+
+ public void testGetShellScriptTestContents() throws Exception {
+ String contents = _verifier.getShellScriptTestContents();
+ // common asserts
+ assertNotNull(contents);
+ assertFalse(contents.length() == 0);
+ assertFalse(contents.indexOf("{0}") > 0);
+ assertFalse(contents.indexOf("{1}") > 0);
+ assertFalse(contents.indexOf("{2}") > 0);
+ assertFalse(contents.indexOf("{3}") > 0);
+ assertTrue(contents.indexOf("autotest.py") > 0);
+ String targetDirPath = _verifier.getTargetDir().getCanonicalPath();
+ String upScriptPath = _verifier.getSimpleCommand()[1];
+ String javaHome = System.getProperty(JavaVersionTester.JAVA_HOME, ""); // change this ++++++
+ assertTrue(javaHome.length() > 0);
+ // platform specific asserts
+ if (Installation.isWindows()) {
+ assertTrue(contents.indexOf("set _INSTALL_DIR=") > 0);
+ assertTrue(contents.indexOf("set _INSTALL_DIR=".concat(targetDirPath)) > 0);
+ assertTrue(contents.indexOf("set _SCRIPT=") > 0);
+ assertTrue(contents.indexOf("set _SCRIPT=".concat(upScriptPath)) > 0);
+ assertTrue(contents.indexOf("set _JAVA_HOME=") > 0);
+ assertTrue(contents.indexOf("set _JAVA_HOME=".concat(javaHome)) > 0);
+ } else {
+ System.out.println(contents);
+ assertTrue(contents.indexOf("_INSTALL_DIR=") > 0);
+ assertTrue(contents.indexOf("_INSTALL_DIR=".concat(quote(targetDirPath))) > 0);
+ assertTrue(contents.indexOf("_SCRIPT=") > 0);
+ assertTrue(contents.indexOf("_SCRIPT=".concat(quote(upScriptPath))) > 0);
+ assertTrue(contents.indexOf("_JAVA_HOME=") > 0);
+ assertTrue(contents.indexOf("_JAVA_HOME=".concat(quote(javaHome))) > 0);
+ }
+ }
+
+ public void testGetShellScriptTestCommand() throws Exception {
+ String prefix = _verifier.getShellScriptTestCommandDir()
+ .getCanonicalPath()
+ .concat(File.separator);
+ String expectedCommand = prefix.concat("jython_test");
+ if (Installation.isWindows()) {
+ expectedCommand = expectedCommand.concat(".bat");
+ }
+ String[] command = _verifier.getShellScriptTestCommand();
+ assertNotNull(command);
+ assertEquals(1, command.length);
+ String commandFileName = command[0];
+ assertEquals(expectedCommand, commandFileName);
+ File commandFile = new File(commandFileName);
+ assertTrue(commandFile.exists());
+ String contents = FileHelper.readAll(commandFile);
+ assertNotNull(contents);
+ assertFalse(contents.length() == 0);
+ assertEquals(_verifier.getShellScriptTestContents(), contents);
+ }
+
+ private File createTargetDirectory() throws IOException {
+ File tmpFile = File.createTempFile("NormalVerifierTest_", "with spaces");
+ FileHelper.createTempDirectory(tmpFile);
+ return tmpFile;
+ }
+
+ private String quote(String value) {
+ return DQ.concat(value).concat(DQ);
+ }
+}
diff --git a/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java b/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java
new file mode 100644
--- /dev/null
+++ b/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java
@@ -0,0 +1,72 @@
+package org.python.util.install.driver;
+
+import java.io.File;
+
+import org.python.util.install.Installation;
+import org.python.util.install.JarInstaller;
+
+import junit.framework.TestCase;
+
+public class StandaloneVerifierTest extends TestCase {
+
+ private StandaloneVerifier _verifier;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ _verifier = new StandaloneVerifier();
+ File targetDir = null;
+ // have to install jython first in order to activate this test
+ // targetDir = new File("C:/Temp/jython.autoinstall.root_54159_dir/006
+ // consoleTest_54165_dir");
+ _verifier.setTargetDir(targetDir);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (_verifier.getTargetDir() != null) {
+ File autotestFile = new File(_verifier.getTargetDir().getCanonicalPath(),
+ StandaloneVerifier.AUTOTEST_PY);
+ if (autotestFile.exists()) {
+ assertTrue(autotestFile.delete());
+ }
+ }
+ }
+
+ public void testVerify() throws Exception {
+ if (_verifier.getTargetDir() != null) {
+ _verifier.verify();
+ }
+ }
+
+ public void testGetSimpleCommand() throws Exception {
+ File javaHome = new File(System.getProperty("java.home"));
+ assertNotNull(javaHome);
+ assertTrue(javaHome.exists());
+ File targetDir = new File(System.getProperty(("user.dir"))); // any existing dir
+ assertNotNull(targetDir);
+ assertTrue(targetDir.exists());
+ String prefix = targetDir.getCanonicalPath().concat(File.separator);
+ String expectedCommand = javaHome.getCanonicalPath()
+ .concat(File.separator)
+ .concat("bin")
+ .concat(File.separator)
+ .concat("java");
+ if (Installation.isWindows()) {
+ expectedCommand = expectedCommand.concat(".exe");
+ }
+ String expectedArgument = prefix.concat("autotest.py");
+ _verifier.setTargetDir(targetDir);
+ String[] command = _verifier.getSimpleCommand();
+ assertNotNull(command);
+ assertEquals(4, command.length);
+ assertEquals(expectedCommand, command[0]);
+ assertEquals("-jar", command[1]);
+ assertEquals(prefix.concat(JarInstaller.JYTHON_JAR), command[2]);
+ assertEquals(expectedArgument, command[3]);
+ }
+
+ public void testDoShellScriptTests() {
+ // we cannot do shell script tests in standalone mode
+ assertFalse(_verifier.doShellScriptTests());
+ }
+}
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list