From a52e488748900b250803604fed5d7918b860f835 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 8 Nov 2013 12:36:33 -0500
Subject: [PATCH] Fixed find commands.

Some of the REST services have been fixed to consistently return a
DataCollection which contains the total count, the requested subset
of results, and links to request other subsets of the results.

The TPSConnectorFindCLI has been split into separate find and show
commands.

Ticket #749
---
 .../com/netscape/certsrv/base/DataCollection.java  |  9 ++++
 .../netscape/certsrv/group/GroupCollection.java    | 34 ++----------
 .../certsrv/group/GroupMemberCollection.java       | 37 +++----------
 .../certsrv/system/TPSConnectorClient.java         |  4 +-
 .../certsrv/system/TPSConnectorResource.java       |  2 +-
 .../netscape/certsrv/user/UserCertCollection.java  | 30 ++---------
 .../com/netscape/certsrv/user/UserCollection.java  | 34 ++----------
 .../certsrv/user/UserMembershipCollection.java     | 37 +++----------
 .../com/netscape/cmstools/group/GroupFindCLI.java  |  5 +-
 .../cmstools/group/GroupMemberFindCLI.java         |  5 +-
 .../netscape/cmstools/logging/ActivityFindCLI.java |  3 +-
 .../cmstools/selftests/SelfTestFindCLI.java        |  3 +-
 .../cmstools/system/TPSConnectorFindCLI.java       | 60 +++++++++-------------
 ...nectorFindCLI.java => TPSConnectorShowCLI.java} | 51 ++++--------------
 .../tps/authenticator/AuthenticatorFindCLI.java    |  3 +-
 .../netscape/cmstools/tps/cert/TPSCertFindCLI.java |  3 +-
 .../cmstools/tps/connection/ConnectionFindCLI.java |  3 +-
 .../cmstools/tps/profile/ProfileFindCLI.java       |  3 +-
 .../tps/profile/ProfileMappingFindCLI.java         |  3 +-
 .../netscape/cmstools/tps/token/TokenFindCLI.java  |  3 +-
 .../netscape/cmstools/user/UserCertFindCLI.java    |  5 +-
 .../com/netscape/cmstools/user/UserFindCLI.java    |  5 +-
 .../cmstools/user/UserMembershipFindCLI.java       |  5 +-
 .../cms/servlet/admin/GroupMemberProcessor.java    |  3 +-
 .../netscape/cms/servlet/admin/GroupService.java   |  4 +-
 .../netscape/cms/servlet/admin/UserService.java    | 48 ++++++++++-------
 .../cms/servlet/tks/TPSConnectorService.java       | 38 +++++++++++---
 .../cmscore/selftests/SelfTestService.java         | 32 ++++++++++--
 .../tps/authenticator/AuthenticatorService.java    |  2 +-
 .../dogtagpki/server/tps/cert/TPSCertService.java  |  2 +-
 .../server/tps/connection/ConnectionService.java   |  2 +-
 .../server/tps/logging/ActivityService.java        |  2 +-
 .../server/tps/profile/ProfileMappingService.java  |  2 +-
 .../server/tps/profile/ProfileService.java         |  2 +-
 .../dogtagpki/server/tps/token/TokenService.java   |  2 +-
 35 files changed, 202 insertions(+), 284 deletions(-)
 copy base/java-tools/src/com/netscape/cmstools/system/{TPSConnectorFindCLI.java => TPSConnectorShowCLI.java} (54%)

