>From 506a749cf094daefce4d2cc435c64e59eb6cfd3f 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.
At this point, only the viewing of profiles is supported.  The next
patches will add CLI code to test adding/ editing a profile.
---
 .../src/com/netscape/cms/servlet/test/CATest.java  | 107 +++----
 .../certsrv/cert/CertEnrollmentRequest.java        |  55 ++--
 .../src/com/netscape/certsrv/profile/IProfile.java |  24 ++
 .../netscape/certsrv/profile/PolicyConstraint.java |  11 +
 .../netscape/certsrv/profile/PolicyDefault.java    |  11 +
 .../netscape/certsrv/profile/ProfileAttribute.java |   7 +-
 .../com/netscape/certsrv/profile/ProfileData.java  | 288 ++++++++++++++---
 .../com/netscape/certsrv/profile/ProfileInput.java | 114 ++++---
 .../netscape/certsrv/profile/ProfileOutput.java    |  32 +-
 .../netscape/certsrv/profile/ProfileResource.java  |  75 +++--
 .../com/netscape/certsrv/property/Descriptor.java  |  14 +
 .../com/netscape/certsrv/property/IDescriptor.java |   3 +
 .../netscape/cms/profile/common/BasicProfile.java  |  45 +++
 .../netscape/cms/servlet/cert/CertProcessor.java   |  10 +-
 .../cms/servlet/cert/EnrollmentProcessor.java      |  10 +-
 .../cms/servlet/profile/PolicyDefaultFactory.java  |  20 +-
 .../cms/servlet/profile/ProfileInputFactory.java   |  11 +-
 .../cms/servlet/profile/ProfileProcessServlet.java |   4 +-
 .../cms/servlet/profile/ProfileService.java        | 352 +++++++++++++++++++--
 19 files changed, 951 insertions(+), 242 deletions(-)

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..ac142d408cb5dee56d63ccc0b8d281956db5fd57 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
@@ -19,7 +19,7 @@ package com.netscape.cms.servlet.test;
 
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 
 import org.apache.commons.cli.CommandLine;
@@ -45,6 +45,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 +320,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 +351,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 +376,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;
     }
 
@@ -436,40 +438,21 @@ 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("IsEnabled: " + info.isEnabled());
+        log("IsVisible: " + 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());
+            ListIterator<ProfileAttribute> iter = entry.getValue().getAttrs().listIterator();
+            while (iter.hasNext()) {
+                ProfileAttribute attr = iter.next();
+                log("Input Attribute Name: " + attr.getName() + "\n");
+                log("Input Attribute Value: " + attr.getValue() + "\n");
             }
-
         }
