svn commit: r1744107 - in /ofbiz/trunk: ./ framework/start/ framework/start/lib/ framework/start/src/org/ofbiz/base/start/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1744107 - in /ofbiz/trunk: ./ framework/start/ framework/start/lib/ framework/start/src/org/ofbiz/base/start/

Taher Alkhateeb
Author: taher
Date: Mon May 16 18:40:49 2016
New Revision: 1744107

URL: http://svn.apache.org/viewvc?rev=1744107&view=rev
Log:
major change in the start component related to OFBIZ-6783

this is a big commit that achieves the following new features in ofbiz:

- add the commons-cli library
- fix build.xml in start menu to include the commons-cli. It is done
  in a way to ensure that the classpath continues to work when ofbiz.jar
  is copied to the root folder
- set a default portoffset value of 0 when not selected in build.xml
- fully redefine the commands passed in java -jar ofbiz.jar using the commons-cli
  api. The commands are now much more consistent and clean
- remove ofbiz dependency on String[] args across the different components and isolate
  them in a new entity class called StartupCommand. This decouples ofbiz from both
  String[] args and commons-cli at the same time
- fix all the calls in the master build.xml to comply with the new commands
- fix the Config.java to remove dependecies on the args array
- create a utility class StartupCommandUtil that takes care of all commons-cli
  operations and abstracts away the implementation in private methods
- substantially reduce the size of main and init in Start.java by refactoring
  them in different places
- create an intermediate function called populateLoaderArgs. This is the first
  step in removing the dependecies on args by "adapting" them using this method
- unify the exception model everywhere to StartupException. This makes exception
  propagation cleaner and easier
- lots of cleanup of the code related in all these areas

Big thanks to Jacques for the substantial help in testing.

Added:
    ofbiz/trunk/framework/start/lib/
    ofbiz/trunk/framework/start/lib/commons-cli-1.3.1.jar   (with props)
    ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java   (with props)
    ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java   (with props)
Modified:
    ofbiz/trunk/.classpath
    ofbiz/trunk/build.xml
    ofbiz/trunk/framework/start/build.xml
    ofbiz/trunk/framework/start/src/org/ofbiz/base/start/CommonsDaemonStart.java
    ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Config.java
    ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Start.java

Modified: ofbiz/trunk/.classpath
URL: http://svn.apache.org/viewvc/ofbiz/trunk/.classpath?rev=1744107&r1=1744106&r2=1744107&view=diff
==============================================================================
--- ofbiz/trunk/.classpath (original)
+++ ofbiz/trunk/.classpath Mon May 16 18:40:49 2016
@@ -104,6 +104,7 @@
  <classpathentry kind="lib" path="framework/service/lib/woden-core-1.0M10.jar"/>
  <classpathentry kind="lib" path="framework/service/lib/wsdl4j-1.6.2.jar"/>
  <classpathentry kind="lib" path="framework/service/lib/xmlschema-core-2.2.1.jar"/>
+ <classpathentry kind="lib" path="framework/start/lib/commons-cli-1.3.1.jar"/>
  <classpathentry kind="lib" path="framework/testtools/lib/spring-core-4.2.3.jar"/>
  <classpathentry kind="lib" path="framework/testtools/lib/spring-test-4.2.3.jar"/>
  <classpathentry kind="lib" path="framework/webapp/lib/ezmorph-0.9.1.jar"/>

Modified: ofbiz/trunk/build.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/build.xml?rev=1744107&r1=1744106&r2=1744107&view=diff
==============================================================================
--- ofbiz/trunk/build.xml (original)
+++ ofbiz/trunk/build.xml Mon May 16 18:40:49 2016
@@ -32,6 +32,7 @@ under the License.
     <property name="site.dir" value="../site"/>
     <property name="memory.initial.param" value="-Xms128M"/>
     <property name="memory.max.param" value="-Xmx512M"/>
+    <property name="portoffset" value="0"/>
 
     <import file="framework/build.xml" optional="false"/>
     <available file="applications/build.xml" property="applications.present"/>
@@ -588,8 +589,8 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="start"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--start"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="start-secure"
@@ -601,8 +602,8 @@ under the License.
             <jvmarg value="-Dnotsoserial.whitelist=${ofbiz.home.dir}/tools/security/notsoserial/empty.txt"/>
             <jvmarg value="-Dnotsoserial.dryrun=${ofbiz.home.dir}/tools/security/notsoserial/is-deserialized.txt"/>
             <jvmarg value="-Dnotsoserial.trace=${ofbiz.home.dir}/tools/security/notsoserial/deserialize-trace.txt"/>
-            <arg value="start"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--start"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="start-batch"
@@ -610,8 +611,8 @@ under the License.
         <java jar="ofbiz.jar" fork="true" spawn="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="start-batch"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--start"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="start-batch-secure"
@@ -623,8 +624,8 @@ under the License.
             <jvmarg value="-Dnotsoserial.whitelist=${ofbiz.home.dir}/tools/security/notsoserial/empty.txt"/>
             <jvmarg value="-Dnotsoserial.dryrun=${ofbiz.home.dir}/tools/security/notsoserial/is-deserialized.txt"/>
             <jvmarg value="-Dnotsoserial.trace=${ofbiz.home.dir}/tools/security/notsoserial/deserialize-trace.txt"/>
-            <arg value="start-batch"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--start"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="start-debug"
@@ -636,8 +637,8 @@ under the License.
             <jvmarg value="-Djava.compiler=NONE"/>
             <jvmarg value="-Xdebug"/>
             <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8091"/>
-            <arg value="start-debug"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--start"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="start-pos"
@@ -645,8 +646,8 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="pos"/>
-            <arg value="-portoffset=${portoffset}"/><!-- Not sure this makes sense and is useful at all -->
+            <arg value="--pos"/>
+            <arg value="--portoffset=${portoffset}"/><!-- Not sure this makes sense and is useful at all -->
         </java>
     </target>
     <target name="start-pos-secure"