diff --git a/base/common/src/com/netscape/certsrv/base/DataCollection.java b/base/common/src/com/netscape/certsrv/base/DataCollection.java
index 0237e8fccbc629565bd93768901f7b4845187591..8432604f01b059abfdac6f1a69d8190ee962d71a 100644
--- a/base/common/src/com/netscape/certsrv/base/DataCollection.java
+++ b/base/common/src/com/netscape/certsrv/base/DataCollection.java
@@ -30,9 +30,18 @@ import org.jboss.resteasy.plugins.providers.atom.Link;
  */
 public class DataCollection<E> {
 
+    Integer total;
     Collection<E> entries = new ArrayList<E>();
     Collection<Link> links = new ArrayList<Link>();
 
+    public Integer getTotal() {
+        return total;
+    }
+
+    public void setTotal(Integer total) {
+        this.total = total;
+    }
+
     public Collection<E> getEntries() {
         return entries;
     }
diff --git a/base/common/src/com/netscape/certsrv/group/GroupCollection.java b/base/common/src/com/netscape/certsrv/group/GroupCollection.java
index 26d108e7b59479da74c79da228a45e5f8ede76bd..4ce8b0268c9c6c7a1fa8b79b8516864e6b84ee6b 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupCollection.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupCollection.java
@@ -18,48 +18,22 @@
 
 package com.netscape.certsrv.group;
 
-import java.util.ArrayList;
 import java.util.Collection;
 
-import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementRef;
 import javax.xml.bind.annotation.XmlRootElement;
 
-import org.jboss.resteasy.plugins.providers.atom.Link;
+import com.netscape.certsrv.base.DataCollection;
 
 
 /**
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="Groups")
-public class GroupCollection {
-
-    Collection<GroupData> groups = new ArrayList<GroupData>();
-    Collection<Link> links = new ArrayList<Link>();
+public class GroupCollection extends DataCollection<GroupData> {
 
     @XmlElementRef
-    public Collection<GroupData> getGroups() {
-        return groups;
-    }
-
-    public void setGroups(Collection<GroupData> groups) {
-        this.groups = groups;
-    }
-
-    public void addGroup(GroupData groupData) {
-        groups.add(groupData);
-    }
-
-    @XmlElement(name="Link")
-    public Collection<Link> getLinks() {
-        return links;
-    }
-
-    public void setLink(Collection<Link> links) {
-        this.links = links;
-    }
-
-    public void addLink(Link link) {
-        links.add(link);
+    public Collection<GroupData> getEntries() {
+        return super.getEntries();
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/group/GroupMemberCollection.java b/base/common/src/com/netscape/certsrv/group/GroupMemberCollection.java
index 6ec013bca505c37d67882935e08298ba49bd8164..b43b16b578cdbc7ed14684c219a1feb5c8dd791d 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupMemberCollection.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupMemberCollection.java
@@ -18,7 +18,6 @@
 
 package com.netscape.certsrv.group;
 
-import java.util.ArrayList;
 import java.util.Collection;
 
 import javax.xml.bind.JAXBContext;
@@ -26,41 +25,17 @@ import javax.xml.bind.Marshaller;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
-import org.jboss.resteasy.plugins.providers.atom.Link;
+import com.netscape.certsrv.base.DataCollection;
 
 /**
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="GroupMembers")
-public class GroupMemberCollection {
-
-    Collection<GroupMemberData> members = new ArrayList<GroupMemberData>();
-    Collection<Link> links = new ArrayList<Link>();
+public class GroupMemberCollection extends DataCollection<GroupMemberData> {
 
     @XmlElement(name="Member")
-    public Collection<GroupMemberData> getMembers() {
-        return members;
-    }
-
-    public void setMembers(Collection<GroupMemberData> members) {
-        this.members = members;
-    }
-
-    public void addMember(GroupMemberData member) {
-        members.add(member);
-    }
-
-    @XmlElement(name="Link")
-    public Collection<Link> getLinks() {
-        return links;
-    }
-
-    public void setLink(Collection<Link> links) {
-        this.links = links;
-    }
-
-    public void addLink(Link link) {
-        links.add(link);
+    public Collection<GroupMemberData> getEntries() {
+        return super.getEntries();
     }
 
     public static void main(String args[]) throws Exception {
@@ -70,12 +45,12 @@ public class GroupMemberCollection {
         GroupMemberData member1 = new GroupMemberData();
         member1.setID("User 1");
         member1.setGroupID("Group 1");
-        response.addMember(member1);
+        response.addEntry(member1);
 
         GroupMemberData member2 = new GroupMemberData();
         member2.setID("User 2");
         member2.setGroupID("Group 1");
-        response.addMember(member2);
+        response.addEntry(member2);
 
         JAXBContext context = JAXBContext.newInstance(GroupMemberCollection.class);
         Marshaller marshaller = context.createMarshaller();
diff --git a/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java b/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java
index b247db907040f8649fa25c060f6dcc46981c5a92..0d5cff91b45d267aad7c724468d8e80a677a62b2 100644
--- a/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java
+++ b/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java
@@ -21,8 +21,8 @@ public class TPSConnectorClient extends Client {
         tpsConnectorClient = createProxy(TPSConnectorResource.class);
     }
 
-    public TPSConnectorCollection listConnectors() {
-        return tpsConnectorClient.listConnectors();
+    public TPSConnectorCollection findConnectors(Integer start, Integer size) {
+        return tpsConnectorClient.findConnectors(start, size);
     }
 
     public TPSConnectorData getConnector(String id) {
diff --git a/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java b/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java
index e10e132dabe80a9e08fbab1bbd83a973ecb09c6a..c29fa3d1961fb4cc4da9323e5a90d42a56efb046 100644
--- a/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java
+++ b/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java
@@ -43,7 +43,7 @@ import com.netscape.certsrv.key.KeyData;
 public interface TPSConnectorResource {
     @GET
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public TPSConnectorCollection listConnectors();
+    public TPSConnectorCollection findConnectors(Integer start, Integer size);
 
     @GET
     @Path("{id}")
diff --git a/base/common/src/com/netscape/certsrv/user/UserCertCollection.java b/base/common/src/com/netscape/certsrv/user/UserCertCollection.java
index a395ed73c686a844558cf1e7325913b61bed3e15..3eb4ed4060df1892af21f45b0b7c125737552cf7 100644
--- a/base/common/src/com/netscape/certsrv/user/UserCertCollection.java
+++ b/base/common/src/com/netscape/certsrv/user/UserCertCollection.java
@@ -18,43 +18,21 @@
 
 package com.netscape.certsrv.user;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
-import org.jboss.resteasy.plugins.providers.atom.Link;
+import com.netscape.certsrv.base.DataCollection;
 
 /**
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="UserCerts")
-public class UserCertCollection {
-
-    List<UserCertData> certs = new ArrayList<UserCertData>();
-    Collection<Link> links = new ArrayList<Link>();
+public class UserCertCollection extends DataCollection<UserCertData> {
 
     @XmlElement(name="Cert")
-    public Collection<UserCertData> getCerts() {
-        return certs;
-    }
-
-    public void addCert(UserCertData cert) {
-        certs.add(cert);
-    }
-
-    @XmlElement(name="Link")
-    public Collection<Link> getLinks() {
-        return links;
-    }
-
-    public void setLink(Collection<Link> links) {
-        this.links = links;
-    }
-
-    public void addLink(Link link) {
-        links.add(link);
+    public Collection<UserCertData> getEntries() {
+        return super.getEntries();
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/user/UserCollection.java b/base/common/src/com/netscape/certsrv/user/UserCollection.java
index d92ecc208253417723df57514ac6f749c1ba68dd..a24a798782e6606f2e0d02fa92d6662d46b90b61 100644
--- a/base/common/src/com/netscape/certsrv/user/UserCollection.java
+++ b/base/common/src/com/netscape/certsrv/user/UserCollection.java
@@ -18,48 +18,22 @@
 
 package com.netscape.certsrv.user;
 
-import java.util.ArrayList;
 import java.util.Collection;
 
-import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementRef;
 import javax.xml.bind.annotation.XmlRootElement;
 
-import org.jboss.resteasy.plugins.providers.atom.Link;
+import com.netscape.certsrv.base.DataCollection;
 
 
 /**
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="Users")
-public class UserCollection {
-
-    Collection<UserData> users = new ArrayList<UserData>();
-    Collection<Link> links = new ArrayList<Link>();
+public class UserCollection extends DataCollection<UserData> {
 
     @XmlElementRef
-    public Collection<UserData> getUsers() {
-        return users;
-    }
-
-    public void setUsers(Collection<UserData> users) {
-        this.users = users;
-    }
-
-    public void addUser(UserData userData) {
-        users.add(userData);
-    }
-
-    @XmlElement(name="Link")
-    public Collection<Link> getLinks() {
-        return links;
-    }
-
-    public void setLink(Collection<Link> links) {
-        this.links = links;
-    }
-
-    public void addLink(Link link) {
-        links.add(link);
+    public Collection<UserData> getEntries() {
+        return super.getEntries();
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/user/UserMembershipCollection.java b/base/common/src/com/netscape/certsrv/user/UserMembershipCollection.java
index 069840d13b95759364b0c1b6f41d7d6fcfcf6b7a..4c2ffa9b4489fb685a4ceb607c7ce150a194803a 100644
--- a/base/common/src/com/netscape/certsrv/user/UserMembershipCollection.java
+++ b/base/common/src/com/netscape/certsrv/user/UserMembershipCollection.java
@@ -18,7 +18,6 @@
 
 package com.netscape.certsrv.user;
 
-import java.util.ArrayList;
 import java.util.Collection;
 
 import javax.xml.bind.JAXBContext;
@@ -26,41 +25,17 @@ import javax.xml.bind.Marshaller;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
-import org.jboss.resteasy.plugins.providers.atom.Link;
+import com.netscape.certsrv.base.DataCollection;
 
 /**
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="UserMemberships")
-public class UserMembershipCollection {
-
-    Collection<UserMembershipData> memberships = new ArrayList<UserMembershipData>();
-    Collection<Link> links = new ArrayList<Link>();
+public class UserMembershipCollection extends DataCollection<UserMembershipData> {
 
     @XmlElement(name="Membership")
-    public Collection<UserMembershipData> getMemberships() {
-        return memberships;
-    }
-
-    public void setMemberships(Collection<UserMembershipData> members) {
-        this.memberships = members;
-    }
-
-    public void addMembership(UserMembershipData member) {
-        memberships.add(member);
-    }
-
-    @XmlElement(name="Link")
-    public Collection<Link> getLinks() {
-        return links;
-    }
-
-    public void setLink(Collection<Link> links) {
-        this.links = links;
-    }
-
-    public void addLink(Link link) {
-        links.add(link);
+    public Collection<UserMembershipData> getEntries() {
+        return super.getEntries();
     }
 
     public static void main(String args[]) throws Exception {
@@ -70,12 +45,12 @@ public class UserMembershipCollection {
         UserMembershipData membership1 = new UserMembershipData();
         membership1.setID("Group 1");
         membership1.setUserID("User 1");
-        response.addMembership(membership1);
+        response.addEntry(membership1);
 
         UserMembershipData membership2 = new UserMembershipData();
         membership2.setID("Group 2");
         membership2.setUserID("User 1");
-        response.addMembership(membership2);
+        response.addEntry(membership2);
 
         JAXBContext context = JAXBContext.newInstance(UserMembershipCollection.class);
         Marshaller marshaller = context.createMarshaller();
diff --git a/base/java-tools/src/com/netscape/cmstools/group/GroupFindCLI.java b/base/java-tools/src/com/netscape/cmstools/group/GroupFindCLI.java
index 7c2361da325841b77fcdcccd0210a8c161511cd2..45c2acf16e61b3810597996809c14716f24087c3 100644
--- a/base/java-tools/src/com/netscape/cmstools/group/GroupFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/group/GroupFindCLI.java
@@ -76,9 +76,10 @@ public class GroupFindCLI extends CLI {
 
         GroupCollection response = groupCLI.groupClient.findGroups(filter, start, size);
 
-        Collection<GroupData> entries = response.getGroups();
+        Collection<GroupData> entries = response.getEntries();
 
-        MainCLI.printMessage(entries.size()+" group(s) matched");
+        MainCLI.printMessage(response.getTotal() + " group(s) matched");
+        if (response.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/group/GroupMemberFindCLI.java b/base/java-tools/src/com/netscape/cmstools/group/GroupMemberFindCLI.java
index b9c9ac76d30df29001ff44f4c2503da0876abd91..ee694912dd83b4f5d7bdcbfc59855fd611ce156e 100644
--- a/base/java-tools/src/com/netscape/cmstools/group/GroupMemberFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/group/GroupMemberFindCLI.java
@@ -82,9 +82,10 @@ public class GroupMemberFindCLI extends CLI {
 
         GroupMemberCollection response = groupMemberCLI.groupClient.findGroupMembers(groupID, start, size);
 
-        Collection<GroupMemberData> entries = response.getMembers();
+        Collection<GroupMemberData> entries = response.getEntries();
 
-        MainCLI.printMessage(entries.size()+" group member(s) matched");
+        MainCLI.printMessage(response.getTotal() + " group member(s) matched");
+        if (response.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/logging/ActivityFindCLI.java b/base/java-tools/src/com/netscape/cmstools/logging/ActivityFindCLI.java
index 0808a0a7059073f1ae0c3d5ba27dd120b54e44b0..08c8496ca0147484bda41e4873b874ead5e19246 100644
--- a/base/java-tools/src/com/netscape/cmstools/logging/ActivityFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/logging/ActivityFindCLI.java
@@ -74,7 +74,8 @@ public class ActivityFindCLI extends CLI {
         ActivityCollection result = activityCLI.activityClient.findActivities(start, size);
         Collection<ActivityData> activities = result.getEntries();
 
-        MainCLI.printMessage(activities.size() + " activity(s) matched");
+        MainCLI.printMessage(result.getTotal() + " activity(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java
index 245c9a61ed486263ee4f21530e3794a72023a56e..4570d9a9173b57c8db2e443a735783b02830b1b4 100644
--- a/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/selftests/SelfTestFindCLI.java
@@ -74,7 +74,8 @@ public class SelfTestFindCLI extends CLI {
         SelfTestCollection result = selfTestCLI.selfTestClient.findSelfTests(start, size);
         Collection<SelfTestData> selfTests = result.getEntries();
 
-        MainCLI.printMessage(selfTests.size() + " connection(s) matched");
+        MainCLI.printMessage(result.getTotal() + " self test(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java
index 4caab729f73e47a4cfa01d4361a3c0feb7d545f6..7378517048194262afb34527ca9fe36df0571597 100644
--- a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 
-import com.netscape.certsrv.base.ResourceNotFoundException;
 import com.netscape.certsrv.system.TPSConnectorCollection;
 import com.netscape.certsrv.system.TPSConnectorData;
 import com.netscape.cmstools.cli.CLI;
@@ -32,10 +31,11 @@ import com.netscape.cmstools.cli.MainCLI;
  * @author Ade Lee
  */
 public class TPSConnectorFindCLI extends CLI {
+
     public TPSConnectorCLI tpsConnectorCLI;
 
     public TPSConnectorFindCLI(TPSConnectorCLI tpsConnectorCLI) {
-        super("find", "Find TPS connector details on TKS", tpsConnectorCLI);
+        super("find", "Find TPS connectors on TKS", tpsConnectorCLI);
         this.tpsConnectorCLI = tpsConnectorCLI;
     }
 
@@ -44,12 +44,13 @@ public class TPSConnectorFindCLI extends CLI {
     }
 
     public void execute(String[] args) throws Exception {
-        Option option = new Option(null, "host", true, "TPS host");
-        option.setArgName("host");
+
+        Option option = new Option(null, "start", true, "Page start");
+        option.setArgName("start");
         options.addOption(option);
 
-        option = new Option(null, "port", true, "TPS port");
-        option.setArgName("port");
+        option = new Option(null, "size", true, "Page size");
+        option.setArgName("size");
         options.addOption(option);
 
         CommandLine cmd = null;
@@ -63,42 +64,29 @@ public class TPSConnectorFindCLI extends CLI {
             System.exit(1);
         }
 
-        String tpsHost = cmd.getOptionValue("host");
-        String tpsPort = cmd.getOptionValue("port");
+        String s = cmd.getOptionValue("start");
+        Integer start = s == null ? null : Integer.valueOf(s);
 
-        if (tpsHost != null) {
-            if (tpsPort == null)
-                tpsPort = "443";
-            try {
-                TPSConnectorData data = tpsConnectorCLI.tpsConnectorClient.getConnector(
-                        tpsHost, tpsPort);
-                TPSConnectorCLI.printConnectorInfo(data);
-            } catch (ResourceNotFoundException e) {
-                System.out.println("  TPS connector not found.");
-                return;
-            }
-        } else {
-            TPSConnectorCollection result = tpsConnectorCLI.tpsConnectorClient.listConnectors();
-            Collection<TPSConnectorData> conns = result.getEntries();
+        s = cmd.getOptionValue("size");
+        Integer size = s == null ? null : Integer.valueOf(s);
 
-            if (conns.isEmpty()) {
-                System.out.println("  No TPS connectors found.");
-                return;
-            }
+        TPSConnectorCollection result = tpsConnectorCLI.tpsConnectorClient.findConnectors(start, size);
 
-            MainCLI.printMessage(conns.size() + " TPS connector(s) matched");
-            boolean first = true;
-            for (TPSConnectorData data: conns) {
-                if (first) {
-                    first = false;
-                } else {
-                    System.out.println();
-                }
+        MainCLI.printMessage(result.getTotal() + " TPS connector(s) matched");
+        if (result.getTotal() == 0) return;
 
-                TPSConnectorCLI.printConnectorInfo(data);
+        Collection<TPSConnectorData> conns = result.getEntries();
+        boolean first = true;
+        for (TPSConnectorData data: conns) {
+            if (first) {
+                first = false;
+            } else {
+                System.out.println();
             }
 
-            MainCLI.printMessage("Number of entries returned " + conns.size());
+            TPSConnectorCLI.printConnectorInfo(data);
         }
+
+        MainCLI.printMessage("Number of entries returned " + conns.size());
     }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorShowCLI.java
similarity index 54%
copy from base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java
copy to base/java-tools/src/com/netscape/cmstools/system/TPSConnectorShowCLI.java
index 4caab729f73e47a4cfa01d4361a3c0feb7d545f6..43d28c8399ae8248e6df9eb0010795532e4b3053 100644
--- a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorShowCLI.java
@@ -17,13 +17,9 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.cmstools.system;
 
-import java.util.Collection;
-
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 
-import com.netscape.certsrv.base.ResourceNotFoundException;
-import com.netscape.certsrv.system.TPSConnectorCollection;
 import com.netscape.certsrv.system.TPSConnectorData;
 import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
@@ -31,11 +27,12 @@ import com.netscape.cmstools.cli.MainCLI;
 /**
  * @author Ade Lee
  */
-public class TPSConnectorFindCLI extends CLI {
+public class TPSConnectorShowCLI extends CLI {
+
     public TPSConnectorCLI tpsConnectorCLI;
 
-    public TPSConnectorFindCLI(TPSConnectorCLI tpsConnectorCLI) {
-        super("find", "Find TPS connector details on TKS", tpsConnectorCLI);
+    public TPSConnectorShowCLI(TPSConnectorCLI tpsConnectorCLI) {
+        super("show", "Show TPS connector details on TKS", tpsConnectorCLI);
         this.tpsConnectorCLI = tpsConnectorCLI;
     }
 
@@ -44,8 +41,10 @@ public class TPSConnectorFindCLI extends CLI {
     }
 
     public void execute(String[] args) throws Exception {
+
         Option option = new Option(null, "host", true, "TPS host");
         option.setArgName("host");
+        option.setRequired(true);
         options.addOption(option);
 
         option = new Option(null, "port", true, "TPS port");
@@ -64,41 +63,11 @@ public class TPSConnectorFindCLI extends CLI {
         }
 
         String tpsHost = cmd.getOptionValue("host");
-        String tpsPort = cmd.getOptionValue("port");
+        String tpsPort = cmd.getOptionValue("port", "443");
 
-        if (tpsHost != null) {
-            if (tpsPort == null)
-                tpsPort = "443";
-            try {
-                TPSConnectorData data = tpsConnectorCLI.tpsConnectorClient.getConnector(
-                        tpsHost, tpsPort);
-                TPSConnectorCLI.printConnectorInfo(data);
-            } catch (ResourceNotFoundException e) {
-                System.out.println("  TPS connector not found.");
-                return;
-            }
-        } else {
-            TPSConnectorCollection result = tpsConnectorCLI.tpsConnectorClient.listConnectors();
-            Collection<TPSConnectorData> conns = result.getEntries();
+        TPSConnectorData data = tpsConnectorCLI.tpsConnectorClient.getConnector(tpsHost, tpsPort);
 
-            if (conns.isEmpty()) {
-                System.out.println("  No TPS connectors found.");
-                return;
-            }
-
-            MainCLI.printMessage(conns.size() + " TPS connector(s) matched");
-            boolean first = true;
-            for (TPSConnectorData data: conns) {
-                if (first) {
-                    first = false;
-                } else {
-                    System.out.println();
-                }
-
-                TPSConnectorCLI.printConnectorInfo(data);
-            }
-
-            MainCLI.printMessage("Number of entries returned " + conns.size());
-        }
+        MainCLI.printMessage("TPS Connector \"" + tpsHost + ":" + tpsPort + "\"");
+        TPSConnectorCLI.printConnectorInfo(data);
     }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/authenticator/AuthenticatorFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/authenticator/AuthenticatorFindCLI.java
index 2ff8288a012b56ecc544970d640dcce034aab0e8..81724bb31a3c82d277ef2938186f0302890d0eb7 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/authenticator/AuthenticatorFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/authenticator/AuthenticatorFindCLI.java
@@ -74,7 +74,8 @@ public class AuthenticatorFindCLI extends CLI {
         AuthenticatorCollection result = authenticatorCLI.authenticatorClient.findAuthenticators(start, size);
         Collection<AuthenticatorData> authenticators = result.getEntries();
 
-        MainCLI.printMessage(authenticators.size() + " authenticator(s) matched");
+        MainCLI.printMessage(result.getTotal() + " authenticator(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java
index 4d0827cb385268657227178bbf412d47042fb370..9ba66a62a66f71d9f8fb0f99b6c77b768a982168 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/cert/TPSCertFindCLI.java
@@ -74,7 +74,8 @@ public class TPSCertFindCLI extends CLI {
         TPSCertCollection result = certCLI.certClient.findCerts(start, size);
         Collection<TPSCertData> certs = result.getEntries();
 
-        MainCLI.printMessage(certs.size() + " certificate(s) matched");
+        MainCLI.printMessage(result.getTotal() + " certificate(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/connection/ConnectionFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/connection/ConnectionFindCLI.java
index 6112db4ff2b733d923111f5416d137da462080a1..7cb4c1b165fd3b24e636f645d2b2e521b779afbc 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/connection/ConnectionFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/connection/ConnectionFindCLI.java
@@ -74,7 +74,8 @@ public class ConnectionFindCLI extends CLI {
         ConnectionCollection result = connectionCLI.connectionClient.findConnections(start, size);
         Collection<ConnectionData> connections = result.getEntries();
 
-        MainCLI.printMessage(connections.size() + " connection(s) matched");
+        MainCLI.printMessage(result.getTotal() + " connection(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileFindCLI.java
index 9f822f6ba5ad9f3045c41396527d578f96976552..9076414622481e89994331eae8b5405a8aeedf7b 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileFindCLI.java
@@ -74,7 +74,8 @@ public class ProfileFindCLI extends CLI {
         ProfileCollection result = profileCLI.profileClient.findProfiles(start, size);
         Collection<ProfileData> profiles = result.getEntries();
 
-        MainCLI.printMessage(profiles.size() + " profile(s) matched");
+        MainCLI.printMessage(result.getTotal() + " profile(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileMappingFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileMappingFindCLI.java
index d96268be72295a457ebece8261100635ed62fee9..6e101a0494289ff9549d9758d5034ff078c5a904 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileMappingFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileMappingFindCLI.java
@@ -74,7 +74,8 @@ public class ProfileMappingFindCLI extends CLI {
         ProfileMappingCollection result = profileMappingCLI.profileMappingClient.findProfileMappings(start, size);
         Collection<ProfileMappingData> profileMappings = result.getEntries();
 
-        MainCLI.printMessage(profileMappings.size() + " profile mapping(s) matched");
+        MainCLI.printMessage(result.getTotal() + " profile mapping(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/token/TokenFindCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/token/TokenFindCLI.java
index 3ade40bb921f6188005f295ab0ce3988874745e3..2e43f3cddd8d4a8bd1e2eb3b237c17474cec266a 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/token/TokenFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/token/TokenFindCLI.java
@@ -74,7 +74,8 @@ public class TokenFindCLI extends CLI {
         TokenCollection result = tokenCLI.tokenClient.findTokens(start, size);
         Collection<TokenData> tokens = result.getEntries();
 
-        MainCLI.printMessage(tokens.size() + " token(s) matched");
+        MainCLI.printMessage(result.getTotal() + " token(s) matched");
+        if (result.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/user/UserCertFindCLI.java b/base/java-tools/src/com/netscape/cmstools/user/UserCertFindCLI.java
index 680b6b362a0266078699a54508cf4c5d7b7d838f..db7c0304b1b1498fe3da5a521b18f14af30eedc1 100644
--- a/base/java-tools/src/com/netscape/cmstools/user/UserCertFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/user/UserCertFindCLI.java
@@ -82,9 +82,10 @@ public class UserCertFindCLI extends CLI {
 
         UserCertCollection response = userCertCLI.userClient.findUserCerts(userID, start, size);
 
-        Collection<UserCertData> entries = response.getCerts();
+        Collection<UserCertData> entries = response.getEntries();
 
-        MainCLI.printMessage(entries.size() + " user cert(s) matched");
+        MainCLI.printMessage(response.getTotal() + " user cert(s) matched");
+        if (response.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/user/UserFindCLI.java b/base/java-tools/src/com/netscape/cmstools/user/UserFindCLI.java
index 4b081920eee32b3a32de72d6221104be620bca14..ed49d1c656390f9bf9b6fbe2b7c5fcd56a908b91 100644
--- a/base/java-tools/src/com/netscape/cmstools/user/UserFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/user/UserFindCLI.java
@@ -76,9 +76,10 @@ public class UserFindCLI extends CLI {
 
         UserCollection response = userCLI.userClient.findUsers(filter, start, size);
 
-        Collection<UserData> entries = response.getUsers();
+        Collection<UserData> entries = response.getEntries();
 
-        MainCLI.printMessage(entries.size() + " user(s) matched");
+        MainCLI.printMessage(response.getTotal() + " user(s) matched");
+        if (response.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/java-tools/src/com/netscape/cmstools/user/UserMembershipFindCLI.java b/base/java-tools/src/com/netscape/cmstools/user/UserMembershipFindCLI.java
index 129aa6dc829a135e89e1f2dc44604f2c1418ace9..66b8f36bbf44e4c67efabaa4efab9ceb129f7637 100644
--- a/base/java-tools/src/com/netscape/cmstools/user/UserMembershipFindCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/user/UserMembershipFindCLI.java
@@ -82,9 +82,10 @@ public class UserMembershipFindCLI extends CLI {
 
         UserMembershipCollection response = userMembershipCLI.userClient.findUserMemberships(userID, start, size);
 
-        Collection<UserMembershipData> entries = response.getMemberships();
+        Collection<UserMembershipData> entries = response.getEntries();
 
-        MainCLI.printMessage(entries.size()+" membership(s) matched");
+        MainCLI.printMessage(response.getTotal() + " membership(s) matched");
+        if (response.getTotal() == 0) return;
 
         boolean first = true;
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
index 9f976d4019847c9176a116153d723cb43c462084..b38277dd03c1f3fd905ab429d552e65245b8a3df 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
@@ -124,11 +124,12 @@ public class GroupMemberProcessor extends Processor {
             // return entries up to the page size
             for ( ; i<start+size && members.hasMoreElements(); i++) {
                 String memberID = members.nextElement();
-                response.addMember(createGroupMemberData(groupID, memberID));
+                response.addEntry(createGroupMemberData(groupID, memberID));
             }
 
             // count the total entries
             for ( ; members.hasMoreElements(); i++) members.nextElement();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java
index 3f250517a21fdcb6e3419bcf5b301659a41ece78..17c4387a37ecc71d4747ed00a5136b7423bf6280 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java
@@ -109,7 +109,6 @@ public class GroupService extends PKIService implements GroupResource {
             Enumeration<IGroup> groups = userGroupManager.listGroups(filter);
 
             GroupCollection response = new GroupCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -118,11 +117,12 @@ public class GroupService extends PKIService implements GroupResource {
             // return entries up to the page size
             for ( ; i<start+size && groups.hasMoreElements(); i++) {
                 IGroup group = groups.nextElement();
-                response.addGroup(createGroupData(group));
+                response.addEntry(createGroupData(group));
             }
 
             // count the total entries
             for ( ; groups.hasMoreElements(); i++) groups.nextElement();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java b/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java
index 3f172abeb50e2f89a2407ee535136b81c53fb8b4..b32bf67566c4d64e99ab8251e04662662cdfe44b 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java
@@ -28,6 +28,7 @@ import java.security.cert.CertificateNotYetValidException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -137,7 +138,6 @@ public class UserService extends PKIService implements UserResource {
             Enumeration<IUser> users = userGroupManager.findUsers(filter);
 
             UserCollection response = new UserCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -146,11 +146,12 @@ public class UserService extends PKIService implements UserResource {
             // return entries up to the page size
             for ( ; i<start+size && users.hasMoreElements(); i++) {
                 IUser user = users.nextElement();
-                response.addUser(createUserData(user));
+                response.addEntry(createUserData(user));
             }
 
             // count the total entries
             for ( ; users.hasMoreElements(); i++) users.nextElement();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
@@ -556,24 +557,33 @@ public class UserService extends PKIService implements UserResource {
                 throw new UserNotFoundException(userID);
             }
 
+            X509Certificate[] certs = user.getX509Certificates();
+            if (certs == null) certs = new X509Certificate[0];
+            Iterator<X509Certificate> entries = Arrays.asList(certs).iterator();
+
             UserCertCollection response = new UserCertCollection();
+            int i = 0;
 
-            X509Certificate[] certs = user.getX509Certificates();
-            if (certs != null) {
-                for (int i=start; i<start+size && i<certs.length; i++) {
-                    X509Certificate cert = certs[i];
-                    response.addCert(createUserCertData(userID, cert));
-                }
+            // skip to the start of the page
+            for ( ; i<start && entries.hasNext(); i++) entries.next();
 
-                if (start > 0) {
-                    URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
-                    response.addLink(new Link("prev", uri));
-                }
+            // return entries up to the page size
+            for ( ; i<start+size && entries.hasNext(); i++) {
+                response.addEntry(createUserCertData(userID, entries.next()));
+            }
 
-                if (start+size < certs.length) {
-                    URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
-                    response.addLink(new Link("next", uri));
-                }
+            // count the total entries
+            for ( ; entries.hasNext(); i++) entries.next();
+            response.setTotal(i);
+
+            if (start > 0) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                response.addLink(new Link("prev", uri));
+            }
+
+            if (start+size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+                response.addLink(new Link("next", uri));
             }
 
             return response;
@@ -944,10 +954,9 @@ public class UserService extends PKIService implements UserResource {
                 throw new UserNotFoundException(userID);
             }
 
-            UserMembershipCollection response = new UserMembershipCollection();
-
             Enumeration<IGroup> groups = userGroupManager.findGroupsByUser(user.getUserDN());
 
+            UserMembershipCollection response = new UserMembershipCollection();
             int i = 0;
 
             // skip to the start of the page
@@ -956,11 +965,12 @@ public class UserService extends PKIService implements UserResource {
             // return entries up to the page size
             for ( ; i<start+size && groups.hasMoreElements(); i++) {
                 IGroup group = groups.nextElement();
-                response.addMembership(createUserMembershipData(userID, group.getName()));
+                response.addEntry(createUserMembershipData(userID, group.getName()));
             }
 
             // count the total entries
             for ( ; groups.hasMoreElements(); i++) groups.nextElement();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java
index 26f25bd4f2c93bdec9a7e711331f44738910896c..9351ffe6042dbe82008cc9536e98035a6ed261a7 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java
@@ -8,6 +8,7 @@ import java.security.NoSuchAlgorithmException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.TreeSet;
 
 import javax.servlet.http.HttpServletRequest;
@@ -53,21 +54,46 @@ public class TPSConnectorService implements TPSConnectorResource {
     @Context
     private HttpServletRequest servletRequest;
 
+    public final static int DEFAULT_SIZE = 20;
+
     public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
 
     @Override
-    public TPSConnectorCollection listConnectors() {
+    public TPSConnectorCollection findConnectors(Integer start, Integer size) {
         try {
-            TPSConnectorCollection ret = new TPSConnectorCollection();
             String tpsList = cs.getString(TPS_LIST, "");
+            Iterator<String> entries = Arrays.asList(StringUtils.split(tpsList,",")).iterator();
 
-            for (String tpsID : StringUtils.split(tpsList,",")) {
-                ret.addEntry(createTPSConnectorData(tpsID));
+            TPSConnectorCollection response = new TPSConnectorCollection();
+            int i = 0;
+
+            // skip to the start of the page
+            for ( ; i<start && entries.hasNext(); i++) entries.next();
+
+            // return entries up to the page size
+            for ( ; i<start+size && entries.hasNext(); i++) {
+                response.addEntry(createTPSConnectorData(entries.next()));
+            }
+
+            // count the total entries
+            for ( ; entries.hasNext(); i++) entries.next();
+            response.setTotal(i);
+
+            if (start > 0) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                response.addLink(new Link("prev", uri));
             }
-            return ret;
+
+            if (start+size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+                response.addLink(new Link("next", uri));
+            }
+
+            return response;
+
         } catch (EBaseException e) {
             e.printStackTrace();
-            throw new PKIException("Unable to get TPS connection data" + e);
+            throw new PKIException("Unable to get TPS connection data: " + e);
         }
     }
 
diff --git a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java
index da7708e49b7a1c2dc1e41bfd6b84caf7a69fa9ff..4fcddb7e473912366e5e60a5f8201f97296d2fe1 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java
@@ -21,6 +21,8 @@ package com.netscape.cmscore.selftests;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.Iterator;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Context;
@@ -96,14 +98,38 @@ public class SelfTestService extends PKIService implements SelfTestResource {
         CMS.debug("SelfTestService.findSelfTests()");
 
         try {
+            start = start == null ? 0 : start;
+            size = size == null ? DEFAULT_SIZE : size;
+
+            ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+            Iterator<String> entries = Arrays.asList(subsystem.listSelfTestsEnabledOnDemand()).iterator();
+
             SelfTestCollection response = new SelfTestCollection();
+            int i = 0;
 
-            ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
-            for (String name : subsystem.listSelfTestsEnabledOnDemand()) {
-                SelfTestData data = createSelfTestData(subsystem, name);
+            // skip to the start of the page
+            for ( ; i<start && entries.hasNext(); i++) entries.next();
+
+            // return entries up to the page size
+            for ( ; i<start+size && entries.hasNext(); i++) {
+                SelfTestData data = createSelfTestData(subsystem, entries.next());
                 response.addEntry(data);
             }
 
+            // count the total entries
+            for ( ; entries.hasNext(); i++) entries.next();
+            response.setTotal(i);
+
+            if (start > 0) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                response.addLink(new Link("prev", uri));
+            }
+
+            if (start+size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+                response.addLink(new Link("next", uri));
+            }
+
             return response;
 
         } catch (Exception e) {
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/authenticator/AuthenticatorService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/authenticator/AuthenticatorService.java
index e1d7ed5cf80fb1e74df72c98bb18e38037ec2c64..6b77a05332b483881eafe066de0cbccd15878c50 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/authenticator/AuthenticatorService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/authenticator/AuthenticatorService.java
@@ -105,7 +105,6 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
             Iterator<AuthenticatorRecord> authenticators = database.getRecords().iterator();
 
             AuthenticatorCollection response = new AuthenticatorCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -118,6 +117,7 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
 
             // count the total entries
             for ( ; authenticators.hasNext(); i++) authenticators.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cert/TPSCertService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cert/TPSCertService.java
index e6f805839dfc3556b8a8de711eb8ad736d0c4819..238ac12dfbc27862aebe4b5f63e78e111433f186 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cert/TPSCertService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cert/TPSCertService.java
@@ -120,7 +120,6 @@ public class TPSCertService extends PKIService implements TPSCertResource {
             Iterator<TPSCertRecord> activities = database.getRecords().iterator();
 
             TPSCertCollection response = new TPSCertCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -133,6 +132,7 @@ public class TPSCertService extends PKIService implements TPSCertResource {
 
             // count the total entries
             for ( ; activities.hasNext(); i++) activities.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/connection/ConnectionService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/connection/ConnectionService.java
index 034af5afdb54fc30e87f1a6ce75cb22a89960601..97043bca5fff2c2fcccab3d7006e7c231124e305 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/connection/ConnectionService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/connection/ConnectionService.java
@@ -105,7 +105,6 @@ public class ConnectionService extends PKIService implements ConnectionResource
             Iterator<ConnectionRecord> connections = database.getRecords().iterator();
 
             ConnectionCollection response = new ConnectionCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -118,6 +117,7 @@ public class ConnectionService extends PKIService implements ConnectionResource
 
             // count the total entries
             for ( ; connections.hasNext(); i++) connections.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/logging/ActivityService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/logging/ActivityService.java
index 16054b414816c3dabfd5c9b4002cd50ce5d42383..5cfb090bfc94efd3785c6fbefe259af74cb3b2e5 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/logging/ActivityService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/logging/ActivityService.java
@@ -110,7 +110,6 @@ public class ActivityService extends PKIService implements ActivityResource {
             Iterator<ActivityRecord> activities = database.getRecords().iterator();
 
             ActivityCollection response = new ActivityCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -123,6 +122,7 @@ public class ActivityService extends PKIService implements ActivityResource {
 
             // count the total entries
             for ( ; activities.hasNext(); i++) activities.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileMappingService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileMappingService.java
index d23485ddd8cccfa573dbd2b1978dbf041e9fdcb4..f9432104b31b2c4ef8a67740af3e0602d97f73ee 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileMappingService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileMappingService.java
@@ -105,7 +105,6 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
             Iterator<ProfileMappingRecord> profileMappings = database.getRecords().iterator();
 
             ProfileMappingCollection response = new ProfileMappingCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -118,6 +117,7 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
             // count the total entries
             for ( ; profileMappings.hasNext(); i++) profileMappings.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileService.java
index 6e52aeec6fe6e19cc8bb219b429a183c73d5a4c2..9bff5188ff12b60fa163765e96983a63901fb5bf 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/ProfileService.java
@@ -108,7 +108,6 @@ public class ProfileService extends PKIService implements ProfileResource {
             Iterator<ProfileRecord> profiles = database.getRecords().iterator();
 
             ProfileCollection response = new ProfileCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -121,6 +120,7 @@ public class ProfileService extends PKIService implements ProfileResource {
 
             // count the total entries
             for ( ; profiles.hasNext(); i++) profiles.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/token/TokenService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/token/TokenService.java
index aa01fd64b0871efff2b41c9db42c3d81e40ee31c..95802e3e2b72beebb69d2c0dbbeb3ec0d90f0290 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/token/TokenService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/token/TokenService.java
@@ -121,7 +121,6 @@ public class TokenService extends PKIService implements TokenResource {
             Iterator<TokenRecord> tokens = database.getRecords().iterator();
 
             TokenCollection response = new TokenCollection();
-
             int i = 0;
 
             // skip to the start of the page
@@ -134,6 +133,7 @@ public class TokenService extends PKIService implements TokenResource {
 
             // count the total entries
             for ( ; tokens.hasNext(); i++) tokens.next();
+            response.setTotal(i);
 
             if (start > 0) {
                 URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
-- 
1.8.1.4

