>From c3801e7b9faf35eab4d98a75cd1d5feecad3deaf Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Tue, 14 May 2013 15:57:52 -0400
Subject: [PATCH] Add interfaces for managing profiles

This adds the initial framework for viewing and managing profiles.
Also adds CLI code for viewing/adding/deleting and editing profiles.
---
 .../src/com/netscape/cms/servlet/test/CATest.java  | 138 +++----
 .../certsrv/cert/CertEnrollmentRequest.java        |  69 ++--
 .../netscape/certsrv/profile/IPolicyDefault.java   |   1 +
 .../src/com/netscape/certsrv/profile/IProfile.java |  24 ++
 .../netscape/certsrv/profile/PolicyConstraint.java |  11 +
 .../certsrv/profile/PolicyConstraintValue.java     |  14 +-
 .../netscape/certsrv/profile/PolicyDefault.java    |  22 +
 .../netscape/certsrv/profile/ProfileClient.java    |  73 ++++
 .../com/netscape/certsrv/profile/ProfileData.java  | 289 ++++++++++++--
 .../com/netscape/certsrv/profile/ProfileInput.java | 113 ++++--
 .../netscape/certsrv/profile/ProfileOutput.java    |  52 ++-
 .../netscape/certsrv/profile/ProfileParameter.java |  66 +++
 .../netscape/certsrv/profile/ProfileResource.java  |  53 ++-
 .../com/netscape/certsrv/property/Descriptor.java  |   8 +
 .../netscape/cms/profile/common/BasicProfile.java  |  42 ++
 .../netscape/cms/servlet/cert/CertProcessor.java   |   7 +-
 .../servlet/cert/CertReviewResponseFactory.java    |   4 +-
 .../cms/servlet/cert/EnrollmentProcessor.java      |   7 +-
 .../servlet/profile/PolicyConstraintFactory.java   |   7 +-
 .../cms/servlet/profile/PolicyDefaultFactory.java  |  30 ++
 .../cms/servlet/profile/ProfileInputFactory.java   |  11 +-
 .../cms/servlet/profile/ProfileProcessServlet.java |   4 +-
 .../cms/servlet/profile/ProfileService.java        | 444 +++++++++++++++++++--
 .../src/com/netscape/cmstools/cli/MainCLI.java     |   2 +
 .../netscape/cmstools/profile/ProfileAddCLI.java   |  60 +++
 .../com/netscape/cmstools/profile/ProfileCLI.java  | 118 ++++++
 .../cmstools/profile/ProfileDisableCLI.java        |  34 ++
 .../cmstools/profile/ProfileEnableCLI.java         |  33 ++
 .../netscape/cmstools/profile/ProfileFindCLI.java  |  39 ++
 .../cmstools/profile/ProfileModifyCLI.java         |  61 +++
 .../cmstools/profile/ProfileRemoveCLI.java         |  33 ++
 .../netscape/cmstools/profile/ProfileShowCLI.java  |  71 ++++
 32 files changed, 1643 insertions(+), 297 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/profile/ProfileClient.java
 create mode 100644 base/common/src/com/netscape/certsrv/profile/ProfileParameter.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileDisableCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileEnableCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileFindCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileModifyCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileRemoveCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/profile/ProfileShowCLI.java

diff --git a/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java b/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java
index 33dcfdfee02bac37c86ef9b1b29debde64ea1bb0..3134f581466cef6e796b8d376dbcc6ad228e2cfd 100644
--- a/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java
+++ b/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java
@@ -18,8 +18,6 @@
 package com.netscape.cms.servlet.test;
 
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.cli.CommandLine;
@@ -45,6 +43,7 @@ import com.netscape.certsrv.cert.CertReviewResponse;
 import com.netscape.certsrv.cert.CertSearchRequest;
 import com.netscape.certsrv.client.ClientConfig;
 import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileData;
 import com.netscape.certsrv.profile.ProfileDataInfo;
 import com.netscape.certsrv.profile.ProfileDataInfos;
@@ -319,26 +318,26 @@ public class CATest {
         //Simulate a "caUserCert" Profile enrollment
 
         ProfileInput certReq = data.createInput("Key Generation");
-        certReq.setInputAttr("cert_request_type", "crmf");
-        certReq.setInputAttr(
+        certReq.addAttribute(new ProfileAttribute("cert_request_type", "crmf", null));
+        certReq.addAttribute(new ProfileAttribute(
                 "cert_request",
-                "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz");
+                "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz", null));
 
         ProfileInput subjectName = data.createInput("Subject Name");
-        subjectName.setInputAttr("sn_uid", "jmagne");
-        subjectName.setInputAttr("sn_e", "jmagne@redhat.com");
-        subjectName.setInputAttr("sn_c", "US");
-        subjectName.setInputAttr("sn_ou", "Development");
-        subjectName.setInputAttr("sn_ou1", "IPA");
-        subjectName.setInputAttr("sn_ou2", "Dogtag");
-        subjectName.setInputAttr("sn_ou3", "CA");
-        subjectName.setInputAttr("sn_cn", "Common");
-        subjectName.setInputAttr("sn_o", "RedHat");
+        subjectName.addAttribute(new ProfileAttribute("sn_uid", "jmagne", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_e", "jmagne@redhat.com", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_c", "US", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou", "Development", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou1", "IPA", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou2", "Dogtag", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou3", "CA", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_cn", "Common", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_o", "RedHat", null));
 
         ProfileInput submitter = data.createInput("Requestor Information");
-        submitter.setInputAttr("requestor_name", "admin");
-        submitter.setInputAttr("requestor_email", "admin@redhat.com");
-        submitter.setInputAttr("requestor_phone", "650-555-5555");
+        submitter.addAttribute(new ProfileAttribute("requestor_name", "admin", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_email", "admin@redhat.com", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_phone", "650-555-5555", null));
         return data;
     }
 
@@ -350,20 +349,20 @@ public class CATest {
         //Simulate a "caUserCert" Profile enrollment
 
         ProfileInput certReq = data.createInput("Key Generation");
-        certReq.setInputAttr("cert_request_type", "crmf");
-        certReq.setInputAttr(
+        certReq.addAttribute(new ProfileAttribute("cert_request_type", "crmf", null));
+        certReq.addAttribute(new ProfileAttribute(
                 "cert_request",
-                "MIIB5DCCAeAwggFGAgQTosnaMIIBB4ABAqVOMEwxETAPBgNVBAMTCGFsZWUgcmEzMR4wHAYJKoZIhvcNAQkBFg9hbGVlQHJlZGhhdC5jb20xFzAVBgoJkiaJk/IsZAEBEwdhbGVlcmEzpoGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkQh3k+1323YgQD+oA9yzftqxbGQlsbz0f2OEeOL5h0uhg/qPlSNMjRN3mAeuaNyF0n/Bdxv4699gRTsyEaVJu7HX+kauSCZv+J0tvHiYuHQz1/TSscU9TNLyQjgXVKQFHEdjZa2cQNdmMDUFWrftAK6BFnsP3Tu712qZPAuBH9QIDAQABqRAwDgYDVR0PAQH/BAQDAgXgMDMwFQYJKwYBBQUHBQEBDAhyZWdUb2tlbjAaBgkrBgEFBQcFAQIMDWF1dGhlbnRpY2F0b3KhgZMwDQYJKoZIhvcNAQEFBQADgYEATNi3vMxn9KMto999sR4ik851jqbb6L0GL1KKgQ/hjIAACQb2H+0OpqeZ2+DcGd+oAQn1YZe8aPoFu+HOWjHlY1E2tm7TI1B6JpCL3TMag3mYryROX7l7LFEa1P730aGOWJF874bG8UWisU190zhCBQUqUjsd9DwaP42qM0gnzas=");
+                "MIIB5DCCAeAwggFGAgQTosnaMIIBB4ABAqVOMEwxETAPBgNVBAMTCGFsZWUgcmEzMR4wHAYJKoZIhvcNAQkBFg9hbGVlQHJlZGhhdC5jb20xFzAVBgoJkiaJk/IsZAEBEwdhbGVlcmEzpoGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkQh3k+1323YgQD+oA9yzftqxbGQlsbz0f2OEeOL5h0uhg/qPlSNMjRN3mAeuaNyF0n/Bdxv4699gRTsyEaVJu7HX+kauSCZv+J0tvHiYuHQz1/TSscU9TNLyQjgXVKQFHEdjZa2cQNdmMDUFWrftAK6BFnsP3Tu712qZPAuBH9QIDAQABqRAwDgYDVR0PAQH/BAQDAgXgMDMwFQYJKwYBBQUHBQEBDAhyZWdUb2tlbjAaBgkrBgEFBQcFAQIMDWF1dGhlbnRpY2F0b3KhgZMwDQYJKoZIhvcNAQEFBQADgYEATNi3vMxn9KMto999sR4ik851jqbb6L0GL1KKgQ/hjIAACQb2H+0OpqeZ2+DcGd+oAQn1YZe8aPoFu+HOWjHlY1E2tm7TI1B6JpCL3TMag3mYryROX7l7LFEa1P730aGOWJF874bG8UWisU190zhCBQUqUjsd9DwaP42qM0gnzas=", null));
 
         ProfileInput subjectName = data.createInput("Subject Name");
-        subjectName.setInputAttr("sn_uid", "aleera3");
-        subjectName.setInputAttr("sn_e", "alee@redhat.com");
-        subjectName.setInputAttr("sn_cn", "alee ra3");
+        subjectName.addAttribute(new ProfileAttribute("sn_uid", "aleera3", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_e", "alee@redhat.com", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_cn", "alee ra3", null));
 
         ProfileInput submitter = data.createInput("Requestor Information");
-        submitter.setInputAttr("requestor_name", "admin");
-        submitter.setInputAttr("requestor_email", "admin@redhat.com");
-        submitter.setInputAttr("requestor_phone", "650-555-1234");
+        submitter.addAttribute(new ProfileAttribute("requestor_name", "admin", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_email", "admin@redhat.com", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_phone", "650-555-1234", null));
         return data;
     }
 
