From a8ccbaa34dd18a4447dbc5fd871cb456fc25fd53 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 1 Oct 2013 12:36:55 -0400
Subject: [PATCH] Added selftest resource.

New REST service and clients have been added for managing selftests
in all subsystems.

Ticket #652
---
 .../ca/CertificateAuthorityApplication.java        |   4 +
 .../src/com/netscape/certsrv/ca/CAClient.java      |   2 +
 .../src/com/netscape/certsrv/kra/KRAClient.java    |   2 +
 .../src/com/netscape/certsrv/ocsp/OCSPClient.java  |   2 +
 .../SelfTestClient.java}                           |  34 ++--
 .../certsrv/selftests/SelfTestCollection.java}     |  42 ++---
 .../netscape/certsrv/selftests/SelfTestData.java   | 189 +++++++++++++++++++++
 .../certsrv/selftests/SelfTestResource.java        |  49 ++++++
 .../src/com/netscape/certsrv/tks/TKSClient.java    |   4 +-
 .../src/com/netscape/certsrv/tps/TPSClient.java    |   2 +
 .../cmscore/selftests/SelfTestService.java         | 137 +++++++++++++++
 .../src/com/netscape/cmstools/cli/CACLI.java       |   2 +
 .../src/com/netscape/cmstools/cli/KRACLI.java      |   2 +
 .../src/com/netscape/cmstools/cli/OCSPCLI.java     |   2 +
 .../src/com/netscape/cmstools/cli/TKSCLI.java      |   2 +
 .../src/com/netscape/cmstools/cli/TPSCLI.java      |   2 +
 .../netscape/cmstools/selftests/SelfTestCLI.java   |  63 +++++++
 .../cmstools/selftests/SelfTestFindCLI.java        |  94 ++++++++++
 .../cmstools/selftests/SelfTestRunCLI.java         |  66 +++++++
 .../cmstools/selftests/SelfTestShowCLI.java        |  87 ++++++++++
 .../kra/KeyRecoveryAuthorityApplication.java       |   4 +
 .../src/com/netscape/ocsp/OCSPApplication.java     |   4 +
 base/tks/src/com/netscape/tks/TKSApplication.java  |   4 +
 .../org/dogtagpki/server/tps/TPSApplication.java   |   4 +
 24 files changed, 761 insertions(+), 42 deletions(-)
 copy base/common/src/com/netscape/certsrv/{tks/TKSClient.java => selftests/SelfTestClient.java} (55%)
 copy base/{java-tools/src/com/netscape/cmstools/cli/CACLI.java => common/src/com/netscape/certsrv/selftests/SelfTestCollection.java} (51%)
 create mode 100644 base/common/src/com/netscape/certsrv/selftests/SelfTestData.java
 create mode 100644 base/common/src/com/netscape/certsrv/selftests/SelfTestResource.java
 create mode 100644 base/common/src/com/netscape/cmscore/selftests/SelfTestService.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/selftests/SelfTestCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/selftests/SelfTestRunCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/selftests/SelfTestShowCLI.java

diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
index 1b96f3121ce3fee1b1ce3b6ed921ba3fd9e3dab3..e12da7fb796196d8d410e8615b91a1b1ff8d7c3d 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
@@ -24,6 +24,7 @@ import com.netscape.cms.servlet.csadmin.SecurityDomainService;
 import com.netscape.cms.servlet.csadmin.SystemConfigService;
 import com.netscape.cms.servlet.profile.ProfileService;
 import com.netscape.cms.servlet.request.CertRequestService;
