From 9fdc29fc2912f3afce6a2661d0f08fe9bc059e5d Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Mon, 16 Jul 2012 20:28:27 -0500
Subject: [PATCH] Added CLI to manage client configuration.

New connect, disconnect, and status commands have been added to
manage client configuration. This way it is no longer necessary
to repeat the connection parameters on a sequence of commands
that connect to the same server. For example:

  pki connect -u <username> -w <password>
  pki user-find
  pki user-del testuser
  pki disconnect

The connect command stores the connection parameters into
$HOME/.pki/client.xml. Subsequent commands will read the
connection parameters from this file to connect to the server.
The disconnect command will remove the file. The status command
can be used to view the connection status.

Ticket #107
---
 .../com/netscape/cms/client/cli/ConnectCLI.java    | 70 +++++++++++++++++++++
 .../com/netscape/cms/client/cli/DisconnectCLI.java | 54 ++++++++++++++++
 .../src/com/netscape/cms/client/cli/MainCLI.java   | 73 ++++++++++++++++++++--
 .../src/com/netscape/cms/client/cli/StatusCLI.java | 58 +++++++++++++++++
 4 files changed, 250 insertions(+), 5 deletions(-)
 create mode 100644 base/common/src/com/netscape/cms/client/cli/ConnectCLI.java
 create mode 100644 base/common/src/com/netscape/cms/client/cli/DisconnectCLI.java
 create mode 100644 base/common/src/com/netscape/cms/client/cli/StatusCLI.java

diff --git a/base/common/src/com/netscape/cms/client/cli/ConnectCLI.java b/base/common/src/com/netscape/cms/client/cli/ConnectCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..085ba40b3104f4c560749f5f1dc2d30ade778abb
--- /dev/null
+++ b/base/common/src/com/netscape/cms/client/cli/ConnectCLI.java
@@ -0,0 +1,70 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.client.cli;
+
+import org.apache.commons.cli.CommandLine;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ConnectCLI extends CLI {
+
+    public MainCLI parent;
+
+    public ConnectCLI(MainCLI parent) throws Exception {
+        super("connect", "Connect to server");
+        this.parent = parent;
+
+        parent.createOptions(options);
+    }
+
+    public void printHelp() {
+        formatter.printHelp(name, options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(1);
+        }
+
+        parent.config = new ClientConfig();
+        parent.parseOptions(cmd);
+        parent.saveConfig();
+
+        MainCLI.printMessage("Connected to \"" + parent.config.getServerURI() + "\"");
+
+        if (parent.config.getCertDatabase() != null)
+            System.out.println("  Certificate database: "+parent.config.getCertDatabase());
+
+        if (parent.config.getCertNickname() != null)
+            System.out.println("  Certificate nickname: "+parent.config.getCertNickname());
+
+        if (parent.config.getUsername() != null)
+            System.out.println("  Username: "+parent.config.getUsername());
+    }
+}
diff --git a/base/common/src/com/netscape/cms/client/cli/DisconnectCLI.java b/base/common/src/com/netscape/cms/client/cli/DisconnectCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f9de2d831f1262e47b7bbb05c0127907977b5fa
--- /dev/null
+++ b/base/common/src/com/netscape/cms/client/cli/DisconnectCLI.java
@@ -0,0 +1,54 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.client.cli;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class DisconnectCLI extends CLI {
+
+    public MainCLI parent;
+
+    public DisconnectCLI(MainCLI parent) throws Exception {
+        super("disconnect", "Disconnect from server");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(name, options);
+    }
+
+    public void printHelpCommand(String pluginName) {
+        CLI plugin = getModule(pluginName);
+        plugin.printHelp();
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        if (parent.isConnected()) {
+
+            parent.removeConfig();
+
+            MainCLI.printMessage("Disconnected from \"" + parent.config.getServerURI() + "\"");
+
+        } else {
+            MainCLI.printMessage("Not connected");
+        }
+    }
+}
diff --git a/base/common/src/com/netscape/cms/client/cli/MainCLI.java b/base/common/src/com/netscape/cms/client/cli/MainCLI.java
index 50c90d8928c3bb95fb45389e286ad1427a8ca955..4b40a03390cf5599c44392784adfab5e3c7561f0 100644
--- a/base/common/src/com/netscape/cms/client/cli/MainCLI.java
+++ b/base/common/src/com/netscape/cms/client/cli/MainCLI.java
@@ -18,7 +18,12 @@
 
 package com.netscape.cms.client.cli;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.net.URI;
 import java.net.URISyntaxException;
 
 import org.apache.commons.cli.CommandLine;