@@ -658,8 +659,8 @@ under the License.
             <jvmarg value="-Dnotsoserial.whitelist=${ofbiz.home.dir}/tools/security/notsoserial/empty.txt"/>
             <jvmarg value="-Dnotsoserial.dryrun=${ofbiz.home.dir}/tools/security/notsoserial/is-deserialized.txt"/>
             <jvmarg value="-Dnotsoserial.trace=${ofbiz.home.dir}/tools/security/notsoserial/deserialize-trace.txt"/>
-            <arg value="pos"/>
-            <arg value="-portoffset=${portoffset}"/><!-- Not sure this makes sense and is useful at all -->
+            <arg value="--pos"/>
+            <arg value="--portoffset=${portoffset}"/><!-- Not sure this makes sense and is useful at all -->
         </java>
     </target>
     <target name="start-both"
@@ -667,8 +668,8 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="both"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--both"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="start-both-secure"
@@ -680,22 +681,22 @@ under the License.
             <jvmarg value="-Dnotsoserial.whitelist=${ofbiz.home.dir}/tools/security/notsoserial/empty.txt"/>
             <jvmarg value="-Dnotsoserial.dryrun=${ofbiz.home.dir}/tools/security/notsoserial/is-deserialized.txt"/>
             <jvmarg value="-Dnotsoserial.trace=${ofbiz.home.dir}/tools/security/notsoserial/deserialize-trace.txt"/>
-            <arg value="both"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--both"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="stop"
             description="Stop OFBiz. Use -Dportoffset=portNumber to shift all ports with the portNumber value.">
         <java jar="ofbiz.jar" fork="true">
-            <arg value="-shutdown"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--shutdown"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
     <target name="status"
             description="Display status of OFBiz. Use -Dportoffset=portNumber to shift all ports with the portNumber value.">
         <java jar="ofbiz.jar" fork="true">
-            <arg value="-status"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--status"/>
+            <arg value="--portoffset=${portoffset}"/>
         </java>
     </target>
 
@@ -708,7 +709,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
         </java>
     </target>
     <target name="load-demo-multitenant" depends="build"
@@ -716,18 +717,18 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
         </java>
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#DEMO1"/>
         </java>
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#DEMO2"/>
         </java>
     </target>
@@ -736,7 +737,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=seed"/>
         </java>
     </target>
@@ -745,7 +746,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=seed,seed-initial,ext"/>
         </java>
     </target>
@@ -754,7 +755,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=seed,seed-initial,ext,ext-test"/>
         </java>
     </target>
@@ -763,7 +764,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true" >
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=${data-readers}"/>
         </java>
     </target>
@@ -773,8 +774,9 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=${delegator}"/>
+            <arg value="--load-data"/>
             <arg value="file=${data-file}"/>
         </java>
     </target>
@@ -788,7 +790,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=tenant"/>
         </java>
         <condition property="hasTenant">
@@ -828,7 +830,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#${tenantId}"/>
         </java>
     </target>
@@ -836,8 +838,9 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#${tenantId}"/>
+            <arg value="--load-data"/>
             <arg value="readers=${data-readers}"/>
         </java>
     </target>
@@ -860,8 +863,9 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#${tenantId}"/>
+            <arg value="--load-data"/>
             <arg value="component=${component}"/>
         </java>
     </target>
@@ -869,9 +873,11 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#${tenantId}"/>
+            <arg value="--load-data"/>
             <arg value="readers=${data-readers}"/>
+            <arg value="--load-data"/>
             <arg value="component=${component}"/>
         </java>
     </target>
@@ -886,7 +892,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=tenant"/>
         </java>
         <condition property="hasReader">
@@ -906,7 +912,7 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="delegator=${delegator}"/>
         </java>
     </target>
@@ -914,8 +920,9 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=${data-readers}"/>
+            <arg value="--load-data"/>
             <arg value="delegator=${delegator}"/>
         </java>
     </target>
@@ -1149,8 +1156,9 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="load-data"/>
+            <arg value="--load-data"/>
             <arg value="readers=${data-readers}"/>
+            <arg value="--load-data"/>
             <arg value="delegator=default#${tenantId}"/>
         </java>
     </target>
@@ -1182,8 +1190,8 @@ under the License.
         <java jar="ofbiz.jar" fork="true" resultproperty="test.result">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="test"/>
-            <arg value="-portoffset=${portoffset}"/>
+            <arg value="--test"/>
+            <arg value="--portoffset=${portoffset}"/>
             <env key="LC_ALL" value="C"/>
         </java>
         <mkdir dir="runtime/logs/test-results/html"/>
@@ -1212,9 +1220,10 @@ under the License.
         <java jar="ofbiz.jar" fork="true">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="testlist"/>
-            <arg file="runtime/test-list-build.xml"/>
-            <arg value="-ant"/>
+            <arg value="--testlist"/>
+            <arg value="file=runtime/test-list-build.xml"/>
+            <arg value="--testlist"/>
+            <arg value="mode=ant"/>
             <env key="LC_ALL" value="C"/>
         </java>
     </target>
@@ -1225,9 +1234,10 @@ under the License.
         <java jar="ofbiz.jar" fork="true" resultproperty="test.result">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="test"/>
-            <arg value="-component=${test.component}"/>
-            <arg value="-case=${test.case}"/>
+            <arg value="--test"/>
+            <arg value="component=${test.component}"/>
+            <arg value="--test"/>
+            <arg value="case=${test.case}"/>
             <env key="LC_ALL" value="C"/>
         </java>
         <delete dir="runtime/logs/test-results/${test.component}-${test.case}"/>