-
     }
 
     private static void printCertInfos(CertDataInfos infos, String filter) {
diff --git a/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java b/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java
index fefef9a4625433851f408781683f8d2c4be00d23..748f2474d5ec41f342be2622cbc069b8c661539d 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java
@@ -27,7 +27,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
+import java.util.ListIterator;
 
 import javax.ws.rs.core.MultivaluedMap;
 import javax.xml.bind.JAXBContext;
@@ -39,6 +39,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 +112,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 +120,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 +134,7 @@ public class CertEnrollmentRequest {
             return oldInput;
 
         ProfileInput newInput = new ProfileInput();
-        newInput.setInputId(name);
+        newInput.setName(name);
 
         getInputs().add(newInput);
 
@@ -149,7 +150,7 @@ public class CertEnrollmentRequest {
         ProfileInput curInput = null;
         while (it.hasNext()) {
             curInput = it.next();
-            if (curInput != null && curInput.getInputId().equals(name))
+            if (curInput != null && curInput.getName().equals(name))
                 break;
         }
 
@@ -157,7 +158,7 @@ public class CertEnrollmentRequest {
     }
 
     public void addOutput(ProfileOutput output) {
-        ProfileOutput curOutput = getOutput(output.getOutputId());
+        ProfileOutput curOutput = getOutput(output.getName());
         if (curOutput != null) {
             getOutputs().remove(curOutput);
         }
@@ -165,7 +166,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);
         }
@@ -178,7 +179,7 @@ public class CertEnrollmentRequest {
         Iterator<ProfileOutput> it = getOutputs().iterator();
         while (it.hasNext()) {
             curOutput = it.next();
-            if (curOutput != null && curOutput.getOutputId().equals(name))
+            if (curOutput != null && curOutput.getName().equals(name))
                 break;
         }
 
@@ -201,9 +202,10 @@ 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());
+            ListIterator<ProfileAttribute> iter = input.getAttrs().listIterator();
+            while (iter.hasNext()) {
+                ProfileAttribute attr = iter.next();
+                ret.put(attr.getName(), attr.getValue());
             }
         }
 
@@ -218,26 +220,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/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/PolicyDefault.java b/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java
index 2b95cf5f00af87451ed302b0bd4a7ef5c226b24b..25799a3f69fb5a62267b3a14900ca699c20ad9a7 100644
--- a/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java
+++ b/base/common/src/com/netscape/certsrv/profile/PolicyDefault.java
@@ -32,6 +32,9 @@ public class PolicyDefault {
     @XmlAttribute(name="id")
     private String name;
 
+    @XmlAttribute
+    private String classId;
+
     @XmlElement(name="description")
     private String text;
 
@@ -62,6 +65,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;
     }
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileAttribute.java b/base/common/src/com/netscape/certsrv/profile/ProfileAttribute.java
index 9c889bb8a1881a241f0d079c66f51385e9427cec..718a69eeade8ec3dddbf43d3de65b92a901f59c5 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileAttribute.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileAttribute.java
@@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
 
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
@@ -36,13 +37,13 @@ public class ProfileAttribute {
     private String value;
 
     @XmlElement
-    private Descriptor descriptor;
+    private IDescriptor descriptor;
 
     public ProfileAttribute() {
         // required for jax-b
     }
 
-    public ProfileAttribute(String name, String value, Descriptor descriptor) {
+    public ProfileAttribute(String name, String value, IDescriptor descriptor) {
         this.name = name;
         this.value = value;
         this.descriptor = descriptor;
@@ -64,7 +65,7 @@ public class ProfileAttribute {
         this.value = value;
     }
 
-    public Descriptor getDescriptor() {
+    public IDescriptor getDescriptor() {
         return descriptor;
     }
 
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileData.java b/base/common/src/com/netscape/certsrv/profile/ProfileData.java
index 465981add8bc81c2f77051e031a83234aaf54179..c59d348a79f61d5156259033615f215adc23f0ba 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,78 @@ 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;
+
+    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;
+    }
+
+    @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, Vector<ProfilePolicy>> policySets = new LinkedHashMap<String, Vector<ProfilePolicy>>();
 
     public void setName(String name) {
         this.name = name;
@@ -76,20 +136,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 +168,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, Vector<ProfilePolicy>> getPolicySets() {
+        return policySets;
+    }
+
+    public void setPolicySets(Map<String, Vector<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..f0b044590967e61c2f2a11378513c9d3b03a9dab 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileInput.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileInput.java
@@ -18,15 +18,11 @@
 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;
 
 public class ProfileInput {
 
@@ -34,61 +30,93 @@ public class 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, input.getValueDescriptor(locale, name)));
+        }
+    }
+
     @XmlElement
-    public String getInputId() {
-        return inputId;
+    public String getClassId() {
+        return classId;
     }
 
-    private String inputId;
+    private String classId;
 
-    @XmlJavaTypeAdapter(InputAttrsAdapter.class)
-    public Map<String, String> InputAttrs = new LinkedHashMap<String, String>();
+    @XmlElement
+    public String getName() {
+        return name;
+    }
+
+    private String name;
 
-    public void setInputAttr(String name, String value) {
-        InputAttrs.put(name, value);
+    @XmlElement
+    public String getText() {
+        return text;
     }
 
-    public void setInputId(String inputId) {
-        this.inputId = inputId;
+    private String text;
+
+    private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>();
+
+    private List<ProfileAttribute> configAttrs = new ArrayList<ProfileAttribute>();
+
+    public void setClassId(String classId) {
+        this.classId = classId;
     }
 
-    public static class InputAttrsAdapter extends XmlAdapter<InputAttrList, Map<String, String>> {
+    public void setName(String name) {
+        this.name = name;
+    }
 
-        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;
-        }
+    public void setText(String text) {
+        this.text = text;
+    }
 
-        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;
-        }
+    @XmlElement(name = "attribute")
+    public List<ProfileAttribute> getAttrs() {
+        return attrs;
+    }
+
+    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 void clearAttributes() {
+        attrs.clear();
     }
 
-    public static class InputAttrList {
-        @XmlElement(name = "InputAttr")
-        public List<Attribute> attributes = new ArrayList<Attribute>();
+    @XmlElement(name = "config_attribute")
+    public List<ProfileAttribute> getConfigAttrs() {
+        return configAttrs;
     }
 
-    public static class Attribute {
+    public void setConfigAttrs(List<ProfileAttribute> configAttrs) {
+        this.configAttrs = configAttrs;
+    }
 
-        @XmlAttribute
-        public String name;
+    public void addConfigAttribute(ProfileAttribute configAttr) {
+        attrs.add(configAttr);
+    }
 
-        @XmlValue
-        public String value;
+    public void removeConfigAttribute(ProfileAttribute configAttr) {
+        attrs.remove(configAttr);
     }
 
-    public Map<String, String> getAttributes() {
-        return InputAttrs;
+    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..4932f646569019dc671859129595d37fbe562fd8 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileOutput.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileOutput.java
@@ -18,7 +18,9 @@
 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;
@@ -33,8 +35,15 @@ public class ProfileOutput {
         // required for jaxb
     }
 
-    @XmlElement
-    private String outputId;
+    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, output.getValueDescriptor(locale, name)));
+        }
+    }
 
     @XmlElement(name = "attributes")
     private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>();
@@ -45,12 +54,15 @@ public class ProfileOutput {
     @XmlElement
     private String text;
 
-    public String getOutputId() {
-        return outputId;
+    @XmlElement
+    private String classId;
+
+    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 +93,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/ProfileResource.java b/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
index 572e6eb8844dca6f77e764fed7b7826d132bcbf0..3b6ffab003254d31fb307b61b199986f25f3b604 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
@@ -1,6 +1,9 @@
 package com.netscape.certsrv.profile;
 
+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;
@@ -8,39 +11,71 @@ import javax.ws.rs.core.MediaType;
 
 import com.netscape.certsrv.authentication.AuthMethodMapping;
 
-
-@Path("agent/profiles")
-@AuthMethodMapping("agent")
+@Path("")
 public interface ProfileResource {
 
+    // EE interfaces
+
     @GET
-    @Path("{id}")
+    @Path("profiles/{id}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public ProfileData retrieveEEProfile(@PathParam("id") String id);
+
+    @GET
+    @Path("profiles")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public ProfileDataInfos listEEProfiles();
+
+    // Agent interfaces
+
+    @GET
+    @Path("agent/profiles/{id}")
+    @AuthMethodMapping("agent")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     public ProfileData retrieveProfile(@PathParam("id") String id);
 
     @GET
+    @Path("agent/profiles")
+    @AuthMethodMapping("agent")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     public ProfileDataInfos listProfiles();
 
-    /**
-     * Used to retrieve a key
-     *
-     * @param data
-     * @return
-     */
-
-    /*
     @POST
-    @Path("retrieve")
+    @Path("agent/profiles/{id}/enable")
+    @AuthMethodMapping("agent")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public ProfileData retrieveProfile(ProfileRetrievalRequestData request);
+    public void enableProfile(@PathParam("id") String id);
 
-    // retrieval - used to test integration with a browser
     @POST
-    @Path("retrieve")
+    @Path("agent/profiles/{id}/disable")
+    @AuthMethodMapping("agent")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public void disableProfile(@PathParam("id") String id);
+
+    //Admin Interfaces
+
+    @GET
+    @Path("admin/profiles/{id}")
+    @AuthMethodMapping("admin")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public ProfileData retrieveAdminProfile(@PathParam("id") String id);
+
+    @GET
+    @Path("admin/profiles")
+    @AuthMethodMapping("admin")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
-    public ProfileData retrievProfile(MultivaluedMap<String, String> form);
-    */
+    public ProfileDataInfos listAdminProfiles();
+
+    @PUT
+    @Path("admin/profiles/{id}")
+    @AuthMethodMapping("admin")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public void createOrModifyProfile(@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..377ea22f14dc384573ad8f020c96d91a29f93ed0 100644
--- a/base/common/src/com/netscape/certsrv/property/Descriptor.java
+++ b/base/common/src/com/netscape/certsrv/property/Descriptor.java
@@ -21,7 +21,9 @@ 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 javax.xml.bind.annotation.adapters.XmlAdapter;
 
 
 /**
@@ -34,9 +36,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() {
@@ -58,6 +67,11 @@ public class Descriptor implements IDescriptor {
         mDescription = description;
     }
 
+    static class Adapter extends XmlAdapter<Descriptor,IDescriptor> {
+        public IDescriptor unmarshal(Descriptor v) { return v; }
+        public Descriptor marshal(IDescriptor v) { return (Descriptor)v; }
+    }
+
     /**
      * Returns the syntax of the property.
      *
diff --git a/base/common/src/com/netscape/certsrv/property/IDescriptor.java b/base/common/src/com/netscape/certsrv/property/IDescriptor.java
index 830ecdb273809a28f76d09a92aa45578bb13b3b4..48ad3af258ab5b0a682c15e5ebf7a93cc02af6f4 100644
--- a/base/common/src/com/netscape/certsrv/property/IDescriptor.java
+++ b/base/common/src/com/netscape/certsrv/property/IDescriptor.java
@@ -19,11 +19,14 @@ package com.netscape.certsrv.property;
 
 import java.util.Locale;
 
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
 /**
  * This interface represents a property descriptor.
  *
  * @version $Revision$, $Date$
  */
+@XmlJavaTypeAdapter(Descriptor.Adapter.class)
 public interface IDescriptor {
 
     // syntax
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..80d9b0857e974b5d9e9567ba10959e5c00193c43 100644
--- a/base/common/src/com/netscape/cms/profile/common/BasicProfile.java
+++ b/base/common/src/com/netscape/cms/profile/common/BasicProfile.java
@@ -19,7 +19,10 @@ package com.netscape.cms.profile.common;
 
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.ListIterator;
 import java.util.Locale;
+import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -116,6 +119,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 +131,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 +186,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 +475,19 @@ public abstract class BasicProfile implements IProfile {
 
     }
 
+    public void deleteAllProfilePolicies() throws EProfileException {
+        for (Map.Entry<String, Vector<ProfilePolicy>> entry : mPolicySet.entrySet()) {
+            String setId = entry.getKey();
+            ListIterator<ProfilePolicy> policies = entry.getValue().listIterator();
+            while (policies.hasNext()) {
+                ProfilePolicy policy = policies.next();
+                deleteProfilePolicy(setId, policy.getId());
+            }
+        }
+
+        mPolicySet.clear();
+    }
+
     public void deleteProfileInput(String inputId) throws EProfileException {
         try {
             mConfig.removeSubStore("input." + inputId);
@@ -499,6 +528,14 @@ public abstract class BasicProfile implements IProfile {
         }
     }
 
+    public void deleteAllProfileInputs() throws EProfileException {
+        Iterator<String> iter = mInputIds.iterator();
+        while (iter.hasNext()) {
+            String id = iter.next();
+            deleteProfileInput(id);
+        }
+    }
+
     public void deleteProfileOutput(String outputId) throws EProfileException {
         try {
             mConfig.removeSubStore("output." + outputId);
@@ -539,6 +576,14 @@ public abstract class BasicProfile implements IProfile {
         }
     }
 
+    public void deleteAllProfileOutputs() throws EProfileException {
+        Iterator<String> iter = mOutputIds.iterator();
+        while (iter.hasNext()) {
+            String id = iter.next();
+            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..e83aa8b6b4ab3ec3dd4a943bc69aec87e064bb2d 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java
@@ -21,8 +21,8 @@ import java.math.BigInteger;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.ListIterator;
 import java.util.Locale;
-import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -38,6 +38,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 +79,10 @@ 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());
+            ListIterator<ProfileAttribute> iter = input.getAttrs().listIterator();
+            while (iter.hasNext()) {
+                ProfileAttribute attr = iter.next();
+                dataInputs.put(attr.getName(), attr.getValue());
             }
         }
 
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..485f0d7dd23569a3119d9ce46a77b8094f320d86 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
@@ -19,8 +19,8 @@ package com.netscape.cms.servlet.cert;
 
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.ListIterator;
 import java.util.Locale;
-import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -35,6 +35,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 +52,10 @@ 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());
+            ListIterator<ProfileAttribute> iter = input.getAttrs().listIterator();
+            while (iter.hasNext()) {
+                ProfileAttribute attr = iter.next();
+                dataInputs.put(attr.getName(), attr.getValue());
             }
         }
 
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..eb8c217b3063f12a60b22fa930a80f6ef36835b8 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
@@ -41,7 +41,7 @@ public class PolicyDefaultFactory {
             ProfileAttribute attr = new ProfileAttribute(
                     defName,
                     def.getValue(defName, locale, request),
-                    (Descriptor) def.getValueDescriptor(locale, defName));
+                    def.getValueDescriptor(locale, defName));
             ret.addAttribute(attr);
         }
         return ret;
@@ -58,7 +58,23 @@ public class PolicyDefaultFactory {
             ProfileAttribute attr = new ProfileAttribute(
                     defName,
                     params.getValueAsString(defName, ""),
-                    (Descriptor) def.getValueDescriptor(locale, defName));
+                    def.getValueDescriptor(locale, defName));
+            ret.addAttribute(attr);
+        }
+        return ret;
+    }
+
+    public static PolicyDefault create(Locale locale, IPolicyDefault def) throws EPropertyException {
+        PolicyDefault ret = new PolicyDefault();
+        ret.setName(def.getName(locale));
+        ret.setText(def.getText(locale));
+
+        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);
         }
         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..3b883adb8d3cbc9e5cfbd5bd53bd591f18c6d0a6 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/ProfileService.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileService.java
@@ -18,26 +18,41 @@
 
 package com.netscape.cms.servlet.profile;
 
+import java.io.File;
+import java.io.IOException;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.Iterator;
+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.IProfileInput;
+import com.netscape.certsrv.profile.IProfileOutput;
 import com.netscape.certsrv.profile.IProfileSubsystem;
 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.ProfilePolicy;
 import com.netscape.certsrv.profile.ProfileResource;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
 import com.netscape.cms.servlet.base.PKIService;
 
 /**
@@ -47,8 +62,22 @@ 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() {
+        return listProfiles(false);
+    }
+
+    public ProfileDataInfos listEEProfiles() {
+        return listProfiles(true);
+    }
+
+    public ProfileDataInfos listAdminProfiles() {
+        return listProfiles(false);
+    }
+
+    public ProfileDataInfos listProfiles(boolean visibleOnly) {
         List<ProfileDataInfo> list = new ArrayList<ProfileDataInfo>();
         ProfileDataInfos infos = new ProfileDataInfos();
 
@@ -62,7 +91,7 @@ public class ProfileService extends PKIService implements ProfileResource {
                 String id = profileIds.nextElement();
                 ProfileDataInfo info = null;
                 try {
-                    info = createProfileDataInfo(id);
+                    info = createProfileDataInfo(id, visibleOnly);
                 } catch (EBaseException e) {
                     continue;
                 }
@@ -77,7 +106,19 @@ public class ProfileService extends PKIService implements ProfileResource {
         return infos;
     }
 
-    public ProfileData retrieveProfile(String profileId) throws ProfileNotFoundException {
+    public ProfileData retrieveProfile(String profileId) {
+        return retrieveProfile(profileId, false);
+    }
+
+    public ProfileData retrieveEEProfile(String profileId) {
+        return retrieveProfile(profileId, true);
+    }
+
+    public ProfileData retrieveAdminProfile(String profileId) {
+        return retrieveProfile(profileId, false);
+    }
+
+    public ProfileData retrieveProfile(String profileId, boolean visibleOnly) throws ProfileNotFoundException {
         ProfileData data = null;
 
         if (ps == null) {
@@ -108,6 +149,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 +176,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 +198,61 @@ 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();
+                        ProfilePolicy p = new ProfilePolicy();
+                        p.setConstraint(PolicyConstraintFactory.create(getLocale(), policy.getConstraint()));
+                        p.setDef(PolicyDefaultFactory.create(getLocale(), policy.getDefault()));
+                        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,6 +266,10 @@ public class ProfileService extends PKIService implements ProfileResource {
             return null;
         }
 
+        if (visibleOnly && !profile.isVisible()) {
+            return null;
+        }
+
         ret = new ProfileDataInfo();
 
         ret.setProfileId(profileId);
@@ -197,9 +277,229 @@ public class ProfileService extends PKIService implements ProfileResource {
         Path profilePath = ProfileResource.class.getAnnotation(Path.class);
 
         UriBuilder profileBuilder = uriInfo.getBaseUriBuilder();
-        profileBuilder.path(profilePath.value() + "/" + profileId);
+        if (visibleOnly) {
+            profileBuilder.path(profilePath.value() + "/profiles/" + profileId);
+        } else {
+            profileBuilder.path(profilePath.value() + "/agent/profiles/" + profileId);
+        }
         ret.setProfileURL(profileBuilder.build().toString());
 
         return ret;
     }
+
+    public void enableProfile(String profileId) {
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        if (ps.isProfileEnable(profileId)) {
+            // throw ProfileAlreadyEnabled exception
+        }
+
+        Principal principal = servletRequest.getUserPrincipal();
+        try {
+            ps.enableProfile(profileId, principal.getName());
+        } catch (EProfileException e) {
+            // TODO
+            e.printStackTrace();
+        }
+    }
+
+    public void disableProfile(String profileId) {
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        if (!ps.isProfileEnable(profileId)) {
+            // throw ProfileAlreadyEnabled exception
+        }
+
+        Principal principal = servletRequest.getUserPrincipal();
+        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
+        }
+    }
+
+    public void createOrModifyProfile(String profileId, ProfileData data){
+        if (ps == null) {
+            // throw internal error exception;
+        }
+
+        IProfile profile = null;
+        try {
+            profile = ps.getProfile(profileId);
+            if (profile == null) {
+                profile = createProfile(profileId, data);
+            }
+        } catch (EBaseException | IOException e) {
+            e.printStackTrace();
+            // throw internal error exception
+        }
+
+        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 (! profile.getAuthenticatorId().equals(data.getAuthenticatorId())) {
+            profile.setAuthenticatorId(data.getAuthenticatorId());
+            auditParams.put("authenticatorId", data.getAuthenticatorId());
+        }
+
+        if (! profile.getAuthzAcl().equals(data.getAuthzAcl())) {
+            profile.setAuthzAcl(data.getAuthzAcl());
+            auditParams.put("authzAcl", data.getAuthzAcl());
+        }
+
+        if (! profile.getDescription(getLocale()).equals(data.getDescription())) {
+            profile.setDescription(getLocale(), data.getDescription());
+            auditParams.put("description", data.getDescription());
+        }
+
+        if (! profile.getId().equals(data.getId())) {
+            profile.setId(data.getId());
+            auditParams.put("id", data.getId());
+        }
+
+        if (! profile.getName(getLocale()).equals(data.getName())) {
+            profile.setName(getLocale(),data.getName());
+            auditParams.put("name", data.getName());
+        }
+
+        // TODO renewal is a string in Profile, should be changed
+        if (! profile.isRenewal().equals(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 (! profile.isXmlOutput().equals(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
+        } catch (EProfileException e) {
+            e.printStackTrace();
+            // throw internal error exception
+        }
+    }
+
+    private void populateProfilePolicies(ProfileData data, IProfile profile) throws EProfileException {
+        profile.deleteAllProfilePolicies();
+        Iterator<Map.Entry<String,Vector<ProfilePolicy>>> it =
+                data.getPolicySets().entrySet().iterator();
+
+        while (it.hasNext()){
+            Map.Entry<String,Vector<ProfilePolicy>> policySet = it.next();
+            String setId = policySet.getKey();
+            for (ProfilePolicy policy: policySet.getValue()) {
+                profile.createProfilePolicy(setId, policy.getId(),
+                        policy.getDef().getClassId(), policy.getConstraint().getClassId());
+            }
+        }
+    }
+
+    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);
+        }
+    }
+
+    private IProfile createProfile(String profileId, ProfileData data) throws EBaseException, IOException {
+        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());
+
+        IProfile profile = ps.createProfile(profileId, data.getClassId(), info.getClassName(), config);
+        return profile;
+    }
+
+    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();
+        }
+
+
+    }
 }
-- 
1.8.1.4