@@ -375,19 +374,20 @@ public class CATest {
         //Simulate a "caUserCert" Profile enrollment
 
         ProfileInput certReq = data.createInput("Key Generation");
-        certReq.setInputAttr("cert_request_type", "pkcs10");
-        certReq.setInputAttr(
+        certReq.addAttribute(new ProfileAttribute("cert_request_type", "pkcs10", null));
+        certReq.addAttribute(new ProfileAttribute(
                 "cert_request",
-                "MIIBZjCB0AIBADAnMQ8wDQYDVQQKEwZyZWRoYXQxFDASBgNVBAMTC2FsZWUtd29ya3BjMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJtuKg9osJEBUwz8LoMQwwm1m7D97NNJEmvEhvBMet+VCtbd/erAFMoVXEgSKks/XFK2ViTeZYpp0A2pe4bm4yxowZm0b6von9BKGQ0jNtLemoOkGRWC/PP+fYP16aH62xu4z8MH1pBubdlAEp3Ppnr93aB1lzQaPVmcR3B4OWhwIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAgZhZOe0LqQD5iywAO7sY0PANVGzzdcmoLZJjjASY3kU5E3K8u3FKh24WJxcWzdC+/FysDkJixJb7xGUm697QwZvGxmAIQH4yIebWJ2KLHQQgRJytjVYySrRo2Fuo/dm2zzf3+o8WBuD2eMsEjsZfuKxhz7EahvyC2y/CuTBA08s="
+                "MIIBZjCB0AIBADAnMQ8wDQYDVQQKEwZyZWRoYXQxFDASBgNVBAMTC2FsZWUtd29ya3BjMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJtuKg9osJEBUwz8LoMQwwm1m7D97NNJEmvEhvBMet+VCtbd/erAFMoVXEgSKks/XFK2ViTeZYpp0A2pe4bm4yxowZm0b6von9BKGQ0jNtLemoOkGRWC/PP+fYP16aH62xu4z8MH1pBubdlAEp3Ppnr93aB1lzQaPVmcR3B4OWhwIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAgZhZOe0LqQD5iywAO7sY0PANVGzzdcmoLZJjjASY3kU5E3K8u3FKh24WJxcWzdC+/FysDkJixJb7xGUm697QwZvGxmAIQH4yIebWJ2KLHQQgRJytjVYySrRo2Fuo/dm2zzf3+o8WBuD2eMsEjsZfuKxhz7EahvyC2y/CuTBA08s=",
+                null)
         );
         ProfileInput subjectName = data.createInput("Subject Name");
-        subjectName.setInputAttr("sn_cn", "alee-workpc");
-        subjectName.setInputAttr("sn_o", "redhat");
+        subjectName.addAttribute(new ProfileAttribute("sn_cn", "alee-workpc", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_o", "redhat", null));
 
         ProfileInput submitter = data.createInput("Requestor Information");
-        submitter.setInputAttr("requestor_name", "admin");
-        submitter.setInputAttr("requestor_email", "admin@redhat.com");
-        submitter.setInputAttr("requestor_phone", "650-555-5555");
+        submitter.addAttribute(new ProfileAttribute("requestor_name", "admin", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_email", "admin@redhat.com", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_phone", "650-555-5555", null));
         return data;
     }
 
@@ -399,18 +399,9 @@ public class CATest {
         }
 
         Collection<ProfileDataInfo> listProfiles = pInfos.getProfileInfos();
-        Iterator<ProfileDataInfo> iter = null;
-
         if (listProfiles != null) {
-            iter = listProfiles.iterator();
-        }
-
-        log("\nProfiles found. \n");
-
-        while (iter != null && iter.hasNext()) {
-            ProfileDataInfo info = iter.next();
-
-            if (info != null) {
+            log("\nProfiles found. \n");
+            for (ProfileDataInfo info: listProfiles) {
                 printProfileDataInfo(info);
             }
         }
@@ -436,40 +427,19 @@ public class CATest {
         log("Name: " + info.getName());
         log("Description: " + info.getDescription());
         log("EnabledBy: " + info.getEnabledBy());
-        log("IsEnabled: " + info.getIsEnabled());
-        log("IsVisible: " + info.getIsVisible() + "\n\n");
+        log("Enabled: " + info.isEnabled());
+        log("Visible: " + info.isVisible() + "\n\n");
 
         log("Profile Input Information: \n");
 
-        List<ProfileInput> inputs = info.getProfileInputsList();
-
-        if (inputs != null) {
-            Iterator<ProfileInput> it = inputs.iterator();
-
-            ProfileInput curInput = null;
-            while (it.hasNext()) {
-                curInput = it.next();
-
-                if (curInput != null) {
-
-                    log("Input Name: " + curInput.getInputId());
-
-                    Map<String, String> attrs = curInput.getAttributes();
-
-                    if (!attrs.isEmpty()) {
-                        for (String key : attrs.keySet()) {
-                            String value = attrs.get(key);
-
-                            log("Input Attribute Name: " + key + "\n");
-                            log("Input Attribute Value: " + value + "\n");
-                        }
-                    }
-
-                }
+        Map<String, ProfileInput> inputs = info.getInputs();
+        for (Map.Entry<String, ProfileInput> entry : inputs.entrySet()) {
+            log("Input Id: " + entry.getKey());
+            for (ProfileAttribute attr: entry.getValue().getAttrs()) {
+                log("Input Attribute Name: " + attr.getName() + "\n");
+                log("Input Attribute Value: " + attr.getValue() + "\n");
             }
-
         }
-
     }
 
     private static void printCertInfos(CertDataInfos infos, String filter) {
@@ -480,18 +450,10 @@ public class CATest {
         }
 
         Collection<CertDataInfo> listCerts = infos.getCertInfos();
-        Iterator<CertDataInfo> iter = null;
-
         if (listCerts != null) {
-            iter = listCerts.iterator();
-        }
-
-        log("\nCertificates found with search filter: " + filter + "\n");
-
-        while (iter != null && iter.hasNext()) {
-            CertDataInfo info = iter.next();
-            if (info != null) {
-                printCertInfo(info);
+            log("\nCertificates found with search filter: " + filter + "\n");
+            for (CertDataInfo info: listCerts) {
+                if (info != null) printCertInfo(info);
             }
         }
     }
@@ -533,11 +495,7 @@ public class CATest {
             log("No requests found");
             return;
         }
-
-        Iterator<CertRequestInfo> iter = list.iterator();
-
-        while (iter != null && iter.hasNext()) {
-            CertRequestInfo info = iter.next();
+        for (CertRequestInfo info: list) {
             printRequestInfo(info);
         }
     }
diff --git a/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java b/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java
index fefef9a4625433851f408781683f8d2c4be00d23..f5feda0fda0ade4d0675a7dec7d233f977eb9815 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java
@@ -25,9 +25,7 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 
 import javax.ws.rs.core.MultivaluedMap;
 import javax.xml.bind.JAXBContext;
@@ -39,6 +37,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
+import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileInput;
 import com.netscape.certsrv.profile.ProfileOutput;
 
@@ -111,7 +110,7 @@ public class CertEnrollmentRequest {
     }
 
     public void addInput(ProfileInput input) {
-        ProfileInput curInput = getInput(input.getInputId());
+        ProfileInput curInput = getInput(input.getName());
         if (curInput != null) {
             getInputs().remove(curInput);
         }
@@ -119,7 +118,7 @@ public class CertEnrollmentRequest {
     }
 
     public void deleteInput(ProfileInput input) {
-        ProfileInput curInput = getInput(input.getInputId());
+        ProfileInput curInput = getInput(input.getName());
         if (curInput != null) {
             getInputs().remove(curInput);
         }
@@ -133,7 +132,7 @@ public class CertEnrollmentRequest {
             return oldInput;
 
         ProfileInput newInput = new ProfileInput();
-        newInput.setInputId(name);
+        newInput.setName(name);
 
         getInputs().add(newInput);
 
@@ -141,23 +140,16 @@ public class CertEnrollmentRequest {
     }
 
     public ProfileInput getInput(String name) {
-
         ProfileInput input = null;
-
-        Iterator<ProfileInput> it = getInputs().iterator();
-
-        ProfileInput curInput = null;
-        while (it.hasNext()) {
-            curInput = it.next();
-            if (curInput != null && curInput.getInputId().equals(name))
+        for (ProfileInput curInput: getInputs()) {
+            if (curInput != null && curInput.getName().equals(name))
                 break;
         }
-
         return input;
     }
 
     public void addOutput(ProfileOutput output) {
-        ProfileOutput curOutput = getOutput(output.getOutputId());
+        ProfileOutput curOutput = getOutput(output.getName());
         if (curOutput != null) {
             getOutputs().remove(curOutput);
         }
@@ -165,7 +157,7 @@ public class CertEnrollmentRequest {
     }
 
     public void deleteOutput(ProfileOutput output) {
-        ProfileOutput curOutput = getOutput(output.getOutputId());
+        ProfileOutput curOutput = getOutput(output.getName());
         if (curOutput != null) {
             getInputs().remove(curOutput);
         }
@@ -173,15 +165,10 @@ public class CertEnrollmentRequest {
 
     public ProfileOutput getOutput(String name) {
         ProfileOutput output = null;
-        ProfileOutput curOutput = null;
-
-        Iterator<ProfileOutput> it = getOutputs().iterator();
-        while (it.hasNext()) {
-            curOutput = it.next();
-            if (curOutput != null && curOutput.getOutputId().equals(name))
+        for (ProfileOutput curOutput: getOutputs()) {
+            if (curOutput != null && curOutput.getName().equals(name))
                 break;
         }
-
         return output;
     }
 
@@ -201,9 +188,8 @@ public class CertEnrollmentRequest {
         if (remoteAddr != null) ret.put("remoteAddr", remoteAddr);
 
         for (ProfileInput input: inputs) {
-            Map<String, String> attrs = input.getAttributes();
-            for (Map.Entry<String, String> entry: attrs.entrySet()) {
-                ret.put(entry.getKey(), entry.getValue());
+            for (ProfileAttribute attr:input.getAttrs()) {
+                ret.put(attr.getName(), attr.getValue());
             }
         }
 
@@ -218,26 +204,27 @@ public class CertEnrollmentRequest {
         //Simulate a "caUserCert" Profile enrollment
 
         ProfileInput certReq = data.createInput("KeyGenInput");
-        certReq.setInputAttr("cert_request_type", "crmf");
-        certReq.setInputAttr(
+        certReq.addAttribute(new ProfileAttribute("cert_request_type", "crmf", null));
+        certReq.addAttribute(new ProfileAttribute(
                 "cert_request",
-                "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz");
+                "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz",
+                null));
 
         ProfileInput subjectName = data.createInput("SubjectNameInput");
-        subjectName.setInputAttr("sn_uid", "jmagne");
-        subjectName.setInputAttr("sn_e", "jmagne@redhat.com");
-        subjectName.setInputAttr("sn_c", "US");
-        subjectName.setInputAttr("sn_ou", "Development");
-        subjectName.setInputAttr("sn_ou1", "IPA");
-        subjectName.setInputAttr("sn_ou2", "Dogtag");
-        subjectName.setInputAttr("sn_ou3", "CA");
-        subjectName.setInputAttr("sn_cn", "Common");
-        subjectName.setInputAttr("sn_o", "RedHat");
+        subjectName.addAttribute(new ProfileAttribute("sn_uid", "jmagne", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_e", "jmagne@redhat.com", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_c", "US", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou", "Development", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou1", "IPA", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou2", "Dogtag", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_ou3", "CA", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_cn", "Common", null));
+        subjectName.addAttribute(new ProfileAttribute("sn_o", "RedHat", null));
 
         ProfileInput submitter = data.createInput("SubmitterInfoInput");
-        submitter.setInputAttr("requestor_name", "admin");
-        submitter.setInputAttr("requestor_email", "admin@redhat.com");
-        submitter.setInputAttr("requestor_phone", "650-555-5555");
+        submitter.addAttribute(new ProfileAttribute("requestor_name", "admin", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_email", "admin@redhat.com", null));
+        submitter.addAttribute(new ProfileAttribute("requestor_phone", "650-555-5555", null));
 
         try {
             JAXBContext context = JAXBContext.newInstance(CertEnrollmentRequest.class);
diff --git a/base/common/src/com/netscape/certsrv/profile/IPolicyDefault.java b/base/common/src/com/netscape/certsrv/profile/IPolicyDefault.java
index e18534d6634029318fbbabd504211a6edd5929a0..2c1d6250eb0edcbb8eeb304481d957ce3c4cc573 100644
--- a/base/common/src/com/netscape/certsrv/profile/IPolicyDefault.java
+++ b/base/common/src/com/netscape/certsrv/profile/IPolicyDefault.java
@@ -133,4 +133,5 @@ public interface IPolicyDefault extends IConfigTemplate {
      */
     public String getValue(String name, Locale locale, IRequest request)
             throws EPropertyException;
+
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/IProfile.java b/base/common/src/com/netscape/certsrv/profile/IProfile.java
index 9125b2f69f31aacc44d98230a468072432594026..1a2b7aa68b05fcc668229d13801d897ba8a3637f 100644
--- a/base/common/src/com/netscape/certsrv/profile/IProfile.java
+++ b/base/common/src/com/netscape/certsrv/profile/IProfile.java
@@ -120,6 +120,8 @@ public interface IProfile {
      */
     public void setAuthenticatorId(String id);
 
+    public void setAuthzAcl(String id);
+
     /**
      * Retrieves the associated authenticator instance.
      *
@@ -266,6 +268,12 @@ public interface IProfile {
     public void deleteProfileInput(String inputId) throws EProfileException;
 
     /**
+     * Delete all profile inputs
+     * @throws EProfileException
+     */
+    public void deleteAllProfileInputs() throws EProfileException;
+
+    /**
      * Deletes output policy by id.
      *
      * @param outputId id of the output policy
@@ -274,6 +282,12 @@ public interface IProfile {
     public void deleteProfileOutput(String outputId) throws EProfileException;
 
     /**
+     * Delete all profile inputs
+     * @exception EProfileException
+     */
+    public void deleteAllProfileOutputs() throws EProfileException;
+
+    /**
      * Creates a input policy.
      *
      * @param id input policy id
@@ -309,6 +323,12 @@ public interface IProfile {
             throws EProfileException;
 
     /**
+     * Delete all profile policies
+     * @exception EProfileException
+     */
+    public void deleteAllProfilePolicies() throws EProfileException;
+
+    /**
      * Retrieves a policy.
      *
      * @param setId set id
@@ -405,4 +425,8 @@ public interface IProfile {
      */
     public void submit(IAuthToken token, IRequest request)
             throws EDeferException, EProfileException;
+
+    public void setRenewal(boolean renewal);
+
+    public void setXMLOutput(boolean xmlOutput);
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/PolicyConstraint.java b/base/common/src/com/netscape/certsrv/profile/PolicyConstraint.java
index 8b43661a2c4ba2a4bd1774d0aac9d1852a0dab63..a0f4e9defcb71eb24b930ce275dbc4bd1f41bd4f 100644
--- a/base/common/src/com/netscape/certsrv/profile/PolicyConstraint.java
+++ b/base/common/src/com/netscape/certsrv/profile/PolicyConstraint.java
@@ -35,6 +35,9 @@ public class PolicyConstraint {
     @XmlElement(name="description")
     private String text;
 
+    @XmlElement
+    private String classId;
+
     @XmlElement(name = "constraint")
     private List<PolicyConstraintValue> constraints = new ArrayList<PolicyConstraintValue>();
 
@@ -62,6 +65,14 @@ public class PolicyConstraint {
         this.text = text;
     }
 
+    public String getClassId() {
+        return classId;
+    }
+
+    public void setClassId(String classId) {
+        this.classId = classId;
+    }
+
     public List<PolicyConstraintValue> getConstraints() {
         return constraints;
     }
diff --git a/base/common/src/com/netscape/certsrv/profile/PolicyConstraintValue.java b/base/common/src/com/netscape/certsrv/profile/PolicyConstraintValue.java
index 5241ad8323c55f755357065f4b9baa040f59ff45..a16b4c59d67741ebb23d8c451a368172f087f74b 100644
--- a/base/common/src/com/netscape/certsrv/profile/PolicyConstraintValue.java
+++ b/base/common/src/com/netscape/certsrv/profile/PolicyConstraintValue.java
@@ -34,13 +34,17 @@ public class PolicyConstraintValue {
     @XmlElement
     private Descriptor descriptor;
 
+    @XmlElement
+    private String value;
+
     public PolicyConstraintValue() {
         // required for jax-b
     }
 
-    public PolicyConstraintValue(String name, Descriptor descriptor) {
+    public PolicyConstraintValue(String name, Descriptor descriptor, String value) {
         this.name = name;
         this.descriptor = descriptor;
+        this.value = value;
     }
 
     public String getName() {
@@ -58,4 +62,12 @@ public class PolicyConstraintValue {
     public void setDescriptor(Descriptor descriptor) {
         this.descriptor = descriptor;
     }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java b/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java
index 2b95cf5f00af87451ed302b0bd4a7ef5c226b24b..f92242cc18c068dae841e1a86b10793216187167 100644
--- a/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java
+++ b/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java
@@ -32,12 +32,18 @@ public class PolicyDefault {
     @XmlAttribute(name="id")
     private String name;
 
+    @XmlAttribute
+    private String classId;
+
     @XmlElement(name="description")
     private String text;
 
     @XmlElement(name="policyAttribute")
     private List<ProfileAttribute> attributes = new ArrayList<ProfileAttribute>();
 
+    @XmlElement(name = "params")
+    private List<ProfileParameter> params = new ArrayList<ProfileParameter>();
+
     public PolicyDefault() {
         // required for jaxb
     }
@@ -62,6 +68,14 @@ public class PolicyDefault {
         this.text = text;
     }
 
+    public String getClassId() {
+        return classId;
+    }
+
+    public void setClassId(String classId) {
+        this.classId = classId;
+    }
+
     public List<ProfileAttribute> getAttributes() {
         return attributes;
     }
@@ -70,4 +84,12 @@ public class PolicyDefault {
         this.attributes = attributes;
     }
 
+    public List<ProfileParameter> getParams() {
+        return params;
+    }
+
+    public void setParams(List<ProfileParameter> params) {
+        this.params = params;
+    }
+
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileClient.java b/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..12b54cc60a1954ed8d88cf1b5399dd8e16a56e57
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileClient.java
@@ -0,0 +1,73 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.profile;
+
+import java.net.URISyntaxException;
+
+import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
+
+/**
+ * @author Ade Lee
+ */
+public class ProfileClient {
+    public PKIClient client;
+    public ProfileResource profileClient;
+
+    public ProfileClient(ClientConfig config) throws URISyntaxException {
+        this(new PKIClient(config));
+    }
+
+    public ProfileClient(PKIClient client) throws URISyntaxException {
+        this.client = client;
+        init();
+    }
+
+    public void init() throws URISyntaxException {
+        profileClient = client.createProxy(ProfileResource.class);
+    }
+
+    public ProfileData retrieveProfile(String id) {
+        return profileClient.retrieveProfile(id);
+    }
+
+    public ProfileDataInfos listProfiles() {
+        return profileClient.listProfiles();
+    }
+
+    public void enableProfile(String id) {
+        profileClient.modifyProfileState(id, "enable");
+    }
+
+    public void disableProfile(String id) {
+        profileClient.modifyProfileState(id, "disable");
+    }
+
+    public void createProfile(ProfileData data){
+        profileClient.createProfile(data);
+    }
+
+    public void modifyProfile(ProfileData data){
+        profileClient.modifyProfile(data.getId(), data);
+    }
+
+    public void deleteProfile(String id) {
+        profileClient.deleteProfile(id);
+    }
+
+}
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileData.java b/base/common/src/com/netscape/certsrv/profile/ProfileData.java
index 465981add8bc81c2f77051e031a83234aaf54179..a8bb11031d6801dc5a86ff0c23c6948822aef964 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileData.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileData.java
@@ -22,13 +22,17 @@
 package com.netscape.certsrv.profile;
 
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Vector;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
 /**
  * @author jmagne
@@ -43,22 +47,79 @@ public class ProfileData {
     protected String id;
 
     @XmlElement
+    protected String classId;
+
+    @XmlElement
     protected String name;
 
     @XmlElement
     protected String description;
 
     @XmlElement
-    protected boolean isEnabled;
+    protected boolean enabled;
 
     @XmlElement
-    protected boolean isVisible;
+    protected boolean visible;
 
     @XmlElement
     protected String enabledBy;
 
-    @XmlElement(name = "Input")
-    protected List<ProfileInput> inputs = new ArrayList<ProfileInput>();
+    @XmlElement
+    protected String authenticatorId;
+
+    @XmlElement
+    protected String authzAcl;
+
+    @XmlElement
+    protected boolean renewal;
+
+    @XmlElement
+    protected boolean isXMLOutput;
+
+    @XmlElement(name = "Inputs")
+    @XmlJavaTypeAdapter(InputAdapter.class)
+    protected Map<String, ProfileInput> inputs = new LinkedHashMap<String, ProfileInput>();
+
+    @XmlElement(name = "Outputs")
+    @XmlJavaTypeAdapter(OutputAdapter.class)
+    protected Map<String, ProfileOutput> outputs = new LinkedHashMap<String, ProfileOutput>();
+
+    @XmlElement(name = "PolicySets")
+    @XmlJavaTypeAdapter(PolicySetAdapter.class)
+    protected Map<String, List<ProfilePolicy>> policySets = new LinkedHashMap<String, List<ProfilePolicy>>();
+
+
+    public String getAuthenticatorId() {
+        return authenticatorId;
+    }
+
+    public void setAuthenticatorId(String authenticatorId) {
+        this.authenticatorId = authenticatorId;
+    }
+
+    public String getAuthzAcl() {
+        return authzAcl;
+    }
+
+    public void setAuthzAcl(String authzAcl) {
+        this.authzAcl = authzAcl;
+    }
+
+    public boolean isRenewal() {
+        return  renewal;
+    }
+
+    public void setRenewal(boolean renewal) {
+        this.renewal = renewal;
+    }
+
+    public boolean isXMLOutput() {
+        return isXMLOutput;
+    }
+
+    public void setXMLOutput(boolean isXMLOutput) {
+        this.isXMLOutput = isXMLOutput;
+    }
 
     public void setName(String name) {
         this.name = name;
@@ -76,20 +137,20 @@ public class ProfileData {
         return description;
     }
 
-    public void setIsEnabled(boolean isEnabled) {
-        this.isEnabled = isEnabled;
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
     }
 
-    public boolean getIsEnabled() {
-        return isEnabled;
+    public boolean isEnabled() {
+        return enabled;
     }
 
-    public void setIsVisible(boolean isVisible) {
-        this.isVisible = isVisible;
+    public void setVisible(boolean visible) {
+        this.visible = visible;
     }
 
-    public boolean getIsVisible() {
-        return isVisible;
+    public boolean isVisible() {
+        return visible;
     }
 
     public void setEnabledBy(String enabledBy) {
@@ -108,40 +169,188 @@ public class ProfileData {
         return id;
     }
 
-    public ProfileInput addProfileInput(String name) {
-
-        ProfileInput oldInput = getProfileInput(name);
-
-        if (oldInput != null)
-            return oldInput;
-
-        ProfileInput newInput = new ProfileInput();
-        newInput.setInputId(name);
-
-        inputs.add(newInput);
-
-        return newInput;
+    public String getClassId() {
+        return classId;
     }
 
-    public ProfileInput getProfileInput(String name) {
-
-        ProfileInput input = null;
-
-        Iterator<ProfileInput> it = inputs.iterator();
-
-        ProfileInput curInput = null;
-        while (it.hasNext()) {
-            curInput = it.next();
+    public void setClassId(String classId) {
+        this.classId = classId;
+    }
 
-            if (curInput != null && curInput.getInputId().equals(name))
-                break;
-        }
+    public void addProfileInput(String id, ProfileInput input) {
+        inputs.put(id, input);
+    }
 
-        return input;
+    public ProfileInput getProfileInput(String id) {
+        return inputs.get(id);
     }
 
-    public List<ProfileInput> getProfileInputsList() {
+    public Map<String, ProfileInput> getInputs() {
         return inputs;
     }
 
+    public void setInputs(Map<String, ProfileInput> inputs) {
+        this.inputs = inputs;
+    }
+
+    public Map<String, ProfileOutput> getOutputs() {
+        return outputs;
+    }
+
+    public void setOutputs(Map<String, ProfileOutput> outputs) {
+        this.outputs = outputs;
+    }
+
+    public Map<String, List<ProfilePolicy>> getPolicySets() {
+        return policySets;
+    }
+
+    public void setPolicySets(Map<String, List<ProfilePolicy>> policySets) {
+        this.policySets = policySets;
+    }
+
+    public void addProfilePolicySet(String id, Vector<ProfilePolicy> policySet) {
+        this.policySets.put(id, policySet);
+    }
+
+    public void addProfileOutput(String id, ProfileOutput output) {
+        outputs.put(id, output);
+    }
+
+    public ProfileOutput getProfileOutput(String id) {
+        return outputs.get(id);
+    }
+
+    public static class InputAdapter extends XmlAdapter<InputList, Map<String, ProfileInput>> {
+
+        public InputList marshal(Map<String,ProfileInput> map) {
+            InputList list = new InputList();
+            for (Map.Entry<String, ProfileInput> entry : map.entrySet()) {
+                Input input = new Input();
+                input.name = entry.getKey();
+                input.value = entry.getValue();
+                list.inputs.add(input);
+            }
+            return list;
+        }
+
+        public Map<String, ProfileInput> unmarshal(InputList list) {
+            Map<String, ProfileInput> map = new LinkedHashMap<String, ProfileInput>();
+            for (Input input : list.inputs) {
+                map.put(input.name, input.value);
+            }
+            return map;
+        }
+    }
+
+    public static class InputList {
+        @XmlElement(name="input")
+        public List<Input> inputs = new ArrayList<Input>();
+    }
+
+    public static class Input {
+
+        @XmlElement(name="id")
+        public String name;
+
+        @XmlElement
+        public ProfileInput value;
+    }
+
+    public static class OutputAdapter extends XmlAdapter<OutputList, Map<String, ProfileOutput>> {
+
+        public OutputList marshal(Map<String,ProfileOutput> map) {
+            OutputList list = new OutputList();
+            for (Map.Entry<String, ProfileOutput> entry : map.entrySet()) {
+                Output output = new Output();
+                output.name = entry.getKey();
+                output.value = entry.getValue();
+                list.outputs.add(output);
+            }
+            return list;
+        }
+
+        public Map<String, ProfileOutput> unmarshal(OutputList list) {
+            Map<String, ProfileOutput> map = new LinkedHashMap<String, ProfileOutput>();
+            for (Output output : list.outputs) {
+                map.put(output.name, output.value);
+            }
+            return map;
+        }
+    }
+
+    public static class OutputList {
+        @XmlElement(name="output")
+        public List<Output> outputs = new ArrayList<Output>();
+    }
+
+    public static class Output {
+
+        @XmlElement(name="id")
+        public String name;
+
+        @XmlElement
+        public ProfileOutput value;
+    }
+
+    public static class PolicySetAdapter extends XmlAdapter<PolicySetList, Map<String, Vector<ProfilePolicy>>> {
+
+        public PolicySetList marshal(Map<String,Vector<ProfilePolicy>> map) {
+            PolicySetList list = new PolicySetList();
+            for (Map.Entry<String, Vector<ProfilePolicy>> entry : map.entrySet()) {
+                PolicySet pset = new PolicySet();
+                pset.name = entry.getKey();
+                pset.value = entry.getValue();
+                list.psets.add(pset);
+            }
+            return list;
+        }
+
+        public Map<String, Vector<ProfilePolicy>> unmarshal(PolicySetList list) {
+            Map<String, Vector<ProfilePolicy>> map = new LinkedHashMap<String, Vector<ProfilePolicy>>();
+            for (PolicySet pset : list.psets) {
+                map.put(pset.name, pset.value);
+            }
+            return map;
+        }
+    }
+
+    public static class PolicySetList {
+        @XmlElement(name="PolicySet")
+        public List<PolicySet> psets = new ArrayList<PolicySet>();
+    }
+
+    public static class PolicySet {
+
+        @XmlElement(name="id")
+        public String name;
+
+        @XmlElement
+        public Vector<ProfilePolicy> value;
+    }
+
+    public static void main(String args[]) throws Exception {
+        Map<String, ProfileInput> inputs = new LinkedHashMap<String, ProfileInput>();
+        //ProfileInput input = new ProfileInput();
+        //input.setClassId(classId);
+        //input.setInputId(inputId);
+        //input.setName(name);
+        //input.setText(text);
+
+
+        ProfileData data = new ProfileData();
+        data.setClassId("com.netscape.cms.profile.common.CAEnrollProfile");
+        data.setDescription("This certificate profile is for enrolling user certificates.");
+        data.setEnabled(true);
+        data.setEnabledBy("admin");
+        data.setId("caUserCertEnrollImpl");
+        data.setInputs(inputs);
+        data.setName("Manual User Dual-Use Certificate Enrollment");
+        //data.setOutputs(outputs);
+        //data.setPolicySets(policySets);
+        data.setRenewal(false);
+        data.setVisible(true);
+        data.setXMLOutput(false);
+    }
+
 }
\ No newline at end of file
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileInput.java b/base/common/src/com/netscape/certsrv/profile/ProfileInput.java
index 64d2aafdbbdd22136f39740df088d70ad566af4a..3a3aefe4c136a15f2aadbace4ae64c0e00812655 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileInput.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileInput.java
@@ -18,77 +18,104 @@
 package com.netscape.certsrv.profile;
 
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
+import java.util.Enumeration;
 import java.util.List;
-import java.util.Map;
+import java.util.Locale;
 
-import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlValue;
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import com.netscape.certsrv.property.Descriptor;
 
 public class ProfileInput {
 
+    private String classId;
+    private String name;
+    private String text;
+    private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>();
+    private List<ProfileAttribute> configAttrs = new ArrayList<ProfileAttribute>();
+
     public ProfileInput() {
         // required for jaxb
     }
 
+    public ProfileInput(IProfileInput input, String classId, Locale locale) {
+        this.name = input.getName(locale);
+        this.classId = classId;
+        Enumeration<String> names = input.getValueNames();
+        while (names.hasMoreElements()) {
+            String name = names.nextElement();
+            addAttribute(new ProfileAttribute(name, null,
+                    (Descriptor) input.getValueDescriptor(locale, name)));
+        }
+    }
+
     @XmlElement
-    public String getInputId() {
-        return inputId;
+    public String getClassId() {
+        return classId;
     }
 
-    private String inputId;
+    @XmlElement
+    public String getName() {
+        return name;
+    }
 
-    @XmlJavaTypeAdapter(InputAttrsAdapter.class)
-    public Map<String, String> InputAttrs = new LinkedHashMap<String, String>();
+    @XmlElement
+    public String getText() {
+        return text;
+    }
 
-    public void setInputAttr(String name, String value) {
-        InputAttrs.put(name, value);
+    public void setClassId(String classId) {
+        this.classId = classId;
     }
 
-    public void setInputId(String inputId) {
-        this.inputId = inputId;
+    public void setName(String name) {
+        this.name = name;
     }
 
-    public static class InputAttrsAdapter extends XmlAdapter<InputAttrList, Map<String, String>> {
+    public void setText(String text) {
+        this.text = text;
+    }
 
-        public InputAttrList marshal(Map<String, String> map) {
-            InputAttrList list = new InputAttrList();
-            for (Map.Entry<String, String> entry : map.entrySet()) {
-                Attribute attribute = new Attribute();
-                attribute.name = entry.getKey();
-                attribute.value = entry.getValue();
-                list.attributes.add(attribute);
-            }
-            return list;
-        }
+    @XmlElement(name = "attribute")
+    public List<ProfileAttribute> getAttrs() {
+        return attrs;
+    }
 
-        public Map<String, String> unmarshal(InputAttrList list) {
-            Map<String, String> map = new LinkedHashMap<String, String>();
-            for (Attribute attribute : list.attributes) {
-                map.put(attribute.name, attribute.value);
-            }
-            return map;
-        }
+    public void setAttrs(List<ProfileAttribute> attrs) {
+        this.attrs = attrs;
+    }
+
+    public void addAttribute(ProfileAttribute attr) {
+        attrs.add(attr);
+    }
+
+    public void removeAttribute(ProfileAttribute attr) {
+        attrs.remove(attr);
     }
 
-    public static class InputAttrList {
-        @XmlElement(name = "InputAttr")
-        public List<Attribute> attributes = new ArrayList<Attribute>();
+    public void clearAttributes() {
+        attrs.clear();
     }
 
-    public static class Attribute {
+    @XmlElement(name = "config_attribute")
+    public List<ProfileAttribute> getConfigAttrs() {
+        return configAttrs;
+    }
 
-        @XmlAttribute
-        public String name;
+    public void setConfigAttrs(List<ProfileAttribute> configAttrs) {
+        this.configAttrs = configAttrs;
+    }
 
-        @XmlValue
-        public String value;
+    public void addConfigAttribute(ProfileAttribute configAttr) {
+        attrs.add(configAttr);
     }
 
-    public Map<String, String> getAttributes() {
-        return InputAttrs;
+    public void removeConfigAttribute(ProfileAttribute configAttr) {
+        attrs.remove(configAttr);
     }
+
+    public void clearConfigAttributes() {
+        configAttrs.clear();
+    }
+
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileOutput.java b/base/common/src/com/netscape/certsrv/profile/ProfileOutput.java
index 2e25f619d2f2860fe493dc595b81497309ab608a..492fdb46a4b0de2a92d7dbe7e8fca2488f0b689e 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileOutput.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileOutput.java
@@ -18,39 +18,55 @@
 package com.netscape.certsrv.profile;
 
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.List;
+import java.util.Locale;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
+import com.netscape.certsrv.property.Descriptor;
+
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
 public class ProfileOutput {
 
-    public ProfileOutput() {
-        // required for jaxb
-    }
-
-    @XmlElement
-    private String outputId;
-
-    @XmlElement(name = "attributes")
-    private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>();
-
     @XmlElement
     private String name;
 
     @XmlElement
     private String text;
 
-    public String getOutputId() {
-        return outputId;
+    @XmlElement
+    private String classId;
+
+    @XmlElement(name = "attributes")
+    private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>();
+
+
+    public ProfileOutput() {
+        // required for jaxb
+    }
+
+    public ProfileOutput(IProfileOutput output, String classId, Locale locale) {
+        this.name = output.getName(locale);
+        this.classId = classId;
+        Enumeration<String> names = output.getValueNames();
+        while (names.hasMoreElements()) {
+            String name = names.nextElement();
+            addAttribute(new ProfileAttribute(name, null,
+                    (Descriptor) output.getValueDescriptor(locale, name)));
+        }
+    }
+
+    public String getClassId() {
+        return classId;
     }
 
-    public void setOutputId(String OutputId) {
-        this.outputId = OutputId;
+    public void setClassId(String classId) {
+        this.classId = classId;
     }
 
     public List<ProfileAttribute> getAttrs() {
@@ -81,4 +97,12 @@ public class ProfileOutput {
         attrs.add(attr);
     }
 
+    public void removeAttribute(ProfileAttribute attr) {
+        attrs.remove(attr);
+    }
+
+    public void clearAttributes() {
+        attrs.clear();
+    }
+
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileParameter.java b/base/common/src/com/netscape/certsrv/profile/ProfileParameter.java
new file mode 100644
index 0000000000000000000000000000000000000000..f137d87ecc9a990079f9d4fb9e03078216974e43
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileParameter.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) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.profile;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ProfileParameter {
+
+ @XmlAttribute
+ private String name;
+
+ @XmlElement
+ private String value;
+
+ public ProfileParameter() {
+     // required for jax-b
+ }
+
+ public ProfileParameter(String name, String value) {
+     this.name = name;
+     this.value = value;
+ }
+
+ public String getName() {
+     return name;
+ }
+
+ public void setName(String name) {
+     this.name = name;
+ }
+
+ public String getValue() {
+     return value;
+ }
+
+ public void setValue(String value) {
+     this.value = value;
+ }
+
+ @Override
+ public String toString() {
+     return "ProfileParameter [name=" + name + ", value=" + value + "]";
+ }
+
+}
\ No newline at end of file
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileResource.java b/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
index 572e6eb8844dca6f77e764fed7b7826d132bcbf0..317215afb943d76819cce7073ae2261743d597fd 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
@@ -1,46 +1,55 @@
 package com.netscape.certsrv.profile;
 
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
 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;
 
 import com.netscape.certsrv.authentication.AuthMethodMapping;
 
-
-@Path("agent/profiles")
-@AuthMethodMapping("agent")
+@Path("")
 public interface ProfileResource {
 
     @GET
-    @Path("{id}")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public ProfileData retrieveProfile(@PathParam("id") String id);
-
-    @GET
+    @Path("profiles")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     public ProfileDataInfos listProfiles();
 
-    /**
-     * Used to retrieve a key
-     *
-     * @param data
-     * @return
-     */
+    @GET
+    @Path("profiles/{id}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public ProfileData retrieveProfile(@PathParam("id") String id);
 
-    /*
     @POST
-    @Path("retrieve")
+    @Path("admin/profiles")
+    @AuthMethodMapping("admin")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public ProfileData retrieveProfile(ProfileRetrievalRequestData request);
+    public void createProfile(ProfileData data);
 
-    // retrieval - used to test integration with a browser
     @POST
-    @Path("retrieve")
+    @Path("agent/profiles/{id}")
+    @AuthMethodMapping("agent")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public void modifyProfileState(@PathParam("id") String id, @QueryParam("action") String action);
+
+    @PUT
+    @Path("admin/profiles/{id}")
+    @AuthMethodMapping("admin")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
-    public ProfileData retrievProfile(MultivaluedMap<String, String> form);
-    */
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public void modifyProfile(@PathParam("id") String id, ProfileData data);
+
+    @DELETE
+    @Path("admin/profiles/{id}")
+    @AuthMethodMapping("admin")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public void deleteProfile(@PathParam("id") String id);
+
 }
\ No newline at end of file
diff --git a/base/common/src/com/netscape/certsrv/property/Descriptor.java b/base/common/src/com/netscape/certsrv/property/Descriptor.java
index d3048e0b9b8be0371044d9c208dce3f06cb8767d..f5069d0461479b9e27e4d30e87f8c5ea43daff0d 100644
--- a/base/common/src/com/netscape/certsrv/property/Descriptor.java
+++ b/base/common/src/com/netscape/certsrv/property/Descriptor.java
@@ -21,6 +21,7 @@ import java.util.Locale;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 
@@ -34,9 +35,16 @@ import javax.xml.bind.annotation.XmlRootElement;
 @XmlAccessorType(XmlAccessType.FIELD)
 public class Descriptor implements IDescriptor {
 
+    @XmlElement(name = "syntax")
     protected String mSyntax = null;
+
+    @XmlElement(name = "constraint")
     protected String mConstraint = null;
+
+    @XmlElement(name = "description")
     protected String mDescription = null;
+
+    @XmlElement(name = "defaultValue")
     protected String mDef = null;
 
     public Descriptor() {
diff --git a/base/common/src/com/netscape/cms/profile/common/BasicProfile.java b/base/common/src/com/netscape/cms/profile/common/BasicProfile.java
index 0c60f081c0e4fd68019397c3af6dc38fe30adf52..c3f6b327deb49ee10597678887bc8bffd94ff4e5 100644
--- a/base/common/src/com/netscape/cms/profile/common/BasicProfile.java
+++ b/base/common/src/com/netscape/cms/profile/common/BasicProfile.java
@@ -20,6 +20,7 @@ package com.netscape.cms.profile.common;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Locale;
+import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -116,6 +117,10 @@ public abstract class BasicProfile implements IProfile {
         }
     }
 
+    public void setRenewal(boolean renewal) {
+        mConfig.putBoolean(PROP_IS_RENEWAL, renewal);
+    }
+
     public String isXmlOutput() {
         try {
             return mConfig.getString(PROP_XML_OUTPUT, "false");
@@ -124,6 +129,10 @@ public abstract class BasicProfile implements IProfile {
         }
     }
 
+    public void setXMLOutput(boolean xmlOutput) {
+        mConfig.putBoolean(PROP_XML_OUTPUT, xmlOutput);
+    }
+
     public String getApprovedBy() {
         try {
             return mConfig.getString(PROP_ENABLE_BY, "");
@@ -175,6 +184,11 @@ public abstract class BasicProfile implements IProfile {
         mConfig.putString("auth." + PROP_INSTANCE_ID, id);
     }
 
+    public void setAuthzAcl(String id) {
+        mAuthzAcl = id;
+        mConfig.putString("authz.acl", id);
+    }
+
     public String getAuthzAcl() {
         return mAuthzAcl;
     }
@@ -459,6 +473,18 @@ public abstract class BasicProfile implements IProfile {
 
     }
 
+    public void deleteAllProfilePolicies() throws EProfileException {
+        for (Map.Entry<String, Vector<ProfilePolicy>> entry : mPolicySet.entrySet()) {
+            String setId = entry.getKey();
+            Vector<ProfilePolicy> pList = new Vector<ProfilePolicy>(entry.getValue());
+            for (ProfilePolicy policy: pList) {
+                deleteProfilePolicy(setId, policy.getId());
+            }
+        }
+
+        mPolicySet.clear();
+    }
+
     public void deleteProfileInput(String inputId) throws EProfileException {
         try {
             mConfig.removeSubStore("input." + inputId);
@@ -499,6 +525,14 @@ public abstract class BasicProfile implements IProfile {
         }
     }
 
+    public void deleteAllProfileInputs() throws EProfileException {
+        // need to use a copy here because we are removing elements from the vector
+        Vector<String> inputs = new Vector<String>(mInputIds);
+        for (String id: inputs) {
+            deleteProfileInput(id);
+        }
+    }
+
     public void deleteProfileOutput(String outputId) throws EProfileException {
         try {
             mConfig.removeSubStore("output." + outputId);
@@ -539,6 +573,14 @@ public abstract class BasicProfile implements IProfile {
         }
     }
 
+    public void deleteAllProfileOutputs() throws EProfileException {
+     // need to use a copy here because we are removing elements from the vector
+        Vector<String> outputs = new Vector<String>(mOutputIds);
+        for (String id: outputs) {
+            deleteProfileOutput(id);
+        }
+    }
+
     public IProfileOutput createProfileOutput(String id, String outputId,
             NameValuePairs nvps)
             throws EProfileException {
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java
index 52326a512b6e1817eede10a7873011bd12227553..8ffa65d9b4f1a8e0e8f8b898fc570d42adb97a78 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java
@@ -22,7 +22,6 @@ import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Locale;
-import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -38,6 +37,7 @@ import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileContext;
 import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileInput;
 import com.netscape.certsrv.request.INotify;
 import com.netscape.certsrv.request.IRequest;
@@ -78,9 +78,8 @@ public class CertProcessor extends Processor {
         // put profile inputs into a local map
         HashMap<String, String> dataInputs = new HashMap<String, String>();
         for (ProfileInput input : data.getInputs()) {
-            Map<String, String> attrs = input.getAttributes();
-            for (Map.Entry<String, String> entry : attrs.entrySet()) {
-                dataInputs.put(entry.getKey(), entry.getValue());
+            for (ProfileAttribute attr: input.getAttrs()) {
+                dataInputs.put(attr.getName(), attr.getValue());
             }
         }
 
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java b/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
index a7d76a4693d878e119bef14fd2f31247482a653c..6071b1dcb90e2b2c2ecbaa400e412df4fc0c83a7 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
@@ -113,7 +113,9 @@ public class CertReviewResponseFactory {
                 dataPolicy.setDef(dataDef);
 
                 //populate constraints
-                PolicyConstraint dataCons = PolicyConstraintFactory.create(locale, policy.getConstraint());
+                // TODO - fix this.
+                PolicyConstraint dataCons = PolicyConstraintFactory.create(locale, policy.getConstraint(),
+                        policy.getConstraint().getClass().getSimpleName());
                 dataPolicy.setConstraint(dataCons);
 
                 dataPolicySet.addPolicy(dataPolicy);
diff --git a/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
index 9e4686698dd5df992cf2d5efa45bee2ece0093fb..31b235d2aae81543c91cf2a27b729868b87cb3da 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
@@ -20,7 +20,6 @@ package com.netscape.cms.servlet.cert;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Locale;
-import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -35,6 +34,7 @@ import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileContext;
 import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileInput;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.cms.servlet.common.CMSRequest;
@@ -51,9 +51,8 @@ public class EnrollmentProcessor extends CertProcessor {
         // put profile inputs into a local map
         HashMap<String, String> dataInputs = new HashMap<String, String>();
         for (ProfileInput input : data.getInputs()) {
-            Map<String, String> attrs = input.getAttributes();
-            for (Map.Entry<String, String> entry : attrs.entrySet()) {
-                dataInputs.put(entry.getKey(), entry.getValue());
+            for (ProfileAttribute attr: input.getAttrs()) {
+                dataInputs.put(attr.getName(), attr.getValue());
             }
         }
 
diff --git a/base/common/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java b/base/common/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java
index 6c1d92a721362c9c3942b8cf0263654315928dbe..648e8bc57f51e62061e6f0bcc239c6370c42f2d9 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java
@@ -27,18 +27,21 @@ import com.netscape.certsrv.property.Descriptor;
 
 public class PolicyConstraintFactory {
 
-    public static PolicyConstraint create(Locale locale, IPolicyConstraint cons) {
+    public static PolicyConstraint create(Locale locale, IPolicyConstraint cons, String classId) {
         PolicyConstraint ret = new PolicyConstraint();
         ret.setName(cons.getName(locale));
         ret.setText(cons.getText(locale));
+        ret.setClassId(classId);
 
         Enumeration<String> conNames = cons.getConfigNames();
         while (conNames.hasMoreElements()) {
             String conName = conNames.nextElement();
             PolicyConstraintValue dataVal =
-                    new PolicyConstraintValue(conName, (Descriptor) cons.getConfigDescriptor(locale, conName));
+                    new PolicyConstraintValue(conName, (Descriptor) cons.getConfigDescriptor(locale, conName),
+                            cons.getConfig(conName));
             ret.addConstraint(dataVal);
         }
+
         return ret;
     }
 }
diff --git a/base/common/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java b/base/common/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
index fe6b436ab12c57e8f087985c33d181689879ee0c..0d6ab04951c92b75886f8772d2b6e7b0829e216c 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
@@ -17,13 +17,16 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.cms.servlet.profile;
 
+import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Locale;
 
 import com.netscape.certsrv.base.IArgBlock;
 import com.netscape.certsrv.profile.IPolicyDefault;
 import com.netscape.certsrv.profile.PolicyDefault;
 import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileParameter;
 import com.netscape.certsrv.property.Descriptor;
 import com.netscape.certsrv.property.EPropertyException;
 import com.netscape.certsrv.request.IRequest;
@@ -64,4 +67,31 @@ public class PolicyDefaultFactory {
         return ret;
     }
 
+    public static PolicyDefault create(Locale locale, IPolicyDefault def, String classId) throws EPropertyException {
+        PolicyDefault ret = new PolicyDefault();
+        ret.setName(def.getName(locale));
+        ret.setText(def.getText(locale));
+        ret.setClassId(classId);
+
+        Enumeration<String> defNames  = def.getValueNames();
+        while (defNames.hasMoreElements()) {
+            String defName = defNames.nextElement();
+            ProfileAttribute attr = new ProfileAttribute();
+            attr.setName(defName);
+            attr.setDescriptor((Descriptor) def.getValueDescriptor(locale, defName));
+            ret.addAttribute(attr);
+        }
+
+        List<ProfileParameter> pList = new ArrayList<ProfileParameter>();
+        Enumeration<String> paramNames  = def.getConfigNames();
+        while (paramNames.hasMoreElements()) {
+            String paramName = paramNames.nextElement();
+            ProfileParameter p = new ProfileParameter(paramName, def.getConfig(paramName));
+            pList.add(p);
+        }
+        ret.setParams(pList);
+
+        return ret;
+    }
+
 }
diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java
index f5a9e7556b531390f1de91242112878d5d52151d..f89d8224e198df38ae896fed413c9482d9353c75 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java
@@ -6,6 +6,7 @@ import java.util.Locale;
 import com.netscape.certsrv.base.IArgBlock;
 import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileInput;
 import com.netscape.certsrv.request.IRequest;
 
@@ -13,13 +14,14 @@ public class ProfileInputFactory {
 
     public static ProfileInput create(IProfileInput input, IRequest request, Locale locale) throws EProfileException  {
         ProfileInput ret = new ProfileInput();
-        ret.setInputId(input.getName(locale));
+        ret.setName(input.getName(locale));
+        ret.setClassId(input.getClass().getSimpleName());
         Enumeration<String> names = input.getValueNames();
         while (names.hasMoreElements()) {
             String name = names.nextElement();
             String value = input.getValue(name, locale, request);
             if (value != null) {
-                ret.setInputAttr(name, value);
+                ret.addAttribute(new ProfileAttribute(name, value, null));
             }
         }
         return ret;
@@ -27,13 +29,14 @@ public class ProfileInputFactory {
 
     public static ProfileInput create(IProfileInput input, IArgBlock params, Locale locale) throws EProfileException {
         ProfileInput ret = new ProfileInput();
-        ret.setInputId(input.getName(locale));
+        ret.setName(input.getName(locale));
+        ret.setClassId(input.getClass().getSimpleName());
         Enumeration<String> names = input.getValueNames();
         while (names.hasMoreElements()) {
             String name = names.nextElement();
             String value = params.getValueAsString(name, null);
             if (value != null) {
-                ret.setInputAttr(name, value);
+                ret.addAttribute(new ProfileAttribute(name, value, null));
             }
         }
         return ret;
diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java
index 4b5ef292dad8d7b8c84b774839d0b017e84e4f4f..82b168e6fd6e9cf440120b2c18196f5a7d64f5bb 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java
@@ -37,8 +37,8 @@ import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.ERejectException;
 import com.netscape.certsrv.profile.ProfileAttribute;
 import com.netscape.certsrv.profile.ProfileOutput;
-import com.netscape.certsrv.property.Descriptor;
 import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.template.ArgList;
 import com.netscape.certsrv.template.ArgSet;
@@ -157,7 +157,7 @@ public class ProfileProcessServlet extends ProfileServlet {
             for (ProfileOutput output: data.getOutputs()) {
                 for (ProfileAttribute attr: output.getAttrs()){
                     ArgSet outputset = new ArgSet();
-                    Descriptor desc = attr.getDescriptor();
+                    IDescriptor desc = attr.getDescriptor();
                     outputset.set(ARG_OUTPUT_ID, attr.getName());
                     outputset.set(ARG_OUTPUT_SYNTAX, desc.getSyntax());
                     outputset.set(ARG_OUTPUT_CONSTRAINT, desc.getConstraint());
diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileService.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileService.java
index 2b790b8cb5985ff7a590425e7efebeb6512fa30f..e8adc9b2a051baaa2d1009ba31785c25f60bc6a5 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/ProfileService.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileService.java
@@ -18,27 +18,49 @@
 
 package com.netscape.cms.servlet.profile;
 
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Vector;
 
-import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.core.UriBuilder;
 
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
 import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileEx;
 import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.IProfilePolicy;
 import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.profile.PolicyConstraint;
+import com.netscape.certsrv.profile.PolicyConstraintValue;
+import com.netscape.certsrv.profile.PolicyDefault;
 import com.netscape.certsrv.profile.ProfileData;
 import com.netscape.certsrv.profile.ProfileDataInfo;
 import com.netscape.certsrv.profile.ProfileDataInfos;
 import com.netscape.certsrv.profile.ProfileInput;
 import com.netscape.certsrv.profile.ProfileNotFoundException;
+import com.netscape.certsrv.profile.ProfileOutput;
+import com.netscape.certsrv.profile.ProfileParameter;
+import com.netscape.certsrv.profile.ProfilePolicy;
 import com.netscape.certsrv.profile.ProfileResource;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
 import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cmscore.realm.PKIPrincipal;
 
 /**
  * @author alee
@@ -47,22 +69,31 @@ import com.netscape.cms.servlet.base.PKIService;
 public class ProfileService extends PKIService implements ProfileResource {
 
     private IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
+    private IPluginRegistry registry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+    private IConfigStore cs = CMS.getConfigStore().getSubStore("profile");
 
     public ProfileDataInfos listProfiles() {
         List<ProfileDataInfo> list = new ArrayList<ProfileDataInfo>();
         ProfileDataInfos infos = new ProfileDataInfos();
+        boolean visibleOnly = true;
 
         if (ps == null) {
             return null;
         }
 
+        PKIPrincipal principal = (PKIPrincipal)servletRequest.getUserPrincipal();
+        if ((principal != null) &&
+            (principal.hasRole("Certificate Manager Agents") ||
+             principal.hasRole("Certificate Manager Administrators"))) {
+            visibleOnly = false;
+        }
         Enumeration<String> profileIds = ps.getProfileIds();
         if (profileIds != null) {
             while (profileIds.hasMoreElements()) {
                 String id = profileIds.nextElement();
                 ProfileDataInfo info = null;
                 try {
-                    info = createProfileDataInfo(id);
+                    info = createProfileDataInfo(id, visibleOnly);
                 } catch (EBaseException e) {
                     continue;
                 }
@@ -79,11 +110,19 @@ public class ProfileService extends PKIService implements ProfileResource {
 
     public ProfileData retrieveProfile(String profileId) throws ProfileNotFoundException {
         ProfileData data = null;
+        boolean visibleOnly = false;
 
         if (ps == null) {
             return null;
         }
 
+        PKIPrincipal principal = (PKIPrincipal)servletRequest.getUserPrincipal();
+        if ((principal != null) &&
+            (principal.hasRole("Certificate Manager Agents") ||
+             principal.hasRole("Certificate Manager Administrators"))) {
+            visibleOnly = true;
+        }
+
         Enumeration<String> profileIds = ps.getProfileIds();
 
         IProfile profile = null;
@@ -108,6 +147,10 @@ public class ProfileService extends PKIService implements ProfileResource {
             throw new ProfileNotFoundException(profileId);
         }
 
+        if (visibleOnly && !profile.isVisible()) {
+            throw new ProfileNotFoundException(profileId);
+        }
+
         try {
             data = createProfileData(profileId);
         } catch (EBaseException e) {
@@ -131,22 +174,21 @@ public class ProfileService extends PKIService implements ProfileResource {
 
         ProfileData data = new ProfileData();
 
-        Locale locale = Locale.getDefault();
-        String name = profile.getName(locale);
-        String desc = profile.getDescription(locale);
-
-        data.setName(name);
-        data.setDescription(desc);
-        data.setIsEnabled(ps.isProfileEnable(profileId));
-        data.setIsVisible(profile.isVisible());
+        data.setAuthenticatorId(profile.getAuthenticatorId());
+        data.setAuthzAcl(profile.getAuthzAcl());
+        data.setClassId(cs.getString(profileId + ".class_id"));
+        data.setDescription(profile.getDescription(getLocale()));
+        data.setEnabled(ps.isProfileEnable(profileId));
         data.setEnabledBy(ps.getProfileEnableBy(profileId));
         data.setId(profileId);
+        data.setName(profile.getName(getLocale()));
+        data.setRenewal(Boolean.getBoolean(profile.isRenewal()));
+        data.setVisible(profile.isVisible());
+        data.setXMLOutput(Boolean.getBoolean(profile.isXmlOutput()));
 
         Enumeration<String> inputIds = profile.getProfileInputIds();
-
-        String inputName = null;
-
         if (inputIds != null) {
+            IConfigStore inputStore = profile.getConfigStore().getSubStore("input");
             while (inputIds.hasMoreElements()) {
                 String inputId = inputIds.nextElement();
                 IProfileInput profileInput = profile.getProfileInput(inputId);
@@ -154,29 +196,65 @@ public class ProfileService extends PKIService implements ProfileResource {
                 if (profileInput == null) {
                     continue;
                 }
-                inputName = profileInput.getName(locale);
 
-                Enumeration<String> inputNames = profileInput.getValueNames();
+                String classId = inputStore.getString(inputId + ".class_id");
 
-                ProfileInput input = data.addProfileInput(inputName);
+                ProfileInput input = new ProfileInput(profileInput, classId, getLocale());
+                data.addProfileInput(inputId, input);
+            }
+        }
 
-                String curInputName = null;
-                while (inputNames.hasMoreElements()) {
-                    curInputName = inputNames.nextElement();
+        // profile outputs
+        Enumeration<String> outputIds = profile.getProfileOutputIds();
+        if (outputIds != null) {
+            IConfigStore outputStore = profile.getConfigStore().getSubStore("output");
+            while (outputIds.hasMoreElements()) {
+                String outputId = outputIds.nextElement();
+                IProfileOutput profileOutput = profile.getProfileOutput(outputId);
 
-                    if (curInputName != null && !curInputName.equals("")) {
-                        input.setInputAttr(curInputName, "");
+                if (profileOutput == null) {
+                    continue;
+                }
+
+                String classId = outputStore.getString(outputId + ".class_id");
+
+                ProfileOutput output = new ProfileOutput(profileOutput, classId, getLocale());
+                data.addProfileOutput(outputId, output);
+            }
+        }
+
+        // profile policies
+        Enumeration<String> policySetIds = profile.getProfilePolicySetIds();
+        if (policySetIds != null) {
+            while (policySetIds.hasMoreElements()) {
+                Vector<ProfilePolicy> pset = new Vector<ProfilePolicy>();
+                String policySetId = policySetIds.nextElement();
+                Enumeration<com.netscape.cms.profile.common.ProfilePolicy> policies =
+                        profile.getProfilePolicies(policySetId);
+                if (policies != null) {
+                    while (policies.hasMoreElements()) {
+                        com.netscape.cms.profile.common.ProfilePolicy policy = policies.nextElement();
+                        IConfigStore policyStore = profile.getConfigStore().getSubStore(
+                                "policyset." + policySetId + "." + policy.getId());
+                        ProfilePolicy p = new ProfilePolicy();
+                        String constraintClassId = policyStore.getString("constraint.class_id");
+                        p.setConstraint(PolicyConstraintFactory.create(getLocale(), policy.getConstraint(), constraintClassId));
+                        String defaultClassId = policyStore.getString("default.class_id");
+                        p.setDef(PolicyDefaultFactory.create(getLocale(), policy.getDefault(), defaultClassId));
+                        p.setId(policy.getId());
+                        pset.add(p);
                     }
-
+                }
+                if (!pset.isEmpty()) {
+                    data.addProfilePolicySet(policySetId, pset);
                 }
             }
         }
 
         return data;
-
     }
 
-    public ProfileDataInfo createProfileDataInfo(String profileId) throws EBaseException {
+    public ProfileDataInfo createProfileDataInfo(String profileId, boolean visibleOnly) throws EBaseException {
 
         if (profileId == null) {
             throw new EBaseException("Error creating ProfileDataInfo.");
@@ -190,16 +268,324 @@ public class ProfileService extends PKIService implements ProfileResource {
             return null;
         }
 
+        if (visibleOnly && !profile.isVisible()) {
+            return null;
+        }
+
         ret = new ProfileDataInfo();
 
         ret.setProfileId(profileId);
 
-        Path profilePath = ProfileResource.class.getAnnotation(Path.class);
-
         UriBuilder profileBuilder = uriInfo.getBaseUriBuilder();
-        profileBuilder.path(profilePath.value() + "/" + profileId);
-        ret.setProfileURL(profileBuilder.build().toString());
+
+        // TODO - fix this once we figure out the auth problem
+        //URI uri = profileBuilder.path(ProfileResource.class).path("{id}").
+        //        build(profileId);
+
+        URI uri = null;
+        if (visibleOnly) {
+            uri = profileBuilder.path(ProfileResource.class).path("profiles").path("{id}")
+                    .build(profileId);
+        } else {
+            uri = profileBuilder.path(ProfileResource.class).path("agent").path("profiles")
+                    .path("{id}").build(profileId);
+        }
+
+        ret.setProfileURL(uri.toString());
 
         return ret;
     }
+
+    public void modifyProfileState(String profileId, String action) {
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        Principal principal = servletRequest.getUserPrincipal();
+
+        switch (action) {
+        case "enable":
+            if (ps.isProfileEnable(profileId)) {
+                // throw new ProfileAlreadyEnabled exception
+            }
+            try {
+                ps.enableProfile(profileId, principal.getName());
+            } catch (EProfileException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+            break;
+        case "disable":
+            if (!ps.isProfileEnable(profileId)) {
+                // throw new ProfileAlreadyDisabled exception
+            }
+            String userid = principal.getName();
+            try {
+                if (ps.checkOwner()) {
+                    if (ps.getProfileEnableBy(profileId).equals(userid)) {
+                        ps.disableProfile(profileId);
+                    } else {
+                        // audit log messages
+                        // throw Unauthorized exception
+                    }
+                } else {
+                    ps.disableProfile(profileId);
+                }
+            } catch (EProfileException e) {
+                e.printStackTrace();
+                // throw internal error exception
+            }
+            break;
+        default:
+            // throw Bad Request exception
+        }
+    }
+
+    public void createProfile(ProfileData data){
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        IProfile profile = null;
+        String profileId = data.getId();
+        try {
+            profile = ps.getProfile(profileId);
+            if (profile != null) {
+                // throw Profile Already Exists Exception
+            }
+            String config = CMS.getConfigStore().getString("instanceRoot") + "/ca/profiles/ca/" +
+                    profileId + ".cfg";
+            File configFile = new File(config);
+            configFile.createNewFile();
+            IPluginInfo info = registry.getPluginInfo("profile", data.getClassId());
+
+            profile = ps.createProfile(profileId, data.getClassId(), info.getClassName(), config);
+            profile.setName(getLocale(),data.getName());
+            profile.setDescription(getLocale(), data.getDescription());
+            profile.setVisible(data.isVisible());
+            profile.getConfigStore().commit(false);
+            ps.createProfileConfig(profileId, data.getClassId(), config);
+
+            if (profile instanceof IProfileEx) {
+                // populates profile specific plugins such as
+                // policies, inputs and outputs with defaults
+                ((IProfileEx) profile).populate();
+            }
+        } catch (EBaseException | IOException e) {
+            e.printStackTrace();
+            // throw internal error exception
+        }
+
+        changeProfileData(data, profile);
+    }
+
+    public void modifyProfile(String profileId, ProfileData data){
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        IProfile profile = null;
+        try {
+            profile = ps.getProfile(profileId);
+            if (profile == null) {
+                // throw ProfileNotExist Exception
+            }
+        } catch (EBaseException e) {
+            e.printStackTrace();
+            // throw internal error exception
+        }
+
+        changeProfileData(data, profile);
+    }
+
+    private void changeProfileData(ProfileData data, IProfile profile) {
+        String profileId = data.getId();
+        if (profile == null) {
+            // throw internal error exception
+        }
+        if (ps.isProfileEnable(profileId)) {
+            // throw bad request - profile must be disabled
+        }
+
+        Map<String, String> auditParams = new LinkedHashMap<String, String>();
+
+        if (differs(profile.getAuthenticatorId(), data.getAuthenticatorId())) {
+            profile.setAuthenticatorId(data.getAuthenticatorId());
+            auditParams.put("authenticatorId", data.getAuthenticatorId());
+        }
+
+        if (differs(profile.getAuthzAcl(),data.getAuthzAcl())) {
+            profile.setAuthzAcl(data.getAuthzAcl());
+            auditParams.put("authzAcl", data.getAuthzAcl());
+        }
+
+        if (differs(profile.getDescription(getLocale()), data.getDescription())) {
+            profile.setDescription(getLocale(), data.getDescription());
+            auditParams.put("description", data.getDescription());
+        }
+
+        if (differs(profile.getId(),data.getId())) {
+            profile.setId(data.getId());
+            auditParams.put("id", data.getId());
+        }
+
+        if (differs(profile.getName(getLocale()),data.getName())) {
+            profile.setName(getLocale(),data.getName());
+            auditParams.put("name", data.getName());
+        }
+
+        // TODO renewal is a string in Profile, should be changed
+        if (differs(profile.isRenewal(),Boolean.toString(data.isRenewal()))) {
+            profile.setRenewal(data.isRenewal());
+            auditParams.put("renewal", Boolean.toString(data.isRenewal()));
+        }
+
+        if (! profile.isVisible() == data.isVisible()) {
+            profile.setVisible(data.isVisible());
+            auditParams.put("visible", Boolean.toString(data.isVisible()));
+        }
+
+        // TODO xmloutput is a string in Profile, should be changed
+        if (differs(profile.isXmlOutput(),Boolean.toString(data.isXMLOutput()))) {
+            profile.setXMLOutput(data.isXMLOutput());
+            auditParams.put("xmloutput", Boolean.toString(data.isXMLOutput()));
+        }
+
+        // add audit log for auditParams
+
+        try {
+            populateProfileInputs(data, profile);
+
+            // add audit log for profile inputs
+
+            populateProfileOutputs(data, profile);
+
+            // add audit log for profile outputs
+
+            populateProfilePolicies(data, profile);
+
+            // add audit log for profile policies
+
+            profile.getConfigStore().commit(false);
+        } catch (EPropertyException e) {
+            e.printStackTrace();
+            // throw bad request exception
+        } catch (EBaseException e) {
+            e.printStackTrace();
+            // throw internal error exception
+        }
+    }
+
+    private boolean differs(String v1, String v2) {
+        if (v1 != null) {
+            if (!v1.equals(v2)) {
+                return true;
+            }
+        } else {
+            if (v2 != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void populateProfilePolicies(ProfileData data, IProfile profile) throws EProfileException, EPropertyException {
+        profile.deleteAllProfilePolicies();
+        for (Map.Entry<String,List<ProfilePolicy>> policySet:
+            data.getPolicySets().entrySet()) {
+            String setId = policySet.getKey();
+            for (ProfilePolicy policy: policySet.getValue()) {
+                PolicyDefault def = policy.getDef();
+                PolicyConstraint con = policy.getConstraint();
+
+                // create policy using defaults for PolicyDefault and PolicyConstraint
+                IProfilePolicy p = profile.createProfilePolicy(setId, policy.getId(),
+                        def.getClassId(), con.getClassId());
+
+                // change specific elements to match incoming data for PolicyDefault
+                IConfigStore pstore = profile.getConfigStore().getSubStore(
+                        "policyset." + setId + "." + policy.getId());
+                if (!def.getName().isEmpty()) {
+                    pstore.putString("default.name", def.getName());
+                }
+                /*if (!def.getText().isEmpty()) {
+                    pstore.putString("default.description", def.getText());
+                }*/
+                for (ProfileParameter param: def.getParams()) {
+                    if (!param.getValue().isEmpty()) {
+                        p.getDefault().setConfig(param.getName(), param.getValue());
+                    }
+                }
+
+                // change specific elements to match incoming data for PolicyConstraint
+                if (!con.getName().isEmpty()) {
+                    pstore.putString("constraint.name", con.getName());
+                }
+                /*if (!con.getText().isEmpty()) {
+                    pstore.putString("constraint.description", con.getText());
+                }*/
+                for (PolicyConstraintValue pcv : con.getConstraints()) {
+                    if (!pcv.getValue().isEmpty()) {
+                        p.getConstraint().setConfig(pcv.getName(), pcv.getValue());
+                    }
+                }
+            }
+        }
+    }
+
+    private void populateProfileOutputs(ProfileData data, IProfile profile) throws EProfileException {
+        profile.deleteAllProfileOutputs();
+        Map<String, ProfileOutput> outputs = data.getOutputs();
+        for (Entry<String, ProfileOutput> entry: outputs.entrySet()) {
+            String id = entry.getKey();
+            String classId = entry.getValue().getClassId();
+
+            NameValuePairs nvp = new NameValuePairs();
+            // TODO - add a field for params in ProfileOuput
+            // No current examples
+            profile.createProfileOutput(id, classId, nvp);
+        }
+    }
+
+    private void populateProfileInputs(ProfileData data, IProfile profile) throws EProfileException {
+        profile.deleteAllProfileInputs();
+       Map<String, ProfileInput> inputs = data.getInputs();
+        for (Entry<String, ProfileInput> entry: inputs.entrySet()) {
+            String id = entry.getKey();
+            String classId = entry.getValue().getClassId();
+
+            NameValuePairs nvp = new NameValuePairs();
+            // TODO - add a field for params in ProfileInput.
+            // an example of this is DomainController.cfg
+            profile.createProfileInput(id, classId, nvp);
+        }
+    }
+
+    public void deleteProfile(@PathParam("id") String profileId) {
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        try {
+            IProfile profile = ps.getProfile(profileId);
+            if (profile == null) {
+                // log already deleted
+                return;
+            }
+
+            if (ps.isProfileEnable(profileId)) {
+                // log attempt to delete profile when enabled
+                // throw unauthorized exception
+            }
+
+            String configFile = CMS.getConfigStore().getString("profile." + profileId + ".config");
+
+            ps.deleteProfile(profileId, configFile);
+        } catch (EBaseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+
+    }
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
index 50095b173c5b9a4d43c320cc5e81b9dcc25555c2..ae93320f9c31fa34c8550c4e982f11e496cc6343 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -39,6 +39,7 @@ import com.netscape.cmstools.cert.CertCLI;
 import com.netscape.cmstools.client.ClientCLI;
 import com.netscape.cmstools.group.GroupCLI;
 import com.netscape.cmstools.key.KeyCLI;
+import com.netscape.cmstools.profile.ProfileCLI;
 import com.netscape.cmstools.system.KRAConnectorCLI;
 import com.netscape.cmstools.system.SecurityDomainCLI;
 import com.netscape.cmstools.user.UserCLI;
@@ -69,6 +70,7 @@ public class MainCLI extends CLI {
         addModule(new GroupCLI(this));
         addModule(new KeyCLI(this));
         addModule(new KRAConnectorCLI(this));
+        addModule(new ProfileCLI(this));
         addModule(new SecurityDomainCLI(this));
         addModule(new UserCLI(this));
     }
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c30fdbd7cb693d556600061abc712acdc2439ba
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java
@@ -0,0 +1,60 @@
+package com.netscape.cmstools.profile;
+
+import java.io.FileNotFoundException;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.ParseException;
+
+import com.netscape.certsrv.profile.ProfileData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileAddCLI extends CLI {
+    public ProfileCLI parent;
+
+    public ProfileAddCLI(ProfileCLI parent) {
+        super("add", "Add profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " <file>", options);
+    }
+
+    public void execute(String[] args) {
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(-1);
+        }
+
+        String[] cLineArgs = cmd.getArgs();
+
+        if (cLineArgs.length < 1) {
+            System.err.println("Error: No filename specified.");
+            printHelp();
+            System.exit(-1);
+        }
+        String filename = cLineArgs[0];
+        if (filename == null || filename.trim().length() == 0) {
+            System.err.println("Error: Missing input file name.");
+            printHelp();
+            System.exit(-1);
+        }
+
+        try {
+            ProfileData data = ProfileCLI.readProfileFromFile(filename);
+            parent.client.createProfile(data);
+            MainCLI.printMessage("Added profile " + data.getId());
+        } catch (FileNotFoundException | JAXBException  e) {
+            System.err.println("Error: " + e.getMessage());
+            System.exit(-1);
+        }
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..37b88bcb5c654c93d2e1b0a2fb353e8d1b556df6
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileCLI.java
@@ -0,0 +1,118 @@
+package com.netscape.cmstools.profile;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.profile.ProfileClient;
+import com.netscape.certsrv.profile.ProfileData;
+import com.netscape.certsrv.profile.ProfileDataInfo;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileCLI extends CLI {
+    public MainCLI parent;
+    public ProfileClient client;
+
+    public ProfileCLI(MainCLI parent) {
+        super("profile", "Profile management commands");
+        this.parent = parent;
+
+        addModule(new ProfileFindCLI(this));
+        addModule(new ProfileShowCLI(this));
+        addModule(new ProfileAddCLI(this));
+        addModule(new ProfileModifyCLI(this));
+        addModule(new ProfileRemoveCLI(this));
+        addModule(new ProfileEnableCLI(this));
+        addModule(new ProfileDisableCLI(this));
+    }
+
+    public void printHelp() {
+
+        System.out.println("Commands:");
+
+        int leftPadding = 1;
+        int rightPadding = 25;
+
+        for (CLI module : modules.values()) {
+            String label = name + "-" + module.getName();
+
+            int padding = rightPadding - leftPadding - label.length();
+            if (padding < 1)
+                padding = 1;
+
+            System.out.print(StringUtils.repeat(" ", leftPadding));
+            System.out.print(label);
+            System.out.print(StringUtils.repeat(" ", padding));
+            System.out.println(module.getDescription());
+        }
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        client = new ProfileClient(parent.client);
+
+        if (args.length == 0) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String command = args[0];
+        String[] commandArgs = Arrays.copyOfRange(args, 1, args.length);
+
+        if (command == null) {
+            printHelp();
+            System.exit(1);
+        }
+
+        CLI module = getModule(command);
+        if (module != null) {
+            module.execute(commandArgs);
+
+        } else {
+            System.err.println("Error: Invalid command \"" + command + "\"");
+            printHelp();
+            System.exit(1);
+        }
+    }
+
+    public static void printProfileDataInfo(ProfileDataInfo info) {
+        System.out.println("Profile ID:  " + info.getProfileId());
+        System.out.println("Profile URL: " + info.getProfileURL());
+    }
+
+    public static void printProfile(ProfileData profileData) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static void saveProfileToFile(String filename, ProfileData data)
+            throws JAXBException, FileNotFoundException {
+        JAXBContext context = JAXBContext.newInstance(ProfileData.class);
+        Marshaller marshaller = context.createMarshaller();
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+
+        FileOutputStream stream = new FileOutputStream(filename);
+        marshaller.marshal(data, stream);
+
+        MainCLI.printMessage("Saved profile " + data.getId() + " to " + filename);
+    }
+
+    public static ProfileData readProfileFromFile(String filename)
+            throws JAXBException, FileNotFoundException {
+        ProfileData data = null;
+        JAXBContext context = JAXBContext.newInstance(ProfileData.class);
+        Unmarshaller unmarshaller = context.createUnmarshaller();
+        FileInputStream fis = new FileInputStream(filename);
+        data = (ProfileData) unmarshaller.unmarshal(fis);
+        return data;
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileDisableCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileDisableCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..0279cf36a879accd885c6aa3834f9e89fe8e71c1
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileDisableCLI.java
@@ -0,0 +1,34 @@
+package com.netscape.cmstools.profile;
+
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileDisableCLI extends CLI {
+
+    public ProfileCLI parent;
+
+    public ProfileDisableCLI(ProfileCLI parent) {
+        super("disable", "Disable profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " <profile_id>", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        if (args.length != 1) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String profileId = args[0];
+
+        parent.client.disableProfile(profileId);
+
+        MainCLI.printMessage("Disabled profile \"" + profileId + "\"");
+    }
+
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileEnableCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileEnableCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..727e49b0ac429f38f3b5336e17214bdcb3027e9a
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileEnableCLI.java
@@ -0,0 +1,33 @@
+package com.netscape.cmstools.profile;
+
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileEnableCLI extends CLI {
+
+    public ProfileCLI parent;
+
+    public ProfileEnableCLI(ProfileCLI parent) {
+        super("enable", "Enable profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " <profile_id>", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        if (args.length != 1) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String profileId = args[0];
+
+        parent.client.enableProfile(profileId);
+
+        MainCLI.printMessage("Enabled profile \"" + profileId + "\"");
+    }
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileFindCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileFindCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ced7c0b8174be186b0942b7a2b43183d65609b5
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileFindCLI.java
@@ -0,0 +1,39 @@
+package com.netscape.cmstools.profile;
+
+import java.util.Collection;
+
+import com.netscape.certsrv.profile.ProfileDataInfo;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileFindCLI extends CLI {
+
+    public ProfileCLI parent;
+
+    public ProfileFindCLI(ProfileCLI parent) {
+        super("find", "Find profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " [FILTER] [OPTIONS...]", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        Collection<ProfileDataInfo> infos = parent.client.listProfiles().getProfileInfos();
+        boolean first = true;
+
+        for (ProfileDataInfo info: infos) {
+            if (first) {
+                first = false;
+            } else {
+                System.out.println();
+            }
+            ProfileCLI.printProfileDataInfo(info);
+        }
+
+        MainCLI.printMessage("Number of entries returned " + infos.size());
+    }
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileModifyCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileModifyCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..5259a7fe7a92e2e5212a9855b7faf3e13b6824a2
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileModifyCLI.java
@@ -0,0 +1,61 @@
+package com.netscape.cmstools.profile;
+
+import java.io.FileNotFoundException;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.ParseException;
+
+import com.netscape.certsrv.profile.ProfileData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileModifyCLI extends CLI {
+
+    public ProfileCLI parent;
+
+    public ProfileModifyCLI(ProfileCLI parent) {
+        super("mod", "Modify profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " <file>", options);
+    }
+
+    public void execute(String[] args) {
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(-1);
+        }
+
+        String[] cLineArgs = cmd.getArgs();
+
+        if (cLineArgs.length < 1) {
+            System.err.println("Error: No filename specified.");
+            printHelp();
+            System.exit(-1);
+        }
+        String filename = cLineArgs[0];
+        if (filename == null || filename.trim().length() == 0) {
+            System.err.println("Error: Missing input file name.");
+            printHelp();
+            System.exit(-1);
+        }
+
+        try {
+            ProfileData data = ProfileCLI.readProfileFromFile(filename);
+            parent.client.modifyProfile(data);
+            MainCLI.printMessage("Modified profile " + data.getId());
+        } catch (FileNotFoundException | JAXBException  e) {
+            System.err.println("Error: " + e.getMessage());
+            System.exit(-1);
+        }
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileRemoveCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileRemoveCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2e3eae53f4879869fd474af99fbd2221a60ac59
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileRemoveCLI.java
@@ -0,0 +1,33 @@
+package com.netscape.cmstools.profile;
+
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileRemoveCLI extends CLI {
+
+    public ProfileCLI parent;
+
+    public ProfileRemoveCLI(ProfileCLI parent) {
+        super("del", "Remove profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " <profile_id>", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        if (args.length != 1) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String profileId = args[0];
+
+        parent.client.deleteProfile(profileId);
+
+        MainCLI.printMessage("Deleted profile \"" + profileId + "\"");
+    }
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileShowCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileShowCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..de83c1eb95474abd891cf6a5c8ccf5c99d460226
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileShowCLI.java
@@ -0,0 +1,71 @@
+package com.netscape.cmstools.profile;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.ParseException;
+
+import com.netscape.certsrv.profile.ProfileData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class ProfileShowCLI extends CLI {
+
+    public ProfileCLI parent;
+
+    public ProfileShowCLI(ProfileCLI parent) {
+        super("show", "Show profiles");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name + " <profile_id>", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+        CommandLine cmd = null;
+
+        Option option = new Option(null, "output", true, "Output filename");
+        option.setArgName("filename");
+        options.addOption(option);
+
+        try {
+            cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(-1);
+        }
+
+        String[] cLineArgs = cmd.getArgs();
+        if (cLineArgs.length < 1) {
+            System.err.println("Error: Missing profile ID.");
+            printHelp();
+            System.exit(-1);
+        }
+
+        String profileId = cLineArgs[0];
+
+        String filename = null;
+        if (cmd.hasOption("output")) {
+            filename = cmd.getOptionValue("output");
+        } else {
+            System.err.println("Error: Missing output file name.");
+            printHelp();
+            System.exit(-1);
+        }
+
+        if (filename == null || filename.trim().length() == 0) {
+            System.err.println("Error: Missing output file name.");
+            printHelp();
+            System.exit(-1);
+        }
+
+        ProfileData profileData = parent.client.retrieveProfile(profileId);
+
+        MainCLI.printMessage("Profile \"" + profileId + "\"");
+
+        ProfileCLI.printProfile(profileData);
+        ProfileCLI.saveProfileToFile(filename, profileData);
+    }
+
+}
-- 
1.8.1.4