@@ -1254,9 +1264,10 @@ under the License.
         <jvmarg value="-Djava.compiler=NONE"/>
         <jvmarg value="-Xdebug"/>
         <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8091"/>
-        <arg value="test"/>
-        <arg value="-component=${test.component}"/>
-        <arg value="-case=${test.case}"/>
+        <arg value="--test"/>
+        <arg value="component=${test.component}"/>
+        <arg value="--test"/>
+        <arg value="case=${test.case}"/>
         <env key="LC_ALL" value="C"/>
       </java>
       <delete dir="runtime/logs/test-results/${test.component}-${test.case}"/>
@@ -1279,9 +1290,10 @@ under the License.
         <java jar="ofbiz.jar" fork="true" resultproperty="test.result">
             <jvmarg value="${memory.initial.param}"/>
             <jvmarg value="${memory.max.param}"/>
-            <arg value="test"/>
-            <arg value="-component=${test.component}"/>
-            <arg value="-suitename=${test.suiteName}"/>
+            <arg value="--test"/>
+            <arg value="component=${test.component}"/>
+            <arg value="--test"/>
+            <arg value="suitename=${test.suiteName}"/>
             <env key="LC_ALL" value="C"/>
         </java>
         <fail message="Test run was unsuccessful">

Modified: ofbiz/trunk/framework/start/build.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/build.xml?rev=1744107&r1=1744106&r2=1744107&view=diff
==============================================================================
--- ofbiz/trunk/framework/start/build.xml (original)
+++ ofbiz/trunk/framework/start/build.xml Mon May 16 18:40:49 2016
@@ -29,12 +29,28 @@ under the License.
     <property name="name" value="ofbiz"/>
 
     <!-- ================================================================== -->
+    <!-- classpath setup to allow start component to access external libs   -->
+    <!-- the setup ensures correct path when ofbiz.jar is copied to root    -->
+    <!-- ================================================================== -->
+
+    <path id="startlibs.absolute">
+        <fileset dir="lib" includes="**/commons-cli*.jar"/>
+    </path>
+    <property name="ofbiz.absolute" location="../.."/>
+    <pathconvert property="startlibs.relative" refid="startlibs.absolute">
+        <map from="${ofbiz.absolute}" to="."/>
+    </pathconvert>
+    <manifestclasspath property="ofbiz.jar.cp" jarfile="ofbiz.jar">
+        <classpath path="${startlibs.relative}"/>
+    </manifestclasspath>
+
+    <!-- ================================================================== -->
     <!-- Compilation of the source files                                    -->
     <!-- ================================================================== -->
 
     <target name="classes" depends="prepare">
         <!-- compile start -->
-        <javac18 destdir="${build.dir}/classes" srcdir="${src.dir}"/>
+        <javac18 destdir="${build.dir}/classes" srcdir="${src.dir}" classpathref="startlibs.absolute"/>
     </target>
 
     <target name="jar" depends="classes">
@@ -45,6 +61,7 @@ under the License.
                     <attribute name="Implementation-Title" value="Apache OFBiz Startup"/>
                     <attribute name="Implementation-Vendor" value="The Apache Apache OFBiz Project"/>
                     <attribute name="Main-Class" value="org.ofbiz.base.start.Start"/>
+                    <attribute name="Class-Path" value="${ofbiz.jar.cp}"/>
                 </manifest>
             </main-elements>
         </main-jar>