+import com.netscape.cmscore.selftests.SelfTestService;
 
 public class CertificateAuthorityApplication extends Application {
     private Set<Object> singletons = new HashSet<Object>();
@@ -44,6 +45,9 @@ public class CertificateAuthorityApplication extends Application {
         // profile management
         classes.add(ProfileService.class);
 
+        // selftests
+        classes.add(SelfTestService.class);
+
         // user and group management
         classes.add(GroupMemberService.class);
         classes.add(GroupService.class);
diff --git a/base/common/src/com/netscape/certsrv/ca/CAClient.java b/base/common/src/com/netscape/certsrv/ca/CAClient.java
index a58d0236d6cab5823eed73d658e1326ba26ceab0..e0bc6c9b3159f030d169933cf5bf5e6ecd2a4142 100644
--- a/base/common/src/com/netscape/certsrv/ca/CAClient.java
+++ b/base/common/src/com/netscape/certsrv/ca/CAClient.java
@@ -37,6 +37,7 @@ import com.netscape.certsrv.profile.ProfileData;
 import com.netscape.certsrv.profile.ProfileDataInfos;
 import com.netscape.certsrv.profile.ProfileResource;
 import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.selftests.SelfTestClient;
 import com.netscape.certsrv.user.UserClient;
 
 public class CAClient extends SubsystemClient {
@@ -53,6 +54,7 @@ public class CAClient extends SubsystemClient {
     public void init() throws URISyntaxException {
 
         addClient(new GroupClient(client, name));
+        addClient(new SelfTestClient(client, name));
         addClient(new UserClient(client, name));
 
         certRequestClient = createProxy(CertRequestResource.class);
diff --git a/base/common/src/com/netscape/certsrv/kra/KRAClient.java b/base/common/src/com/netscape/certsrv/kra/KRAClient.java
index 3bebb150e1991afd09c0aae9396c1accf0e50213..28991caf6249f445151caa7b90bfc2684a9d84f5 100644
--- a/base/common/src/com/netscape/certsrv/kra/KRAClient.java
+++ b/base/common/src/com/netscape/certsrv/kra/KRAClient.java
@@ -21,6 +21,7 @@ import com.netscape.certsrv.key.KeyRequestInfos;
 import com.netscape.certsrv.key.KeyRequestResource;
 import com.netscape.certsrv.key.KeyResource;
 import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.selftests.SelfTestClient;
 import com.netscape.certsrv.system.SystemCertResource;
 import com.netscape.certsrv.user.UserClient;
 import com.netscape.cmsutil.util.Utils;
@@ -39,6 +40,7 @@ public class KRAClient extends SubsystemClient {
     public void init() throws URISyntaxException {
 
         addClient(new GroupClient(client, name));
+        addClient(new SelfTestClient(client, name));
         addClient(new UserClient(client, name));
 
         systemCertClient = createProxy(SystemCertResource.class);
diff --git a/base/common/src/com/netscape/certsrv/ocsp/OCSPClient.java b/base/common/src/com/netscape/certsrv/ocsp/OCSPClient.java
index ed65e8b001c4c70a4d0d4cc06b031c3b9a28bc34..ab85bd2000da6d7c588eee5d8576b0c4032a2061 100644
--- a/base/common/src/com/netscape/certsrv/ocsp/OCSPClient.java
+++ b/base/common/src/com/netscape/certsrv/ocsp/OCSPClient.java
@@ -22,6 +22,7 @@ import java.net.URISyntaxException;
 import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.client.SubsystemClient;
 import com.netscape.certsrv.group.GroupClient;
+import com.netscape.certsrv.selftests.SelfTestClient;
 import com.netscape.certsrv.user.UserClient;
 
 public class OCSPClient extends SubsystemClient {
@@ -33,6 +34,7 @@ public class OCSPClient extends SubsystemClient {
 
     public void init() throws URISyntaxException {
         addClient(new GroupClient(client, name));
+        addClient(new SelfTestClient(client, name));
         addClient(new UserClient(client, name));
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/tks/TKSClient.java b/base/common/src/com/netscape/certsrv/selftests/SelfTestClient.java
similarity index 55%
copy from base/common/src/com/netscape/certsrv/tks/TKSClient.java
copy to base/common/src/com/netscape/certsrv/selftests/SelfTestClient.java
index a13089f865c6b70ad1f485ed764f93816a26d1bb..e9a081bb479223b835f49a4a40b6c0f81fce35d1 100644
--- a/base/common/src/com/netscape/certsrv/tks/TKSClient.java
+++ b/base/common/src/com/netscape/certsrv/selftests/SelfTestClient.java
@@ -15,26 +15,38 @@
 //(C) 2013 Red Hat, Inc.
 //All rights reserved.
 //--- END COPYRIGHT BLOCK ---
-package com.netscape.certsrv.tks;
+package com.netscape.certsrv.selftests;
 
 import java.net.URISyntaxException;
 
+import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.client.PKIClient;
-import com.netscape.certsrv.client.SubsystemClient;
-import com.netscape.certsrv.group.GroupClient;
-import com.netscape.certsrv.system.TPSConnectorClient;
-import com.netscape.certsrv.user.UserClient;
 
-public class TKSClient extends SubsystemClient {
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestClient extends Client {
 
-    public TKSClient(PKIClient client) throws URISyntaxException {
-        super(client, "tks");
+    public SelfTestResource resource;
+
+    public SelfTestClient(PKIClient client, String subsystem) throws URISyntaxException {
+        super(client, subsystem, "selftest");
         init();
     }
 
     public void init() throws URISyntaxException {
-        addClient(new GroupClient(client, name));
-        addClient(new UserClient(client, name));
-        addClient(new TPSConnectorClient(client, name));
+        resource = createProxy(SelfTestResource.class);
+    }
+
+    public SelfTestCollection findSelfTests(Integer start, Integer size) {
+        return resource.findSelfTests(start, size);
+    }
+
+    public void executeSelfTests(String action) {
+        resource.executeSelfTests(action);
+    }
+
+    public SelfTestData getSelfTest(String selfTestID) {
+        return resource.getSelfTest(selfTestID);
     }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java b/base/common/src/com/netscape/certsrv/selftests/SelfTestCollection.java
similarity index 51%
copy from base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
copy to base/common/src/com/netscape/certsrv/selftests/SelfTestCollection.java
index ce253d884c597d1f56835a1e537cf485cc7becd4..946d2822d18a00e21e8886830af235f7d2f7cbba 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
+++ b/base/common/src/com/netscape/certsrv/selftests/SelfTestCollection.java
@@ -16,41 +16,23 @@
 // All rights reserved.
 // --- END COPYRIGHT BLOCK ---
 
-package com.netscape.cmstools.cli;
+package com.netscape.certsrv.selftests;
 
-import com.netscape.certsrv.ca.CAClient;
-import com.netscape.certsrv.client.Client;
-import com.netscape.cmstools.group.GroupCLI;
-import com.netscape.cmstools.user.UserCLI;
+import java.util.Collection;
+
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.netscape.certsrv.base.DataCollection;
 
 /**
  * @author Endi S. Dewata
  */
-public class CACLI extends SubsystemCLI {
+@XmlRootElement(name="SelfTests")
+public class SelfTestCollection extends DataCollection<SelfTestData> {
 
-    public CAClient caClient;
-
-    public CACLI(CLI parent) {
-        super("ca", "CA management commands", parent);
-
-        addModule(new GroupCLI(this));
-        addModule(new UserCLI(this));
-    }
-
-    public void init() throws Exception {
-        client = parent.getClient();
-        caClient = new CAClient(client);
-    }
-
-    public void login() {
-        caClient.login();
-    }
-
-    public void logout() {
-        caClient.logout();
-    }
-
-    public Client getClient(String name) {
-        return caClient.getClient(name);
+    @XmlElementRef
+    public Collection<SelfTestData> getEntries() {
+        return super.getEntries();
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/selftests/SelfTestData.java b/base/common/src/com/netscape/certsrv/selftests/SelfTestData.java
new file mode 100644
index 0000000000000000000000000000000000000000..b10dc0a246a889785ce7398a5d3579803c653d07
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/selftests/SelfTestData.java
@@ -0,0 +1,189 @@
+// --- 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.selftests;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+/**
+ * @author Endi S. Dewata
+ */
+@XmlRootElement(name="SelfTest")
+public class SelfTestData {
+
+    public static Marshaller marshaller;
+    public static Unmarshaller unmarshaller;
+
+    static {
+        try {
+            marshaller = JAXBContext.newInstance(SelfTestData.class).createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+            unmarshaller = JAXBContext.newInstance(SelfTestData.class).createUnmarshaller();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    String id;
+    Boolean enabledAtStartup;
+    Boolean criticalAtStartup;
+    Boolean enabledOnDemand;
+    Boolean criticalOnDemand;
+
+    Link link;
+
+    @XmlAttribute(name="id")
+    public String getID() {
+        return id;
+    }
+
+    public void setID(String id) {
+        this.id = id;
+    }
+
+    @XmlElement(name="EnabledAtStartup")
+    public Boolean isEnabledAtStartup() {
+        return enabledAtStartup;
+    }
+
+    public void setEnabledAtStartup(Boolean enabledAtStartup) {
+        this.enabledAtStartup = enabledAtStartup;
+    }
+
+    @XmlElement(name="CriticalAtStartup")
+    public Boolean isCriticalAtStartup() {
+        return criticalAtStartup;
+    }
+
+    public void setCriticalAtStartup(Boolean criticalAtStartup) {
+        this.criticalAtStartup = criticalAtStartup;
+    }
+
+    @XmlElement(name="EnabledOnDemand")
+    public Boolean isEnabledOnDemand() {
+        return enabledOnDemand;
+    }
+
+    public void setEnabledOnDemand(Boolean enabledOnDemand) {
+        this.enabledOnDemand = enabledOnDemand;
+    }
+
+    @XmlElement(name="CriticalOnDemand")
+    public Boolean isCriticalOnDemand() {
+        return criticalOnDemand;
+    }
+
+    public void setCriticalOnDemand(Boolean criticalOnDemand) {
+        this.criticalOnDemand = criticalOnDemand;
+    }
+
+    @XmlElement(name="Link")
+    public Link getLink() {
+        return link;
+    }
+
+    public void setLink(Link link) {
+        this.link = link;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((criticalOnDemand == null) ? 0 : criticalOnDemand.hashCode());
+        result = prime * result + ((enabledOnDemand == null) ? 0 : enabledOnDemand.hashCode());
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        result = prime * result + ((link == null) ? 0 : link.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SelfTestData other = (SelfTestData) obj;
+        if (criticalOnDemand == null) {
+            if (other.criticalOnDemand != null)
+                return false;
+        } else if (!criticalOnDemand.equals(other.criticalOnDemand))
+            return false;
+        if (enabledOnDemand == null) {
+            if (other.enabledOnDemand != null)
+                return false;
+        } else if (!enabledOnDemand.equals(other.enabledOnDemand))
+            return false;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        if (link == null) {
+            if (other.link != null)
+                return false;
+        } else if (!link.equals(other.link))
+            return false;
+        return true;
+    }
+
+    public String toString() {
+        try {
+            StringWriter sw = new StringWriter();
+            marshaller.marshal(this, sw);
+            return sw.toString();
+
+        } catch (Exception e) {
+            return super.toString();
+        }
+    }
+
+    public static SelfTestData valueOf(String string) throws Exception {
+        try {
+            return (SelfTestData)unmarshaller.unmarshal(new StringReader(string));
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static void main(String args[]) throws Exception {
+
+        SelfTestData before = new SelfTestData();
+        before.setID("selftest1");
+        before.setEnabledOnDemand(true);
+        before.setCriticalOnDemand(false);
+
+        String string = before.toString();
+        System.out.println(string);
+
+        SelfTestData after = SelfTestData.valueOf(string);
+        System.out.println(before.equals(after));
+    }
+}
diff --git a/base/common/src/com/netscape/certsrv/selftests/SelfTestResource.java b/base/common/src/com/netscape/certsrv/selftests/SelfTestResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d847cae7cbca8bfc13380f35cf28810191f60f2
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/selftests/SelfTestResource.java
@@ -0,0 +1,49 @@
+// --- 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.selftests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+@Path("selftests")
+public interface SelfTestResource {
+
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public SelfTestCollection findSelfTests(
+            @QueryParam("start") Integer start,
+            @QueryParam("size") Integer size);
+
+    @POST
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public void executeSelfTests(@QueryParam("action") String action);
+
+    @GET
+    @Path("{selfTestID}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public SelfTestData getSelfTest(@PathParam("selfTestID") String selfTestID);
+}
diff --git a/base/common/src/com/netscape/certsrv/tks/TKSClient.java b/base/common/src/com/netscape/certsrv/tks/TKSClient.java
index a13089f865c6b70ad1f485ed764f93816a26d1bb..a972241ce6521e9cd92138f2f99088704d7f3d0a 100644
--- a/base/common/src/com/netscape/certsrv/tks/TKSClient.java
+++ b/base/common/src/com/netscape/certsrv/tks/TKSClient.java
@@ -22,6 +22,7 @@ import java.net.URISyntaxException;
 import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.client.SubsystemClient;
 import com.netscape.certsrv.group.GroupClient;
+import com.netscape.certsrv.selftests.SelfTestClient;
 import com.netscape.certsrv.system.TPSConnectorClient;
 import com.netscape.certsrv.user.UserClient;
 
@@ -34,7 +35,8 @@ public class TKSClient extends SubsystemClient {
 
     public void init() throws URISyntaxException {
         addClient(new GroupClient(client, name));
-        addClient(new UserClient(client, name));
+        addClient(new SelfTestClient(client, name));
         addClient(new TPSConnectorClient(client, name));
+        addClient(new UserClient(client, name));
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/tps/TPSClient.java b/base/common/src/com/netscape/certsrv/tps/TPSClient.java
index fcd87f18293e014cf2d03b3ed22e06bc7decb4d4..eeccdb0183e7f89f219c136e4fab62ca7afc7e2a 100644
--- a/base/common/src/com/netscape/certsrv/tps/TPSClient.java
+++ b/base/common/src/com/netscape/certsrv/tps/TPSClient.java
@@ -23,6 +23,7 @@ import com.netscape.certsrv.client.PKIClient;
 import com.netscape.certsrv.client.SubsystemClient;
 import com.netscape.certsrv.group.GroupClient;
 import com.netscape.certsrv.logging.ActivityClient;
+import com.netscape.certsrv.selftests.SelfTestClient;
 import com.netscape.certsrv.tps.authenticator.AuthenticatorClient;
 import com.netscape.certsrv.tps.cert.TPSCertClient;
 import com.netscape.certsrv.tps.config.ConfigClient;
@@ -49,6 +50,7 @@ public class TPSClient extends SubsystemClient {
         addClient(new ConnectionClient(client, name));
         addClient(new GroupClient(client, name));
         addClient(new ProfileMappingClient(client, name));
+        addClient(new SelfTestClient(client, name));
         addClient(new TokenClient(client, name));
         addClient(new UserClient(client, name));
     }
diff --git a/base/common/src/com/netscape/cmscore/selftests/SelfTestService.java b/base/common/src/com/netscape/cmscore/selftests/SelfTestService.java
new file mode 100644
index 0000000000000000000000000000000000000000..35d665a75fff5034d556106ac87b5b1b22bf8bb2
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/selftests/SelfTestService.java
@@ -0,0 +1,137 @@
+// --- 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.cmscore.selftests;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.selftests.EMissingSelfTestException;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+import com.netscape.certsrv.selftests.SelfTestCollection;
+import com.netscape.certsrv.selftests.SelfTestData;
+import com.netscape.certsrv.selftests.SelfTestResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestService extends PKIService implements SelfTestResource {
+
+    @Context
+    private UriInfo uriInfo;
+
+    @Context
+    private HttpHeaders headers;
+
+    @Context
+    private Request request;
+
+    @Context
+    private HttpServletRequest servletRequest;
+
+    public final static int DEFAULT_SIZE = 20;
+
+    public SelfTestService() {
+        CMS.debug("SelfTestService.<init>()");
+    }
+
+    public SelfTestData createSelfTestData(ISelfTestSubsystem subsystem, String selfTestID) throws UnsupportedEncodingException, EMissingSelfTestException {
+
+        SelfTestData selfTestData = new SelfTestData();
+        selfTestData.setID(selfTestID);
+        selfTestData.setEnabledAtStartup(subsystem.isSelfTestEnabledAtStartup(selfTestID));
+        selfTestData.setCriticalAtStartup(subsystem.isSelfTestCriticalAtStartup(selfTestID));
+        selfTestData.setEnabledOnDemand(subsystem.isSelfTestEnabledOnDemand(selfTestID));
+        selfTestData.setCriticalOnDemand(subsystem.isSelfTestCriticalOnDemand(selfTestID));
+
+        selfTestID = URLEncoder.encode(selfTestID, "UTF-8");
+        URI uri = uriInfo.getBaseUriBuilder().path(SelfTestResource.class).path("{selfTestID}").build(selfTestID);
+        selfTestData.setLink(new Link("self", uri));
+
+        return selfTestData;
+    }
+
+    @Override
+    public SelfTestCollection findSelfTests(Integer start, Integer size) {
+
+        CMS.debug("SelfTestService.findSelfTests()");
+
+        try {
+            SelfTestCollection response = new SelfTestCollection();
+
+            ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+            for (String name : subsystem.listSelfTestsEnabledOnDemand()) {
+                SelfTestData data = createSelfTestData(subsystem, name);
+                response.addEntry(data);
+            }
+
+            return response;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new PKIException(e.getMessage());
+        }
+    }
+
+    @Override
+    public SelfTestData getSelfTest(String selfTestID) {
+
+        CMS.debug("SelfTestService.getSelfTest(\"" + selfTestID + "\")");
+
+        try {
+            ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+            return createSelfTestData(subsystem, selfTestID);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new PKIException(e.getMessage());
+        }
+    }
+
+    @Override
+    public void executeSelfTests(String action) {
+
+        CMS.debug("SelfTestService.executeSelfTests(\"" + action + "\")");
+
+        if (!"run".equals(action)) {
+            throw new BadRequestException("Invalid action: " + action);
+        }
+
+        try {
+            ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+            subsystem.runSelfTestsOnDemand();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new PKIException(e.getMessage());
+        }
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java b/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
index ce253d884c597d1f56835a1e537cf485cc7becd4..fdef872fbf534c00b8a20afd6dab729505e41201 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
@@ -21,6 +21,7 @@ package com.netscape.cmstools.cli;
 import com.netscape.certsrv.ca.CAClient;
 import com.netscape.certsrv.client.Client;
 import com.netscape.cmstools.group.GroupCLI;
+import com.netscape.cmstools.selftests.SelfTestCLI;
 import com.netscape.cmstools.user.UserCLI;
 
 /**
@@ -34,6 +35,7 @@ public class CACLI extends SubsystemCLI {
         super("ca", "CA management commands", parent);
 
         addModule(new GroupCLI(this));
+        addModule(new SelfTestCLI(this));
         addModule(new UserCLI(this));
     }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/KRACLI.java b/base/java-tools/src/com/netscape/cmstools/cli/KRACLI.java
index ecc72688a21cacdeb71ee50f2a123c8b0adcf73e..3929b6f8de61552df5d8ed1b9ebb9817bad511c6 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/KRACLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/KRACLI.java
@@ -21,6 +21,7 @@ package com.netscape.cmstools.cli;
 import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.kra.KRAClient;
 import com.netscape.cmstools.group.GroupCLI;
+import com.netscape.cmstools.selftests.SelfTestCLI;
 import com.netscape.cmstools.user.UserCLI;
 
 /**
@@ -34,6 +35,7 @@ public class KRACLI extends SubsystemCLI {
         super("kra", "KRA management commands", parent);
 
         addModule(new GroupCLI(this));
+        addModule(new SelfTestCLI(this));
         addModule(new UserCLI(this));
     }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/OCSPCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/OCSPCLI.java
index e28b97cdb16afc501e492b74246b37efd1dd3d66..3768a48e745e4632d22a755751e137ec40ec6299 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/OCSPCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/OCSPCLI.java
@@ -21,6 +21,7 @@ package com.netscape.cmstools.cli;
 import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.ocsp.OCSPClient;
 import com.netscape.cmstools.group.GroupCLI;
+import com.netscape.cmstools.selftests.SelfTestCLI;
 import com.netscape.cmstools.user.UserCLI;
 
 /**
@@ -34,6 +35,7 @@ public class OCSPCLI extends SubsystemCLI {
         super("ocsp", "OCSP management commands", parent);
 
         addModule(new GroupCLI(this));
+        addModule(new SelfTestCLI(this));
         addModule(new UserCLI(this));
     }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java
index b8c90ed4712a092e661a35fe5a5c2c37e0c1a216..dd4f179c262036b286d3f44526f9a4a8fac2211e 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java
@@ -21,6 +21,7 @@ package com.netscape.cmstools.cli;
 import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.tks.TKSClient;
 import com.netscape.cmstools.group.GroupCLI;
+import com.netscape.cmstools.selftests.SelfTestCLI;
 import com.netscape.cmstools.system.TPSConnectorCLI;
 import com.netscape.cmstools.user.UserCLI;
 
@@ -35,6 +36,7 @@ public class TKSCLI extends SubsystemCLI {
         super("tks", "TKS management commands", parent);
 
         addModule(new GroupCLI(this));
+        addModule(new SelfTestCLI(this));
         addModule(new TPSConnectorCLI(this));
         addModule(new UserCLI(this));
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/TPSCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/TPSCLI.java
index 09596fae7718528affa381192036c949515585c7..a3fe27eb831579add73fcb781f1ecc5b361e2b73 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/TPSCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/TPSCLI.java
@@ -22,6 +22,7 @@ import com.netscape.certsrv.client.Client;
 import com.netscape.certsrv.tps.TPSClient;
 import com.netscape.cmstools.group.GroupCLI;
 import com.netscape.cmstools.logging.ActivityCLI;
+import com.netscape.cmstools.selftests.SelfTestCLI;
 import com.netscape.cmstools.tps.authenticator.AuthenticatorCLI;
 import com.netscape.cmstools.tps.cert.TPSCertCLI;
 import com.netscape.cmstools.tps.config.ConfigCLI;
@@ -47,6 +48,7 @@ public class TPSCLI extends SubsystemCLI {
         addModule(new ConnectionCLI(this));
         addModule(new GroupCLI(this));
         addModule(new ProfileCLI(this));
+        addModule(new SelfTestCLI(this));
         addModule(new TokenCLI(this));
         addModule(new UserCLI(this));
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestCLI.java b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e64e0576a76679944c17155a8f568146ce8d4ee
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestCLI.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.cmstools.selftests;
+
+import java.io.IOException;
+
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.selftests.SelfTestClient;
+import com.netscape.certsrv.selftests.SelfTestData;
+import com.netscape.cmstools.cli.CLI;
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestCLI extends CLI {
+
+    public SelfTestClient selfTestClient;
+
+    public SelfTestCLI(CLI parent) {
+        super("selftest", "Selftest management commands", parent);
+
+        addModule(new SelfTestFindCLI(this));
+        addModule(new SelfTestRunCLI(this));
+        addModule(new SelfTestShowCLI(this));
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        client = parent.getClient();
+        selfTestClient = (SelfTestClient)parent.getClient("selftest");
+
+        super.execute(args);
+    }
+
+    public static void printSelfTestData(SelfTestData selfTestData) throws IOException {
+        System.out.println("  SelfTest ID: " + selfTestData.getID());
+        if (selfTestData.isEnabledAtStartup() != null) System.out.println("  Enabled at startup: " + selfTestData.isEnabledAtStartup());
+        if (selfTestData.isCriticalAtStartup() != null) System.out.println("  Critical at startup: " + selfTestData.isCriticalAtStartup());
+        if (selfTestData.isEnabledOnDemand() != null) System.out.println("  Enabled on demand: " + selfTestData.isEnabledOnDemand());
+        if (selfTestData.isCriticalOnDemand() != null) System.out.println("  Critical on demand: " + selfTestData.isCriticalOnDemand());
+
+        Link link = selfTestData.getLink();
+        if (verbose && link != null) {
+            System.out.println("  Link: " + link.getHref());
+        }
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..245c9a61ed486263ee4f21530e3794a72023a56e
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java
@@ -0,0 +1,94 @@
+// --- 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.cmstools.selftests;
+
+import java.util.Collection;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+
+import com.netscape.certsrv.selftests.SelfTestCollection;
+import com.netscape.certsrv.selftests.SelfTestData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestFindCLI extends CLI {
+
+    public SelfTestCLI selfTestCLI;
+
+    public SelfTestFindCLI(SelfTestCLI selfTestCLI) {
+        super("find", "Find selftests", selfTestCLI);
+        this.selfTestCLI = selfTestCLI;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(getFullName() + " [OPTIONS...]", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        Option option = new Option(null, "start", true, "Page start");
+        option.setArgName("start");
+        options.addOption(option);
+
+        option = new Option(null, "size", true, "Page size");
+        option.setArgName("size");
+        options.addOption(option);
+
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+
+        } catch (Exception e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(1);
+        }
+
+        String s = cmd.getOptionValue("start");
+        Integer start = s == null ? null : Integer.valueOf(s);
+
+        s = cmd.getOptionValue("size");
+        Integer size = s == null ? null : Integer.valueOf(s);
+
+        SelfTestCollection result = selfTestCLI.selfTestClient.findSelfTests(start, size);
+        Collection<SelfTestData> selfTests = result.getEntries();
+
+        MainCLI.printMessage(selfTests.size() + " connection(s) matched");
+
+        boolean first = true;
+
+        for (SelfTestData selfTestInfo : selfTests) {
+
+            if (first) {
+                first = false;
+            } else {
+                System.out.println();
+            }
+
+            SelfTestCLI.printSelfTestData(selfTestInfo);
+        }
+
+        MainCLI.printMessage("Number of entries returned " + selfTests.size());
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestRunCLI.java b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestRunCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4b51084a84b9aa9ec9a98ef0f2e1f6dceb1f04d
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestRunCLI.java
@@ -0,0 +1,66 @@
+// --- 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.cmstools.selftests;
+
+import org.apache.commons.cli.CommandLine;
+
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestRunCLI extends CLI {
+
+    public SelfTestCLI selfTestCLI;
+
+    public SelfTestRunCLI(SelfTestCLI selfTestCLI) {
+        super("run", "Run selftests", selfTestCLI);
+        this.selfTestCLI = selfTestCLI;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(getFullName(), options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+
+        } catch (Exception e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(1);
+        }
+
+        String[] cmdArgs = cmd.getArgs();
+
+        if (cmdArgs.length != 0) {
+            printHelp();
+            System.exit(1);
+        }
+
+        selfTestCLI.selfTestClient.executeSelfTests("run");
+
+        MainCLI.printMessage("Selftests completed");
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestShowCLI.java b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestShowCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..88527b32da315aa79e27ac0c780181db140692ac
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestShowCLI.java
@@ -0,0 +1,87 @@
+// --- 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.cmstools.selftests;
+
+import java.io.FileWriter;
+import java.io.PrintWriter;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+
+import com.netscape.certsrv.selftests.SelfTestData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestShowCLI extends CLI {
+
+    public SelfTestCLI selfTestCLI;
+
+    public SelfTestShowCLI(SelfTestCLI selfTestCLI) {
+        super("show", "Show selftest", selfTestCLI);
+        this.selfTestCLI = selfTestCLI;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(getFullName() + " <SelfTest ID>", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        Option option = new Option(null, "output", true, "Output file to store selfTest properties.");
+        option.setArgName("file");
+        options.addOption(option);
+
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+
+        } catch (Exception e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(1);
+        }
+
+        String[] cmdArgs = cmd.getArgs();
+
+        if (cmdArgs.length != 1) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String selfTestID = args[0];
+        String output = cmd.getOptionValue("output");
+
+        SelfTestData selfTestInfo = selfTestCLI.selfTestClient.getSelfTest(selfTestID);
+
+        if (output == null) {
+            MainCLI.printMessage("SelfTest \"" + selfTestID + "\"");
+            SelfTestCLI.printSelfTestData(selfTestInfo);
+
+        } else {
+            try (PrintWriter out = new PrintWriter(new FileWriter(output))) {
+                out.println(selfTestInfo);
+            }
+            MainCLI.printMessage("Stored selfTest \"" + selfTestID + "\" into " + output);
+        }
+    }
+}
diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
index f04ee9bb57607c4e12f9f17e2edf4600d2666626..b72fa423bda9528bf75a0c05b6033015c96c82ed 100644
--- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
+++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
@@ -18,6 +18,7 @@ import com.netscape.cms.servlet.admin.UserService;
 import com.netscape.cms.servlet.csadmin.SystemConfigService;
 import com.netscape.cms.servlet.key.KeyService;
 import com.netscape.cms.servlet.request.KeyRequestService;
+import com.netscape.cmscore.selftests.SelfTestService;
 
 public class KeyRecoveryAuthorityApplication extends Application {
 
@@ -36,6 +37,9 @@ public class KeyRecoveryAuthorityApplication extends Application {
         classes.add(KeyService.class);
         classes.add(KeyRequestService.class);
 
+        // selftests
+        classes.add(SelfTestService.class);
+
         // user and group management
         classes.add(GroupMemberService.class);
         classes.add(GroupService.class);
diff --git a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
index 1dc4a9df1b19400ddcf2625c4742dd6cd61f09cb..951a29b60fb33979dc85a85b40b16a49d8c993be 100644
--- a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
+++ b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
@@ -16,6 +16,7 @@ import com.netscape.cms.servlet.admin.UserCertService;
 import com.netscape.cms.servlet.admin.UserMembershipService;
 import com.netscape.cms.servlet.admin.UserService;
 import com.netscape.cms.servlet.csadmin.SystemConfigService;
+import com.netscape.cmscore.selftests.SelfTestService;
 
 public class OCSPApplication extends Application {
 
@@ -30,6 +31,9 @@ public class OCSPApplication extends Application {
         // installer
         classes.add(SystemConfigService.class);
 
+        // selftests
+        classes.add(SelfTestService.class);
+
         // user and group management
         classes.add(GroupMemberService.class);
         classes.add(GroupService.class);
diff --git a/base/tks/src/com/netscape/tks/TKSApplication.java b/base/tks/src/com/netscape/tks/TKSApplication.java
index 1ec0576e47f3a0addbda4085e57ac9322a5ba78c..27701e8ec1b6c5018af9951f51bdcf39b41de5f9 100644
--- a/base/tks/src/com/netscape/tks/TKSApplication.java
+++ b/base/tks/src/com/netscape/tks/TKSApplication.java
@@ -17,6 +17,7 @@ import com.netscape.cms.servlet.admin.UserMembershipService;
 import com.netscape.cms.servlet.admin.UserService;
 import com.netscape.cms.servlet.csadmin.SystemConfigService;
 import com.netscape.cms.servlet.tks.TPSConnectorService;
+import com.netscape.cmscore.selftests.SelfTestService;
 
 public class TKSApplication extends Application {
 
@@ -31,6 +32,9 @@ public class TKSApplication extends Application {
         // installer
         classes.add(SystemConfigService.class);
 
+        // selftests
+        classes.add(SelfTestService.class);
+
         // user and group management
         classes.add(GroupMemberService.class);
         classes.add(GroupService.class);
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSApplication.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSApplication.java
index 53dc7bb8a54092e464f6c0063fbdc61d61d0a179..0387298cee18d89414644c1437258d84c097a21e 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSApplication.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSApplication.java
@@ -41,6 +41,7 @@ import com.netscape.cms.servlet.admin.UserCertService;
 import com.netscape.cms.servlet.admin.UserMembershipService;
 import com.netscape.cms.servlet.admin.UserService;
 import com.netscape.cms.servlet.csadmin.SystemConfigService;
+import com.netscape.cmscore.selftests.SelfTestService;
 
 /**
  * @author Endi S. Dewata <edewata@redhat.com>
@@ -86,6 +87,9 @@ public class TPSApplication extends Application {
         // profiles
         classes.add(ProfileMappingService.class);
 
+        // selftests
+        classes.add(SelfTestService.class);
+
         // tokens
         classes.add(TokenService.class);
 
-- 
1.8.1.4