@@ -39,11 +44,22 @@ import com.netscape.cms.client.user.UserCLI;
  */
 public class MainCLI extends CLI {
 
+    public File pkiDir;
+    public File clientXml;
+
     public ClientConfig config = new ClientConfig();
 
     public MainCLI() throws Exception {
         super("pki", "PKI command-line interface");
 
+        File userHome = new File(System.getProperty("user.home"));
+        pkiDir = new File(userHome, ".pki");
+        clientXml = new File(pkiDir, "client.xml");
+
+        addModule(new ConnectCLI(this));
+        addModule(new DisconnectCLI(this));
+        addModule(new StatusCLI(this));
+
         addModule(new CertCLI(this));
         addModule(new GroupCLI(this));
         addModule(new UserCLI(this));
@@ -121,6 +137,8 @@ public class MainCLI extends CLI {
 
     public void parseOptions(CommandLine cmd) throws URISyntaxException {
 
+        URI serverURI = config.getServerURI();
+
         String uri = cmd.getOptionValue("U");
 
         String protocol = cmd.getOptionValue("P", "http");
@@ -128,10 +146,18 @@ public class MainCLI extends CLI {
         String port = cmd.getOptionValue("p", "8080");
         String type = cmd.getOptionValue("t", "ca");
 
-        if (uri == null)
-            uri = protocol + "://" + hostname + ":" + port + "/" + type;
+        // If no server URI is stored in config, or if any of the U/P/h/p/t options are specified,
+        // store the new server URI into config.
+        if (serverURI == null ||
+                cmd.hasOption("U") ||
+                cmd.hasOption("P") || cmd.hasOption("h") || cmd.hasOption("p") || cmd.hasOption("t")) {
 
-        config.setServerURI(uri);
+            if (uri == null) {
+                uri = protocol + "://" + hostname + ":" + port + "/" + type;
+            }
+
+            config.setServerURI(uri);
+        }
 
         String certDatabase = cmd.getOptionValue("d");
         String certNickname = cmd.getOptionValue("n");
@@ -142,16 +168,50 @@ public class MainCLI extends CLI {
         if (certDatabase != null)
             config.setCertDatabase(new File(certDatabase).getAbsolutePath());
 
-        if (certNickname != null)
+        if (certNickname != null) { // client cert auth
             config.setCertNickname(certNickname);
+            config.setUsername(null);
 
-        if (username != null)
+        } else if (username != null) { // basic auth
+            config.setCertNickname(null);
             config.setUsername(username);
+        }
 
         if (password != null)
             config.setPassword(password);
     }
 
+    public void saveConfig() throws Exception {
+
+        if (verbose) System.out.println("Saving config file: "+clientXml);
+
+        if (pkiDir.exists()) pkiDir.mkdirs();
+
+        PrintWriter out = new PrintWriter(new FileWriter(clientXml));
+        out.print(config);
+        out.close();
+    }
+
+    public boolean isConnected() {
+        return clientXml.exists();
+    }
+
+    public void loadConfig() throws Exception {
+
+        if (verbose) System.out.println("Loading config file: "+clientXml);
+
+        BufferedReader in = new BufferedReader(new FileReader(clientXml));
+        StringBuilder sb = new StringBuilder();
+        String line;
+        while ((line = in.readLine()) != null) sb.append(line);
+
+        config = ClientConfig.valueOf(sb.toString());
+    }
+
+    public void removeConfig() throws Exception {
+        clientXml.delete();
+    }
+
     public void execute(String[] args) throws Exception {
 
         CLI module;
@@ -185,6 +245,9 @@ public class MainCLI extends CLI {
                 System.out.println();
             }
 
+            if (isConnected())
+                loadConfig();
+
             parseOptions(cmd);
 
             String command = cmdArgs[0];
diff --git a/base/common/src/com/netscape/cms/client/cli/StatusCLI.java b/base/common/src/com/netscape/cms/client/cli/StatusCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d8a841d0f0bdf40b92876ebb50775aa2dedcc34
--- /dev/null
+++ b/base/common/src/com/netscape/cms/client/cli/StatusCLI.java
@@ -0,0 +1,58 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.client.cli;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class StatusCLI extends CLI {
+
+    public MainCLI parent;
+
+    public StatusCLI(MainCLI parent) throws Exception {
+        super("status", "Connection status");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(name, options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        if (parent.isConnected()) {
+
+            parent.loadConfig();
+
+            MainCLI.printMessage("Connected to \"" + parent.config.getServerURI() + "\"");
+
+            if (parent.config.getCertDatabase() != null)
+                System.out.println("  Certificate database: "+parent.config.getCertDatabase());
+
+            if (parent.config.getCertNickname() != null)
+                System.out.println("  Certificate nickname: "+parent.config.getCertNickname());
+
+            if (parent.config.getUsername() != null)
+                System.out.println("  Username: "+parent.config.getUsername());
+
+        } else {
+            MainCLI.printMessage("Not connected");
+        }
+    }
+}
-- 
1.7.11.2

