summaryrefslogtreecommitdiffstats
path: root/base/common/src/com/netscape/cmscore/request
diff options
context:
space:
mode:
authorEndi Sukma Dewata <edewata@redhat.com>2012-03-24 02:27:47 -0500
committerEndi Sukma Dewata <edewata@redhat.com>2012-03-26 11:43:54 -0500
commit621d9e5c413e561293d7484b93882d985b3fe15f (patch)
tree638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/common/src/com/netscape/cmscore/request
parent40d3643b8d91886bf210aa27f711731c81a11e49 (diff)
downloadpki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz
pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz
pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131
Diffstat (limited to 'base/common/src/com/netscape/cmscore/request')
-rw-r--r--base/common/src/com/netscape/cmscore/request/ARequestQueue.java1578
-rw-r--r--base/common/src/com/netscape/cmscore/request/ARequestRecord.java42
-rw-r--r--base/common/src/com/netscape/cmscore/request/CertRequestConstants.java73
-rw-r--r--base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java78
-rw-r--r--base/common/src/com/netscape/cmscore/request/RequestAttr.java61
-rw-r--r--base/common/src/com/netscape/cmscore/request/RequestQueue.java709
-rw-r--r--base/common/src/com/netscape/cmscore/request/RequestRecord.java883
-rw-r--r--base/common/src/com/netscape/cmscore/request/RequestRepository.java217
-rw-r--r--base/common/src/com/netscape/cmscore/request/RequestSubsystem.java187
-rw-r--r--base/common/src/com/netscape/cmscore/request/Schema.java50
10 files changed, 3878 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cmscore/request/ARequestQueue.java b/base/common/src/com/netscape/cmscore/request/ARequestQueue.java
new file mode 100644
index 000000000..16db3985c
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/ARequestQueue.java
@@ -0,0 +1,1578 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509ExtensionException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IAttrSet;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.AgentApprovals;
+import com.netscape.certsrv.request.IEnrollmentRequest;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestScheduler;
+import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * The ARequestQueue class is an abstract class that implements
+ * most portions of the IRequestQueue interface. This includes
+ * the state engine as defined for processing IRequest objects.
+ * <p>
+ * !Put state machine description here!
+ * <p>
+ * This class defines several abstract protected functions that need to be defined by the concrete implementation. In
+ * particular, this class does not implement the operations for storing requests persistantly.
+ * <p>
+ * This class also provides several accessor functions for setting fields in the IRequest object. These functions are
+ * provided as an aid to saving and restoring the state in the database.
+ * <p>
+ * This class also implements the locking operations specified by the IRequestQueue interface.
+ * <p>
+ *
+ * @author thayes
+ * @version $Revision$ $Date$
+ */
+public abstract class ARequestQueue
+ implements IRequestQueue {
+
+ /**
+ * global request version for tracking request changes.
+ */
+ public final static String REQUEST_VERSION = "1.0.0";
+
+ /**
+ * Create a new (unique) RequestId. (abstract)
+ * <p>
+ * This method must be implemented by the specialized class to generate a new id from data in the persistant store.
+ * This id is used to create a new request object.
+ * <p>
+ *
+ * @return
+ * a new RequestId object.
+ * @exception EBaseException
+ * indicates that creation of the new id could not be completed.
+ * @see RequestId
+ */
+ protected abstract RequestId newRequestId()
+ throws EBaseException;
+
+ /**
+ * Read a request from the persistant store. (abstract)
+ * <p>
+ * This function is called to create the in-memory version of a request object.
+ * <p>
+ * The implementation of this object can use the createRequest member function to create a new instance of an
+ * IRequest, and use the setRequestStatus, setCreationTime and setModificationTime functions to set those values.
+ * <p>
+ *
+ * @param id
+ * the id of the request to read.
+ * @return
+ * a new IRequest object. null is returned if the object cannot
+ * be located.
+ * @exception EBaseException
+ * TODO: this is not implemented yet
+ * @see #createRequest
+ * @see #setRequestStatus
+ * @see #setModificationTime
+ * @see #setCreationTime
+ */
+ protected abstract IRequest readRequest(RequestId id);
+
+ /**
+ * Add the request to the store. (abstract)
+ * <p>
+ * This function is called when a new request immediately after creating a new request.
+ * <p>
+ *
+ * @param request
+ * the request to add.
+ * @exception EBaseException
+ * TODO: this is not implemented yet
+ */
+ protected abstract void addRequest(IRequest request) throws EBaseException;
+
+ /**
+ * Modify the request in the store. (abstract)
+ * <p>
+ * Update the persistant copy of this request with the current values in the object.
+ * <p>
+ * Currently there are no hints for what has changed, so the entire request should be updated.
+ * <p>
+ *
+ * @param request
+ * @exception EBaseException
+ * TODO: this is not implemented yet
+ */
+ protected abstract void modifyRequest(IRequest request);
+
+ /**
+ * Get complete list of RequestId values found i this
+ * queue.
+ * <p>
+ * This method can form the basis for creating other types of search/list operations (although there are probably
+ * more efficient ways of doing this. ARequestQueue implements default versions of some of the searching by using
+ * this method as a basis.
+ * <p>
+ * TODO: return IRequestList -or- just use listRequests as the basic engine.
+ * <p>
+ *
+ * @return
+ * an Enumeration that generates RequestId objects.
+ */
+ abstract protected Enumeration<RequestId> getRawList();
+
+ /**
+ * protected access for setting the current state of a request.
+ * <p>
+ *
+ * @param request
+ * The request to be modified.
+ * @param status
+ * The new value for the request status.
+ */
+ protected final void setRequestStatus(IRequest request, RequestStatus status) {
+ Request r = (Request) request;
+
+ r.setRequestStatus(status);
+ }
+
+ /**
+ * protected access for setting the modification time of a request.
+ * <p>
+ *
+ * @param request
+ * The request to be modified.
+ * @param date
+ * The new value for the time.
+ */
+ protected final void setModificationTime(IRequest request, Date date) {
+ Request r = (Request) request;
+
+ r.mModificationTime = date;
+ }
+
+ /**
+ * protected access for setting the creation time of a request.
+ * <p>
+ *
+ * @param request
+ * The request to be modified.
+ * @param date
+ * The new value for the time.
+ */
+ protected final void setCreationTime(IRequest request, Date date) {
+ Request r = (Request) request;
+
+ r.mCreationTime = date;
+ }
+
+ /**
+ * protected access for creating a new Request object
+ * <p>
+ *
+ * @param id
+ * The identifier for the new request
+ * @return
+ * A new request object. The caller should fill in other data
+ * values from the datastore.
+ */
+ protected final IRequest createRequest(RequestId id, String requestType) {
+ Request r;
+
+ /*
+ * Determine the specialized class to create for this type
+ *
+ * TODO: this set of classes is an example only. The real set
+ * needs to be determined and implemented.
+ */
+ if (requestType != null && requestType.equals("enrollment")) {
+ r = new EnrollmentRequest(id);
+ } else {
+ r = new Request(id);
+ }
+
+ return r;
+ }
+
+ /**
+ * Implements IRequestQueue.newRequest
+ * <p>
+ *
+ * @see IRequestQueue#newRequest
+ */
+ public IRequest newRequest(String requestType)
+ throws EBaseException {
+ if (requestType == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_REQUEST_TYPE", "null"));
+ }
+ RequestId rId = newRequestId();
+ IRequest r = createRequest(rId, requestType);
+
+ // Commented out the lock call because unlock is never called.
+ // mTable.lock(rId);
+
+ // TODO: move this to the first update. This will require
+ // some state information to track the current state.
+ r.setRequestType(requestType);
+ r.setExtData(IRequest.REQ_VERSION, REQUEST_VERSION);
+
+ // NOT_UPDATED mean request is in memory and has
+ // not been serialized to database yet. An add
+ // operation is required to serialize a NOT_UPDATED
+ // request.
+ r.setExtData("dbStatus", "NOT_UPDATED");
+ // addRequest(r);
+
+ // expose requestId to policy so that it can be
+ // used with predicate
+ r.setExtData("requestId", rId.toString());
+
+ return r;
+ }
+
+ /**
+ * Implements IRequestQueue.cloneRequest
+ * <p>
+ *
+ * @see IRequestQueue#cloneRequest
+ */
+ public IRequest cloneRequest(IRequest r)
+ throws EBaseException {
+ // 1. check for valid state. (Are any invalid ?)
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs == RequestStatus.BEGIN)
+ throw new EBaseException("Invalid Status");
+
+ // 2. create new request
+ String reqType = r.getRequestType();
+ IRequest clone = newRequest(reqType);
+
+ // 3. copy all attributes of original request to clone and modify.
+ // source id (from remote authority) is not copied.
+ // TODO: set the original request id to some place in the request.
+ clone.copyContents(r);
+ // NOT_UPDATED mean request is in memory and has
+ // not been serialized to database yet. An add
+ // operation is required to serialize a NOT_UPDATED
+ // request.
+ clone.setExtData("dbStatus", "NOT_UPDATED");
+
+ return clone;
+ }
+
+ /**
+ * Implements IRequestQueue.findRequest
+ * <p>
+ *
+ * @see IRequestQueue#findRequest
+ */
+ public IRequest findRequest(RequestId id)
+ throws EBaseException {
+ IRequest r;
+
+ // mTable.lock(id);
+
+ r = readRequest(id);
+
+ // if (r == null) mTable.unlock(id);
+
+ return r;
+ }
+
+ private IRequestScheduler mRequestScheduler = null;
+
+ public void setRequestScheduler(IRequestScheduler scheduler) {
+ mRequestScheduler = scheduler;
+ }
+
+ public IRequestScheduler getRequestScheduler() {
+ return mRequestScheduler;
+ }
+
+ /**
+ * Implements IRequestQueue.processRequest
+ * <p>
+ *
+ * @see IRequestQueue#processRequest
+ */
+ public final void processRequest(IRequest r)
+ throws EBaseException {
+
+ // #610553 Thread Scheduler
+ IRequestScheduler scheduler = getRequestScheduler();
+
+ if (scheduler != null) {
+ scheduler.requestIn(r);
+ }
+
+ try {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.BEGIN)
+ throw new EBaseException("Invalid Status");
+
+ stateEngine(r);
+ } finally {
+ if (scheduler != null) {
+ scheduler.requestOut(r);
+ }
+ }
+ }
+
+ /**
+ * Implements IRequestQueue.markRequestPending
+ * <p>
+ *
+ * @see IRequestQueue#markRequestPending
+ */
+ public final void markRequestPending(IRequest r)
+ throws EBaseException {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.BEGIN)
+ throw new EBaseException("Invalid Status");
+
+ // 2. Change the request state. This method of making
+ // a request PENDING does NOT invoke the PENDING notifiers.
+ // To change this, just call stateEngine at the completion of this
+ // routine.
+ setRequestStatus(r, RequestStatus.PENDING);
+
+ updateRequest(r);
+ stateEngine(r);
+ }
+
+ /**
+ * Implements IRequestQueue.cloneAndMarkPending
+ * <p>
+ *
+ * @see IRequestQueue#cloneAndMarkPending
+ */
+ public IRequest cloneAndMarkPending(IRequest r)
+ throws EBaseException {
+ IRequest clone = cloneRequest(r);
+
+ markRequestPending(clone);
+ return clone;
+ }
+
+ /**
+ * Implements IRequestQueue.approveRequest
+ * <p>
+ *
+ * @see IRequestQueue#approveRequest
+ */
+ public final void approveRequest(IRequest r)
+ throws EBaseException {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.PENDING)
+ throw new EBaseException("Invalid Status");
+
+ AgentApprovals aas = AgentApprovals.fromStringVector(
+ r.getExtDataInStringVector(AgentApprovals.class.getName()));
+ if (aas == null) {
+ aas = new AgentApprovals();
+ }
+
+ // Record agent who did this
+ String agentName = getUserIdentity();
+
+ if (agentName == null)
+ throw new EBaseException("Missing agent information");
+
+ aas.addApproval(agentName);
+ r.setExtData(AgentApprovals.class.getName(), (Vector<?>) aas.toStringVector());
+
+ PolicyResult pr = mPolicy.apply(r);
+
+ if (pr == PolicyResult.ACCEPTED) {
+ setRequestStatus(r, RequestStatus.APPROVED);
+ } else if (pr == PolicyResult.DEFERRED ||
+ pr == PolicyResult.REJECTED) {
+ }
+
+ // Always update. The policy code may have made changes to the
+ // request that we want to keep.
+ updateRequest(r);
+
+ stateEngine(r);
+ }
+
+ /**
+ * Implements IRequestQueue.rejectRequest
+ * <p>
+ *
+ * @see IRequestQueue#rejectRequest
+ */
+ public final void rejectRequest(IRequest r)
+ throws EBaseException {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.PENDING)
+ throw new EBaseException("Invalid Status");
+
+ // 2. Change state
+ setRequestStatus(r, RequestStatus.REJECTED);
+ updateRequest(r);
+
+ // 3. Continue processing
+ stateEngine(r); // does nothing
+ }
+
+ /**
+ * Implments IRequestQueue.cancelRequest
+ * <p>
+ *
+ * @see IRequestQueue#cancelRequest
+ */
+ public final void cancelRequest(IRequest r)
+ throws EBaseException {
+ setRequestStatus(r, RequestStatus.CANCELED);
+ updateRequest(r);
+
+ stateEngine(r);
+
+ return;
+ }
+
+ /**
+ * caller must lock request and release request
+ */
+ public final void markAsServiced(IRequest r) {
+ setRequestStatus(r, RequestStatus.COMPLETE);
+ updateRequest(r);
+
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ return;
+ }
+
+ /**
+ * Implements IRequestQueue.listRequests
+ * <p>
+ * Should be overridden by the specialized class if a more efficient method is available for implementing this
+ * operation.
+ * <P>
+ *
+ * @see IRequestQueue#listRequests
+ */
+ public IRequestList listRequests() {
+ return new RequestList(getRawList());
+ }
+
+ /**
+ * Implements IRequestQueue.listRequestsByStatus
+ * <p>
+ * Should be overridden by the specialized class if a more efficient method is available for implementing this
+ * operation.
+ * <P>
+ *
+ * @see IRequestQueue#listRequestsByStatus
+ */
+ public IRequestList listRequestsByStatus(RequestStatus s) {
+ return new RequestListByStatus(getRawList(), s, this);
+ }
+
+ /**
+ * Implements IRequestQueue.releaseRequest
+ * <p>
+ *
+ * @see IRequestQueue#releaseRequest
+ */
+ public final void releaseRequest(IRequest request) {
+ // mTable.unlock(request.getRequestId());
+ }
+
+ public void updateRequest(IRequest r) {
+ ((Request) r).mModificationTime = CMS.getCurrentDate();
+
+ String name = getUserIdentity();
+
+ if (name != null)
+ r.setExtData(IRequest.UPDATED_BY, name);
+
+ // TODO: use a state flag to determine whether to call
+ // addRequest or modifyRequest (see newRequest as well)
+ modifyRequest(r);
+ }
+
+ // PRIVATE functions
+
+ private final void stateEngine(IRequest r)
+ throws EBaseException {
+ boolean complete = false;
+
+ while (!complete) {
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs == RequestStatus.BEGIN) {
+ PolicyResult pr = PolicyResult.ACCEPTED;
+
+ if (mPolicy != null)
+ pr = mPolicy.apply(r);
+
+ if (pr == PolicyResult.ACCEPTED) {
+ setRequestStatus(r, RequestStatus.APPROVED);
+ } else if (pr == PolicyResult.DEFERRED) {
+ setRequestStatus(r, RequestStatus.PENDING);
+ } else {
+ setRequestStatus(r, RequestStatus.REJECTED);
+ }
+
+ // if policy accepts the request, the request
+ // will be processed right away. So speed up
+ // the request processing, we do not want to
+ // have too many db operation.
+ if (pr != PolicyResult.ACCEPTED) {
+ updateRequest(r);
+ }
+ } else if (rs == RequestStatus.PENDING) {
+ if (mPendingNotify != null)
+ mPendingNotify.notify(r);
+
+ complete = true;
+ } else if (rs == RequestStatus.APPROVED) {
+ boolean svcComplete;
+
+ svcComplete = mService.serviceRequest(r);
+
+ // Completed requests call the notifier and are done. Others
+ // wait for the serviceComplete call.
+ if (svcComplete) {
+ setRequestStatus(r, RequestStatus.COMPLETE);
+ } else {
+ setRequestStatus(r, RequestStatus.SVC_PENDING);
+ }
+
+ updateRequest(r);
+ } else if (rs == RequestStatus.SVC_PENDING) {
+ complete = true;
+ } else if (rs == RequestStatus.CANCELED) {
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ complete = true;
+ } else if (rs == RequestStatus.REJECTED) {
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ complete = true;
+ } else if (rs == RequestStatus.COMPLETE) {
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ complete = true;
+ }
+ }
+ }
+
+ /**
+ * log a change in the request status
+ */
+ protected void logChange(IRequest request) {
+ // write the queue name and request id
+ // write who changed it
+ // write what change (which state change) was made
+ // - new (processRequest)
+ // - approve
+ // - reject
+
+ // Ordering
+ // - make change in memory
+ // - log change and result
+ // - update record
+ }
+
+ /**
+ * get the identity of the current user
+ */
+ protected String getUserIdentity() {
+ // Record agent who did this
+ SessionContext s = SessionContext.getContext();
+ String name = (String) s.get(SessionContext.USER_ID);
+
+ return name;
+ }
+
+ /**
+ * New non-blocking recover method.
+ */
+ public void recover() {
+ if (CMS.isRunningMode()) {
+ RecoverThread t = new RecoverThread(this);
+
+ t.start();
+ }
+ }
+
+ /**
+ * recover from a crash. Resends all requests that are in
+ * the APPROVED state.
+ */
+ public void recoverWillBlock() {
+ // Get a list of all requests that are APPROVED
+ IRequestList list = listRequestsByStatus(RequestStatus.APPROVED);
+
+ while (list != null && list.hasMoreElements()) {
+ RequestId rid = list.nextRequestId();
+ IRequest request;
+
+ try {
+ request = findRequest(rid);
+
+ //if (request == null) log_error
+
+ // Recheck the status - should be the same!!
+ if (request.getRequestStatus() == RequestStatus.APPROVED) {
+ stateEngine(request);
+ }
+
+ releaseRequest(request);
+ } catch (EBaseException e) {
+ // log
+ }
+ }
+ }
+
+ public INotify getPendingNotify() {
+ return mPendingNotify;
+ }
+
+ // Constructor
+ protected ARequestQueue(IPolicy policy, IService service, INotify notify,
+ INotify pendingNotify) {
+ mPolicy = policy;
+ mService = service;
+ mNotify = notify;
+ mPendingNotify = pendingNotify;
+
+ mLogger = CMS.getLogger();
+ }
+
+ // Instance variables
+ // RequestIDTable mTable = new RequestIDTable();
+
+ IPolicy mPolicy;
+ IService mService;
+ INotify mNotify;
+ INotify mPendingNotify;
+
+ protected ILogger mLogger;
+}
+
+//
+// Table of RequestId values that are currently in use by some thread.
+// The fact that the request is in this table constitutes a lock
+// on the value.
+//
+/*
+ class RequestIDTable {
+ public synchronized void lock(RequestId id) {
+ while (true) {
+ if (mHashtable.put(id, id) == null)
+ break;
+
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ };
+ }
+ }
+
+ public synchronized void unlock(RequestId id) {
+ mHashtable.remove(id);
+
+ notifyAll();
+ }
+
+ // instance variables
+ Hashtable mHashtable = new Hashtable();
+ }
+ */
+
+//
+// Request - implementation of the IRequest interface. This
+// version is returned by ARequestQueue (and its derivatives)
+//
+class Request
+ implements IRequest {
+ // IRequest.getRequestId
+ public RequestId getRequestId() {
+ return mRequestId;
+ }
+
+ // IRequest.getRequestStatus
+ public RequestStatus getRequestStatus() {
+ return mRequestStatus;
+ }
+
+ // Obsolete
+ public void setRequestStatus(RequestStatus s) {
+ mRequestStatus = s;
+ // expose request status so that we can do predicate upon it
+ setExtData(IRequest.REQ_STATUS, s.toString());
+ }
+
+ public boolean isSuccess() {
+ Integer result = getExtDataInInteger(IRequest.RESULT);
+
+ if (result != null && result.equals(IRequest.RES_SUCCESS))
+ return true;
+ else
+ return false;
+ }
+
+ public String getError(Locale locale) {
+ return getExtDataInString(IRequest.ERROR);
+ }
+
+ // IRequest.getSourceId
+ public String getSourceId() {
+ return mSourceId;
+ }
+
+ // IRequest.setSourceId
+ public void setSourceId(String id) {
+ mSourceId = id;
+ }
+
+ // IRequest.getRequestOwner
+ public String getRequestOwner() {
+ return mOwner;
+ }
+
+ // IRequest.setRequestOwner
+ public void setRequestOwner(String id) {
+ mOwner = id;
+ }
+
+ // IRequest.getRequestType
+ public String getRequestType() {
+ return mRequestType;
+ }
+
+ // IRequest.setRequestType
+ public void setRequestType(String type) {
+ mRequestType = type;
+ setExtData(IRequest.REQ_TYPE, type);
+ }
+
+ // IRequest.getRequestVersion
+ public String getRequestVersion() {
+ return getExtDataInString(IRequest.REQ_VERSION);
+ }
+
+ // IRequest.getCreationTime
+ public Date getCreationTime() {
+ return mCreationTime;
+ }
+
+ public String getContext() {
+ return mContext;
+ }
+
+ public void setContext(String ctx) {
+ mContext = ctx;
+ }
+
+ // IRequest.getModificationTime
+ public Date getModificationTime() {
+ return mModificationTime;
+ }
+
+ /**
+ * this isn't that efficient but will do for now.
+ */
+ public void copyContents(IRequest req) {
+ Enumeration<String> e = req.getExtDataKeys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ if (!key.equals(IRequest.ISSUED_CERTS) &&
+ !key.equals(IRequest.ERRORS) &&
+ !key.equals(IRequest.REMOTE_REQID)) {
+ if (req.isSimpleExtDataValue(key)) {
+ setExtData(key, req.getExtDataInString(key));
+ } else {
+ setExtData(key, req.getExtDataInHashtable(key));
+ }
+ }
+ }
+ }
+
+ /**
+ * This function used to check that the keys obeyed LDAP attribute name
+ * syntax rules. Keys are being encoded now, so it is changed to just
+ * filter out null and empty string keys.
+ *
+ * @param key The key to check
+ * @return false if invalid
+ */
+ protected boolean isValidExtDataKey(String key) {
+ return key != null &&
+ (!key.equals(""));
+ }
+
+ protected boolean isValidExtDataHashtableValue(Hashtable<String, String> hash) {
+ if (hash == null) {
+ return false;
+ }
+ Enumeration<String> keys = hash.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ if (!((key instanceof String) && isValidExtDataKey((String) key))) {
+ return false;
+ }
+ /*
+ * TODO should the Value type be String?
+ */
+ Object value = hash.get(key);
+ if (!(value instanceof String)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean setExtData(String key, String value) {
+ if (!isValidExtDataKey(key)) {
+ return false;
+ }
+ if (value == null) {
+ return false;
+ }
+
+ mExtData.put(key, value);
+ return true;
+ }
+
+ public boolean setExtData(String key, Hashtable<String, String> value) {
+ if (!(isValidExtDataKey(key) && isValidExtDataHashtableValue(value))) {
+ return false;
+ }
+
+ mExtData.put(key, new ExtDataHashtable<String>(value));
+ return true;
+ }
+
+ public boolean isSimpleExtDataValue(String key) {
+ return (mExtData.get(key) instanceof String);
+ }
+
+ public String getExtDataInString(String key) {
+ Object value = mExtData.get(key);
+ if (value == null) {
+ return null;
+ }
+ if (!(value instanceof String)) {
+ return null;
+ }
+ return (String) value;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Hashtable<String, String> getExtDataInHashtable(String key) {
+ Object value = mExtData.get(key);
+ if (value == null) {
+ return null;
+ }
+ if (!(value instanceof Hashtable)) {
+ return null;
+ }
+ return new ExtDataHashtable<String>((Hashtable<String, String>) value);
+ }
+
+ public Enumeration<String> getExtDataKeys() {
+ return mExtData.keys();
+ }
+
+ public void deleteExtData(String type) {
+ mExtData.remove(type);
+ }
+
+ public boolean setExtData(String key, String subkey, String value) {
+ if (!(isValidExtDataKey(key) && isValidExtDataKey(subkey))) {
+ return false;
+ }
+ if (isSimpleExtDataValue(key)) {
+ return false;
+ }
+ if (value == null) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ Hashtable<String, String> existingValue = (Hashtable<String, String>) mExtData.get(key);
+ if (existingValue == null) {
+ existingValue = new ExtDataHashtable<String>();
+ mExtData.put(key, existingValue);
+ }
+ existingValue.put(subkey, value);
+ return true;
+ }
+
+ public String getExtDataInString(String key, String subkey) {
+ Hashtable<String, String> value = getExtDataInHashtable(key);
+ if (value == null) {
+ return null;
+ }
+ return value.get(subkey);
+ }
+
+ public boolean setExtData(String key, Integer value) {
+ if (value == null) {
+ return false;
+ }
+ return setExtData(key, value.toString());
+ }
+
+ public Integer getExtDataInInteger(String key) {
+ String strVal = getExtDataInString(key);
+ if (strVal == null) {
+ return null;
+ }
+ try {
+ return Integer.valueOf(strVal);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ public boolean setExtData(String key, Integer[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ stringArray[index] = data[index].toString();
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public Integer[] getExtDataInIntegerArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ Integer[] intArray = new Integer[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ intArray[index] = new Integer(stringArray[index]);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ return intArray;
+ }
+
+ public boolean setExtData(String key, BigInteger value) {
+ if (value == null) {
+ return false;
+ }
+ return setExtData(key, value.toString());
+ }
+
+ public BigInteger getExtDataInBigInteger(String key) {
+ String strVal = getExtDataInString(key);
+ if (strVal == null) {
+ return null;
+ }
+ try {
+ return new BigInteger(strVal);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ public boolean setExtData(String key, BigInteger[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ stringArray[index] = data[index].toString();
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public BigInteger[] getExtDataInBigIntegerArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ BigInteger[] intArray = new BigInteger[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ intArray[index] = new BigInteger(stringArray[index]);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ return intArray;
+ }
+
+ public boolean setExtData(String key, Throwable e) {
+ if (e == null) {
+ return false;
+ }
+ return setExtData(key, e.toString());
+ }
+
+ public boolean setExtData(String key, byte[] data) {
+ if (data == null) {
+ return false;
+ }
+ return setExtData(key, CMS.BtoA(data));
+ }
+
+ public byte[] getExtDataInByteArray(String key) {
+ String value = getExtDataInString(key);
+ if (value != null) {
+ return CMS.AtoB(value);
+ }
+ return null;
+ }
+
+ public boolean setExtData(String key, X509CertImpl data) {
+ if (data == null) {
+ return false;
+ }
+ try {
+ return setExtData(key, data.getEncoded());
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+
+ public X509CertImpl getExtDataInCert(String key) {
+ byte[] data = getExtDataInByteArray(key);
+ if (data != null) {
+ try {
+ return new X509CertImpl(data);
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public boolean setExtData(String key, X509CertImpl[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ try {
+ stringArray[index] = CMS.BtoA(data[index].getEncoded());
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public X509CertImpl[] getExtDataInCertArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ X509CertImpl[] certArray = new X509CertImpl[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ certArray[index] = new X509CertImpl(CMS.AtoB(stringArray[index]));
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return certArray;
+ }
+
+ public boolean setExtData(String key, X509CertInfo data) {
+ if (data == null) {
+ return false;
+ }
+ try {
+ return setExtData(key, data.getEncodedInfo(true));
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+
+ public X509CertInfo getExtDataInCertInfo(String key) {
+ byte[] data = getExtDataInByteArray(key);
+ if (data != null) {
+ try {
+ return new X509CertInfo(data);
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public boolean setExtData(String key, X509CertInfo[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ try {
+ stringArray[index] = CMS.BtoA(data[index].getEncodedInfo(true));
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public X509CertInfo[] getExtDataInCertInfoArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ X509CertInfo[] certArray = new X509CertInfo[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ certArray[index] = new X509CertInfo(CMS.AtoB(stringArray[index]));
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return certArray;
+ }
+
+ public boolean setExtData(String key, RevokedCertImpl[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ try {
+ stringArray[index] = CMS.BtoA(data[index].getEncoded());
+ } catch (CRLException e) {
+ return false;
+ }
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public RevokedCertImpl[] getExtDataInRevokedCertArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ RevokedCertImpl[] certArray = new RevokedCertImpl[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ certArray[index] = new RevokedCertImpl(CMS.AtoB(stringArray[index]));
+ } catch (CRLException e) {
+ return null;
+ } catch (X509ExtensionException e) {
+ return null;
+ }
+ }
+ return certArray;
+ }
+
+ public boolean setExtData(String key, Vector<?> stringVector) {
+ String[] stringArray;
+ if (stringVector == null) {
+ return false;
+ }
+ try {
+ stringArray = (String[]) stringVector.toArray(new String[0]);
+ } catch (ArrayStoreException e) {
+ return false;
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public Vector<String> getExtDataInStringVector(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ return new Vector<String>(Arrays.asList(stringArray));
+ }
+
+ public boolean getExtDataInBoolean(String key, boolean defVal) {
+ String val = getExtDataInString(key);
+ if (val == null)
+ return defVal;
+ return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("ON");
+ }
+
+ public boolean getExtDataInBoolean(String prefix, String type, boolean defVal) {
+ String val = getExtDataInString(prefix, type);
+ if (val == null)
+ return defVal;
+ return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("ON");
+ }
+
+ public boolean setExtData(String key, IAuthToken data) {
+ if (data == null) {
+ return false;
+ }
+ Hashtable<String, String> hash = new Hashtable<String, String>();
+ Enumeration<String> keys = data.getElements();
+ while (keys.hasMoreElements()) {
+ try {
+ String authKey = keys.nextElement();
+ hash.put(authKey, data.getInString(authKey));
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+ return setExtData(key, hash);
+ }
+
+ public IAuthToken getExtDataInAuthToken(String key) {
+ Hashtable<String, String> hash = getExtDataInHashtable(key);
+ if (hash == null) {
+ return null;
+ }
+ AuthToken authToken = new AuthToken(null);
+ Enumeration<String> keys = hash.keys();
+ while (keys.hasMoreElements()) {
+ try {
+ String hashKey = (String) keys.nextElement();
+ authToken.set(hashKey, (String) hash.get(hashKey));
+ } catch (ClassCastException e) {
+ return null;
+ }
+ }
+ return authToken;
+ }
+
+ public boolean setExtData(String key, CertificateExtensions data) {
+ if (data == null) {
+ return false;
+ }
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ try {
+ data.encode(byteStream);
+ } catch (CertificateException e) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+ return setExtData(key, byteStream.toByteArray());
+ }
+
+ public CertificateExtensions getExtDataInCertExts(String key) {
+ CertificateExtensions exts = null;
+ byte[] extensionsData = getExtDataInByteArray(key);
+ if (extensionsData != null) {
+ exts = new CertificateExtensions();
+ try {
+ exts.decodeEx(new ByteArrayInputStream(extensionsData));
+ // exts.decode() does not work when the CertExts size is 0
+ // exts.decode(new ByteArrayInputStream(extensionsData));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return exts;
+ }
+
+ public boolean setExtData(String key, CertificateSubjectName data) {
+ if (data == null) {
+ return false;
+ }
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ try {
+ data.encode(byteStream);
+ } catch (IOException e) {
+ return false;
+ }
+ return setExtData(key, byteStream.toByteArray());
+ }
+
+ public CertificateSubjectName getExtDataInCertSubjectName(String key) {
+ CertificateSubjectName name = null;
+ byte[] nameData = getExtDataInByteArray(key);
+ if (nameData != null) {
+ try {
+ // You must use DerInputStream
+ // using ByteArrayInputStream fails
+ name = new CertificateSubjectName(
+ new DerInputStream(nameData));
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ return name;
+ }
+
+ public boolean setExtData(String key, String[] values) {
+ if (values == null) {
+ return false;
+ }
+ Hashtable<String, String> hashValue = new Hashtable<String, String>();
+ for (int index = 0; index < values.length; index++) {
+ hashValue.put(Integer.toString(index), values[index]);
+ }
+ return setExtData(key, hashValue);
+ }
+
+ public String[] getExtDataInStringArray(String key) {
+ int index;
+
+ Hashtable<String, String> hashValue = getExtDataInHashtable(key);
+ if (hashValue == null) {
+ String s = getExtDataInString(key);
+ if (s == null) {
+ return null;
+ } else {
+ String[] sa = { s };
+ return sa;
+ }
+ }
+ Set<String> arrayKeys = hashValue.keySet();
+ Vector<Object> listValue = new Vector<Object>(arrayKeys.size());
+ for (Iterator<String> iter = arrayKeys.iterator(); iter.hasNext();) {
+ String arrayKey = iter.next();
+ try {
+ index = Integer.parseInt(arrayKey);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ if (listValue.size() < (index + 1)) {
+ listValue.setSize(index + 1);
+ }
+ listValue.set(index,
+ hashValue.get(arrayKey));
+ }
+ return listValue.toArray(new String[0]);
+ }
+
+ public IAttrSet asIAttrSet() {
+ return new RequestIAttrSetWrapper(this);
+ }
+
+ Request(RequestId id) {
+ mRequestId = id;
+ setRequestStatus(RequestStatus.BEGIN);
+ }
+
+ // instance variables
+ protected RequestId mRequestId;
+ protected RequestStatus mRequestStatus;
+ protected String mSourceId;
+ protected String mSource;
+ protected String mOwner;
+ protected String mRequestType;
+ protected String mContext; // string for now.
+ protected ExtDataHashtable<Object> mExtData = new ExtDataHashtable<Object>();
+
+ Date mCreationTime = CMS.getCurrentDate();
+ Date mModificationTime = CMS.getCurrentDate();
+}
+
+class RequestIAttrSetWrapper implements IAttrSet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8231914824991772682L;
+ IRequest mRequest;
+
+ public RequestIAttrSetWrapper(IRequest request) {
+ mRequest = request;
+ }
+
+ public void set(String name, Object obj) throws EBaseException {
+ try {
+ mRequest.setExtData(name, (String) obj);
+ } catch (ClassCastException e) {
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ public Object get(String name) throws EBaseException {
+ return mRequest.getExtDataInString(name);
+ }
+
+ public void delete(String name) throws EBaseException {
+ mRequest.deleteExtData(name);
+ }
+
+ public Enumeration<String> getElements() {
+ return mRequest.getExtDataKeys();
+ }
+}
+
+/**
+ * Example of a specialized request class.
+ */
+class EnrollmentRequest
+ extends Request
+ implements IEnrollmentRequest {
+ EnrollmentRequest(RequestId id) {
+ super(id);
+ }
+}
+
+class RequestListByStatus
+ implements IRequestList {
+ public boolean hasMoreElements() {
+ return (mNext != null);
+ }
+
+ public Object nextRequest() {
+ return null;
+ }
+
+ public IRequest nextRequestObject() {
+ return null;
+ }
+
+ public RequestId nextElement() {
+ RequestId next = mNext;
+
+ update();
+
+ return next;
+ }
+
+ public RequestId nextRequestId() {
+ RequestId next = mNext;
+
+ update();
+
+ return next;
+ }
+
+ public RequestListByStatus(Enumeration<RequestId> e, RequestStatus s, IRequestQueue q) {
+ mEnumeration = e;
+ mStatus = s;
+ mQueue = q;
+
+ update();
+ }
+
+ protected void update() {
+ RequestId rId;
+
+ mNext = null;
+
+ while (mNext == null) {
+ if (!mEnumeration.hasMoreElements())
+ break;
+
+ rId = mEnumeration.nextElement();
+
+ try {
+ IRequest r = mQueue.findRequest(rId);
+
+ if (r.getRequestStatus() == mStatus)
+ mNext = rId;
+
+ mQueue.releaseRequest(r);
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ protected RequestStatus mStatus;
+ protected IRequestQueue mQueue;
+ protected Enumeration<RequestId> mEnumeration;
+ protected RequestId mNext;
+}
+
+class RequestList
+ implements IRequestList {
+ public boolean hasMoreElements() {
+ return mEnumeration.hasMoreElements();
+ }
+
+ public RequestId nextElement() {
+ return mEnumeration.nextElement();
+ }
+
+ public RequestId nextRequestId() {
+ return (RequestId) mEnumeration.nextElement();
+ }
+
+ public Object nextRequest() {
+ return null;
+ }
+
+ public IRequest nextRequestObject() {
+ return null;
+ }
+
+ public RequestList(Enumeration<RequestId> e) {
+ mEnumeration = e;
+ }
+
+ protected Enumeration<RequestId> mEnumeration;
+}
+
+class RecoverThread extends Thread {
+ private ARequestQueue mQ = null;
+
+ public RecoverThread(ARequestQueue q) {
+ mQ = q;
+ setName("RequestRecoverThread");
+ }
+
+ public void run() {
+ mQ.recoverWillBlock();
+ }
+}
diff --git a/base/common/src/com/netscape/cmscore/request/ARequestRecord.java b/base/common/src/com/netscape/cmscore/request/ARequestRecord.java
new file mode 100644
index 000000000..e23d4007c
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/ARequestRecord.java
@@ -0,0 +1,42 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.util.Date;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * The low level (attributes only) version of the database
+ * record object. This exists so that RecordAttr methods can use
+ * this type definition,
+ *
+ * RequestRecord refers both to this class and to RecordAttr objects.
+ */
+class ARequestRecord {
+ RequestId mRequestId;
+ RequestStatus mRequestState;
+ Date mCreateTime;
+ Date mModifyTime;
+ String mSourceId;
+ String mOwner;
+ String mRequestType;
+ Hashtable<String, Object> mExtData;
+};
diff --git a/base/common/src/com/netscape/cmscore/request/CertRequestConstants.java b/base/common/src/com/netscape/cmscore/request/CertRequestConstants.java
new file mode 100644
index 000000000..eab41fcd5
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/CertRequestConstants.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+/**
+ * temporary location for cert request constants.
+ * XXX we really need to centralize all these but for now they are here
+ * as needed.
+ */
+public class CertRequestConstants {
+ // request types - these have string values.
+ // made to match policy constants.
+ public final static String GETCRL_REQUEST = "getCRL";
+ public final static String GETCACHAIN_REQUEST = "getCAChain";
+ public final static String GETREVOCATIONINFO_REQUEST = "getRevocationInfo";
+
+ public final static String REVOCATION_CHECK_CHALLENGE_REQUEST = "checkChallengePhrase";
+ public final static String GETCERTS_FOR_CHALLENGE_REQUEST = "getCertsForChallenge";
+
+ // BigInteger Value and BigIntegerValue array.
+ public final static String SERIALNO = "serialNumber";
+ public final static String SERIALNOS = "serialNumbers";
+
+ // int value.
+ public final static String REVOKE_REASON = "revokeReason";
+
+ // this has a string value.
+ public final static String HOLDINSTRCODE = "holdInstrCode";
+ public final static String HOLDCALLISSUER = "holdCallIssuer";
+ public final static String HOLDREJECT = "holdReject";
+
+ // this has a Date value.
+ public final static String INVALIDITYDATE = "InvalidityDate";
+
+ // this has a CRLExtensions value.
+ public final static String CRLEXTS = "CRLExts";
+
+ // this has a String value - it is either null or set.
+ public final static String DOGETCACHAIN = "doGetCAChain";
+
+ // this has a CertificateChain value.
+ public final static String CACERTCHAIN = "CACertChain";
+
+ // this has a CRL value.
+ public final static String CRL = "CRL";
+
+ // this has a X509CertImpl value.
+ public final static String CERTIFICATE = "certificate";
+
+ // this is an array of EBaseException for service errors when
+ // there's an error processing an array of something such as
+ // certs to renew, certs to revoke, etc.
+ public final static String SVCERRORS = "serviceErrors";
+
+ // crl update status after a revocation.
+ public final static String CRL_UPDATE_STATUS = "crlUpdateStatus";
+ public final static String CRL_UPDATE_ERROR = "crlUpdateError";
+}
diff --git a/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java b/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java
new file mode 100644
index 000000000..86e6c0530
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java
@@ -0,0 +1,78 @@
+package com.netscape.cmscore.request;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Subclass of Hashtable returned by IRequest.getExtDataInHashtable. Its
+ * purpose is to hide the fact that LDAP doesn't preserve the case of keys.
+ * It does this by lowercasing all keys used to access the Hashtable.
+ */
+public class ExtDataHashtable<V> extends Hashtable<String, V> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8401134619951331450L;
+
+ public ExtDataHashtable() {
+ super();
+ }
+
+ public ExtDataHashtable(int i) {
+ super(i);
+ }
+
+ public ExtDataHashtable(int i, float v) {
+ super(i, v);
+ }
+
+ public ExtDataHashtable(Map<? extends String, ? extends V> map) {
+ // the super constructor seems to call putAll, but I can't
+ // rely on that behaviour
+ super();
+ putAll(map);
+ }
+
+ public boolean containsKey(Object o) {
+ if (o instanceof String) {
+ String key = (String) o;
+ return super.containsKey(key.toLowerCase());
+ }
+ return super.containsKey(o);
+ }
+
+ public V get(Object o) {
+ if (o instanceof String) {
+ String key = (String) o;
+ return super.get(key.toLowerCase());
+ }
+ return super.get(o);
+ }
+
+ public V put(String oKey, V val) {
+ if (oKey instanceof String) {
+ String key = (String) oKey;
+ return super.put(key.toLowerCase(), val);
+ }
+ return super.put(oKey, val);
+ }
+
+ public void putAll(Map<? extends String, ? extends V> map) {
+ Set<? extends String> keys = map.keySet();
+ for (Iterator<? extends String> i = keys.iterator(); i.hasNext();) {
+ Object key = i.next();
+ put((String) key, map.get(key));
+ }
+ }
+
+ public V remove(Object o) {
+ if (o instanceof String) {
+ String key = (String) o;
+ return super.remove(key.toLowerCase());
+ }
+ return super.remove(o);
+ }
+}
diff --git a/base/common/src/com/netscape/cmscore/request/RequestAttr.java b/base/common/src/com/netscape/cmscore/request/RequestAttr.java
new file mode 100644
index 000000000..25734c91e
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/RequestAttr.java
@@ -0,0 +1,61 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.ldap.IRequestMod;
+
+/**
+ * The RequestAttr class defines the methods used
+ * to transfer data between the various representations of
+ * a request. The three forms are:
+ * 1) LDAPAttributes (and Modifications)
+ * 2) Database record IDBAttrSet
+ * 3) IRequest (Request) object
+ */
+abstract class RequestAttr {
+
+ /**
+ *
+ */
+
+ abstract void set(ARequestRecord r, Object o);
+
+ abstract Object get(ARequestRecord r);
+
+ abstract void read(IRequestMod a, IRequest r, ARequestRecord rr);
+
+ abstract void add(IRequest r, ARequestRecord rr);
+
+ abstract void mod(ModificationSet mods, IRequest r);
+
+ RequestAttr(String attrName, IDBAttrMapper mapper) {
+ mAttrName = attrName;
+ mMapper = mapper;
+ }
+
+ protected void addmod(ModificationSet mods, Object o) {
+ mods.add(mAttrName, Modification.MOD_REPLACE, o);
+ }
+
+ String mAttrName;
+ IDBAttrMapper mMapper;
+}
diff --git a/base/common/src/com/netscape/cmscore/request/RequestQueue.java b/base/common/src/com/netscape/cmscore/request/RequestQueue.java
new file mode 100644
index 000000000..ef13d3c29
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/RequestQueue.java
@@ -0,0 +1,709 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.repository.IRepository;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestRecord;
+import com.netscape.certsrv.request.IRequestVirtualList;
+import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.request.ldap.IRequestMod;
+import com.netscape.cmscore.dbs.DBSubsystem;
+import com.netscape.cmscore.util.Debug;
+
+public class RequestQueue
+ extends ARequestQueue
+ implements IRequestMod {
+ // ARequestQueue.newRequestId
+ protected RequestId newRequestId()
+ throws EBaseException {
+ // get the next request Id
+ BigInteger next = mRepository.getNextSerialNumber();
+
+ RequestId rid = new RequestId(next);
+
+ return rid;
+ }
+
+ protected IRequest readRequest(RequestId id) {
+ RequestRecord record;
+
+ // String name = Schema.LDAP_ATTR_REQUEST_ID + "=" +
+ String name = "cn" + "=" +
+ id + "," + mBaseDN;
+
+ Object obj = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ obj = dbs.read(name);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ // TODO Errors!!!
+ if (obj == null || !(obj instanceof RequestRecord))
+ return null;
+
+ record = (RequestRecord) obj;
+
+ /*
+ setRequestStatus(r, record.mRequestState);
+ r.setSourceId(record.mSourceId);
+ r.setRequestOwner(record.mOwner);
+ record.storeAttrs(r, record.mRequestAttrs);
+ setModificationTime(r, record.mModifyTime);
+ setCreationTime(r, record.mCreateTime);
+ */
+ return makeRequest(record);
+ }
+
+ protected void addRequest(IRequest r) throws EBaseException {
+ // setup to call dbs.add(name, IAttrSet)
+ RequestRecord record = new RequestRecord();
+
+ record.add(r);
+
+ // compute the name of the object
+ // String name = Schema.LDAP_ATTR_REQUEST_ID + "=" +
+ String name = "cn" + "=" +
+ record.mRequestId + "," + mBaseDN;
+
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ dbs.add(name, record);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ throw e;
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+ }
+
+ protected void modifyRequest(IRequest r) {
+ String dbStatus = r.getExtDataInString("dbStatus");
+
+ if (!dbStatus.equals("UPDATED")) {
+ try {
+ r.setExtData("dbStatus", "UPDATED");
+ addRequest(r);
+ } catch (EBaseException e) {
+ System.out.println(e.toString());
+ }
+ return;
+ }
+
+ ModificationSet mods = new ModificationSet();
+
+ try {
+ RequestRecord.mod(mods, r);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ }
+
+ /*
+ //
+ mods.add(IRequestRecord.ATTR_REQUEST_STATE,
+ Modification.MOD_REPLACE, r.getRequestStatus());
+
+ mods.add(IRequestRecord.ATTR_SOURCE_ID,
+ Modification.MOD_REPLACE, r.getSourceId());
+
+ mods.add(IRequestRecord.ATTR_REQUEST_OWNER,
+ Modification.MOD_REPLACE, r.getRequestOwner());
+
+ mods.add(IRequestRecord.ATTR_MODIFY_TIME,
+ Modification.MOD_REPLACE, r.getModificationTime());
+
+ java.util.Hashtable ht = RequestRecord.loadAttrs(r);
+ mods.add(RequestRecord.ATTR_REQUEST_ATTRS,
+ Modification.MOD_REPLACE, ht);
+ */
+
+ // String name = Schema.LDAP_ATTR_REQUEST_ID + "=" +
+ String name = "cn" + "=" +
+ r.getRequestId() + "," + mBaseDN;
+
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ dbs.modify(name, mods);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+ }
+
+ IRequest makeRequest(RequestRecord record) {
+ IRequest r = createRequest(record.mRequestId, record.mRequestType);
+
+ try {
+ // convert (copy) fields
+ record.read(this, r);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ }
+
+ return r;
+ }
+
+ public void modRequestStatus(IRequest r, RequestStatus s) {
+ setRequestStatus(r, s);
+ }
+
+ public void modCreationTime(IRequest r, Date d) {
+ setCreationTime(r, d);
+ }
+
+ public void modModificationTime(IRequest r, Date d) {
+ setModificationTime(r, d);
+ }
+
+ /**
+ * Resets serial number.
+ */
+ public void resetSerialNumber(BigInteger serial) throws EBaseException {
+ mRepository.resetSerialNumber(serial);
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeAllObjects() throws EBaseException {
+ mRepository.removeAllObjects();
+ }
+
+ public BigInteger getLastRequestIdInRange(BigInteger reqId_low_bound, BigInteger reqId_upper_bound) {
+ CMS.debug("RequestQueue: getLastRequestId: low " + reqId_low_bound + " high " + reqId_upper_bound);
+ if (reqId_low_bound == null || reqId_upper_bound == null || reqId_low_bound.compareTo(reqId_upper_bound) >= 0) {
+ CMS.debug("RequestQueue: getLastRequestId: bad upper and lower bound range.");
+ return null;
+ }
+
+ String filter = "(" + "requeststate" + "=*" + ")";
+
+ RequestId fromId = new RequestId(reqId_upper_bound);
+
+ CMS.debug("RequestQueue: getLastRequestId: filter " + filter + " fromId " + fromId);
+ ListEnumeration recList = (ListEnumeration) getPagedRequestsByFilter(fromId, filter, 5 * -1, "requestId");
+
+ int size = recList.getSize();
+
+ CMS.debug("RequestQueue: getLastRequestId: size " + size);
+
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ CMS.debug("RequestQueue: getSizeBeforeJumpTo: " + ltSize);
+
+ if (size <= 0) {
+ CMS.debug("RequestQueue: getLastRequestId: request list is empty.");
+
+ BigInteger ret = new BigInteger(reqId_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ return ret;
+ }
+
+ IRequest curRec = null;
+
+ RequestId curId = null;
+
+ String reqId = null;
+
+ for (int i = 0; i < 5; i++) {
+ curRec = recList.getElementAt(i);
+
+ if (curRec != null) {
+
+ curId = curRec.getRequestId();
+
+ reqId = curId.toString();
+
+ CMS.debug("RequestQueue: curReqId: " + reqId);
+
+ BigInteger curIdInt = new BigInteger(reqId);
+
+ if (((curIdInt.compareTo(reqId_low_bound) == 0) || (curIdInt.compareTo(reqId_low_bound) == 1)) &&
+ ((curIdInt.compareTo(reqId_upper_bound) == 0) || (curIdInt.compareTo(reqId_upper_bound) == -1))) {
+ CMS.debug("RequestQueue: getLastRequestId : returning value " + curIdInt);
+ return curIdInt;
+ }
+
+ }
+
+ }
+
+ BigInteger ret = new BigInteger(reqId_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ return ret;
+
+ }
+
+ /**
+ * Implements IRequestQueue.findRequestBySourceId
+ * <p>
+ *
+ * @see com.netscape.certsrv.request.IRequestQueue#findRequestBySourceId
+ */
+ public RequestId findRequestBySourceId(String id) {
+ IRequestList irl = findRequestsBySourceId(id);
+
+ if (irl == null)
+ return null;
+
+ return irl.nextRequestId();
+ }
+
+ /**
+ * Implements IRequestQueue.findRequestsBySourceId
+ * <p>
+ *
+ * @see com.netscape.certsrv.request.IRequestQueue#findRequestsBySourceId
+ */
+ public IRequestList findRequestsBySourceId(String id) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ // Need only the requestid in the result of the search
+ // TODO: generic search returning RequestId
+ String filter = "(" + IRequestRecord.ATTR_SOURCE_ID + "=" + id + ")";
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, filter);
+ } catch (EBaseException e) {
+ Debug.trace("Error in Ldap Request searching code: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null || !results.hasMoreElements())
+ return null;
+
+ return new SearchEnumeration(this, results);
+
+ }
+
+ protected Enumeration<RequestId> getRawList() {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, "(requestId=*)");
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /**
+ */
+ public IRequestList listRequestsByFilter(String f) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /**
+ */
+ public IRequestList listRequestsByFilter(String f, int maxSize) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f, maxSize);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /**
+ */
+ public IRequestList listRequestsByFilter(String f, int maxSize, int timeLimit) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f, maxSize, timeLimit);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ public IRequestList listRequestsByStatus(RequestStatus s) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ String f1;
+ String f2;
+
+ f1 = "(" + IRequestRecord.ATTR_REQUEST_STATE + "=" + s + ")";
+ f2 = "(" + IRequestRecord.ATTR_REQUEST_ID + "=*)";
+
+ f1 = "(&" + f1 + f2 + ")";
+
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f1);
+ } catch (EBaseException e) {
+ //System.err.println("Error: "+e);
+ //e.printStackTrace();
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /*
+ * Implements IRequestQueue.getPagedRequests
+ */
+ public IRequestVirtualList getPagedRequests(int pageSize) {
+ return getPagedRequestsByFilter("(requestId=*)", pageSize, "requestId");
+ }
+
+ /*
+ * Implements IRequestQueue.getPagedRequestsByFilter
+ */
+ public IRequestVirtualList
+ getPagedRequestsByFilter(String filter, int pageSize, String sortKey) {
+ return getPagedRequestsByFilter(null, filter, pageSize, sortKey);
+ }
+
+ public IRequestVirtualList
+ getPagedRequestsByFilter(RequestId from, String filter, int pageSize,
+ String sortKey) {
+ return getPagedRequestsByFilter(from, false, filter, pageSize, sortKey);
+ }
+
+ public IRequestVirtualList
+ getPagedRequestsByFilter(RequestId from, boolean jumpToEnd, String filter, int pageSize,
+ String sortKey) {
+ IDBVirtualList<Object> results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ } catch (EBaseException e) {
+ return null;
+ }
+
+ try {
+
+ if (from == null) {
+ results = dbs.createVirtualList(mBaseDN, filter, (String[]) null,
+ sortKey, pageSize);
+ } else {
+ int len = from.toString().length();
+ String internalRequestId = null;
+
+ if (jumpToEnd) {
+ internalRequestId = "99";
+ } else {
+ if (len > 9) {
+ internalRequestId = Integer.toString(len) + from.toString();
+ } else {
+ internalRequestId = "0" + Integer.toString(len) +
+ from.toString();
+ }
+ }
+
+ results = dbs.createVirtualList(mBaseDN, filter, (String[]) null,
+ internalRequestId, sortKey, pageSize);
+ }
+ } catch (EBaseException e) {
+ return null;
+ } finally {
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ try {
+ results.setSortKey(sortKey);
+ } catch (EBaseException e) {//XXX
+ System.out.println(e.toString());
+ return null;
+ }
+
+ return new ListEnumeration(this, results);
+ }
+
+ public RequestQueue(String name, int increment, IPolicy p, IService s, INotify n,
+ INotify pendingNotify)
+ throws EBaseException {
+ super(p, s, n, pendingNotify);
+
+ mDB = DBSubsystem.getInstance();
+ mBaseDN = "ou=" + name + ",ou=requests," + mDB.getBaseDN();
+
+ mRepository = new RequestRepository(name, increment, mDB, this);
+
+ }
+
+ /*
+ * list record attributes (debugging output)
+ */
+ static void listRecordAttrs(String s, Hashtable<String, Object> h) {
+ System.err.println(s);
+ Enumeration<String> e = h.keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ System.err.println("Attr: " + name + " Value: " + h.get(name));
+ }
+ }
+
+ /*
+ * return request repository
+ */
+ public IRepository getRequestRepository() {
+ return (IRepository) mRepository;
+ }
+
+ public String getPublishingStatus() {
+ return mRepository.getPublishingStatus();
+ }
+
+ public void setPublishingStatus(String status) {
+ mRepository.setPublishingStatus(status);
+ }
+
+ protected String mBaseDN;
+ protected IDBSubsystem mDB;
+ protected RequestRepository mRepository;
+}
+
+class SearchEnumeration
+ implements IRequestList {
+ public RequestId nextRequestId() {
+ Object obj;
+
+ obj = mResults.nextElement();
+
+ if (obj == null || !(obj instanceof RequestRecord))
+ return null;
+
+ RequestRecord r = (RequestRecord) obj;
+
+ return r.mRequestId;
+ }
+
+ public boolean hasMoreElements() {
+ return mResults.hasMoreElements();
+ }
+
+ public RequestId nextElement() {
+ return nextRequestId();
+ }
+
+ public SearchEnumeration(IDBSearchResults r) {
+ mResults = r;
+ }
+
+ public SearchEnumeration(RequestQueue queue, IDBSearchResults r) {
+ mResults = r;
+ mQueue = queue;
+ }
+
+ public Object nextRequest() {
+ Object obj;
+
+ obj = mResults.nextElement();
+
+ if (obj == null || !(obj instanceof RequestRecord))
+ return null;
+
+ RequestRecord r = (RequestRecord) obj;
+
+ return r;
+ }
+
+ public IRequest nextRequestObject() {
+ RequestRecord record = (RequestRecord) nextRequest();
+ if (record != null)
+ return mQueue.makeRequest(record);
+ return null;
+ }
+
+ protected IDBSearchResults mResults;
+ protected RequestQueue mQueue;
+}
+
+class ListEnumeration
+ implements IRequestVirtualList {
+ public IRequest getElementAt(int i) {
+ RequestRecord record = (RequestRecord) mList.getElementAt(i);
+
+ if (record == null)
+ return null;
+
+ return mQueue.makeRequest(record);
+ }
+
+ public int getCurrentIndex() {
+ return mList.getCurrentIndex();
+ }
+
+ public int getSize() {
+ return mList.getSize();
+ }
+
+ public int getSizeBeforeJumpTo() {
+ return mList.getSizeBeforeJumpTo();
+
+ }
+
+ public int getSizeAfterJumpTo() {
+ return mList.getSizeAfterJumpTo();
+
+ }
+
+ ListEnumeration(RequestQueue queue, IDBVirtualList<Object> list) {
+ mQueue = queue;
+ mList = list;
+ }
+
+ protected RequestQueue mQueue;
+ protected IDBVirtualList<Object> mList;
+}
diff --git a/base/common/src/com/netscape/cmscore/request/RequestRecord.java b/base/common/src/com/netscape/cmscore/request/RequestRecord.java
new file mode 100644
index 000000000..1d066f0ad
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/RequestRecord.java
@@ -0,0 +1,883 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBDynAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestRecord;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.request.ldap.IRequestMod;
+import com.netscape.cmscore.dbs.BigIntegerMapper;
+import com.netscape.cmscore.dbs.DateMapper;
+import com.netscape.cmscore.dbs.StringMapper;
+import com.netscape.cmscore.util.Debug;
+
+//
+// A request record is the stored version of a request.
+// It has a set of attributes that are mapped into LDAP
+// attributes for actual directory operations.
+//
+public class RequestRecord
+ extends ARequestRecord
+ implements IRequestRecord, IDBObj {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8044665107558872084L;
+
+ public RequestId getRequestId() {
+ return mRequestId;
+ }
+
+ public Enumeration<String> getAttrNames() {
+ return mAttrTable.keys();
+ }
+
+ // IDBObj.get
+ public Object get(String name) {
+ if (name.equals(IRequestRecord.ATTR_REQUEST_ID))
+ return mRequestId;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_STATE))
+ return mRequestState;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_TYPE))
+ return mRequestType;
+ else if (name.equals(IRequestRecord.ATTR_MODIFY_TIME))
+ return mModifyTime;
+ else if (name.equals(IRequestRecord.ATTR_CREATE_TIME))
+ return mCreateTime;
+ else if (name.equals(IRequestRecord.ATTR_SOURCE_ID))
+ return mSourceId;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_OWNER))
+ return mOwner;
+ else if (name.equals(IRequestRecord.ATTR_EXT_DATA))
+ return mExtData;
+ else {
+ RequestAttr ra = mAttrTable.get(name);
+
+ if (ra != null)
+ return ra.get(this);
+ }
+
+ return null;
+ }
+
+ // IDBObj.set
+ @SuppressWarnings("unchecked")
+ public void set(String name, Object o) {
+ if (name.equals(IRequestRecord.ATTR_REQUEST_ID))
+ mRequestId = (RequestId) o;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_STATE))
+ mRequestState = (RequestStatus) o;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_TYPE))
+ mRequestType = (String) o;
+ else if (name.equals(IRequestRecord.ATTR_CREATE_TIME))
+ mCreateTime = (Date) o;
+ else if (name.equals(IRequestRecord.ATTR_MODIFY_TIME))
+ mModifyTime = (Date) o;
+ else if (name.equals(IRequestRecord.ATTR_SOURCE_ID))
+ mSourceId = (String) o;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_OWNER))
+ mOwner = (String) o;
+ else if (name.equals(IRequestRecord.ATTR_EXT_DATA))
+ mExtData = (Hashtable<String, Object>) o;
+ else {
+ RequestAttr ra = mAttrTable.get(name);
+
+ if (ra != null)
+ ra.set(this, o);
+ }
+ }
+
+ // IDBObj.delete
+ public void delete(String name)
+ throws EBaseException {
+ throw new EBaseException("Invalid call to delete");
+ }
+
+ // IDBObj.getElements
+ public Enumeration<String> getElements() {
+ return mAttrs.elements();
+ }
+
+ // IDBObj.getSerializableAttrNames
+ public Enumeration<String> getSerializableAttrNames() {
+ return mAttrs.elements();
+ }
+
+ // copy values from r to the local record
+ void add(IRequest r) throws EBaseException {
+ // Collect the values for the record
+ mRequestId = r.getRequestId();
+ mRequestType = r.getRequestType();
+ mRequestState = r.getRequestStatus();
+ mSourceId = r.getSourceId();
+ mOwner = r.getRequestOwner();
+ mCreateTime = r.getCreationTime();
+ mModifyTime = r.getModificationTime();
+ mExtData = loadExtDataFromRequest(r);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ mRequestA[i].add(r, this);
+ }
+ }
+
+ void read(IRequestMod a, IRequest r) throws EBaseException {
+ a.modRequestStatus(r, mRequestState);
+ r.setSourceId(mSourceId);
+ r.setRequestOwner(mOwner);
+ a.modModificationTime(r, mModifyTime);
+ a.modCreationTime(r, mCreateTime);
+ storeExtDataIntoRequest(r);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ mRequestA[i].read(a, r, this);
+ }
+ }
+
+ static void mod(ModificationSet mods, IRequest r) throws EBaseException {
+ //
+ mods.add(IRequestRecord.ATTR_REQUEST_STATE,
+ Modification.MOD_REPLACE, r.getRequestStatus());
+
+ mods.add(IRequestRecord.ATTR_SOURCE_ID,
+ Modification.MOD_REPLACE, r.getSourceId());
+
+ mods.add(IRequestRecord.ATTR_REQUEST_OWNER,
+ Modification.MOD_REPLACE, r.getRequestOwner());
+
+ mods.add(IRequestRecord.ATTR_MODIFY_TIME,
+ Modification.MOD_REPLACE, r.getModificationTime());
+
+ mods.add(IRequestRecord.ATTR_EXT_DATA,
+ Modification.MOD_REPLACE, loadExtDataFromRequest(r));
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ mRequestA[i].mod(mods, r);
+ }
+ }
+
+ static void register(IDBSubsystem db)
+ throws EDBException {
+ IDBRegistry reg = db.getRegistry();
+
+ reg.registerObjectClass(RequestRecord.class.getName(), mOC);
+
+ reg.registerAttribute(IRequestRecord.ATTR_REQUEST_ID, new RequestIdMapper());
+ reg.registerAttribute(IRequestRecord.ATTR_REQUEST_STATE, new RequestStateMapper());
+ reg.registerAttribute(IRequestRecord.ATTR_CREATE_TIME,
+ new DateMapper(Schema.LDAP_ATTR_CREATE_TIME));
+ reg.registerAttribute(IRequestRecord.ATTR_MODIFY_TIME,
+ new DateMapper(Schema.LDAP_ATTR_MODIFY_TIME));
+ reg.registerAttribute(IRequestRecord.ATTR_SOURCE_ID,
+ new StringMapper(Schema.LDAP_ATTR_SOURCE_ID));
+ reg.registerAttribute(IRequestRecord.ATTR_REQUEST_OWNER,
+ new StringMapper(Schema.LDAP_ATTR_REQUEST_OWNER));
+ ExtAttrDynMapper extAttrMapper = new ExtAttrDynMapper();
+ reg.registerAttribute(IRequestRecord.ATTR_EXT_DATA, extAttrMapper);
+ reg.registerDynamicMapper(extAttrMapper);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ RequestAttr ra = mRequestA[i];
+
+ reg.registerAttribute(ra.mAttrName, ra.mMapper);
+ }
+ }
+
+ protected static final String mOC[] =
+ { Schema.LDAP_OC_TOP, Schema.LDAP_OC_REQUEST, Schema.LDAP_OC_EXTENSIBLE };
+
+ protected static Hashtable<String, Object> loadExtDataFromRequest(IRequest r) throws EBaseException {
+ Hashtable<String, Object> h = new Hashtable<String, Object>();
+
+ Enumeration<String> e = r.getExtDataKeys();
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ if (r.isSimpleExtDataValue(key)) {
+ h.put(key, r.getExtDataInString(key));
+ } else {
+ h.put(key, r.getExtDataInHashtable(key));
+ }
+ }
+
+ return h;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void storeExtDataIntoRequest(IRequest r) throws EBaseException {
+ Enumeration<String> e = mExtData.keys();
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ Object value = mExtData.get(key);
+ if (value instanceof String) {
+ r.setExtData(key, (String) value);
+ } else if (value instanceof Hashtable) {
+ r.setExtData(key, (Hashtable<String, String>) value);
+ } else {
+ throw new EDBException("Illegal data value in RequestRecord: " +
+ r.toString());
+ }
+ }
+ }
+
+ protected static Vector<String> mAttrs = new Vector<String>();
+
+ static Hashtable<String, RequestAttr> mAttrTable = new Hashtable<String, RequestAttr>();
+
+ /*
+ * This table contains attribute handlers for attributes
+ * of the request. These attributes are ones that are stored
+ * apart from the generic name/value pairs supported by the get/set
+ * interface plus the hashtable for the name/value pairs themselves.
+ *
+ * NOTE: Eventually, all attributes should be done here. Currently
+ * only the last ones added are implemented this way.
+ */
+ static RequestAttr mRequestA[] = {
+
+ new RequestAttr(IRequest.ATTR_REQUEST_TYPE,
+ new StringMapper(Schema.LDAP_ATTR_REQUEST_TYPE)) {
+ void set(ARequestRecord r, Object o) {
+ r.mRequestType = (String) o;
+ }
+
+ Object get(ARequestRecord r) {
+ return r.mRequestType;
+ }
+
+ void read(IRequestMod a, IRequest r, ARequestRecord rr) {
+ r.setRequestType(rr.mRequestType);
+ }
+
+ void add(IRequest r, ARequestRecord rr) {
+ rr.mRequestType = r.getRequestType();
+ }
+
+ void mod(ModificationSet mods, IRequest r) {
+ addmod(mods, r.getRequestType());
+ }
+ }
+
+ };
+ static {
+ mAttrs.add(IRequestRecord.ATTR_REQUEST_ID);
+ mAttrs.add(IRequestRecord.ATTR_REQUEST_STATE);
+ mAttrs.add(IRequestRecord.ATTR_CREATE_TIME);
+ mAttrs.add(IRequestRecord.ATTR_MODIFY_TIME);
+ mAttrs.add(IRequestRecord.ATTR_SOURCE_ID);
+ mAttrs.add(IRequestRecord.ATTR_REQUEST_OWNER);
+ mAttrs.add(IRequestRecord.ATTR_EXT_DATA);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ RequestAttr ra = mRequestA[i];
+
+ mAttrs.add(ra.mAttrName);
+ mAttrTable.put(ra.mAttrName, ra);
+ }
+ }
+
+}
+
+//
+// A mapper between an request state object and
+// its LDAP attribute representation
+// <P>
+//
+// @author thayes
+// @version $Revision$ $Date$
+//
+class RequestStateMapper
+ implements IDBAttrMapper {
+ // IDBAttrMapper methods
+
+ //
+ //
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) {
+ RequestStatus rs = (RequestStatus) obj;
+
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_STATE,
+ rs.toString()));
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(Schema.LDAP_ATTR_REQUEST_STATE);
+
+ if (attr == null)
+ throw new EBaseException("schema violation");
+
+ String value = (String) attr.getStringValues().nextElement();
+
+ parent.set(name, RequestStatus.fromString(value));
+ }
+
+ public String mapSearchFilter(String name, String op, String value) {
+ return Schema.LDAP_ATTR_REQUEST_STATE + op + value;
+ }
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_REQUEST_STATE);
+ }
+}
+
+//
+// A mapper between an request id object and
+// its LDAP attribute representation
+// <P>
+//
+// @author thayes
+// @version $Revision$ $Date$
+//
+class RequestIdMapper
+ implements IDBAttrMapper {
+ // IDBAttrMapper methods
+
+ //
+ //
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) {
+ RequestId rid = (RequestId) obj;
+
+ String v = BigIntegerMapper.BigIntegerToDB(new BigInteger(rid.toString()));
+
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_ID, v));
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(Schema.LDAP_ATTR_REQUEST_ID);
+
+ if (attr == null)
+ throw new EBaseException("schema violation");
+
+ String value = (String) attr.getStringValues().nextElement();
+
+ parent.set(name, new RequestId(
+ BigIntegerMapper.BigIntegerFromDB(value).toString()));
+ }
+
+ public String mapSearchFilter(String name, String op, String value) {
+ String v = null;
+
+ try {
+ v = BigIntegerMapper.BigIntegerToDB(new BigInteger(value));
+ } catch (NumberFormatException e) {
+ v = value;
+ }
+ return Schema.LDAP_ATTR_REQUEST_ID + op + v;
+ }
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_REQUEST_ID);
+ }
+}
+
+/**
+ * A mapper between an request attr set and its LDAP attribute representation.
+ *
+ * The attr attribute is no longer used. This class is kept for historical
+ * and migration purposes.
+ *
+ * @author thayes
+ * @version $Revision$ $Date$
+ * @deprecated
+ */
+class RequestAttrsMapper
+ implements IDBAttrMapper {
+ // IDBAttrMapper methods
+
+ //
+ //
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) {
+ @SuppressWarnings("unchecked")
+ Hashtable<String, Object> ht = (Hashtable<String, Object>) obj;
+ Enumeration<String> e = ht.keys();
+
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(bos);
+
+ String key = null;
+ Object value = null;
+
+ while (e.hasMoreElements()) {
+ key = e.nextElement();
+ value = ht.get(key);
+ byte data[] = null;
+
+ try {
+ data = encode(value);
+ os.writeObject(key);
+ os.writeObject(data);
+ } catch (NotSerializableException x) {
+ if (Debug.ON) {
+ System.err.println("Error: attribute '" + key + "' (" +
+ x.getMessage() + ") is not serializable");
+ x.printStackTrace();
+ }
+ } catch (Exception x) {
+ if (Debug.ON) {
+ System.err.println("Error: attribute '" + key +
+ "' - error during serialization: " + x);
+ x.printStackTrace();
+ }
+ }
+ }
+
+ os.writeObject(null);
+ os.close();
+
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_ATTRS,
+ bos.toByteArray()));
+ } catch (Exception x) {
+ Debug.trace("Output Mapping Error in requeset ID " +
+ ((RequestRecord) parent).getRequestId().toString() + " : " + x);
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ }
+ }
+
+ private byte[] encode(Object value)
+ throws NotSerializableException, IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(bos);
+
+ os.writeObject(value);
+ os.close();
+
+ return bos.toByteArray();
+ }
+
+ private Object decode(byte[] data)
+ throws ObjectStreamException, IOException, ClassNotFoundException {
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ ObjectInputStream is = new ObjectInputStream(bis);
+
+ return is.readObject();
+ }
+
+ private Hashtable<String, Object> decodeHashtable(byte[] data)
+ throws ObjectStreamException, IOException, ClassNotFoundException {
+ Hashtable<String, Object> ht = new Hashtable<String, Object>();
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ ObjectInputStream is = new ObjectInputStream(bis);
+
+ String key = null;
+
+ try {
+
+ while (true) {
+ key = (String) is.readObject();
+
+ // end of table is marked with null
+ if (key == null)
+ break;
+
+ byte[] bytes = (byte[]) is.readObject();
+
+ ht.put(key, decode(bytes));
+ }
+ } catch (ObjectStreamException e) {
+ Debug.trace("Key " + key); // would be nice to know object type.
+ throw e;
+ } catch (IOException e) {
+ Debug.trace("Key " + key); // would be nice to know object type.
+ throw e;
+ } catch (ClassNotFoundException e) {
+ Debug.trace("Key " + key); // would be nice to know object type.
+ throw e;
+ }
+
+ return ht;
+ }
+
+ /**
+ * Implements IDBAttrMapper.mapLDAPAttributeSetToObject
+ * <p>
+ *
+ * @see IDBAttrMapper#mapLDAPAttributeSetToObject
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ Hashtable<String, Object> ht = null;
+
+ //
+ // Data is stored in a (single valued) binary attribute
+ //
+ byte[] value;
+
+ LDAPAttribute attr = null;
+
+ try {
+ attr = attrs.getAttribute(Schema.LDAP_ATTR_REQUEST_ATTRS);
+
+ if (attr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> values = attr.getByteValues();
+
+ value = (byte[]) values.nextElement();
+
+ ht = decodeHashtable(value);
+ }
+ } catch (Exception x) {
+ Debug.trace("Mapping error in request Id " +
+ ((RequestRecord) parent).getRequestId().toString() + " : " + x);
+ Debug.trace("Attr " + attr.getName());
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ }
+
+ parent.set(name, ht);
+ }
+
+ public String mapSearchFilter(String name, String op, String value) {
+ return Schema.LDAP_ATTR_REQUEST_ID + op + value;
+ }
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_REQUEST_ATTRS);
+ }
+}
+
+/**
+ * Maps dynamic data for the extData- prefix to and from the extData Hashtable
+ * in RequestRecord.
+ *
+ * The data in RequestRecord is stored in a Hashtable. It comes in two forms:
+ * 1. String key1 => String value1
+ * String key2 => String value2
+ * This is stored in LDAP as:
+ * extData-key1 => value1
+ * extData-key2 => value2
+ *
+ * 2. String key => Hashtable value
+ * where value stores:
+ * String key2 => String value2
+ * String key3 => String value3
+ * This is stored in LDAP as:
+ * extData-key;key2 => value2
+ * extData-key;key3 => value3
+ *
+ * These can be mixed, but each top-level key can only be associated with
+ * a String value or a Hashtable value.
+ *
+ */
+class ExtAttrDynMapper implements IDBDynAttrMapper {
+
+ public boolean supportsLDAPAttributeName(String attrName) {
+ return (attrName != null) &&
+ attrName.toLowerCase().startsWith(extAttrPrefix);
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ /**
+ * Decodes extdata encoded keys.
+ * -- followed by a 4 digit hexadecimal string is decoded to the character
+ * representing the hex string.
+ *
+ * The routine is written to be highly efficient. It only allocates
+ * the StringBuffer if needed and copies the pieces in large chunks.
+ *
+ * @param key The key to decode
+ * @return The decoded key.
+ */
+ public String decodeKey(String key) {
+ StringBuffer output = null;
+ char[] input = key.toCharArray();
+ int startCopyIndex = 0;
+
+ int index = 0;
+ while (index < input.length) {
+ if (input[index] == '-') {
+ if (((index + 1) < input.length) &&
+ (input[index + 1] == '-')) {
+ if (output == null) {
+ output = new StringBuffer(input.length);
+ }
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ index += 2;
+ if ((index + 3) < input.length) {
+ output.append(
+ Character.toChars(
+ Integer.parseInt(new String(input, index, 4),
+ 16))
+ );
+ }
+ index += 4;
+ startCopyIndex = index;
+ } else {
+ index++;
+ }
+ } else {
+ index++;
+ }
+ }
+
+ if (output == null) {
+ return key;
+ } else {
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ return output.toString();
+ }
+ }
+
+ /**
+ * Encoded extdata keys for storage in LDAP.
+ *
+ * The rules for encoding are trickier than decoding. We want to allow
+ * '-' by itself to be stored in the database (for the common case of keys
+ * like 'Foo-Bar'. Therefore we are using '--' as the encoding character.
+ * The rules are:
+ * 1) All characters [^-a-zA-Z0-9] are encoded as --XXXX where XXXX is the
+ * hex representation of the digit.
+ * 2) [a-zA-Z0-9] are always passed through unencoded
+ * 3) [-] is passed through as long as it is preceded and followed
+ * by [a-zA-Z0-9] (or if it's at the beginning/end of the string)
+ * 4) If [-] is preceded or followed by [^a-zA-Z0-9] then
+ * the - as well as all following [^a-zA-Z0-9] characters are encoded
+ * as --XXXX.
+ *
+ * This routine tries to be as efficient as possible with StringBuffer and
+ * large copies. However, the encoding unfortunately requires several
+ * objects to be allocated.
+ *
+ * @param key The key to encode
+ * @return The encoded key
+ */
+ public String encodeKey(String key) {
+ StringBuffer output = null;
+ char[] input = key.toCharArray();
+ int startCopyIndex = 0;
+
+ int index = 0;
+ while (index < input.length) {
+ if (!isAlphaNum(input[index])) {
+ if ((input[index] == '-') &&
+ ((index + 1) < input.length) &&
+ (isAlphaNum(input[index + 1]))) {
+ index += 2;
+ } else if ((input[index] == '-') &&
+ ((index + 1) == input.length)) {
+ index += 1;
+ } else {
+ if (output == null) {
+ output = new StringBuffer(input.length + 5);
+ }
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ while ((index < input.length) &&
+ (!isAlphaNum(input[index]))) {
+ output.append("--");
+ String hexString = Integer.toHexString(input[index]);
+ int padding = 4 - hexString.length();
+ while (padding > 0) {
+ output.append('0');
+ padding--;
+ }
+ output.append(hexString);
+ index++;
+ }
+ startCopyIndex = index;
+ }
+ } else {
+ index++;
+ }
+ }
+
+ if (output == null) {
+ return key;
+ } else {
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ return output.toString();
+ }
+ }
+
+ protected boolean isAlphaNum(char in) {
+ if ((in >= 'a') && (in <= 'z')) {
+ return true;
+ }
+ if ((in >= 'A') && (in <= 'Z')) {
+ return true;
+ }
+ if ((in >= '0') && (in <= '9')) {
+ return true;
+ }
+ return false;
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ @SuppressWarnings("unchecked")
+ Hashtable<String, Object> ht = (Hashtable<String, Object>) obj;
+ Enumeration<String> e = ht.keys();
+
+ try {
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ Object value = ht.get(key);
+ if (value instanceof String) {
+ String stringValue = (String) value;
+ attrs.add(new LDAPAttribute(
+ extAttrPrefix + encodeKey(key),
+ stringValue));
+ } else if (value instanceof Hashtable) {
+ @SuppressWarnings("unchecked")
+ Hashtable<String, String> innerHash = (Hashtable<String, String>) value;
+ Enumeration<String> innerHashEnum = innerHash.keys();
+ while (innerHashEnum.hasMoreElements()) {
+ String innerKey = innerHashEnum.nextElement();
+ String innerValue = innerHash.get(innerKey);
+ attrs.add(new LDAPAttribute(
+ extAttrPrefix + encodeKey(key) + ";" + encodeKey(innerKey),
+ innerValue));
+ }
+ }
+ }
+ } catch (Exception x) {
+ Debug.trace("Output Mapping Error in requeset ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " + x);
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, String name,
+ IDBObj parent)
+ throws EBaseException {
+ Hashtable<String, Object> ht = new Hashtable<String, Object>();
+ Hashtable<String, String> valueHashtable;
+
+ Enumeration<LDAPAttribute> attrEnum = attrs.getAttributes();
+ while (attrEnum.hasMoreElements()) {
+ LDAPAttribute attr = attrEnum.nextElement();
+ String baseName = attr.getBaseName();
+ if (baseName.toLowerCase().startsWith(extAttrPrefix)) {
+ String keyName = decodeKey(
+ baseName.substring(extAttrPrefix.length()));
+ String[] subTypes = attr.getSubtypes();
+ String[] values = attr.getStringValueArray();
+ if (values.length != 1) {
+ String message = "Output Mapping Error in request ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " +
+ "more than one value returned for " +
+ keyName;
+ Debug.trace(message);
+ throw new EBaseException(message);
+ }
+ if ((subTypes != null) && (subTypes.length > 0)) {
+ if (subTypes.length != 1) {
+ String message = "Output Mapping Error in request ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " +
+ "more than one subType returned for " +
+ keyName;
+ Debug.trace(message);
+ throw new EBaseException(message);
+ }
+ Object value = ht.get(keyName);
+ if ((value != null) && (!(value instanceof Hashtable))) {
+ String message = "Output Mapping Error in request ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " +
+ "combined no-subtype and subtype data for key " +
+ keyName;
+ Debug.trace(message);
+ throw new EBaseException(message);
+ }
+ valueHashtable = (Hashtable<String, String>) value;
+ if (valueHashtable == null) {
+ valueHashtable = new Hashtable<String, String>();
+ ht.put(keyName, valueHashtable);
+ }
+ valueHashtable.put(decodeKey(subTypes[0]), values[0]);
+ } else {
+ ht.put(keyName, values[0]);
+ }
+ }
+ }
+
+ parent.set(name, ht);
+ }
+
+ public String mapSearchFilter(String name, String op, String value) throws EBaseException {
+ return name + op + value;
+ }
+
+ protected final static String extAttrPrefix = "extdata-";
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_EXT_ATTR);
+ }
+}
diff --git a/base/common/src/com/netscape/cmscore/request/RequestRepository.java b/base/common/src/com/netscape/cmscore/request/RequestRepository.java
new file mode 100644
index 000000000..0a4a4ebf9
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/RequestRepository.java
@@ -0,0 +1,217 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.math.BigInteger;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cmscore.dbs.Repository;
+import com.netscape.cmscore.dbs.RepositoryRecord;
+
+/**
+ * TODO: what does this class provide beyond the Repository
+ * base class??
+ * <p>
+ *
+ * @author thayes
+ * @version $Revision$ $Date$
+ */
+class RequestRepository
+ extends Repository {
+
+ IDBSubsystem mDB = null;
+ IRequestQueue mRequestQueue = null;
+
+ /**
+ * Create a request repository that uses the LDAP database
+ * <p>
+ *
+ * @param name
+ * the name of the repository. This String is used to
+ * construct the DN for the repository's LDAP entry.
+ * @param db
+ * the LDAP database system.
+ */
+ public RequestRepository(String name, int increment, IDBSubsystem db)
+ throws EDBException {
+ super(db, increment, "ou=" + name + ",ou=requests," + db.getBaseDN());
+
+ CMS.debug("RequestRepository: constructor 1");
+ mBaseDN = "ou=" + name + ",ou=requests," + db.getBaseDN();
+
+ // Let RequestRecord class register its
+ // database mapping and object mapping values
+ RequestRecord.register(db);
+ mDB = db;
+ }
+
+ public RequestRepository(String name, int increment, IDBSubsystem db, IRequestQueue requestQueue)
+ throws EDBException {
+ super(db, increment, "ou=" + name + ",ou=requests," + db.getBaseDN());
+
+ CMS.debug("RequestRepository: constructor2.");
+ mRequestQueue = requestQueue;
+ mBaseDN = "ou=" + name + ",ou=requests," + db.getBaseDN();
+
+ // Let RequestRecord class register its
+ // database mapping and object mapping values
+ RequestRecord.register(db);
+ mDB = db;
+ }
+
+ /**
+ * get the LDAP base DN for this repository. This
+ * value can be used by the request queue to create the
+ * name for the request records themselves.
+ * <p>
+ *
+ * @return
+ * the LDAP base DN.
+ */
+ public String getBaseDN() {
+ return mBaseDN;
+ }
+
+ /**
+ * Resets serial number.
+ */
+ public void resetSerialNumber(BigInteger serial) throws EBaseException {
+ setTheSerialNumber(serial);
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeAllObjects() throws EBaseException {
+ IDBSSession s = mDB.createSession();
+ try {
+ IDBSearchResults sr = s.search(getBaseDN(),
+ "(" + RequestRecord.ATTR_REQUEST_ID + "=*)");
+ while (sr.hasMoreElements()) {
+ RequestRecord r = (RequestRecord) sr.nextElement();
+ String name = "cn" + "=" +
+ r.getRequestId().toString() + "," + getBaseDN();
+ s.delete(name);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public BigInteger getLastSerialNumberInRange(BigInteger min, BigInteger max) {
+
+ CMS.debug("RequestRepository: in getLastSerialNumberInRange: min " + min + " max " + max);
+
+ CMS.debug("RequestRepository: mRequestQueue " + mRequestQueue);
+
+ BigInteger ret = null;
+
+ if (mRequestQueue == null) {
+
+ CMS.debug("RequestRepository: mRequestQueue is null.");
+
+ } else {
+
+ CMS.debug("RequestRepository: about to call mRequestQueue.getLastRequestIdInRange");
+ ret = mRequestQueue.getLastRequestIdInRange(min, max);
+
+ }
+
+ return ret;
+
+ }
+
+ /**
+ * the LDAP base DN for this repository
+ */
+ protected String mBaseDN;
+
+ public String getPublishingStatus() {
+ RepositoryRecord record = null;
+ Object obj = null;
+ IDBSSession dbs = null;
+ String status = null;
+
+ try {
+ dbs = mDB.createSession();
+ obj = dbs.read(mBaseDN);
+ } catch (Exception e) {
+ CMS.debug("RequestRepository: getPublishingStatus: Error: " + e);
+ CMS.debugStackTrace();
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null) {
+ try {
+ dbs.close();
+ } catch (Exception ex) {
+ CMS.debug("RequestRepository: getPublishingStatus: Error: " + ex);
+ }
+ }
+ }
+
+ if (obj != null || (obj instanceof RepositoryRecord)) {
+ record = (RepositoryRecord) obj;
+ status = record.getPublishingStatus();
+ } else {
+ CMS.debug("RequestRepository: obj is NOT instanceof RepositoryRecord");
+ }
+ CMS.debug("RequestRepository: getPublishingStatus mBaseDN: " + mBaseDN +
+ " status: " + ((status != null) ? status : "null"));
+
+ return status;
+ }
+
+ public void setPublishingStatus(String status) {
+ IDBSSession dbs = null;
+
+ CMS.debug("RequestRepository: setPublishingStatus mBaseDN: " + mBaseDN + " status: " + status);
+ ModificationSet mods = new ModificationSet();
+
+ if (status != null && status.length() > 0) {
+ mods.add(IRepositoryRecord.ATTR_PUB_STATUS,
+ Modification.MOD_REPLACE, status);
+
+ try {
+ dbs = mDB.createSession();
+ dbs.modify(mBaseDN, mods);
+ } catch (Exception e) {
+ CMS.debug("RequestRepository: setPublishingStatus: Error: " + e);
+ CMS.debugStackTrace();
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null) {
+ try {
+ dbs.close();
+ } catch (Exception ex) {
+ CMS.debug("RequestRepository: setPublishingStatus: Error: " + ex);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/base/common/src/com/netscape/cmscore/request/RequestSubsystem.java b/base/common/src/com/netscape/cmscore/request/RequestSubsystem.java
new file mode 100644
index 000000000..862ddaa68
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/RequestSubsystem.java
@@ -0,0 +1,187 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestSubsystem;
+import com.netscape.certsrv.request.IService;
+import com.netscape.cmscore.dbs.DBSubsystem;
+
+/**
+ * RequestSubsystem
+ * <p>
+ * This class is reponsible for managing storage of request objects in the local database.
+ * <p>
+ * TODO: review this It provides: + registration of LDAP/JAVA mapping classes with the DBSubsystem + creation of
+ * RequestQueue storage in the database + retrieval of existing RequestQueue objects from the database
+ * <p>
+ *
+ * @author thayes
+ * @version $Revision$, $Date$
+ */
+public class RequestSubsystem
+ implements IRequestSubsystem, ISubsystem {
+
+ public final static String ID = IRequestSubsystem.SUB_ID;
+
+ // singleton enforcement
+
+ private static RequestSubsystem mInstance = new RequestSubsystem();
+
+ public static RequestSubsystem getInstance() {
+ return mInstance;
+ }
+
+ private RequestSubsystem() {
+ }
+
+ // end singleton enforcement.
+
+ //
+ // Create a new request queue. The LDAP DN for the entry
+ // in the database is supplied by the caller.
+ //
+ public void createRequestQueue(String name)
+ throws EBaseException {
+
+ /*
+ String dbName = makeQueueName(name);
+ IDBSSession dbs = createDBSSession();
+
+ // Create Repository record here
+
+ dbs.add(dbName, r);
+ */
+ }
+
+ public IRequestQueue
+ getRequestQueue(String name, int increment, IPolicy p, IService s, INotify n)
+ throws EBaseException {
+ return getRequestQueue(name, increment, p, s, n, null);
+ }
+
+ public IRequestQueue
+ getRequestQueue(String name, int increment, IPolicy p, IService s, INotify n,
+ INotify pendingNotifier)
+ throws EBaseException {
+ RequestQueue rq = new RequestQueue(name, increment, p, s, n, pendingNotifier);
+
+ // can't do this here because the service depends on getting rq
+ // (to get request) and since this method hasn't returned it's rq is null.
+ //rq.recover();
+
+ return rq;
+ }
+
+ //
+ // ISubsystem methods:
+ // getId, setId, init, startup, shutdown, getConfigStore
+ //
+
+ /**
+ * Implements ISubsystem.getId
+ * <p>
+ *
+ * @see ISubsystem#getId
+ */
+ public String getId() {
+ return mId;
+ }
+
+ // ISubsystem.setId
+ public void setId(String id)
+ throws EBaseException {
+ mId = id;
+ }
+
+ // ISubsystem.init
+ public void init(ISubsystem parent, IConfigStore config) {
+ mParent = parent;
+ mConfig = config;
+ }
+
+ /**
+ * Implements ISubsystem.startup
+ * <p>
+ *
+ * @see ISubsystem#startup
+ */
+ public void startup()
+ throws EBaseException {
+ mLogger = CMS.getLogger();
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_REQQUEUE, ILogger.LL_INFO,
+ "Request subsystem started");
+ }
+
+ public void shutdown() {
+ mRequestQueue = null;
+
+ if (mLogger != null) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_REQQUEUE, ILogger.LL_INFO,
+ "Request subsystem stopped");
+ }
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ //
+ // Access to the DBSubsystem environment value
+ //
+ protected IDBSubsystem getDBSubsystem() {
+ return DBSubsystem.getInstance();
+ }
+
+ //
+ // Create a database session in the default database
+ // system.
+ //
+ protected IDBSSession createDBSSession()
+ throws EBaseException {
+ return getDBSubsystem().createSession();
+ }
+
+ //
+ // Make a queue name
+ //
+ protected String makeQueueName(String name) {
+ IDBSubsystem db = getDBSubsystem();
+
+ return "cn=" + name + "," + db.getBaseDN();
+ }
+
+ // Instance variables
+
+ private IConfigStore mConfig;
+ private ISubsystem mParent;
+ private String mId = IRequestSubsystem.SUB_ID;
+ private IRequestQueue mRequestQueue;
+
+ protected ILogger mLogger;
+}
diff --git a/base/common/src/com/netscape/cmscore/request/Schema.java b/base/common/src/com/netscape/cmscore/request/Schema.java
new file mode 100644
index 000000000..89a7b74b9
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/request/Schema.java
@@ -0,0 +1,50 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+//
+// The Schema class contains constant string values for
+// LDAP attribute and object class names used in this package
+//
+class Schema {
+ public static final String LDAP_OC_TOP = "top";
+ public static final String LDAP_OC_REQUEST = "request";
+ public static final String LDAP_OC_EXTENSIBLE = "extensibleObject";
+
+ public static final String LDAP_ATTR_REQUEST_ID = "requestId";
+ public static final String LDAP_ATTR_REQUEST_STATE = "requestState";
+ public static final String LDAP_ATTR_CREATE_TIME = "dateOfCreate";
+ public static final String LDAP_ATTR_MODIFY_TIME = "dateOfModify";
+ public static final String LDAP_ATTR_REQUEST_XATTRS = "adminMessages";
+ public static final String LDAP_ATTR_SOURCE_ID = "requestSourceId";
+
+ public static final String LDAP_ATTR_REQUEST_OWNER = "requestOwner";
+ public static final String LDAP_ATTR_REQUEST_ATTRS = "requestAttributes";
+ public static final String LDAP_ATTR_AGENT_GROUP = "requestAgentGroup";
+ public static final String LDAP_ATTR_REQUEST_TYPE = "requestType";
+ public static final String LDAP_ATTR_REQUEST_ERROR = "requestError";
+
+ // This attribute is a placeholder used by ExtAttrDynMapper
+ public static final String LDAP_ATTR_EXT_ATTR = "extAttr";
+
+ // Indicates a special state that may be searched for exactly
+ // such as requiresAgentService. The idea is to reduce the space
+ // used in indexes to optimize common queries.
+ // NOT IMPLEMENTED
+ public static final String LDAP_ATTR_REQUEST_FLAG = "requestFlag";
+}