Added: ofbiz/trunk/framework/start/lib/commons-cli-1.3.1.jar
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/lib/commons-cli-1.3.1.jar?rev=1744107&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ofbiz/trunk/framework/start/lib/commons-cli-1.3.1.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/CommonsDaemonStart.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/src/org/ofbiz/base/start/CommonsDaemonStart.java?rev=1744107&r1=1744106&r2=1744107&view=diff
==============================================================================
--- ofbiz/trunk/framework/start/src/org/ofbiz/base/start/CommonsDaemonStart.java (original)
+++ ofbiz/trunk/framework/start/src/org/ofbiz/base/start/CommonsDaemonStart.java Mon May 16 18:40:49 2016
@@ -30,7 +30,7 @@ public final class CommonsDaemonStart {
     }
 
     public void init(String[] args) throws StartupException {
-        Start.getInstance().init(args, true);
+        Start.getInstance().init(StartupCommandUtil.parseOfbizCommands(args));
     }
 
     public void destroy() {

Modified: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Config.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Config.java?rev=1744107&r1=1744106&r2=1744107&view=diff
==============================================================================
--- ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Config.java (original)
+++ ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Config.java Mon May 16 18:40:49 2016
@@ -24,12 +24,14 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.TimeZone;
 
@@ -52,24 +54,30 @@ public class Config {
     public final String classpathAddComponent;
     public final String classpathAddFilesFromPath;
 
-    Config(String[] args) throws IOException {
-        String firstArg = args.length > 0 ? args[0] : "";
-        // Needed when portoffset is used with these commands, start.properties fits for all of them
-        if ("start-batch".equalsIgnoreCase(firstArg)
-                || "start-debug".equalsIgnoreCase(firstArg)
-                || "stop".equalsIgnoreCase(firstArg)
-                || "-shutdown".equalsIgnoreCase(firstArg) // shutdown & status hack (was pre-existing to portoffset introduction, also useful with it)
-                || "-status".equalsIgnoreCase(firstArg)) {
-            firstArg = "start";
-        }
-        // default command is "start"
-        if (firstArg == null || firstArg.trim().length() == 0) {
-            firstArg = "start";
+    Config(List<StartupCommand> ofbizCommands) throws StartupException {
+        String fileName = determineOfbizPropertiesFileName(ofbizCommands);
+        String config = "org/ofbiz/base/start/" + fileName + ".properties";
+        Properties props;
+        try {
+            props = this.getPropertiesFile(config);
+        } catch (IOException e) {
+            throw new StartupException(e);
         }
-        String config =  "org/ofbiz/base/start/" + firstArg + ".properties";
-
-        Properties props = this.getPropertiesFile(config);
         System.out.println("Start.java using configuration file " + config);
+        
+        // set portOffsetValue
+        int portOffsetValue = 0;
+        Optional<StartupCommand> portOffsetCommand = ofbizCommands.stream()
+                .filter(command -> command.getName().equals(StartupCommandUtil.StartupOption.PORTOFFSET.getName()))
+                .findFirst();
+        if(portOffsetCommand.isPresent()) {
+            Map<String,String> commandArgs = portOffsetCommand.get().getProperties();
+            try {
+                portOffsetValue = Integer.parseInt(commandArgs.keySet().iterator().next());
+            } catch(NumberFormatException e) {
+                throw new StartupException("invalid portoffset number", e);
+            }
+        }
 
         // set the ofbiz.home
         String ofbizHomeTmp = props.getProperty("ofbiz.home", ".");
@@ -98,20 +106,18 @@ public class Config {
         adminKey = getProp(props, "ofbiz.admin.key", "NA");
 
         // create the host InetAddress
-        adminAddress = InetAddress.getByName(serverHost);
+        try {
+            adminAddress = InetAddress.getByName(serverHost);
+        } catch (UnknownHostException e) {
+            throw new StartupException(e);
+        }
 
         // parse the port number
         int adminPortTmp;
         try {
             adminPortTmp = Integer.parseInt(adminPortStr);
-            if (args.length > 0) {
-                for (String arg : args) {
-                    if (arg.toLowerCase().contains("portoffset=") && !arg.toLowerCase().contains("${portoffset}")) {
-                        adminPortTmp = adminPortTmp != 0 ? adminPortTmp : 10523; // This is necessary because the ASF machines don't allow ports 1 to 3, see  INFRA-6790
-                        adminPortTmp += Integer.parseInt(arg.split("=")[1]);
-                    }
-                }
-            }
+            adminPortTmp = adminPortTmp != 0 ? adminPortTmp : 10523; // This is necessary because the ASF machines don't allow ports 1 to 3, see  INFRA-6790
+            adminPortTmp += portOffsetValue;
         } catch (Exception e) {
             System.out.println("Error while parsing admin port number (so default to 10523) = " + e);
             adminPortTmp = 10523;
@@ -195,33 +201,37 @@ public class Config {
         loaders = Collections.unmodifiableList(loadersTmp);
 
         // set the port offset
-        Integer portOffset = 0;
-        if (args != null) {
-            for (String argument : args) {
-                // arguments can prefix w/ a '-'. Just strip them off
-                if (argument.startsWith("-")) {
-                    int subIdx = 1;
-                    if (argument.startsWith("--")) {
-                        subIdx = 2;
-                    }
-                    argument = argument.substring(subIdx);
-                }
-                // parse the arguments
-                if (argument.indexOf("=") != -1) {
-                    String argumentName = argument.substring(0, argument.indexOf("="));
-                    String argumentVal = argument.substring(argument.indexOf("=") + 1);
-                    if ("portoffset".equalsIgnoreCase(argumentName) && !"${portoffset}".equals(argumentVal)) {
-                        try {
-                            portOffset = Integer.valueOf(argumentVal);
-                        } catch (NumberFormatException e) {
-                            System.out.println("Error while parsing portoffset (the default value 0 will be used) = " + e);
-                        }
-                    }
-                }
-            }
-        }
-        this.portOffset = portOffset;
+        this.portOffset = portOffsetValue;
+    }
 
+    private String determineOfbizPropertiesFileName(List<StartupCommand> ofbizCommands) {
+        String fileName = null;
+        if (ofbizCommands.stream().anyMatch(command ->
+        command.getName() == StartupCommandUtil.StartupOption.START.getName()
+        || command.getName() == StartupCommandUtil.StartupOption.SHUTDOWN.getName()
+        || command.getName() == StartupCommandUtil.StartupOption.STATUS.getName() )
+        || ofbizCommands.isEmpty()
+        || ofbizCommands.stream().allMatch(command ->
+            command.getName() == StartupCommandUtil.StartupOption.PORTOFFSET.getName())
+                ){
+            fileName = "start";
+        } else if(ofbizCommands.stream().anyMatch(
+                option -> option.getName() == StartupCommandUtil.StartupOption.BOTH.getName())) {
+            fileName = "both";
+        } else if(ofbizCommands.stream().anyMatch(
+                option -> option.getName() == StartupCommandUtil.StartupOption.LOAD_DATA.getName())) {
+            fileName = "load-data";
+        } else if(ofbizCommands.stream().anyMatch(
+                option -> option.getName() == StartupCommandUtil.StartupOption.POS.getName())) {
+            fileName = "pos";
+        } else if(ofbizCommands.stream().anyMatch(
+                option -> option.getName() == StartupCommandUtil.StartupOption.TEST.getName())) {
+            fileName = "test";
+        } else if(ofbizCommands.stream().anyMatch(
+                option -> option.getName() == StartupCommandUtil.StartupOption.TEST_LIST.getName())) {
+            fileName = "testlist";
+        }
+        return fileName;
     }
 
     private String getOfbizHomeProp(Properties props, String key, String def) {

Modified: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Start.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Start.java?rev=1744107&r1=1744106&r2=1744107&view=diff
==============================================================================
--- ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Start.java (original)
+++ ofbiz/trunk/framework/start/src/org/ofbiz/base/start/Start.java Mon May 16 18:40:49 2016
@@ -23,30 +23,32 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.net.ConnectException;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
 
 /**
  * OFBiz startup class.
  *
+ * <p>
  * This class implements a thread-safe state machine. The design is critical
  * for reliable starting and stopping of the server.
- *
+ * </p>
+ * <p>
  * The machine's current state and state changes must be encapsulated in this
  * class. Client code may query the current state, but it may not change it.
- *
+ * </p>
+ * <p>
  * This class uses a singleton pattern to guarantee that only one server instance
- * is running in the VM. Client code retrieves the instance by using the getInstance()
- * static method.
- *
+ * is running in the VM. Client code retrieves the instance by using the
+ * <tt>getInstance()</tt> static method.
+ * </p>
  */
 public final class Start {
 
@@ -66,29 +68,37 @@ public final class Start {
      * such as starting, stopping or checking the status of the server.
      *
      * @param args: The commands for ofbiz
-     * @throws StartupException: propagates to the servlet container
+     * @throws StartupException: terminates ofbiz or propagates to caller
      */
     public static void main(String[] args) throws StartupException {
-        Command command = evaluateOfbizCommand(args);
-        if (command == Command.HELP) {
-            help(System.out);
-            return;
-        } else if (command == Command.HELP_ERROR) {
-            help(System.err);
+        List<StartupCommand> ofbizCommands = null;
+        try {
+            ofbizCommands = StartupCommandUtil.parseOfbizCommands(args);
+        } catch (StartupException e) {
+            // incorrect arguments passed to the command line
+            System.err.println("Error: " + e.getMessage() + System.lineSeparator());
+            StartupCommandUtil.printOfbizStartupHelp(System.err);
             System.exit(1);
         }
-        instance.init(args, command == Command.COMMAND);
-        try {
-            if (command == Command.STATUS) {
+
+        CommandType commandType = evaluateOfbizCommands(ofbizCommands);
+        if(commandType != CommandType.HELP) {
+            instance.init(ofbizCommands);
+        }
+        switch (commandType) {
+            case HELP:
+                StartupCommandUtil.printOfbizStartupHelp(System.out);
+                break;
+            case STATUS:
                 System.out.println("Current Status : " + instance.status());
-            } else if (command == Command.SHUTDOWN) {
+                break;
+            case SHUTDOWN:
                 System.out.println("Shutting down server : " + instance.shutdown());
-            } else {
-                // general start
+                break;
+            case START:
+                populateLoaderArgs(ofbizCommands);
                 instance.start();
-            }
-        } catch (Exception e) {
-            throw new StartupException(e);
+                break;
         }
     }
 
@@ -125,48 +135,16 @@ public final class Start {
         }
     }
 
-    void init(String[] args, boolean fullInit) throws StartupException {
-        String globalSystemPropsFileName = System.getProperty("ofbiz.system.props");
-        if (globalSystemPropsFileName != null) {
-            FileInputStream stream = null;
-            try {
-                stream = new FileInputStream(globalSystemPropsFileName);
-                System.getProperties().load(stream);
-            } catch (IOException e) {
-                throw new StartupException("Couldn't load global system props", e);
-            } finally {
-                if (stream != null) {
-                    try {
-                        stream.close();
-                    } catch (IOException e) {
-                        throw new StartupException("Couldn't close stream", e);
-                    }
-                }
-            }
-        }
+    void init(List<StartupCommand> ofbizCommands) throws StartupException {
+        loadGlobalOfbizSystemProperties("ofbiz.system.props");
         try {
-            this.config = new Config(args);
-        } catch (IOException e) {
-            throw new StartupException("Couldn't not fetch config instance", e);
-        }
-        // parse the startup arguments
-        if (args.length > 1) {
-            this.loaderArgs.addAll(Arrays.asList(args).subList(1, args.length));
-            // Needed when portoffset is used with these commands
-            try {
-                if ("status".equals(args[0])) {
-                    System.out.println("Current Status : " + instance.status());
-                } else if ("stop".equals(args[0])) {
-                    System.out.println("Shutting down server : " + instance.shutdown());
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-                System.exit(99);
-            }
-        }
-        if (!fullInit) {
-            return;
+            this.config = new Config(ofbizCommands);
+        } catch (StartupException e) {
+            throw new StartupException("Could not fetch config instance", e);
         }
+    }
+
+    void start() throws StartupException {
         // create the log directory
         createLogDirectory();
         // create the listener thread
@@ -185,14 +163,11 @@ public final class Start {
 
         // initialize the startup loaders
         initStartLoaders();
-    }
-
-    void start() throws Exception {
         if (!startStartLoaders()) {
             if (this.serverState.get() == ServerState.STOPPING) {
                 return;
             } else {
-                throw new Exception("Error during start.");
+                throw new StartupException("Error during start.");
             }
         }
         if (config.shutdownAfterLoad) {
@@ -231,58 +206,81 @@ public final class Start {
         System.exit(0);
     }
 
-    private static Command evaluateOfbizCommand(String[] args) {
-        Command command = null;
-        for (String arg : args) {
-            if (arg.equals("-help") || arg.equals("-?")) {
-                command = checkCommand(command, Command.HELP);
-            } else if (arg.equals("-status")) {
-                command = checkCommand(command, Command.STATUS);
-            } else if (arg.equals("-shutdown")) {
-                command = checkCommand(command, Command.SHUTDOWN);
-            } else if (arg.startsWith("-")) {
-                if (!arg.contains("portoffset")) {
-                    command = checkCommand(command, Command.COMMAND);
-                }
-            } else {
-                command = checkCommand(command, Command.COMMAND);
-                if (command == Command.COMMAND) {
-                } else {
-                    command = Command.HELP_ERROR;
+    private static CommandType evaluateOfbizCommands(List<StartupCommand> ofbizCommands) {
+        if (ofbizCommands.stream().anyMatch(
+                command -> command.getName().equals(StartupCommandUtil.StartupOption.HELP.getName()))) {
+            return CommandType.HELP;
+        } else if (ofbizCommands.stream().anyMatch(
+                command -> command.getName().equals(StartupCommandUtil.StartupOption.STATUS.getName()))) {
+            return CommandType.STATUS;
+        } else if (ofbizCommands.stream().anyMatch(
+                command -> command.getName().equals(StartupCommandUtil.StartupOption.SHUTDOWN.getName()))) {
+            return CommandType.SHUTDOWN;
+        } else {
+            return CommandType.START;
+        }
+    }
+
+    private enum CommandType {
+        HELP, STATUS, SHUTDOWN, START
+    }
+
+    private void loadGlobalOfbizSystemProperties(String globalOfbizPropertiesFileName) throws StartupException {
+        String globalSystemPropsFileName = System.getProperty(globalOfbizPropertiesFileName);
+        if (globalSystemPropsFileName != null) {
+            FileInputStream stream = null;
+            try {
+                stream = new FileInputStream(globalSystemPropsFileName);
+                System.getProperties().load(stream);
+            } catch (IOException e) {
+                throw new StartupException("Couldn't load global system props", e);
+            } finally {
+                if (stream != null) {
+                    try {
+                        stream.close();
+                    } catch (IOException e) {
+                        throw new StartupException("Couldn't close stream", e);
+                    }
                 }
             }
         }
-        if (command == null) {
-            command = Command.COMMAND;
-        }
-        return command;
     }
 
-    private static Command checkCommand(Command command, Command wanted) {
-        if (wanted == Command.HELP || wanted.equals(command)) {
-            return wanted;
-        } else if (command == null) {
-            return wanted;
-        } else {
-            System.err.println("Duplicate command detected(was " + command + ", wanted " + wanted);
-            return Command.HELP_ERROR;
+    /**
+     * populates the loaderArgs with arguments as expected by the
+     * containers that will receive them.
+     *
+     * TODO A better solution is to change the signature of all
+     * containers to receive a <tt>List</tt> of <tt>StartupCommand</tt>s
+     * instead and delete the methods populateLoaderArgs, commandExistsInList
+     * and retrieveCommandArgumentEntries along with the loaderArgs list.
+     */
+    private static void populateLoaderArgs(List<StartupCommand> ofbizCommands) {
+        final String LOAD_DATA = StartupCommandUtil.StartupOption.LOAD_DATA.getName();
+        final String TEST = StartupCommandUtil.StartupOption.TEST.getName();
+        final String TEST_LIST = StartupCommandUtil.StartupOption.TEST_LIST.getName();
+        
+        if(commandExistsInList(ofbizCommands, LOAD_DATA)) {
+            retrieveCommandArguments(ofbizCommands, LOAD_DATA).entrySet().stream().forEach(entry ->
+            instance.loaderArgs.add("-" + entry.getKey() + "=" + entry.getValue()));
+        } else if(commandExistsInList(ofbizCommands, TEST)) {
+            retrieveCommandArguments(ofbizCommands, TEST).entrySet().stream().forEach(entry ->
+            instance.loaderArgs.add("-" + entry.getKey() + "=" + entry.getValue()));
+        } else if(commandExistsInList(ofbizCommands, TEST_LIST)) {
+            Map<String,String> testListArgs = retrieveCommandArguments(ofbizCommands, TEST_LIST);
+            instance.loaderArgs.add(testListArgs.get("file"));
+            instance.loaderArgs.add("-" + testListArgs.get("mode"));
         }
     }
 
-    private static void help(PrintStream out) {
-        // Currently some commands have no dash, see OFBIZ-5872
-        out.println("");
-        out.println("Usage: java -jar ofbiz.jar [command] [arguments]");
-        out.println("both    -----> Runs simultaneously the POS (Point of Sales) application and OFBiz standard");
-        out.println("-help, -? ----> This screen");
-        out.println("load-data -----> Creates tables/load data, eg: load-data -readers=seed,demo,ext -timeout=7200 -delegator=default -group=org.ofbiz. Or: load-data -file=/tmp/dataload.xml");
-        out.println("pos     -----> Runs the POS (Point of Sales) application");
-        out.println("start -------> Starts the server");
-        out.println("-status ------> Gives the status of the server");
-        out.println("-shutdown ----> Shutdowns the server");
-        out.println("test --------> Runs the JUnit test script");
-        out.println("[no config] --> Uses default config");
-        out.println("[no command] -> Starts the server with default config");
+    private static boolean commandExistsInList(List<StartupCommand> ofbizCommands, String commandName) {
+        return ofbizCommands.stream().anyMatch(command -> command.getName().equals(commandName));
+    }
+
+    private static Map<String,String> retrieveCommandArguments(List<StartupCommand> ofbizCommands, String commandName) {
+        return ofbizCommands.stream()
+                .filter(option-> option.getName().equals(commandName))
+                .collect(Collectors.toList()).get(0).getProperties();
     }
 
     private void createListenerThread() throws StartupException {
@@ -303,12 +301,6 @@ public final class Start {
         }
     }
 
-    /**
-     * Creates a new <code>NativeLibClassLoader</code> instance.
-     *
-     * @return A new <code>NativeLibClassLoader</code> instance
-     * @throws IOException
-     */
     private NativeLibClassLoader createClassLoader() throws IOException {
         ClassLoader parent = Thread.currentThread().getContextClassLoader();
         if (parent instanceof NativeLibClassLoader) {
@@ -426,13 +418,15 @@ public final class Start {
         return response;
     }
 
-    private String shutdown() throws IOException {
-        return sendSocketCommand(Control.SHUTDOWN);
+    private String shutdown() throws StartupException {
+        try {
+            return sendSocketCommand(Control.SHUTDOWN);
+        } catch (Exception e) {
+            throw new StartupException(e);
+        }
     }
 
     /**
-     * Returns <code>true</code> if all loaders were started.
-     *
      * @return <code>true</code> if all loaders were started.
      */
     private boolean startStartLoaders() {
@@ -453,13 +447,13 @@ public final class Start {
         return this.serverState.compareAndSet(ServerState.STARTING, ServerState.RUNNING);
     }
 
-    private String status() throws IOException {
+    private String status() throws StartupException {
         try {
             return sendSocketCommand(Control.STATUS);
         } catch (ConnectException e) {
             return "Not Running";
         } catch (IOException e) {
-            throw e;
+            throw new StartupException(e);
         }
     }
 
@@ -527,10 +521,6 @@ public final class Start {
         }
     }
 
-    private enum Command {
-        HELP, HELP_ERROR, STATUS, SHUTDOWN, COMMAND
-    }
-
     private enum Control {
         SHUTDOWN {
             @Override

Added: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java?rev=1744107&view=auto
==============================================================================
--- ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java (added)
+++ ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java Mon May 16 18:40:49 2016
@@ -0,0 +1,49 @@
+package org.ofbiz.base.start;
+
+import java.util.Map;
+
+/**
+ * A command line argument passed to ofbiz
+ *
+ * <p>
+ * A <tt>StartupCommand</tt> represents a processed command line argument passed
+ * to ofbiz such that it is no longer a raw string but an instance of this class.
+ * For example: <code>java -jar ofbiz.jar --status</code> where status is a command.
+ * </p>
+ */
+public class StartupCommand {
+    private String name;
+    private Map<String,String> properties;
+
+    public String getName() {
+        return name;
+    }
+    public Map<String,String> getProperties() {
+        return properties;
+    }
+
+    private StartupCommand(Builder builder) {
+        this.name = builder.name;
+        this.properties = builder.properties;
+    }
+
+    public static class Builder {
+        //required parameters
+        private final String name;
+
+        //optional parameters      
+        private Map<String,String> properties;
+
+        public Builder(String name) {
+            this.name = name;
+        }
+        public Builder properties(Map<String,String> properties) {
+            this.properties = properties;
+            return this;
+        }
+
+        public StartupCommand build() {
+            return new StartupCommand(this);
+        }
+    }
+}

Propchange: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommand.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java?rev=1744107&view=auto
==============================================================================
--- ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java (added)
+++ ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java Mon May 16 18:40:49 2016
@@ -0,0 +1,237 @@
+package org.ofbiz.base.start;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+/**
+ * A utility class for processing OFBiz command line arguments
+ *
+ * <p>
+ * Defines OFBiz startup options called through main e.g. --load-data or --help
+ * in addition to utility methods for parsing and handling these options
+ * </p>
+ */
+public final class StartupCommandUtil {
+
+    /*
+     * Make sure of defining the same set of values in:
+     *
+     * - The StartupOptions in the StartupOption enum
+     * - The commons-cli options (e.g. BOTH, HELP, etc ...)
+     * - The getOfbizStartupOptions method
+     *
+     * Keeping these items in sync means that OFBiz behaves correctly
+     * while being decoupled from the commons-cli library and the only
+     * place where commons-cli is used is in this class
+     */
+
+    public enum StartupOption {
+        BOTH("both"),
+        HELP("help"),
+        LOAD_DATA("load-data"),
+        PORTOFFSET("portoffset"),
+        POS("pos"),
+        SHUTDOWN("shutdown"),
+        START("start"),
+        STATUS("status"),
+        TEST("test"),
+        TEST_LIST("testlist");
+        
+        private String name;
+        private StartupOption(String name) {
+            this.name = name;
+        }
+        public String getName() {
+            return name;
+        }
+    }
+
+    private static final Option BOTH = Option.builder("b")
+            .longOpt(StartupOption.BOTH.getName())
+            .desc("Runs simultaneously both the POS (Point of Sales) application and OFBiz server")
+            .hasArg(false)
+            .build();
+    private static final Option HELP = Option.builder("?")
+            .longOpt(StartupOption.HELP.getName())
+            .desc("Prints this help screen to the user")
+            .hasArg(false)
+            .build();
+    private static final Option LOAD_DATA = Option.builder("l")
+            .longOpt(StartupOption.LOAD_DATA.getName())
+            .desc("Creates tables/load data e.g:"
+                    + System.lineSeparator()
+                    + "-l readers=seed,demo,ext"
+                    + System.lineSeparator()
+                    + "-l timeout=7200"
+                    + System.lineSeparator()
+                    + "-l delegator=default"
+                    + System.lineSeparator()
+                    + "-l group=org.ofbiz"
+                    + System.lineSeparator()
+                    + "-l dir=directory/of/files"
+                    + System.lineSeparator()
+                    + "-l file=/tmp/dataload.xml")
+            .numberOfArgs(2)
+            .valueSeparator('=')
+            .optionalArg(true)
+            .argName("key=value")
+            .build();
+    private static final Option PORTOFFSET = Option.builder("o")
+            .longOpt(StartupOption.PORTOFFSET.getName())
+            .desc("Offsets the default network port for OFBiz")
+            .hasArg()
+            .argName("offset")
+            .optionalArg(false)
+            .build();
+    private static final Option POS = Option.builder("p")
+            .longOpt(StartupOption.POS.getName())
+            .desc("Runs the POS (Point of Sales) application")
+            .hasArg(false)
+            .build();
+    private static final Option SHUTDOWN = Option.builder("d")
+            .longOpt(StartupOption.SHUTDOWN.getName())
+            .desc("Shutdown OFBiz")
+            .hasArg(false)
+            .build();
+    private static final Option START = Option.builder("u")
+            .longOpt(StartupOption.START.getName())
+            .desc("Start OFBiz")
+            .hasArg(false)
+            .build();
+    private static final Option STATUS = Option.builder("s")
+            .longOpt(StartupOption.STATUS.getName())
+            .desc("Gives the status of OFBiz")
+            .hasArg(false)
+            .build();
+    private static final Option TEST = Option.builder("t")
+            .longOpt(StartupOption.TEST.getName())
+            .desc("Runs the selected test or all if none selected e.g.: "
+                    + System.lineSeparator()
+                    + "--test component=base --test case=somecase"
+                    + System.lineSeparator()
+                    + "--test component=base --test suitename=somesuite")
+            .numberOfArgs(2)
+            .valueSeparator('=')
+            .optionalArg(true)
+            .argName("key=value")
+            .build();
+    private static final Option TEST_LIST = Option.builder("x")
+            .longOpt(StartupOption.TEST_LIST.getName())
+            .desc("Generates an ant build script or a text file of all tests in ofbiz."
+                    + System.lineSeparator()
+                    + "The ant build script can run all test suites in isolation."
+                    + System.lineSeparator()
+                    + "The text file contains all tests in the format <component>:<suite-name>."
+                    + System.lineSeparator()
+                    + "The file arg determines the output file, and mode determines ant or text e.g:"
+                    + System.lineSeparator()
+                    + "--testlist file=runtime/test-list-build.xml"
+                    + System.lineSeparator()
+                    + "--testlist mode=ant or --testlist mode=text")
+            .numberOfArgs(2)
+            .valueSeparator('=')
+            .argName("key=value")
+            .build();
+
+    static final List<StartupCommand> parseOfbizCommands(final String[] args) throws StartupException {
+        CommandLine commandLine = null;
+        CommandLineParser parser = new DefaultParser();
+        try {
+            commandLine = parser.parse(StartupCommandUtil.getOfbizStartupOptions(), args);
+        } catch (ParseException e) {
+            throw new StartupException(e.getMessage());
+        }
+        if(!commandLine.getArgList().isEmpty()) {
+            throw new StartupException("unrecognized options / properties: " + commandLine.getArgList());
+        }
+        validateAllCommandArguments(commandLine);
+        return mapCommonsCliOptionsToStartupCommands(commandLine);
+    }
+
+    static final void printOfbizStartupHelp(final PrintStream printStream) {
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printHelp(
+                new PrintWriter(printStream, true),
+                HelpFormatter.DEFAULT_WIDTH,
+                "java -jar ofbiz.jar",
+                System.lineSeparator() + "Executes OFBiz command e.g. start, shutdown, check status, etc",
+                getOfbizStartupOptions(),
+                HelpFormatter.DEFAULT_LEFT_PAD,
+                HelpFormatter.DEFAULT_DESC_PAD,
+                "note: Only one command can execute at a time. Portoffset may be appended",
+                true);
+    }
+
+    private static final List<StartupCommand> mapCommonsCliOptionsToStartupCommands(final CommandLine commandLine) {
+        List<Option> optionList = Arrays.asList(commandLine.getOptions());
+        return optionList.stream()
+                .map(option -> new StartupCommand.Builder(option.getLongOpt())
+                    .properties(populateMapFromProperties(commandLine.getOptionProperties(option.getLongOpt())))
+                    .build())
+                .collect(Collectors.toList());
+    }
+
+    private static final Map<String,String> populateMapFromProperties(final Properties properties) {
+        return properties.entrySet().stream().collect(Collectors.toMap(
+                entry -> String.valueOf(entry.getKey()),
+                entry -> String.valueOf(entry.getValue())));
+    }
+
+    private static final void validateAllCommandArguments(CommandLine commandLine) throws StartupException {
+        // TEST_LIST validation
+        if(commandLine.hasOption(StartupOption.TEST_LIST.getName())) {
+            Properties optionProperties = commandLine.getOptionProperties(StartupOption.TEST_LIST.getName());
+            if(!optionProperties.containsKey("file")
+                    || !optionProperties.containsKey("mode") ) {
+                throw new StartupException("You must pass both file and mode arguments to --" + StartupOption.TEST_LIST.getName());
+            } else if (!optionProperties.get("mode").toString().equals("text")
+                    && !optionProperties.get("mode").toString().equals("ant")) {
+                throw new StartupException("mode only accepts text or ant in the option --"  + StartupOption.TEST_LIST.getName());
+            }
+        // PORTOFFSET validation
+        } else if(commandLine.hasOption(StartupOption.PORTOFFSET.getName())) {
+            Properties optionProperties = commandLine.getOptionProperties(StartupOption.PORTOFFSET.getName());
+            try {
+                int portOffset = Integer.parseInt(optionProperties.keySet().iterator().next().toString());
+                if(portOffset < 0) {
+                    throw new StartupException("you can only pass positive integers to the option --" + StartupOption.PORTOFFSET.getName());
+                }
+            } catch (NumberFormatException e) {
+                throw new StartupException("you can only pass positive integers to the option --" + StartupOption.PORTOFFSET.getName(), e);
+            }
+        }
+        //TODO add more validations
+    }
+
+    private static final Options getOfbizStartupOptions() {
+        OptionGroup ofbizCommandOptions = new OptionGroup();
+        ofbizCommandOptions.addOption(BOTH);
+        ofbizCommandOptions.addOption(HELP);
+        ofbizCommandOptions.addOption(LOAD_DATA);
+        ofbizCommandOptions.addOption(POS);
+        ofbizCommandOptions.addOption(SHUTDOWN);
+        ofbizCommandOptions.addOption(START);
+        ofbizCommandOptions.addOption(STATUS);
+        ofbizCommandOptions.addOption(TEST);
+        ofbizCommandOptions.addOption(TEST_LIST);
+
+        Options options = new Options();
+        options.addOptionGroup(ofbizCommandOptions);
+        options.addOption(PORTOFFSET);
+        return options;
+    }
+}

Propchange: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/start/src/org/ofbiz/base/start/StartupCommandUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain