LOG4J2-2011 replace JCommander command line parser with picocli to let users run Log4j2 utility applications without requiring an external dependency
diff --git a/log4j-server/pom.xml b/log4j-server/pom.xml
index 9674ab8..d5493c3 100644
--- a/log4j-server/pom.xml
+++ b/log4j-server/pom.xml
@@ -40,11 +40,6 @@
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
     </dependency>
-    <!-- Command line parsing -->
-    <dependency>
-      <groupId>com.beust</groupId>
-      <artifactId>jcommander</artifactId>
-    </dependency>
     <!-- Used for JMS server (needs an implementation of course) -->
     <dependency>
       <groupId>org.jboss.spec.javax.jms</groupId>
diff --git a/log4j-server/src/main/java/org/apache/logging/log4j/server/AbstractSocketServer.java b/log4j-server/src/main/java/org/apache/logging/log4j/server/AbstractSocketServer.java
index e2dff83..4f487f5 100644
--- a/log4j-server/src/main/java/org/apache/logging/log4j/server/AbstractSocketServer.java
+++ b/log4j-server/src/main/java/org/apache/logging/log4j/server/AbstractSocketServer.java
@@ -30,8 +30,6 @@
 import java.util.List;
 import java.util.Objects;
 
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.validators.PositiveInteger;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LogEventListener;
@@ -41,8 +39,8 @@
 import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
 import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
 import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
-import org.apache.logging.log4j.core.util.InetAddressConverter;
 import org.apache.logging.log4j.core.util.Log4jThread;
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Option;
 import org.apache.logging.log4j.util.Strings;
 
 /**
@@ -57,22 +55,19 @@
 
     protected static class CommandLineArguments extends BasicCommandLineArguments {
 
-        @Parameter(names = { "--config", "-c" }, description = "Log4j configuration file location (path or URL).")
+        @Option(names = { "--config", "-c" }, description = "Log4j configuration file location (path or URL).")
         private String configLocation;
 
-        @Parameter(names = { "--interactive",
-                "-i" }, description = "Accepts commands on standard input (\"exit\" is the only command).")
+        @Option(names = { "--interactive", "-i" }, description = "Accepts commands on standard input (\"exit\" is the only command).")
         private boolean interactive;
 
-        @Parameter(names = { "--port",
-                "-p" }, validateWith = PositiveInteger.class, description = "The server port number, or 0 to automatically allocate a port number.")
+        @Option(names = { "--port", "-p" }, description = "The server port number, or 0 to automatically allocate a port number.")
         private int port;
 
-        @Parameter(names = { "--localbindaddress",
-                "-a" }, converter = InetAddressConverter.class, description = "Server socket local bind address.")
+        @Option(names = { "--localbindaddress", "-a" }, description = "Server socket local bind address.")
         private InetAddress localBindAddress;
 
-        @Parameter(names = {"--classes", "-C"}, description = "Additional classes to allow deserialization")
+        @Option(names = {"--classes", "-C"}, description = "Additional classes to allow deserialization")
         private List<String> allowedClasses;
 
         String getConfigLocation() {
diff --git a/log4j-server/src/main/java/org/apache/logging/log4j/server/TcpSocketServer.java b/log4j-server/src/main/java/org/apache/logging/log4j/server/TcpSocketServer.java
index 51c071c..50e1d82 100644
--- a/log4j-server/src/main/java/org/apache/logging/log4j/server/TcpSocketServer.java
+++ b/log4j-server/src/main/java/org/apache/logging/log4j/server/TcpSocketServer.java
@@ -30,28 +30,29 @@
 import java.util.concurrent.ConcurrentHashMap;

 import java.util.concurrent.ConcurrentMap;

 

-import com.beust.jcommander.Parameter;

-import com.beust.jcommander.validators.PositiveInteger;

 import org.apache.logging.log4j.core.config.ConfigurationFactory;

 import org.apache.logging.log4j.core.parser.ParseException;

-import org.apache.logging.log4j.core.util.BasicCommandLineArguments;

 import org.apache.logging.log4j.core.util.Closer;

 import org.apache.logging.log4j.core.util.Log4jThread;

+import org.apache.logging.log4j.core.util.picocli.CommandLine;

+import org.apache.logging.log4j.core.util.picocli.CommandLine.Command;

+import org.apache.logging.log4j.core.util.picocli.CommandLine.Option;

 import org.apache.logging.log4j.message.EntryMessage;

 

 /**

  * Listens for Log4j events on a TCP server socket and passes them on to Log4j.

- * 

+ *

  * @param <T>

  *        The kind of input stream read

  * @see #main(String[])

  */

 public class TcpSocketServer<T extends InputStream> extends AbstractSocketServer<T> {

 

+    @Command(name = "TcpSocketServer")

     protected static class CommandLineArguments extends AbstractSocketServer.CommandLineArguments {

-        

-        @Parameter(names = { "--backlog",

-                "-b" }, validateWith = PositiveInteger.class, description = "Server socket backlog.")

+

+        @Option(names = { "--backlog",

+                "-b" }, description = "Server socket backlog. Must be a positive integer.")

         // Same default as ServerSocket

         private int backlog = 50;

 

@@ -61,8 +62,7 @@
 

         void setBacklog(final int backlog) {

             this.backlog = backlog;

-        }        

-

+        }

     }

 

     /**

@@ -118,7 +118,7 @@
 

     /**

      * Creates a socket server that reads JSON log events.

-     * 

+     *

      * @param port

      *        The port number, or 0 to automatically allocate a port number.

      * @return a new a socket server

@@ -155,7 +155,7 @@
 

     /**

      * Creates a socket server that reads serialized log events.

-     * 

+     *

      * @param port

      *        The port number, or 0 to automatically allocate a port number.

      * @return a new a socket server

@@ -170,7 +170,7 @@
 

     /**

      * Creates a socket server that reads serialized log events.

-     * 

+     *

      * @param port

      *        The port number, or 0 to automatically allocate a port number.

      * @param backlog

@@ -213,7 +213,7 @@
 

     /**

      * Creates a socket server that reads XML log events.

-     * 

+     *

      * @param port

      *        The port number, or 0 to automatically allocate a port number.

      * @return a new a socket server

@@ -251,22 +251,23 @@
 

     /**

      * Main startup for the server. Run with "--help" for to print command line help on the console.

-     * 

+     *

      * @param args

      *        The command line arguments.

      * @throws Exception

      *         if an error occurs.

      */

     public static void main(final String[] args) throws Exception {

-        final CommandLineArguments cla = BasicCommandLineArguments.parseCommandLine(args, TcpSocketServer.class, new CommandLineArguments());

-        if (cla.isHelp()) {

+        CommandLineArguments cla = CommandLine.populateCommand(new CommandLineArguments(), args);

+        if (cla.isHelp() || cla.backlog < 0 || cla.getPort() < 0) {

+            CommandLine.usage(cla, System.err);

             return;

         }

         if (cla.getConfigLocation() != null) {

             ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(cla.getConfigLocation()));

         }

         final TcpSocketServer<InputStream> socketServer = TcpSocketServer.createJsonSocketServer(

-            cla.getPort(), cla.getBacklog(), cla.getLocalBindAddress());

+                cla.getPort(), cla.getBacklog(), cla.getLocalBindAddress());

         final Thread serverThread = socketServer.startNewThread();

         if (cla.isInteractive()) {

             socketServer.awaitTermination(serverThread);

@@ -279,7 +280,7 @@
 

     /**

      * Constructor.

-     * 

+     *

      * @param port

      *        The port number, or 0 to automatically allocate a port number.

      * @param backlog

@@ -299,9 +300,9 @@
 

     /**

      * Constructor.

-     * 

+     *

      * @param port

-     *         The port number, or 0 to automatically allocate a port number. 

+     *         The port number, or 0 to automatically allocate a port number.

      * @param logEventInput

      *        the log even input

      * @throws IOException

@@ -314,7 +315,7 @@
 

     /**

      * Constructor.

-     * 

+     *

      * @param port

      *        to listen.

      * @param logEventInput

@@ -379,7 +380,7 @@
 

     /**

      * Shutdown the server.

-     * 

+     *

      * @throws IOException if the server socket could not be closed

      */

     @Override

diff --git a/log4j-server/src/main/java/org/apache/logging/log4j/server/UdpSocketServer.java b/log4j-server/src/main/java/org/apache/logging/log4j/server/UdpSocketServer.java
index db66653..533c4b2 100644
--- a/log4j-server/src/main/java/org/apache/logging/log4j/server/UdpSocketServer.java
+++ b/log4j-server/src/main/java/org/apache/logging/log4j/server/UdpSocketServer.java
@@ -28,11 +28,11 @@
 
 import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.parser.ParseException;
-import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
+import org.apache.logging.log4j.core.util.picocli.CommandLine;
 
 /**
- * Listens for Log4j events on a datagram socket and passes them on to Log4j. 
- * 
+ * Listens for Log4j events on a datagram socket and passes them on to Log4j.
+ *
  * @param <T>
  *            The kind of input stream read
  * @see #main(String[])
@@ -41,7 +41,7 @@
 
     /**
      * Creates a socket server that reads JSON log events.
-     * 
+     *
      * @param port
      *            the port to listen
      * @return a new a socket server
@@ -54,7 +54,7 @@
 
     /**
      * Creates a socket server that reads serialized log events.
-     * 
+     *
      * @param port
      *            the port to listen
      * @return a new a socket server
@@ -82,7 +82,7 @@
 
     /**
      * Creates a socket server that reads XML log events.
-     * 
+     *
      * @param port
      *            the port to listen
      * @return a new a socket server
@@ -95,15 +95,16 @@
 
     /**
      * Main startup for the server. Run with "--help" for to print command line help on the console.
-     * 
+     *
      * @param args
      *            The command line arguments.
      * @throws Exception
      *             if an error occurs.
      */
     public static void main(final String[] args) throws Exception {
-        final CommandLineArguments cla = BasicCommandLineArguments.parseCommandLine(args, UdpSocketServer.class, new CommandLineArguments());
-        if (cla.isHelp()) {
+        final CommandLineArguments cla = CommandLine.populateCommand(new CommandLineArguments(), args);
+        if (cla.isHelp() || cla.getPort() < 0) {
+            CommandLine.usage(cla, System.err);
             return;
         }
         if (cla.getConfigLocation() != null) {
@@ -124,7 +125,7 @@
 
     /**
      * Constructor.
-     * 
+     *
      * @param port
      *            to listen on.
      * @param logEventInput
diff --git a/log4j-server/src/main/java/org/apache/logging/log4j/server/mom/jms/AbstractJmsReceiver.java b/log4j-server/src/main/java/org/apache/logging/log4j/server/mom/jms/AbstractJmsReceiver.java
index 9103d69..a85d2f6 100644
--- a/log4j-server/src/main/java/org/apache/logging/log4j/server/mom/jms/AbstractJmsReceiver.java
+++ b/log4j-server/src/main/java/org/apache/logging/log4j/server/mom/jms/AbstractJmsReceiver.java
@@ -39,7 +39,7 @@
 
     /**
      * Executes a JmsServer with the given command line arguments.
-     * 
+     *
      * @param interactive
      *            Whether or not this is an interactive application by providing a command line and exit on error.
      * @param args
@@ -48,7 +48,7 @@
      * @throws Exception
      */
     protected void doMain(boolean interactive, final String... args) throws Exception {
-        // TODO Too many args, Use JCommander
+        // TODO Too many args, Use picocli
         if (args.length < 5) {
             usage();
             if (interactive) {
diff --git a/pom.xml b/pom.xml
index d28a3c0..ca95638 100644
--- a/pom.xml
+++ b/pom.xml
@@ -217,11 +217,6 @@
   <dependencyManagement>
     <dependencies>
       <dependency>
-        <groupId>com.beust</groupId>
-        <artifactId>jcommander</artifactId>
-        <version>1.48</version>
-      </dependency>
-      <dependency>
         <groupId>org.apache.logging.log4j</groupId>
         <artifactId>log4j-api</artifactId>
         <version>${project.version}</version>
@@ -429,7 +424,7 @@
               <goals>
                 <goal>report</goal>
               </goals>
-            </execution>          
+            </execution>
           </executions>
         </plugin>
       </plugins>