From 8247bdca2fa5bdd832258da13eaa38ab17605436 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 1 Aug 2013 04:17:07 -0400
Subject: [PATCH] Refactored client framework.

A new Client class was added as a base for all client classes. The
SubsystemClient was added as a base for all subsystem clients. It also
provides methods to authenticate against the subsystem. The DRMClient
has been renamed to KRAClient to match the actual subsystem name.

Ticket #701
---
 .../src/com/netscape/cms/servlet/test/CATest.java  |  3 +-
 .../cms/servlet/test/ConfigurationTest.java        |  3 +-
 .../netscape/certsrv/account/AccountClient.java    | 24 +++++----
 .../src/com/netscape/certsrv/ca/CAClient.java      | 17 +++---
 .../src/com/netscape/certsrv/cert/CertClient.java  | 19 ++++---
 .../KRAConnectorClient.java => client/Client.java} | 40 +++++++-------
 .../com/netscape/certsrv/client/ClientConfig.java  |  9 ++++
 .../src/com/netscape/certsrv/client/PKIClient.java | 32 +++++++++--
 .../com/netscape/certsrv/client/PKIConnection.java |  3 +-
 .../netscape/certsrv/client/SubsystemClient.java   | 63 ++++++++++++++++++++++
 .../com/netscape/certsrv/group/GroupClient.java    | 19 ++++---
 .../src/com/netscape/certsrv/key/KeyClient.java    | 19 ++++---
 .../certsrv/kra/{DRMClient.java => KRAClient.java} | 19 +++----
 .../netscape/certsrv/profile/ProfileClient.java    | 18 +++----
 .../certsrv/system/KRAConnectorClient.java         | 17 +++---
 .../certsrv/system/SecurityDomainClient.java       | 17 +++---
 .../certsrv/system/SystemConfigClient.java         | 17 +++---
 .../com/netscape/certsrv/token/TokenClient.java    | 21 ++++----
 .../src/com/netscape/certsrv/tps/TPSClient.java    | 19 +++----
 .../src/com/netscape/certsrv/user/UserClient.java  | 21 ++++----
 .../cmstools/system/SecurityDomainCLI.java         |  2 +-
 .../src/com/netscape/cms/servlet/test/DRMTest.java |  7 +--
 22 files changed, 250 insertions(+), 159 deletions(-)
 copy base/common/src/com/netscape/certsrv/{system/KRAConnectorClient.java => client/Client.java} (54%)
 create mode 100644 base/common/src/com/netscape/certsrv/client/SubsystemClient.java
 rename base/common/src/com/netscape/certsrv/kra/{DRMClient.java => KRAClient.java} (89%)

diff --git a/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java b/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java
index fd0db892a23fbe54c75d364d9af35e022d0b6e85..7e12b8675d8b56480daff55cccd5455b06261cd0 100644
--- a/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java
+++ b/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java
@@ -42,6 +42,7 @@ import com.netscape.certsrv.cert.CertRequestInfos;
 import com.netscape.certsrv.cert.CertReviewResponse;
 import com.netscape.certsrv.cert.CertSearchRequest;
 import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileData;
@@ -155,7 +156,7 @@ public class CATest {
             config.setServerURI(protocol + "://" + host + ":" + port + "/ca");
             config.setCertNickname(clientCertNickname);
 
-            client = new CAClient(config);
+            client = new CAClient(new PKIClient(config));
         } catch (Exception e) {
             e.printStackTrace();
             return;
diff --git a/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java b/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java
index e0110b5c8fd08102571fe06f0cd7c95e4dc90b28..f74ab714d407df94e315a65e59f96914aba6f8ae 100644
--- a/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java
+++ b/base/common/functional/src/com/netscape/cms/servlet/test/ConfigurationTest.java
@@ -57,6 +57,7 @@ import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
 import org.mozilla.jss.util.Password;
 
 import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.system.ConfigurationRequest;
 import com.netscape.certsrv.system.ConfigurationResponse;
 import com.netscape.certsrv.system.SystemCertData;
@@ -189,7 +190,7 @@ public class ConfigurationTest {
             ClientConfig config = new ClientConfig();
             config.setServerURI(protocol + "://" + host + ":" + port + "/" + cstype);
 
-            client = new SystemConfigClient(config);
+            client = new SystemConfigClient(new PKIClient(config));
         } catch (URISyntaxException e1) {
             e1.printStackTrace();
             System.exit(1);
diff --git a/base/common/src/com/netscape/certsrv/account/AccountClient.java b/base/common/src/com/netscape/certsrv/account/AccountClient.java
index 36adcf57a1aa0c6cb2234384e74b3a46850df26a..333f65679ba0eef074aa3614d88c4a53f47dc4f8 100644
--- a/base/common/src/com/netscape/certsrv/account/AccountClient.java
+++ b/base/common/src/com/netscape/certsrv/account/AccountClient.java
@@ -19,35 +19,39 @@ package com.netscape.certsrv.account;
 
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author Endi S. Dewata
  */
-public class AccountClient {
+public class AccountClient extends Client {
 
-    public PKIClient client;
     public AccountResource resource;
-
-    public AccountClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
+    public boolean loggedIn;
 
     public AccountClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public AccountClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "account");
         init();
     }
 
     public void init() throws URISyntaxException {
-        resource = client.createProxy(AccountResource.class);
+        resource = createProxy(AccountResource.class);
     }
 
     public void login() {
         resource.login();
+        loggedIn = true;
     }
 
     public void logout() {
-        resource.logout();
+        if (loggedIn) {
+            resource.logout();
+            loggedIn = false;
+        }
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/ca/CAClient.java b/base/common/src/com/netscape/certsrv/ca/CAClient.java
index 906caada79d4c4f96387619e57185204a47ec9bd..abd54a63b4fa5899c3f9949340ed367cf99055e7 100644
--- a/base/common/src/com/netscape/certsrv/ca/CAClient.java
+++ b/base/common/src/com/netscape/certsrv/ca/CAClient.java
@@ -29,34 +29,29 @@ import com.netscape.certsrv.cert.CertRequestResource;
 import com.netscape.certsrv.cert.CertResource;
 import com.netscape.certsrv.cert.CertReviewResponse;
 import com.netscape.certsrv.cert.CertSearchRequest;
-import com.netscape.certsrv.client.ClientConfig;
 import com.netscape.certsrv.client.PKIClient;
+import com.netscape.certsrv.client.SubsystemClient;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.profile.ProfileData;
 import com.netscape.certsrv.profile.ProfileDataInfos;
 import com.netscape.certsrv.profile.ProfileResource;
 import com.netscape.certsrv.request.RequestId;
 
-public class CAClient {
+public class CAClient extends SubsystemClient {
 
-    private PKIClient client;
     private CertResource certClient;
     private CertRequestResource certRequestClient;
     private ProfileResource profileClient;
 
-    public CAClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public CAClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        super(client, "ca");
         init();
     }
 
     public void init() throws URISyntaxException {
-        certRequestClient = client.createProxy(CertRequestResource.class);
-        certClient = client.createProxy(CertResource.class);
-        profileClient = client.createProxy(ProfileResource.class);
+        certRequestClient = createProxy(CertRequestResource.class);
+        certClient = createProxy(CertResource.class);
+        profileClient = createProxy(ProfileResource.class);
     }
 
     public Collection<CertRequestInfo> listRequests(String requestState, String requestType) {
diff --git a/base/common/src/com/netscape/certsrv/cert/CertClient.java b/base/common/src/com/netscape/certsrv/cert/CertClient.java
index 42c78eb2c09400ec3edad8a41b1ab3037741219c..7bd75caea2b8cf3fbc2b5072af1b59967e7daa2f 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertClient.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertClient.java
@@ -19,7 +19,7 @@ package com.netscape.certsrv.cert;
 
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.request.RequestId;
@@ -27,24 +27,23 @@ import com.netscape.certsrv.request.RequestId;
 /**
  * @author Endi S. Dewata
  */
-public class CertClient {
+public class CertClient extends Client {
 
-    public PKIClient client;
     public CertResource certClient;
     public CertRequestResource certRequestResource;
 
-    public CertClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public CertClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public CertClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "cert");
         init();
     }
 
     public void init() throws URISyntaxException {
-        certClient = client.createProxy(CertResource.class);
-        certRequestResource = client.createProxy(CertRequestResource.class);
+        certClient = createProxy(CertResource.class);
+        certRequestResource = createProxy(CertRequestResource.class);
     }
 
     public CertData getCert(CertId id) {
diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java b/base/common/src/com/netscape/certsrv/client/Client.java
similarity index 54%
copy from base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
copy to base/common/src/com/netscape/certsrv/client/Client.java
index ea71cf645010e1449c26f4f57913ea6bf763a825..f47717d3f6172572e13eb0f0b627b5c0063db60b 100644
--- a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
+++ b/base/common/src/com/netscape/certsrv/client/Client.java
@@ -15,40 +15,44 @@
 // (C) 2013 Red Hat, Inc.
 // All rights reserved.
 // --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.client;
 
-package com.netscape.certsrv.system;
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
-import com.netscape.certsrv.client.PKIClient;
-
 /**
- * @author Ade Lee
+ * @author Endi S. Dewata
  */
-public class KRAConnectorClient {
+public class Client {
 
+    // server connection
     public PKIClient client;
-    public KRAConnectorResource kraConnectorClient;
 
-    public KRAConnectorClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
+    // subsystem name
+    public String subsystem;
+
+    // client name
+    public String name;
+
+    public Client(PKIClient client, String name) {
+        // by default use the subsystem specified in server URI
+        this(client, client.getSubsystem(), name);
     }
 
-    public KRAConnectorClient(PKIClient client) throws URISyntaxException {
+    public Client(PKIClient client, String subsystem, String name) {
         this.client = client;
-        init();
+        this.subsystem = subsystem;
+        this.name = name;
     }
 
-    public void init() throws URISyntaxException {
-        kraConnectorClient = client.createProxy(KRAConnectorResource.class);
+    public String getSubsystem() {
+        return subsystem;
     }
 
-    public void addConnector(KRAConnectorInfo info) {
-        kraConnectorClient.addConnector(info);
+    public String getName() {
+        return name;
     }
 
-    public void removeConnector(String host, String port) {
-        kraConnectorClient.removeConnector(host, port);
+    public <T> T createProxy(Class<T> clazz) throws URISyntaxException {
+        return client.createProxy(subsystem, clazz);
     }
-
 }
diff --git a/base/common/src/com/netscape/certsrv/client/ClientConfig.java b/base/common/src/com/netscape/certsrv/client/ClientConfig.java
index 6be7abae27d360860e7023a36e33c08d56dd8b0f..c85db52d3b0ea8dd13d451e56b7c45d38b855126 100644
--- a/base/common/src/com/netscape/certsrv/client/ClientConfig.java
+++ b/base/common/src/com/netscape/certsrv/client/ClientConfig.java
@@ -69,6 +69,15 @@ public class ClientConfig {
         this.serverURI = serverUri;
     }
 
+    public String getSubsystem() {
+        // path could be an empty string, "/", or "/<subsystem>"
+        String path = serverURI.getPath();
+        if (path.length() <= 1) return null;
+
+        // return subsystem name
+        return path.substring(1);
+    }
+
     @XmlElement(name="CertDatabase")
     public String getCertDatabase() {
         return certDatabase;
diff --git a/base/common/src/com/netscape/certsrv/client/PKIClient.java b/base/common/src/com/netscape/certsrv/client/PKIClient.java
index 3b316ceb3355cd6d653143b29ef78f4d16d1f6ef..3bfc8080bacb675837c00fbd96f8fa02283b1fbc 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIClient.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIClient.java
@@ -2,6 +2,7 @@ package com.netscape.certsrv.client;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.cert.CertificateEncodingException;
@@ -27,6 +28,7 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
+import com.netscape.certsrv.base.PKIException;
 import com.netscape.cmsutil.util.Utils;
 
 
@@ -35,7 +37,7 @@ public class PKIClient {
     public ClientConfig config;
     public PKIConnection connection;
 
-    File certDatabase;
+    public File certDatabase;
 
     public boolean verbose;
 
@@ -45,8 +47,32 @@ public class PKIClient {
         connection = new PKIConnection(this);
     }
 
-    public <T> T createProxy(Class<T> clazz) throws URISyntaxException {
-        return connection.createProxy(clazz);
+    public <T> T createProxy(String subsystem, Class<T> clazz) throws URISyntaxException {
+
+        if (subsystem == null) {
+            // by default use the subsystem specified in server URI
+            subsystem = getSubsystem();
+        }
+
+        if (subsystem == null) {
+            throw new PKIException("Missing subsystem name.");
+        }
+
+        URI serverURI = config.getServerURI();
+        URI resourceURI = new URI(
+            serverURI.getScheme(),
+            serverURI.getUserInfo(),
+            serverURI.getHost(),
+            serverURI.getPort(),
+            "/" + subsystem + "/rest",
+            serverURI.getQuery(),
+            serverURI.getFragment());
+
+        return connection.createProxy(resourceURI, clazz);
+    }
+
+    public String getSubsystem() {
+        return config.getSubsystem();
     }
 
     public <T> T getEntity(ClientResponse<T> response) {
diff --git a/base/common/src/com/netscape/certsrv/client/PKIConnection.java b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
index 397e7ca91f288a3ad01edb97d532da9b2c597739..d057deba0c674e98de0a99b12addf64eaf117f74 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIConnection.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
@@ -509,8 +509,7 @@ public class PKIConnection {
 
     }
 
-    public <T> T createProxy(Class<T> clazz) throws URISyntaxException {
-        URI uri = new URI(config.getServerURI()+"/rest");
+    public <T> T createProxy(URI uri, Class<T> clazz) throws URISyntaxException {
         return ProxyFactory.create(clazz, uri, executor, providerFactory);
     }
 
diff --git a/base/common/src/com/netscape/certsrv/client/SubsystemClient.java b/base/common/src/com/netscape/certsrv/client/SubsystemClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..7acdcce38ff134a52a836bc9b6ff225018545530
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/client/SubsystemClient.java
@@ -0,0 +1,63 @@
+// --- 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) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.client;
+
+import java.net.URISyntaxException;
+import java.util.LinkedHashMap;
+
+import com.netscape.certsrv.account.AccountClient;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SubsystemClient extends Client {
+
+    public AccountClient accountClient;
+
+    public LinkedHashMap<String, Client> clients = new LinkedHashMap<String, Client>();
+
+    public SubsystemClient(PKIClient client, String name) throws URISyntaxException {
+        // subsystem name should match the client name
+        super(client, name, name);
+
+        accountClient = new AccountClient(client, name);
+    }
+
+    public void addClient(Client client) {
+        clients.put(client.getName(), client);
+    }
+
+    public Client getClient(String name) {
+        return clients.get(name);
+    }
+
+    /**
+     * Log in to the subsystem.
+     */
+    public void login() {
+        accountClient.login();
+    }
+
+    /**
+     * Log out from the subsystem.
+     */
+    public void logout() {
+        accountClient.logout();
+    }
+}
diff --git a/base/common/src/com/netscape/certsrv/group/GroupClient.java b/base/common/src/com/netscape/certsrv/group/GroupClient.java
index ac666fae693e6d75bd73f39bcc4dbcc8b563f290..33be6e7727766c7e7b5c47cddaec39aae525e7b0 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupClient.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupClient.java
@@ -21,30 +21,29 @@ import java.net.URISyntaxException;
 
 import org.jboss.resteasy.client.ClientResponse;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author Endi S. Dewata
  */
-public class GroupClient {
+public class GroupClient extends Client {
 
-    public PKIClient client;
     public GroupResource groupClient;
     public GroupMemberResource groupMemberClient;
 
-    public GroupClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public GroupClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public GroupClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "group");
         init();
     }
 
     public void init() throws URISyntaxException {
-        groupClient = client.createProxy(GroupResource.class);
-        groupMemberClient = client.createProxy(GroupMemberResource.class);
+        groupClient = createProxy(GroupResource.class);
+        groupMemberClient = createProxy(GroupMemberResource.class);
     }
 
     public GroupCollection findGroups(String groupIDFilter, Integer start, Integer size) {
diff --git a/base/common/src/com/netscape/certsrv/key/KeyClient.java b/base/common/src/com/netscape/certsrv/key/KeyClient.java
index 7deef0472eee728618f036cbf008924fce8f7604..be4e5ed587ae02f8deb33e64ae7a4aa354a440bc 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyClient.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyClient.java
@@ -19,31 +19,30 @@ package com.netscape.certsrv.key;
 
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.request.RequestId;
 
 /**
  * @author Endi S. Dewata
  */
-public class KeyClient {
+public class KeyClient extends Client {
 
-    public PKIClient client;
     public KeyResource keyClient;
     public KeyRequestResource keyRequestClient;
 
-    public KeyClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public KeyClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public KeyClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "key");
         init();
     }
 
     public void init() throws URISyntaxException {
-        keyClient = client.createProxy(KeyResource.class);
-        keyRequestClient = client.createProxy(KeyRequestResource.class);
+        keyClient = createProxy(KeyResource.class);
+        keyRequestClient = createProxy(KeyRequestResource.class);
     }
 
     public KeyDataInfos findKeys(String clientID, String status, Integer maxSize, Integer maxTime) {
diff --git a/base/common/src/com/netscape/certsrv/kra/DRMClient.java b/base/common/src/com/netscape/certsrv/kra/KRAClient.java
similarity index 89%
rename from base/common/src/com/netscape/certsrv/kra/DRMClient.java
rename to base/common/src/com/netscape/certsrv/kra/KRAClient.java
index 75e85a2aee57cbed9f5db548b9136cafc177cc4a..ae91d18537dec8d3e5be7bb12992acf6f3f0fb10 100644
--- a/base/common/src/com/netscape/certsrv/kra/DRMClient.java
+++ b/base/common/src/com/netscape/certsrv/kra/KRAClient.java
@@ -7,8 +7,8 @@ import java.util.Iterator;
 import org.jboss.resteasy.client.ClientResponse;
 
 import com.netscape.certsrv.cert.CertData;
-import com.netscape.certsrv.client.ClientConfig;
 import com.netscape.certsrv.client.PKIClient;
+import com.netscape.certsrv.client.SubsystemClient;
 import com.netscape.certsrv.dbs.keydb.KeyId;
 import com.netscape.certsrv.key.KeyArchivalRequest;
 import com.netscape.certsrv.key.KeyData;
@@ -23,26 +23,21 @@ import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.system.SystemCertResource;
 import com.netscape.cmsutil.util.Utils;
 
-public class DRMClient {
+public class KRAClient extends SubsystemClient {
 
-    private PKIClient client;
     private KeyResource keyClient;
     private KeyRequestResource keyRequestClient;
     private SystemCertResource systemCertClient;
 
-    public DRMClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
-    public DRMClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+    public KRAClient(PKIClient client) throws URISyntaxException {
+        super(client, "kra");
         init();
     }
 
     public void init() throws URISyntaxException {
-        systemCertClient = client.createProxy(SystemCertResource.class);
-        keyRequestClient = client.createProxy(KeyRequestResource.class);
-        keyClient = client.createProxy(KeyResource.class);
+        systemCertClient = createProxy(SystemCertResource.class);
+        keyRequestClient = createProxy(KeyRequestResource.class);
+        keyClient = createProxy(KeyResource.class);
     }
 
     public String getTransportCert() {
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileClient.java b/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
index 12b54cc60a1954ed8d88cf1b5399dd8e16a56e57..c4ecf6bec170f61146ecbb4ba6726f54d46a5fdb 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
@@ -19,27 +19,27 @@ package com.netscape.certsrv.profile;
 
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author Ade Lee
  */
-public class ProfileClient {
-    public PKIClient client;
+public class ProfileClient extends Client {
+
     public ProfileResource profileClient;
 
-    public ProfileClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public ProfileClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public ProfileClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "profile");
         init();
     }
 
     public void init() throws URISyntaxException {
-        profileClient = client.createProxy(ProfileResource.class);
+        profileClient = createProxy(ProfileResource.class);
     }
 
     public ProfileData retrieveProfile(String id) {
diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
index ea71cf645010e1449c26f4f57913ea6bf763a825..514390eaec7970045ef20668adf23ad7ea91b37e 100644
--- a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
+++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java
@@ -19,28 +19,27 @@
 package com.netscape.certsrv.system;
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author Ade Lee
  */
-public class KRAConnectorClient {
+public class KRAConnectorClient extends Client {
 
-    public PKIClient client;
     public KRAConnectorResource kraConnectorClient;
 
-    public KRAConnectorClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public KRAConnectorClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public KRAConnectorClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "kraconnector");
         init();
     }
 
     public void init() throws URISyntaxException {
-        kraConnectorClient = client.createProxy(KRAConnectorResource.class);
+        kraConnectorClient = createProxy(KRAConnectorResource.class);
     }
 
     public void addConnector(KRAConnectorInfo info) {
diff --git a/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
index 490f837dabe2dc6fdf3c6a57c01955aabd33c002..3eb21cfce421a0a59c2d5aca4c444c87216841d0 100644
--- a/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
@@ -19,29 +19,28 @@ package com.netscape.certsrv.system;
 
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 
 /**
  * @author alee
  */
-public class SecurityDomainClient {
+public class SecurityDomainClient extends Client {
 
-    private PKIClient client;
     private SecurityDomainResource securityDomainClient;
 
-    public SecurityDomainClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public SecurityDomainClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public SecurityDomainClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "securitydomain");
         init();
     }
 
     public void init() throws URISyntaxException {
-        securityDomainClient = client.createProxy(SecurityDomainResource.class);
+        securityDomainClient = createProxy(SecurityDomainResource.class);
     }
 
     public InstallToken getInstallToken(String hostname, String subsystem) {
diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java b/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
index aa4e6842e53a3a96e845354a8b799a10175d9f0a..07d728896827ebfc76aae93207ff0047c8603007 100644
--- a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
@@ -19,7 +19,7 @@ package com.netscape.certsrv.system;
 
 import java.net.URISyntaxException;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 
@@ -27,22 +27,21 @@ import com.netscape.certsrv.client.PKIClient;
  * @author alee
  *
  */
-public class SystemConfigClient {
+public class SystemConfigClient extends Client {
 
-    private PKIClient client;
     private SystemConfigResource configClient;
 
-    public SystemConfigClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public SystemConfigClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public SystemConfigClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "systemconfig");
         init();
     }
 
     public void init() throws URISyntaxException {
-        configClient = client.createProxy(SystemConfigResource.class);
+        configClient = createProxy(SystemConfigResource.class);
     }
 
     public ConfigurationResponse configure(ConfigurationRequest data) {
diff --git a/base/common/src/com/netscape/certsrv/token/TokenClient.java b/base/common/src/com/netscape/certsrv/token/TokenClient.java
index d14fb9e2e4cad86c194b1c406ed892fba0e4d843..d6fbd4e1f7081e5d03e9aacf5ddc88222ea361a5 100644
--- a/base/common/src/com/netscape/certsrv/token/TokenClient.java
+++ b/base/common/src/com/netscape/certsrv/token/TokenClient.java
@@ -21,24 +21,27 @@ import java.net.URISyntaxException;
 
 import org.jboss.resteasy.client.ClientResponse;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author Endi S. Dewata
  */
-public class TokenClient {
+public class TokenClient extends Client {
 
-    public PKIClient client;
     public TokenResource resource;
 
-    public TokenClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public TokenClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
-        resource = client.createProxy(TokenResource.class);
+        this(client, client.getSubsystem());
+    }
+
+    public TokenClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "token");
+        init();
+    }
+
+    public void init() throws URISyntaxException {
+        resource = createProxy(TokenResource.class);
     }
 
     public TokenCollection findTokens(Integer start, Integer size) {
diff --git a/base/common/src/com/netscape/certsrv/tps/TPSClient.java b/base/common/src/com/netscape/certsrv/tps/TPSClient.java
index 2ab50ac1b20721e05d7b8adeaa0e744167511251..7b35ab208b4bd99eb5eff67ca3c87a1c4512449b 100644
--- a/base/common/src/com/netscape/certsrv/tps/TPSClient.java
+++ b/base/common/src/com/netscape/certsrv/tps/TPSClient.java
@@ -17,26 +17,23 @@
 //--- END COPYRIGHT BLOCK ---
 package com.netscape.certsrv.tps;
 
-import com.netscape.certsrv.client.ClientConfig;
+import java.net.URISyntaxException;
+
 import com.netscape.certsrv.client.PKIClient;
+import com.netscape.certsrv.client.SubsystemClient;
 import com.netscape.certsrv.token.TokenClient;
 
 /**
  * @author Endi S. Dewata
  */
-public class TPSClient {
-
-    public TokenClient tokenClient;
-
-    public TPSClient(ClientConfig config) throws Exception {
-        this(new PKIClient(config));
-    }
+public class TPSClient extends SubsystemClient {
 
     public TPSClient(PKIClient client) throws Exception {
-        tokenClient = new TokenClient(client);
+        super(client, "tps");
+        init();
     }
 
-    public TokenClient getTokenClient() {
-        return tokenClient;
+    public void init() throws URISyntaxException {
+        addClient(new TokenClient(client, name));
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/user/UserClient.java b/base/common/src/com/netscape/certsrv/user/UserClient.java
index 5f1ebd5b8a1935d61af3229f58720ffddc26946f..0c51821fe855eee2299e3545a6585e9be5250443 100644
--- a/base/common/src/com/netscape/certsrv/user/UserClient.java
+++ b/base/common/src/com/netscape/certsrv/user/UserClient.java
@@ -21,32 +21,31 @@ import java.net.URISyntaxException;
 
 import org.jboss.resteasy.client.ClientResponse;
 
-import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author Endi S. Dewata
  */
-public class UserClient {
+public class UserClient extends Client {
 
-    public PKIClient client;
     public UserResource userClient;
     public UserCertResource userCertClient;
     public UserMembershipResource userMembershipClient;
 
-    public UserClient(ClientConfig config) throws URISyntaxException {
-        this(new PKIClient(config));
-    }
-
     public UserClient(PKIClient client) throws URISyntaxException {
-        this.client = client;
+        this(client, client.getSubsystem());
+    }
+
+    public UserClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "user");
         init();
     }
 
     public void init() throws URISyntaxException {
-        userClient = client.createProxy(UserResource.class);
-        userCertClient = client.createProxy(UserCertResource.class);
-        userMembershipClient = client.createProxy(UserMembershipResource.class);
+        userClient = createProxy(UserResource.class);
+        userCertClient = createProxy(UserCertResource.class);
+        userMembershipClient = createProxy(UserMembershipResource.class);
     }
 
     public UserCollection findUsers(String filter, Integer start, Integer size) {
diff --git a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
index ed107f831f9f1b52f9049f797bee38e0455220ce..fc23a5257a389f256060d7a610c10c2b9c98ac53 100644
--- a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
@@ -68,7 +68,7 @@ public class SecurityDomainCLI extends CLI {
 
     public void execute(String[] args) throws Exception {
 
-        client = new SecurityDomainClient(parent.config);
+        client = new SecurityDomainClient(parent.client);
 
         if (args.length == 0) {
             printHelp();
diff --git a/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java b/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
index ec277e5dc144ea6ac705a2d68312656b06c42c4f..8b254a5e354686f47f4e2bcfa9866fdfb5768fc0 100644
--- a/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
+++ b/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
@@ -38,12 +38,13 @@ import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.util.Password;
 
 import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.dbs.keydb.KeyId;
 import com.netscape.certsrv.key.KeyData;
 import com.netscape.certsrv.key.KeyDataInfo;
 import com.netscape.certsrv.key.KeyRequestInfo;
 import com.netscape.certsrv.key.KeyRequestResource;
-import com.netscape.certsrv.kra.DRMClient;
+import com.netscape.certsrv.kra.KRAClient;
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.request.RequestNotFoundException;
 import com.netscape.cms.servlet.base.PKIService;
@@ -195,13 +196,13 @@ public class DRMTest {
         // Set base URI and get client
 
 
-        DRMClient client;
+        KRAClient client;
         try {
             ClientConfig config = new ClientConfig();
             config.setServerURI(protocol + "://" + host + ":" + port + "/kra");
             config.setCertNickname(clientCertNickname);
 
-            client = new DRMClient(config);
+            client = new KRAClient(new PKIClient(config));
 
         } catch (Exception e) {
             e.printStackTrace();
-- 
1.8.1.4

