summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cmscore/base
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/base')
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java712
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java213
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java256
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java767
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java610
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java55
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java74
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java43
8 files changed, 2730 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java b/pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java
new file mode 100644
index 000000000..2e0d19201
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java
@@ -0,0 +1,712 @@
+// --- 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.base;
+
+
+import java.util.*;
+import java.io.*;
+import netscape.security.pkcs.*;
+import java.security.*;
+import java.math.BigInteger;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * This class represents a set of indexed arguments.
+ * Each argument is indexed by a key, which can be
+ * used during the argument retrieval.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ArgBlock implements IArgBlock {
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ public static final String
+ CERT_NEW_REQUEST_HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String
+ CERT_NEW_REQUEST_TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+ public static final String
+ CERT_REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
+ public static final String
+ CERT_REQUEST_TRAILER = "-----END CERTIFICATE REQUEST-----";
+ public static final String
+ CERT_RENEWAL_HEADER = "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ public static final String
+ CERT_RENEWAL_TRAILER = "-----END RENEWAL CERTIFICATE REQUEST-----";
+
+ private Hashtable mArgs = new Hashtable();
+
+ private String mType = "unspecified-argblock";
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+ /**
+ * Constructs an argument block with the given hashtable values.
+ * @param realm the type of argblock - used for debugging the values
+ */
+ public ArgBlock(String realm, Hashtable httpReq) {
+ mType = realm;
+ populate(httpReq);
+ }
+
+ /**
+ * Constructs an argument block with the given hashtable values.
+ *
+ * @param httpReq hashtable keys and values
+ */
+ public ArgBlock(Hashtable httpReq) {
+ populate(httpReq);
+ }
+
+ private void populate(Hashtable httpReq) {
+ // Add all parameters from the request
+ Enumeration e = httpReq.keys();
+
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ String value = (String) httpReq.get(name);
+
+ addStringValue(name, value);
+ }
+ }
+ }
+
+ /**
+ * Constructs an empty argument block.
+ */
+ public ArgBlock() {
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * Checks if this argument block contains the given key.
+ *
+ * @param n key
+ * @return true if key is present
+ */
+ public boolean isValuePresent(String n) {
+ CMS.traceHashKey(mType, n);
+ if (mArgs.get(n) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Adds string-based value into this argument block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addStringValue(String n, String v) {
+ if (v == null) {
+ return mArgs.put(n, Character.valueOf((char) 0));
+ } else {
+ return mArgs.put(n, v);
+ }
+ }
+
+ /**
+ * Retrieves argument value as string.
+ *
+ * @param n key
+ * @return argument value as string
+ * @exception EBaseException failed to retrieve value
+ */
+ public String getValueAsString(String n) throws EBaseException {
+ String t= (String)mArgs.get(n);
+ CMS.traceHashKey(mType, n, t);
+
+ if (t != null) {
+ return t;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as string.
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as string
+ */
+ public String getValueAsString(String n, String def) {
+ String val = (String) mArgs.get(n);
+ CMS.traceHashKey(mType, n, val, def);
+
+ if (val != null) {
+ return val;
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Retrieves argument value as integer.
+ *
+ * @param n key
+ * @return argument value as int
+ * @exception EBaseException failed to retrieve value
+ */
+ public int getValueAsInt(String n) throws EBaseException {
+ if (mArgs.get(n) != null) {
+ CMS.traceHashKey(mType, n, (String)mArgs.get(n));
+ try {
+ return new Integer((String) mArgs.get(n)).intValue();
+ } catch (NumberFormatException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_TYPE", n, e.toString()));
+ }
+ } else {
+ CMS.traceHashKey(mType, n, "<notpresent>");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as integer.
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as int
+ */
+ public int getValueAsInt(String n, int def) {
+ CMS.traceHashKey(mType, n, (String)mArgs.get(n), ""+def);
+ if (mArgs.get(n) != null) {
+ try {
+ return new Integer((String) mArgs.get(n)).intValue();
+ } catch (NumberFormatException e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Retrieves argument value as big integer.
+ *
+ * @param n key
+ * @return argument value as big integer
+ * @exception EBaseException failed to retrieve value
+ */
+ public BigInteger getValueAsBigInteger(String n)
+ throws EBaseException {
+ String v = (String) mArgs.get(n);
+
+ if (v != null) {
+ try {
+ return new BigInteger(v, 10);
+ } catch (NumberFormatException e) {
+ try {
+ return new BigInteger(v, 16);
+ } catch (NumberFormatException ex) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_TYPE", n, ex.toString()));
+ }
+ }
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as big integer.
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as big integer
+ */
+ public BigInteger getValueAsBigInteger(String n, BigInteger def) {
+ try {
+ return getValueAsBigInteger(n);
+ } catch (EBaseException e) {
+ return def;
+ }
+ }
+
+ /**
+ * Retrieves argument value as object
+ *
+ * @param n key
+ * @return argument value as object
+ * @exception EBaseException failed to retrieve value
+ */
+ public Object getValue(Object n) throws EBaseException {
+ if (mArgs.get(n) != null) {
+ return mArgs.get(n);
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", (String) n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as object
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as object
+ */
+ public Object getValue(Object n, Object def) {
+ if (mArgs.get(n) != null) {
+ return mArgs.get(n);
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Gets boolean value. They should be "true" or "false".
+ *
+ * @param name name of the input type
+ * @return boolean type: <code>true</code> or <code>false</code>
+ * @exception EBaseException failed to retrieve value
+ */
+ public boolean getValueAsBoolean(String name) throws EBaseException {
+ String val = (String) mArgs.get(name);
+ CMS.traceHashKey(mType, name, val);
+
+ if (val != null) {
+ if (val.equalsIgnoreCase("true") ||
+ val.equalsIgnoreCase("on"))
+ return true;
+ else
+ return false;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", name));
+ }
+ }
+
+ /**
+ * Gets boolean value. They should be "true" or "false".
+ *
+ * @param name name of the input type
+ * @return boolean type: <code>true</code> or <code>false</code>
+ */
+ public boolean getValueAsBoolean(String name, boolean def) {
+ boolean val;
+
+ try {
+ val = getValueAsBoolean(name);
+ return val;
+ } catch (EBaseException e) {
+ return def;
+ }
+ }
+
+ /**
+ * Gets KeyGenInfo
+ *
+ * @param name name of the input type
+ * @param verify true if signature validation is required
+ * @exception EBaseException
+ * @return KeyGenInfo object
+ */
+ public KeyGenInfo getValueAsKeyGenInfo(String name, KeyGenInfo def)
+ throws EBaseException {
+ KeyGenInfo keyGenInfo;
+
+ CMS.traceHashKey(mType, name);
+ if (mArgs.get(name) != null) {
+ try {
+ keyGenInfo = new KeyGenInfo((String) mArgs.get(name));
+ } catch (IOException e) {
+ return def;
+ }
+
+ } else {
+ return def;
+ }
+ return keyGenInfo;
+ }
+
+ /**
+ * Gets PKCS10 request. This pkcs10 attribute does not
+ * contain header information.
+ *
+ * @param name name of the input type
+ * @return pkcs10 request
+ * @exception EBaseException failed to retrieve value
+ */
+ public PKCS10 getValueAsRawPKCS10(String name) throws EBaseException {
+ PKCS10 request;
+
+ if (mArgs.get(name) != null) {
+ CMS.traceHashKey(mType, name, (String)mArgs.get(name));
+
+ String tempStr = unwrap((String) mArgs.get(name), false);
+
+ if (tempStr == null) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, "Empty Content"));
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, e.toString()));
+ }
+ } else {
+ CMS.traceHashKey(mType, name, "<notpresent>");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", name));
+ }
+
+ return request;
+ }
+
+ /**
+ * Gets PKCS10 request. This pkcs10 attribute does not
+ * contain header information.
+ *
+ * @param name name of the input type
+ * @param def default PKCS10
+ * @return pkcs10 request
+ * @exception EBaseException failed to retrieve value
+ */
+ public PKCS10 getValueAsRawPKCS10(String name, PKCS10 def)
+ throws EBaseException {
+ PKCS10 request;
+
+ CMS.traceHashKey(mType, name);
+ if (mArgs.get(name) != null) {
+
+ String tempStr = unwrap((String) mArgs.get(name), false);
+
+ if (tempStr == null) {
+ return def;
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ return request;
+ }
+
+ /**
+ * Retrieves PKCS10
+ *
+ * @param name name of the input type
+ * @param checkheader true if header must be present
+ * @return PKCS10 object
+ * @exception EBaseException failed to retrieve value
+ */
+ public PKCS10 getValueAsPKCS10(String name, boolean checkheader)
+ throws EBaseException {
+ PKCS10 request;
+
+ CMS.traceHashKey(mType, name);
+ if (mArgs.get(name) != null) {
+
+ String tempStr = unwrap((String) mArgs.get(name), checkheader);
+
+ if (tempStr == null) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, "Empty Content"));
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, e.toString()));
+ }
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", name));
+ }
+
+ return request;
+ }
+
+ /**
+ * Retrieves PKCS10
+ *
+ * @param name name of the input type
+ * @param checkheader true if header must be present
+ * @param def default PKCS10
+ * @return PKCS10 object
+ * @exception EBaseException
+ */
+ public PKCS10 getValueAsPKCS10(
+ String name, boolean checkheader, PKCS10 def)
+ throws EBaseException {
+ PKCS10 request;
+
+ CMS.traceHashKey(mType, name);
+
+ if (mArgs.get(name) != null) {
+
+ String tempStr = unwrap((String) mArgs.get(name), checkheader);
+
+ if (tempStr == null) {
+ return def;
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+
+ return request;
+ }
+
+ /**
+ * Retrieves PKCS10
+ *
+ * @param name name of the input type
+ * @param def default PKCS10
+ * @return PKCS10 object
+ * @exception EBaseException
+ */
+ public PKCS10 getValuePKCS10(String name, PKCS10 def)
+ throws EBaseException {
+ PKCS10 request;
+ String p10b64 = (String) mArgs.get(name);
+ CMS.traceHashKey(mType, name);
+
+ if (p10b64 != null) {
+
+ try {
+ request = decodePKCS10(p10b64);
+ return request;
+ } catch (Exception e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Sets argument into this block.
+ *
+ * @param name key
+ * @param ob value
+ */
+ public void set(String name, Object ob) {
+ mArgs.put(name, ob);
+ }
+
+ /**
+ * Retrieves argument.
+ *
+ * @param name key
+ * @return object value
+ */
+ public Object get(String name) {
+ CMS.traceHashKey(mType, name);
+ return mArgs.get(name);
+ }
+
+ /**
+ * Deletes argument by the given key.
+ *
+ * @param name key
+ */
+ public void delete(String name) {
+ mArgs.remove(name);
+ }
+
+ /**
+ * Retrieves a list of argument keys.
+ *
+ * @return a list of string-based keys
+ */
+ public Enumeration getElements() {
+ return mArgs.keys();
+ }
+
+ /**
+ * Retrieves a list of argument keys.
+ *
+ * @return a list of string-based keys
+ */
+ public Enumeration elements() {
+ return mArgs.keys();
+ }
+
+ /**
+ * Adds long-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addLongValue(String n, long v) {
+ return mArgs.put(n, Long.valueOf(v));
+ }
+
+ /**
+ * Adds integer-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addIntegerValue(String n, int v) {
+ return mArgs.put(n, Integer.valueOf(v));
+ }
+
+ /**
+ * Adds boolean-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addBooleanValue(String n, boolean v) {
+ if (v) {
+ return mArgs.put(n, new Boolean("true"));
+ } else {
+ return mArgs.put(n, new Boolean("false"));
+ }
+ }
+
+ /**
+ * Adds integer-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @param radix radix
+ * @return value
+ */
+ public Object addBigIntegerValue(String n, BigInteger v, int radix) {
+ return mArgs.put(n, v.toString(radix));
+ }
+
+ /*==========================================================
+ * private methods
+ *==========================================================*/
+
+
+ /**
+ * Unwrap PKCS10 Package
+ *
+ * @param request string formated PKCS10 request
+ * @exception EBaseException
+ * @return Base64Encoded PKCS10 request
+ */
+ private String unwrap(String request, boolean checkHeader)
+ throws EBaseException {
+ String unwrapped;
+ String header = null;
+ int head = -1;
+ int trail = -1;
+
+ // check for "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_NEW_REQUEST_HEADER);
+ trail = request.indexOf(CERT_NEW_REQUEST_TRAILER);
+
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_NEW_REQUEST_HEADER;
+ }
+ }
+
+ // check for "-----BEGIN CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_REQUEST_HEADER);
+ trail = request.indexOf(CERT_REQUEST_TRAILER);
+
+ // If this is not a request header, check if this is a renewal
+ // header.
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_REQUEST_HEADER;
+
+ }
+ }
+
+ // check for "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_RENEWAL_HEADER);
+ trail = request.indexOf(CERT_RENEWAL_TRAILER);
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_RENEWAL_HEADER;
+ }
+ }
+
+ // Now validate if any headers or trailers are in place
+ if (head == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_HEADER"));
+ }
+ if (trail == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_TRAILER"));
+ }
+
+ if (header != null) {
+ unwrapped = request.substring(head + header.length(), trail);
+ } else {
+ unwrapped = request;
+ }
+
+ // strip all the crtl-characters (i.e. \r\n)
+ StringTokenizer st = new StringTokenizer(unwrapped, "\t\r\n ");
+ StringBuffer stripped = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ stripped.append(st.nextToken());
+ }
+
+ return stripped.toString();
+ }
+
+ /**
+ * Decode Der encoded PKCS10 certifictae Request
+ *
+ * @param base64Request Base64 Encoded Certificate Request
+ * @exception Exception
+ * @return PKCS10
+ */
+ private PKCS10 decodePKCS10(String base64Request)
+ throws EBaseException {
+ PKCS10 pkcs10 = null;
+
+ try {
+ byte[] decodedBytes = com.netscape.osutil.OSUtil.AtoB(base64Request);
+
+ pkcs10 = new PKCS10(decodedBytes);
+ } catch (NoSuchProviderException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (SignatureException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ return pkcs10;
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java b/pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java
new file mode 100644
index 000000000..79bb60c67
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java
@@ -0,0 +1,213 @@
+// --- 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.base;
+
+
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.cmsutil.util.Utils;
+
+
+/**
+ * FileConfigStore:
+ * Extends HashConfigStore with methods to load/save from/to file for
+ * persistent storage. This is a configuration store agent who
+ * reads data from a file.
+ * <P>
+ * Note that a LdapConfigStore can be implemented so that it reads
+ * the configuration stores from the Ldap directory.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ * @see PropConfigStore
+ */
+public class FileConfigStore extends PropConfigStore implements
+ IConfigStore {
+
+ private File mFile = null;
+
+ /**
+ * Constructs a file configuration store.
+ * <P>
+ *
+ * @param fileName file name
+ * @exception EBaseException failed to create file configuration
+ */
+ public FileConfigStore(String fileName) throws EBaseException {
+ super(null); // top-level store without a name
+ mFile = new File(fileName);
+ if (!mFile.exists()) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_CONFIG_FILE",
+ mFile.getPath()));
+ }
+ load(fileName);
+ }
+
+ /**
+ * Loads property file into memory.
+ * <P>
+ *
+ * @param fileName file name
+ * @exception EBaseException failed to load configuration
+ */
+ public void load(String fileName) throws EBaseException {
+ try {
+ FileInputStream fi = new FileInputStream(fileName);
+ BufferedInputStream bis = new BufferedInputStream(fi);
+
+ super.load(bis);
+ } catch (IOException e) {
+ throw new EBaseException("input stream error " + fileName, e);
+ }
+ }
+
+ /**
+ * The original config file is copied to
+ * <filename>.<current_time_in_milliseconds>.
+ * Commits the current properties to the configuration file.
+ * <P>
+ *
+ * @param backup
+ */
+ public void commit(boolean createBackup) throws EBaseException {
+ if (createBackup) {
+ File newName = new File(mFile.getPath() + "." +
+ Long.toString(System.currentTimeMillis()));
+
+ try {
+ if( Utils.isNT() ) {
+ // NT is very picky on the path
+ Utils.exec( "copy " +
+ mFile.getAbsolutePath().replace( '/', '\\' ) +
+ " " +
+ newName.getAbsolutePath().replace( '/',
+ '\\' ) );
+ } else {
+ // Create a copy of the original file which
+ // preserves the original file permissions.
+ Utils.exec( "cp -p " + mFile.getAbsolutePath() + " " +
+ newName.getAbsolutePath() );
+ }
+
+ // Proceed only if the backup copy was successful.
+ if( !newName.exists() ) {
+ throw new EBaseException( "backup copy failed" );
+ } else {
+ // Make certain that the backup file has
+ // the correct permissions.
+ if( !Utils.isNT() ) {
+ Utils.exec( "chmod 00660 " + newName.getAbsolutePath() );
+ }
+ }
+ } catch( EBaseException e ) {
+ throw new EBaseException( "backup copy failed" );
+ }
+ }
+
+ // Overwrite the contents of the original file
+ // to preserve the original file permissions.
+ save( mFile.getPath() );
+
+ try {
+ // Make certain that the original file retains
+ // the correct permissions.
+ if( !Utils.isNT() ) {
+ Utils.exec( "chmod 00660 " + mFile.getCanonicalPath() );
+ }
+ } catch( Exception e ) {
+ }
+ }
+
+ /**
+ * Saves in-memory properties to a specified file.
+ * <P>
+ * Note that the superclass's save is synchronized. It
+ * means no properties can be altered (inserted) at
+ * the saving time.
+ * <P>
+ *
+ * @param fileName filename
+ * @exception EBaseException failed to save configuration
+ */
+ public void save(String fileName) throws EBaseException {
+ try {
+ FileOutputStream fo = new FileOutputStream(fileName);
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(fo));
+
+ printSubStore(writer, this, "");
+ writer.close();
+ fo.close();
+ } catch (IOException e) {
+ throw new EBaseException("output stream error " + fileName, e);
+ }
+ }
+
+ private void printSubStore(PrintWriter writer, IConfigStore store,
+ String name) throws EBaseException,
+ IOException {
+ // print keys
+ Enumeration e0 = store.getPropertyNames();
+ Vector v = new Vector();
+
+ while (e0.hasMoreElements()) {
+ v.addElement(e0.nextElement());
+ }
+
+ // sorting them lexicographically
+ while (v.size() > 0) {
+ String pname = (String) v.firstElement();
+ int j = 0;
+
+ for (int i = 1; i < v.size(); i++) {
+ String s = (String) v.elementAt(i);
+
+ if (pname.compareTo(s) > 0) {
+ j = i;
+ pname = (String) v.elementAt(i);
+ }
+ }
+ v.removeElementAt(j);
+ writer.println(name + pname + "=" + store.getString(pname));
+ }
+
+ // print substores
+ Enumeration e1 = store.getSubStoreNames();
+
+ while (e1.hasMoreElements()) {
+ v.addElement(e1.nextElement());
+ }
+ while (v.size() > 0) {
+ String pname = (String) v.firstElement();
+ int j = 0;
+
+ for (int i = 1; i < v.size(); i++) {
+ String s = (String) v.elementAt(i);
+
+ if (pname.compareTo(s) > 0) {
+ j = i;
+ pname = (String) v.elementAt(i);
+ }
+ }
+ v.removeElementAt(j);
+ printSubStore(writer, store.getSubStore(pname), name +
+ pname + ".");
+ }
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java b/pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java
new file mode 100644
index 000000000..93d88a550
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java
@@ -0,0 +1,256 @@
+// --- 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.base;
+
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.CryptoToken;
+import javax.swing.border.EmptyBorder;
+
+
+/**
+ * A class to retrieve passwords through a modal Java dialog box
+ */
+public class JDialogPasswordCallback implements PasswordCallback {
+
+ public Password getPasswordFirstAttempt(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+ return getPW(info, false);
+ }
+
+ public Password getPasswordAgain(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+ return getPW(info, true);
+ }
+
+ // This structure holds information local to a getPW() call, for use
+ // by action listeners
+ private static class PWHolder {
+ public Password password = null;
+ public boolean cancelled = true;
+ }
+
+ private void resetGBC(GridBagConstraints gbc) {
+ gbc.gridx = gbc.RELATIVE;
+ gbc.gridy = gbc.RELATIVE;
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.fill = gbc.HORIZONTAL;
+ gbc.anchor = gbc.CENTER;
+ gbc.ipadx = 0;
+ gbc.ipady = 0;
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ }
+
+ /**
+ * This function can be overriden if different heading is required.
+ */
+ public String getPrompt(PasswordCallbackInfo info) {
+ return "Enter the password for \"" + info.getName() + "\": ";
+ }
+
+ /**
+ * This method does the work of displaying the dialog box,
+ * extracting the information, and returning it.
+ */
+ private Password getPW(PasswordCallbackInfo info, boolean retry)
+ throws PasswordCallback.GiveUpException {
+ // These need to final so they can be accessed from action listeners
+ final PWHolder pwHolder = new PWHolder();
+ final JFrame f = new JFrame("Password Dialog");
+ final JPasswordField pwField = new JPasswordField(15);
+
+ ///////////////////////////////////////////////////
+ // Panel
+ ///////////////////////////////////////////////////
+ JPanel contentPane = new JPanel(new GridBagLayout());
+
+ contentPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+ GridBagConstraints c = new GridBagConstraints();
+
+ ////////////////////////////////////////////////////
+ // Labels
+ ////////////////////////////////////////////////////
+
+ if (retry) {
+ JLabel warning = new JLabel("Password incorrect.");
+
+ warning.setForeground(Color.red);
+ resetGBC(c);
+ c.anchor = c.NORTHWEST;
+ c.gridwidth = c.REMAINDER;
+ // Setting this to NULL causes nasty Exception stack traces
+ // to be printed, although the program still seems to work
+ //warning.setHighlighter(null);
+ contentPane.add(warning, c);
+ }
+
+ String prompt = getPrompt(info);
+ JLabel label = new JLabel(prompt);
+
+ label.setForeground(Color.black);
+ // Setting this to NULL causes nasty Exception stack traces
+ // to be printed, although the program still seems to work
+ //label.setHighlighter(null);
+ resetGBC(c);
+ c.anchor = c.NORTHWEST;
+ c.gridwidth = c.REMAINDER;
+ contentPane.add(label, c);
+
+ ///////////////////////////////////////////////////
+ // Password text field
+ ///////////////////////////////////////////////////
+
+ // Listener for the text field
+ ActionListener getPasswordListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ //input = (JPasswordField)e.getSource();
+
+ // XXX!!! Change to char[] in JDK 1.2
+ String pwString = pwField.getText();
+
+ pwHolder.password = new Password(pwString.toCharArray());
+ pwHolder.cancelled = false;
+ f.dispose();
+ }
+ };
+
+ // There is a bug in JPasswordField. The cursor is advanced by the
+ // width of the character you type, but a '*' is echoed, so the
+ // cursor does not stay lined up with the end of the text.
+ // We use a monospaced font to workaround this.
+
+ pwField.setFont(new Font("Monospaced", Font.PLAIN,
+ pwField.getFont().getSize()));
+ pwField.setEchoChar('*');
+ pwField.addActionListener(getPasswordListener);
+ resetGBC(c);
+ c.anchor = c.CENTER;
+ c.fill = c.NONE;
+ c.insets = new Insets(16, 0, 0, 0);
+ c.gridwidth = c.REMAINDER;
+ //c.gridy++;
+ contentPane.add(pwField, c);
+
+ ///////////////////////////////////////////////////
+ // Cancel button
+ ///////////////////////////////////////////////////
+
+ JPanel buttonPanel = new JPanel(new GridBagLayout());
+
+ JButton ok = new JButton(" OK ");
+
+ ok.addActionListener(getPasswordListener);
+ resetGBC(c);
+ c.fill = c.NONE;
+ c.anchor = c.CENTER;
+ c.gridheight = c.REMAINDER;
+ c.insets = new Insets(10, 0, 0, 4);
+ buttonPanel.add(ok, c);
+
+ JButton cancel = new JButton("Cancel");
+ ActionListener buttonListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ pwHolder.cancelled = true;
+ f.dispose();
+ }
+ };
+
+ cancel.addActionListener(buttonListener);
+ resetGBC(c);
+ c.fill = c.NONE;
+ c.anchor = c.CENTER;
+ c.insets = new Insets(10, 4, 0, 0);
+ c.gridheight = c.REMAINDER;
+ c.gridwidth = c.REMAINDER;
+ buttonPanel.add(cancel, c);
+
+ resetGBC(c);
+ c.fill = c.NONE;
+ c.anchor = c.CENTER;
+ c.gridwidth = c.REMAINDER;
+ c.gridheight = c.REMAINDER;
+ c.insets = new Insets(0, 0, 0, 0);
+ contentPane.add(buttonPanel, c);
+
+ ///////////////////////////////////////////////////
+ // Create modal dialog
+ ///////////////////////////////////////////////////
+ JDialog d = new JDialog(f, "Fedora Certificate System", true);
+
+ WindowListener windowListener = new WindowAdapter() {
+ public void windowOpened(WindowEvent e) {
+ pwField.requestFocus();
+ }
+ };
+
+ d.addWindowListener(windowListener);
+
+ d.setContentPane(contentPane);
+ d.pack();
+ Dimension screenSize = d.getToolkit().getScreenSize();
+ Dimension paneSize = d.getSize();
+
+ d.setLocation((screenSize.width - paneSize.width) / 2,
+ (screenSize.height - paneSize.height) / 2);
+ d.getRootPane().setDefaultButton(ok);
+
+ // toFront seems to cause the dialog to go blank on unix!
+ //d.toFront();
+
+ d.show();
+
+ ///////////////////////////////////////////////////
+ // Return results
+ ///////////////////////////////////////////////////
+ if (pwHolder.cancelled) {
+ throw new PasswordCallback.GiveUpException();
+ }
+
+ return pwHolder.password;
+ }
+
+ // Test program
+ public static void main(String args[]) {
+ try {
+ CryptoManager manager;
+
+ CryptoManager.InitializationValues iv = new
+ CryptoManager.InitializationValues(args[0]);
+
+ CryptoManager.initialize(iv);
+ manager = CryptoManager.getInstance();
+
+ CryptoToken tok = manager.getInternalKeyStorageToken();
+
+ tok.login(new JDialogPasswordCallback());
+ System.out.println("Logged in!!!");
+ System.exit(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java b/pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java
new file mode 100644
index 000000000..f8dd97aa5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java
@@ -0,0 +1,767 @@
+// --- 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.base;
+
+
+import java.io.*;
+import java.util.*;
+import java.math.BigInteger;
+import org.mozilla.jss.util.Base64OutputStream;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * A class represents a in-memory configuration store.
+ * Note this class takes advantage of the recursive nature of
+ * property names. The current property prefix is kept in
+ * mStoreName and the mSource usually points back to another
+ * occurance of the same PropConfigStore, with longer mStoreName. IE
+ * <PRE>
+ * cms.ca0.http.service0 -> mSource=PropConfigStore ->
+ * cms.ca0.http -> mSource=PropConfigStore ->
+ * cms.ca0 -> mSource=PropConfigStore ->
+ * cms -> mSource=SourceConfigStore -> Properties
+ * </PRE>
+ * The chain ends when the store name is reduced down to it's original
+ * value.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class PropConfigStore implements IConfigStore, Cloneable {
+
+ protected static final String PROP_SUBSTORES = "substores";
+
+ /**
+ * The name of this substore
+ */
+ protected String mStoreName = null;
+
+ /**
+ * The source data for this substore
+ */
+ protected ISourceConfigStore mSource = null;
+
+ private static String mDebugType="CS.cfg";
+
+ /**
+ * Constructs a property configuration store. This must
+ * be a brand new store without properties. The subclass
+ * must be a ISourceConfigStore.
+ * <P>
+ *
+ * @param storeName property store name
+ * @exception EBaseException failed to create configuration
+ */
+ public PropConfigStore(String storeName) {
+ mSource = new SourceConfigStore();
+ mStoreName = storeName;
+ }
+
+ /**
+ * Constructs a configuration store. The constructor is
+ * a helper class for substores. Source is the one
+ * that stores all the parameters. Each substore only
+ * store a substore name, and a reference to the source.
+ * <P>
+ *
+ * @param storeName store name
+ * @param prop list of properties
+ * @exception EBaseException failed to create configuration
+ */
+ protected PropConfigStore(String name, ISourceConfigStore source) {
+ mStoreName = name;
+ mSource = source;
+ }
+
+ /**
+ * Returns the name of this store.
+ * <P>
+ *
+ * @return store name
+ */
+ public String getName() {
+ return mStoreName;
+ }
+
+ /**
+ * Retrieves a property from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ public Object get(String name) {
+ return mSource.get(getFullName(name));
+ }
+
+ /**
+ * Retrieves a property from the configuration file. Does not prepend
+ * the config store name to the property.
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ private Object nakedGet(String name) {
+ return mSource.get(name);
+ }
+
+ /**
+ * Puts a property into the configuration file. The
+ * values wont be updated to the file until save
+ * method is invoked.
+ * <P>
+ *
+ * @param name property name
+ * @param value property value
+ */
+ public void put(String name, Object value) {
+ mSource.put(getFullName(name), value);
+ }
+
+ /**
+ * Removes a property from the configuration file.
+ *
+ * @param name property name
+ */
+ public void remove(String name) {
+ ((SourceConfigStore) mSource).remove(getFullName(name));
+ }
+
+ /**
+ * Returns an enumeration of the config store's keys, hidding the store
+ * name.
+ * @see java.util.Hashtable#elements
+ * @see java.util.Enumeration
+ */
+ public Enumeration keys() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h.keys();
+ }
+
+ /**
+ * Retrieves the hashtable where all the properties are kept.
+ *
+ * @return hashtable
+ */
+ public Hashtable hashtable() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h;
+ }
+
+ /**
+ * Return the number of items in this substore
+ */
+ public int size() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h.size();
+ }
+
+ /**
+ * Fills the given hash table with all key/value pairs in the current
+ * config store, removing the config store name prefix
+ * <P>
+ *
+ * @param h the hashtable
+ */
+ private synchronized void enumerate(Hashtable h) {
+ Enumeration e = mSource.keys();
+ // We only want the keys which match the current substore name
+ // without the current substore prefix. This code works even
+ // if mStoreName is null.
+ String fullName = getFullName("");
+ int kIndex = fullName.length();
+
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+
+ if (key.startsWith(fullName)) {
+ h.put(key.substring(kIndex), nakedGet(key));
+ }
+ }
+ }
+
+ /**
+ * Reads a config store from an input stream.
+ *
+ * @param in input stream where properties are located
+ * @exception IOException failed to load
+ */
+ public synchronized void load(InputStream in) throws IOException {
+ mSource.load(in);
+ }
+
+ /**
+ * Stores this config store to the specified output stream.
+ *
+ * @param out outputstream where the properties are saved
+ * @param header optional header information to be saved
+ */
+ public synchronized void save(OutputStream out, String header) {
+ mSource.save(out, header);
+ }
+
+ /**
+ * Retrieves a property value.
+ *
+ * @param name property key
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public String getString(String name) throws EBaseException {
+ String str = (String) get(name);
+
+ if (str == null) {
+ CMS.traceHashKey(mDebugType,getFullName(name),"<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ // should we check for empty string ?
+ // if (str.length() == 0) {
+ // throw new EPropertyNotDefined(getName() + "." + name);
+ // }
+ String ret = null;
+
+ try {
+ ret = new String(str.getBytes(), "UTF8").trim();
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_UTF8_NOT_SUPPORTED"));
+ }
+ CMS.traceHashKey(mDebugType,getFullName(name),ret);
+ return ret;
+ }
+
+ /**
+ * Retrieves a String from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @param defval the default object to return if name does not exist
+ * @return property value
+ */
+ public String getString(String name, String defval) throws EBaseException {
+ String val;
+
+ try {
+ val = getString(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ }
+ CMS.traceHashKey(mDebugType,getFullName(name),val,defval);
+ return val;
+ }
+
+ /**
+ * Puts property value into this configuration store.
+ *
+ * @param name property key
+ * @param value property value
+ */
+ public void putString(String name, String value) {
+ put(name, value);
+ }
+
+ /**
+ * Retrieves a byte array from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @exception IllegalArgumentException if name is not set or is null.
+ *
+ * @return property value
+ */
+ public byte[] getByteArray(String name) throws EBaseException {
+ byte[] arr = getByteArray(name, new byte[0]);
+
+ if (arr.length == 0) {
+ CMS.traceHashKey(mDebugType,getFullName(name),"<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ return arr;
+ }
+
+ /**
+ * Retrieves a byte array from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @param defval the default byte array to return if name does
+ * not exist
+ *
+ * @return property value
+ */
+ public byte[] getByteArray(String name, byte defval[])
+ throws EBaseException {
+ String str = (String) get(name);
+
+ byte returnval;
+
+ if (str == null || str.length() == 0) {
+ CMS.traceHashKey(mDebugType,getFullName(name),
+ "<notpresent>","<bytearray>");
+ return defval;
+ }
+ else {
+ CMS.traceHashKey(mDebugType,getFullName(name),
+ "<bytearray>","<bytearray>");
+ return com.netscape.osutil.OSUtil.AtoB(str);
+ }
+ }
+
+ /**
+ * Puts byte array into this configuration store.
+ *
+ * @param name property key
+ * @param value byte array
+ */
+ public void putByteArray(String name, byte value[]) {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ Base64OutputStream b64 = new Base64OutputStream(new
+ PrintStream(new FilterOutputStream(output)));
+
+ try {
+ b64.write(value);
+ b64.flush();
+
+ // 8859 contains all the base-64 chars, so there are no
+ // internationalization problems here
+ put(name, output.toString("8859_1"));
+ } catch (IOException e) {
+ System.out.println("Warning: base-64 encoding of configuration " +
+ "information failed");
+ }
+ }
+
+ /**
+ * Retrieves boolean-based property value.
+ *
+ * @param name property key
+ * @return boolean value
+ * @exception EBaseException failed to retrieve
+ */
+ public boolean getBoolean(String name) throws EBaseException {
+ String value = (String) get(name);
+
+ if (value == null) {
+ CMS.traceHashKey(mDebugType,getFullName(name),"<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ if (value.length() == 0) {
+ throw new EPropertyNotDefined(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_NOVALUE", getName() + "." + name));
+ }
+
+ if (value.equalsIgnoreCase("true")) {
+ return true;
+ } else if (value.equalsIgnoreCase("false")) {
+ return false;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1", getName() + "." + name, "boolean", "\"true\" or \"false\""));
+ }
+ }
+
+ /**
+ * Retrieves boolean-based property value.
+ *
+ * @param name property key
+ * @param defval default value
+ * @return boolean value
+ * @exception EBaseException failed to retrieve
+ */
+ public boolean getBoolean(String name, boolean defval)
+ throws EBaseException {
+ boolean val;
+
+ try {
+ val = getBoolean(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ } catch (EPropertyNotDefined e) {
+ val = defval;
+ }
+ CMS.traceHashKey(mDebugType,getFullName(name),
+ val?"true":"false", defval?"true":"false");
+ return val;
+ }
+
+ /**
+ * Puts boolean value into the configuration store.
+ *
+ * @param name property key
+ * @param value property value
+ */
+ public void putBoolean(String name, boolean value) {
+ if (value) {
+ put(name, "true");
+ } else {
+ put(name, "false");
+ }
+ }
+
+ /**
+ * Retrieves integer value.
+ *
+ * @param name property key
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public int getInteger(String name) throws EBaseException {
+ String value = (String) get(name);
+
+ if (value == null) {
+ CMS.traceHashKey(mDebugType,getFullName(name),"<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ if (value.length() == 0) {
+ throw new EPropertyNotDefined(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_NOVALUE", getName() + "." + name));
+ }
+ try {
+ CMS.traceHashKey(mDebugType,getFullName(name), value);
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1", getName() + "." + name, "int", "number"));
+ }
+ }
+
+ /**
+ * Retrieves integer value.
+ *
+ * @param name property key
+ * @param defval default value
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public int getInteger(String name, int defval) throws EBaseException {
+ int val;
+
+ try {
+ val = getInteger(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ } catch (EPropertyNotDefined e) {
+ val = defval;
+ }
+ CMS.traceHashKey(mDebugType,getFullName(name),
+ ""+val,""+defval);
+ return val;
+ }
+
+ /**
+ * Puts an integer value.
+ *
+ * @param name property key
+ * @param val property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public void putInteger(String name, int val) {
+ put(name, Integer.toString(val));
+ }
+
+ /**
+ * Retrieves big integer value.
+ *
+ * @param name property key
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public BigInteger getBigInteger(String name) throws EBaseException {
+ String value = (String) get(name);
+
+ if (value == null) {
+ CMS.traceHashKey(mDebugType,getFullName(name),"<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ if (value.length() == 0) {
+ throw new EPropertyNotDefined(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_NOVALUE", getName() + "." + name));
+ }
+ try {
+ if (value.startsWith("0x") || value.startsWith("0X")) {
+ String val = value.substring(2);
+
+ return new BigInteger(val, 16);
+ }
+ return new BigInteger(value);
+ } catch (NumberFormatException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1", getName() + "." + name, "BigInteger", "number"));
+ }
+ }
+
+ /**
+ * Retrieves integer value.
+ *
+ * @param name property key
+ * @param defval default value
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public BigInteger getBigInteger(String name, BigInteger defval)
+ throws EBaseException {
+ BigInteger val;
+
+ try {
+ val = getBigInteger(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ } catch (EPropertyNotDefined e) {
+ val = defval;
+ }
+ return val;
+ }
+
+ /**
+ * Puts a big integer value.
+ *
+ * @param name property key
+ * @param val default value
+ */
+ public void putBigInteger(String name, BigInteger val) {
+ put(name, val.toString());
+ }
+
+ /**
+ * Creates a new sub store.
+ * <P>
+ *
+ * @param name substore name
+ * @return substore
+ */
+ public IConfigStore makeSubStore(String name) {
+
+ /*
+ String names=(String)mSource.get(getFullName(PROP_SUBSTORES));
+
+ if (names==null) {
+ names=name;
+ }
+ else {
+ names=names+","+name;
+ }
+ mSource.put(getFullName(PROP_SUBSTORES), name);
+ */
+ return new PropConfigStore(getFullName(name), mSource);
+ }
+
+ /**
+ * Removes a sub store.<p>
+ *
+ * @param name substore name
+ */
+ public void removeSubStore(String name) {
+ // this operation is expensive!!!
+
+ Enumeration e = mSource.keys();
+ // We only want the keys which match the current substore name
+ // without the current substore prefix. This code works even
+ // if mStoreName is null.
+ String fullName = getFullName(name);
+ int kIndex = fullName.length();
+
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+
+ if (key.startsWith(fullName + ".")) {
+ ((Hashtable) mSource).remove(key);
+ }
+ }
+ }
+
+ /**
+ * Retrieves a sub store. A substore contains a list
+ * of properties and substores. For example,
+ * <PRE>
+ * cms.ldap.host=ds.netscape.com
+ * cms.ldap.port=389
+ * </PRE>
+ * "ldap" is a substore in above example. If the
+ * substore property itself is set, this method
+ * will treat the value as a reference. For example,
+ * <PRE>
+ * cms.ldap=kms.ldap
+ * </PRE>
+ * <P>
+ *
+ * @param name substore name
+ * @return substore
+ */
+ public IConfigStore getSubStore(String name) {
+ String fullname = getFullName(name);
+ String reference = (String) mSource.get(fullname);
+
+ if (reference == null) {
+ PropConfigStore ps = new PropConfigStore(fullname, mSource);
+
+ return ps;
+ } else {
+ PropConfigStore ps = new PropConfigStore(reference, mSource);
+
+ return ps;
+ }
+ }
+
+ /**
+ * Retrieves a list of property names.
+ *
+ * @return a list of string-based property names
+ */
+ public Enumeration getPropertyNames() {
+ // XXX - this operation is expensive!!!
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ Enumeration e = h.keys();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String pname = (String) e.nextElement();
+ int i = pname.indexOf('.'); // substores have "."
+
+ if (i == -1) {
+ String n = pname;
+
+ if (!v.contains(n)) {
+ v.addElement(n);
+ }
+ }
+ }
+ return v.elements();
+ }
+
+ /**
+ * Returns a list of sub store names.
+ * <P>
+ *
+ * @return list of substore names
+ */
+ public Enumeration getSubStoreNames() {
+ // XXX - this operation is expensive!!!
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ Enumeration e = h.keys();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String pname = (String) e.nextElement();
+ int i = pname.indexOf('.'); // substores have "."
+
+ if (i != -1) {
+ String n = pname.substring(0, i);
+
+ if (!v.contains(n)) {
+ v.addElement(n);
+ }
+ }
+ }
+ return v.elements();
+ }
+
+ /**
+ * Retrieves the source configuration store where
+ * the properties are stored.
+ * <P>
+ *
+ * @return source configuration store
+ */
+ public ISourceConfigStore getSourceConfigStore() {
+ return mSource;
+ }
+
+ /**
+ * For debugging purposes. Prints properties of this
+ * substore.
+ */
+ public void printProperties() {
+ Enumeration keys = mSource.keys();
+
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+
+ if (mStoreName == null) {
+ System.out.println(key);
+ } else {
+ if (key.startsWith(mStoreName))
+ System.out.println(key);
+ }
+ }
+ }
+
+ /**
+ * Converts the substore parameters.
+ *
+ * @param name property name
+ * @return fill property name
+ */
+ private String getFullName(String name) {
+ if (mStoreName == null)
+ return name;
+ else
+ return mStoreName + "." + name;
+ }
+
+ /**
+ * Cloning of property configuration store.
+ *
+ * @return a new configuration store
+ */
+ public Object clone() {
+ try {
+ PropConfigStore that = (PropConfigStore) super.clone();
+
+ mStoreName = getName();
+ mSource = new SourceConfigStore();
+ Enumeration subs = getSubStoreNames();
+
+ while (subs.hasMoreElements()) {
+ IConfigStore sub = (IConfigStore)
+ subs.nextElement();
+ IConfigStore newSub = that.makeSubStore(
+ sub.getName());
+ Enumeration props = sub.getPropertyNames();
+
+ while (props.hasMoreElements()) {
+ String n = (String) props.nextElement();
+
+ try {
+ newSub.putString(n,
+ sub.getString(n));
+ } catch (EBaseException ex) {
+ }
+ }
+ }
+ return that;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+
+ }
+
+ /**
+ * Commits properties into the file.
+ *
+ * @param createBackup true if create backup
+ * @exception EBaseException failed to commit properties
+ */
+ public void commit(boolean createBackup) throws EBaseException {
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java b/pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java
new file mode 100644
index 000000000..e2584accf
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java
@@ -0,0 +1,610 @@
+// --- 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.base;
+
+
+import com.netscape.certsrv.base.*;
+import java.util.Date;
+import java.util.Enumeration;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.BufferedWriter;
+import java.util.Hashtable;
+
+
+/**
+ * The <code>Properties</code> class represents a persistent set of
+ * properties. The <code>Properties</code> can be saved to a stream
+ * or loaded from a stream. Each key and its corresponding value in
+ * the property list is a string.
+ * <p>
+ * A property list can contain another property list as its
+ * "defaults"; this second property list is searched if
+ * the property key is not found in the original property list.
+ *
+ * Because <code>Properties</code> inherits from <code>Hashtable</code>, the
+ * <code>put</code> and <code>putAll</code> methods can be applied to a
+ * <code>Properties</code> object. Their use is strongly discouraged as they
+ * allow the caller to insert entries whose keys or values are not
+ * <code>Strings</code>. The <code>setProperty</code> method should be used
+ * instead. If the <code>store</code> or <code>save</code> method is called
+ * on a "compromised" <code>Properties</code> object that contains a
+ * non-<code>String</code> key or value, the call will fail.
+ *
+ */
+public class SimpleProperties extends Hashtable {
+
+ /**
+ * A property list that contains default values for any keys not
+ * found in this property list.
+ *
+ * @serial
+ */
+ protected SimpleProperties defaults;
+
+ /**
+ * Creates an empty property list with no default values.
+ */
+ public SimpleProperties() {
+ this(null);
+ }
+
+ /**
+ * Creates an empty property list with the specified defaults.
+ *
+ * @param defaults the defaults.
+ */
+ public SimpleProperties(SimpleProperties defaults) {
+ this.defaults = defaults;
+ }
+
+ /**
+ * Calls the hashtable method <code>put</code>. Provided for
+ * parallelism with the getProperties method. Enforces use of
+ * strings for property keys and values.
+ * @since JDK1.2
+ */
+ public synchronized Object setProperty(String key, String value) {
+ return put(key, value);
+ }
+
+ private static final String keyValueSeparators = "=: \t\r\n\f";
+
+ private static final String strictKeyValueSeparators = "=:";
+
+ private static final String specialSaveChars = "=: \t\r\n\f#!";
+
+ private static final String whiteSpaceChars = " \t\r\n\f";
+
+ /**
+ * Reads a property list (key and element pairs) from the input stream.
+ * <p>
+ * Every property occupies one line of the input stream. Each line
+ * is terminated by a line terminator (<code>\n</code> or <code>\r</code>
+ * or <code>\r\n</code>). Lines from the input stream are processed until
+ * end of file is reached on the input stream.
+ * <p>
+ * A line that contains only whitespace or whose first non-whitespace
+ * character is an ASCII <code>#</code> or <code>!</code> is ignored
+ * (thus, <code>#</code> or <code>!</code> indicate comment lines).
+ * <p>
+ * Every line other than a blank line or a comment line describes one
+ * property to be added to the table (except that if a line ends with \,
+ * then the following line, if it exists, is treated as a continuation
+ * line, as described
+ * below). The key consists of all the characters in the line starting
+ * with the first non-whitespace character and up to, but not including,
+ * the first ASCII <code>=</code>, <code>:</code>, or whitespace
+ * character. All of the key termination characters may be included in
+ * the key by preceding them with a \.
+ * Any whitespace after the key is skipped; if the first non-whitespace
+ * character after the key is <code>=</code> or <code>:</code>, then it
+ * is ignored and any whitespace characters after it are also skipped.
+ * All remaining characters on the line become part of the associated
+ * element string. Within the element string, the ASCII
+ * escape sequences <code>\t</code>, <code>\n</code>,
+ * <code>\r</code>, <code>\\</code>, <code>\"</code>, <code>\'</code>,
+ * <code>\ &#32;</code> &#32;(a backslash and a space), and
+ * <code>\\u</code><i>xxxx</i> are recognized and converted to single
+ * characters. Moreover, if the last character on the line is
+ * <code>\</code>, then the next line is treated as a continuation of the
+ * current line; the <code>\</code> and line terminator are simply
+ * discarded, and any leading whitespace characters on the continuation
+ * line are also discarded and are not part of the element string.
+ * <p>
+ * As an example, each of the following four lines specifies the key
+ * <code>"Truth"</code> and the associated element value
+ * <code>"Beauty"</code>:
+ * <p>
+ * <pre>
+ * Truth = Beauty
+ * Truth:Beauty
+ * Truth :Beauty
+ * </pre>
+ * As another example, the following three lines specify a single
+ * property:
+ * <p>
+ * <pre>
+ * fruits apple, banana, pear, \
+ * cantaloupe, watermelon, \
+ * kiwi, mango
+ * </pre>
+ * The key is <code>"fruits"</code> and the associated element is:
+ * <p>
+ * <pre>"apple, banana, pear, cantaloupe, watermelon,kiwi, mango"</pre>
+ * Note that a space appears before each <code>\</code> so that a space
+ * will appear after each comma in the final result; the <code>\</code>,
+ * line terminator, and leading whitespace on the continuation line are
+ * merely discarded and are <i>not</i> replaced by one or more other
+ * characters.
+ * <p>
+ * As a third example, the line:
+ * <p>
+ * <pre>cheeses
+ * </pre>
+ * specifies that the key is <code>"cheeses"</code> and the associated
+ * element is the empty string.<p>
+ *
+ * @param in the input stream.
+ * @exception IOException if an error occurred when reading from the
+ * input stream.
+ */
+ public synchronized void load(InputStream inStream) throws IOException {
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(inStream, "8859_1"));
+
+ while (true) {
+ // Get next line
+ String line = in.readLine();
+
+ if (line == null)
+ return;
+
+ if (line.length() > 0) {
+ // Continue lines that end in slashes if they are not comments
+ char firstChar = line.charAt(0);
+
+ if ((firstChar != '#') && (firstChar != '!')) {
+ while (continueLine(line)) {
+ String nextLine = in.readLine();
+
+ if (nextLine == null)
+ nextLine = "";
+ String loppedLine = line.substring(0, line.length() - 1);
+ // Advance beyond whitespace on new line
+ int startIndex = 0;
+
+ for (startIndex = 0; startIndex < nextLine.length(); startIndex++)
+ if (whiteSpaceChars.indexOf(nextLine.charAt(startIndex)) == -1)
+ break;
+ nextLine = nextLine.substring(startIndex, nextLine.length());
+ line = new String(loppedLine + nextLine);
+ }
+ // Find start of key
+ int len = line.length();
+ int keyStart;
+
+ for (keyStart = 0; keyStart < len; keyStart++) {
+ if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1)
+ break;
+ }
+ // Find separation between key and value
+ int separatorIndex;
+
+ for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++) {
+ char currentChar = line.charAt(separatorIndex);
+
+ if (currentChar == '\\')
+ separatorIndex++;
+ else if (keyValueSeparators.indexOf(currentChar) != -1)
+ break;
+ }
+
+ // Skip over whitespace after key if any
+ int valueIndex;
+
+ for (valueIndex = separatorIndex; valueIndex < len; valueIndex++)
+ if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)
+ break;
+
+ // Skip over one non whitespace key value separators if any
+ if (valueIndex < len)
+ if (strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1)
+ valueIndex++;
+
+ // Skip over white space after other separators if any
+ while (valueIndex < len) {
+ if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)
+ break;
+ valueIndex++;
+ }
+ String key = line.substring(keyStart, separatorIndex);
+ String value = (separatorIndex < len) ? line.substring(valueIndex, len) : "";
+
+ // Convert then store key and value
+ // NETSCAPE: no need to convert escape characters
+ // key = loadConvert(key);
+ // value = loadConvert(value);
+ put(key, value);
+ }
+ }
+ }
+ }
+
+ /*
+ * Returns true if the given line is a line that must
+ * be appended to the next line
+ */
+ private boolean continueLine(String line) {
+ int slashCount = 0;
+ int index = line.length() - 1;
+
+ while ((index >= 0) && (line.charAt(index--) == '\\'))
+ slashCount++;
+ return (slashCount % 2 == 1);
+ }
+
+ /*
+ * Converts encoded \\uxxxx to unicode chars
+ * and changes special saved chars to their original forms
+ */
+ private String loadConvert(String theString) {
+ char aChar;
+ int len = theString.length();
+ StringBuffer outBuffer = new StringBuffer(len);
+
+ for (int x = 0; x < len;) {
+ aChar = theString.charAt(x++);
+ if (aChar == '\\') {
+ aChar = theString.charAt(x++);
+ if (aChar == 'u') {
+ // Read the xxxx
+ int value = 0;
+
+ for (int i = 0; i < 4; i++) {
+ aChar = theString.charAt(x++);
+ switch (aChar) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ value = (value << 4) + aChar - '0';
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ value = (value << 4) + 10 + aChar - 'a';
+ break;
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ value = (value << 4) + 10 + aChar - 'A';
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ "Malformed \\uxxxx encoding.");
+ }
+ }
+ outBuffer.append((char) value);
+ } else {
+ if (aChar == 't') aChar = '\t';
+ else if (aChar == 'r') aChar = '\r';
+ else if (aChar == 'n') aChar = '\n';
+ else if (aChar == 'f') aChar = '\f';
+ outBuffer.append(aChar);
+ }
+ } else
+ outBuffer.append(aChar);
+ }
+ return outBuffer.toString();
+ }
+
+ /*
+ * Converts unicodes to encoded \\uxxxx
+ * and writes out any of the characters in specialSaveChars
+ * with a preceding slash
+ */
+ private String saveConvert(String theString) {
+ char aChar;
+ int len = theString.length();
+ StringBuffer outBuffer = new StringBuffer(len * 2);
+
+ for (int x = 0; x < len;) {
+ aChar = theString.charAt(x++);
+ switch (aChar) {
+ case '\\':
+ outBuffer.append('\\');
+ outBuffer.append('\\');
+ continue;
+
+ case '\t':
+ outBuffer.append('\\');
+ outBuffer.append('t');
+ continue;
+
+ case '\n':
+ outBuffer.append('\\');
+ outBuffer.append('n');
+ continue;
+
+ case '\r':
+ outBuffer.append('\\');
+ outBuffer.append('r');
+ continue;
+
+ case '\f':
+ outBuffer.append('\\');
+ outBuffer.append('f');
+ continue;
+
+ default:
+ if ((aChar < 20) || (aChar > 127)) {
+ outBuffer.append('\\');
+ outBuffer.append('u');
+ outBuffer.append(toHex((aChar >> 12) & 0xF));
+ outBuffer.append(toHex((aChar >> 8) & 0xF));
+ outBuffer.append(toHex((aChar >> 4) & 0xF));
+ outBuffer.append(toHex((aChar >> 0) & 0xF));
+ } else {
+ if (specialSaveChars.indexOf(aChar) != -1)
+ outBuffer.append('\\');
+ outBuffer.append(aChar);
+ }
+ }
+ }
+ return outBuffer.toString();
+ }
+
+ /**
+ * Calls the <code>store(OutputStream out, String header)</code> method
+ * and suppresses IOExceptions that were thrown.
+ *
+ * @deprecated This method does not throw an IOException if an I/O error
+ * occurs while saving the property list. As of JDK 1.2, the preferred
+ * way to save a properties list is via the <code>store(OutputStream out,
+ * String header)</code> method.
+ *
+ * @param out an output stream.
+ * @param header a description of the property list.
+ * @exception ClassCastException if this <code>Properties</code> object
+ * contains any keys or values that are not <code>Strings</code>.
+ */
+ public synchronized void save(OutputStream out, String header) {
+ try {
+ store(out, header);
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Writes this property list (key and element pairs) in this
+ * <code>Properties</code> table to the output stream in a format suitable
+ * for loading into a <code>Properties</code> table using the
+ * <code>load</code> method.
+ * <p>
+ * Properties from the defaults table of this <code>Properties</code>
+ * table (if any) are <i>not</i> written out by this method.
+ * <p>
+ * If the header argument is not null, then an ASCII <code>#</code>
+ * character, the header string, and a line separator are first written
+ * to the output stream. Thus, the <code>header</code> can serve as an
+ * identifying comment.
+ * <p>
+ * Next, a comment line is always written, consisting of an ASCII
+ * <code>#</code> character, the current date and time (as if produced
+ * by the <code>toString</code> method of <code>Date</code> for the
+ * current time), and a line separator as generated by the Writer.
+ * <p>
+ * Then every entry in this <code>Properties</code> table is written out,
+ * one per line. For each entry the key string is written, then an ASCII
+ * <code>=</code>, then the associated element string. Each character of
+ * the element string is examined to see whether it should be rendered as
+ * an escape sequence. The ASCII characters <code>\</code>, tab, newline,
+ * and carriage return are written as <code>\\</code>, <code>\t</code>,
+ * <code>\n</code>, and <code>\r</code>, respectively. Characters less
+ * than <code>\u0020</code> and characters greater than
+ * <code>\u007E</code> are written as <code>\\u</code><i>xxxx</i> for
+ * the appropriate hexadecimal value <i>xxxx</i>. Space characters, but
+ * not embedded or trailing space characters, are written with a preceding
+ * <code>\</code>. The key and value characters <code>#</code>,
+ * <code>!</code>, <code>=</code>, and <code>:</code> are written with a
+ * preceding slash to ensure that they are properly loaded.
+ * <p>
+ * After the entries have been written, the output stream is flushed. The
+ * output stream remains open after this method returns.
+ *
+ * @param out an output stream.
+ * @param header a description of the property list.
+ * @exception ClassCastException if this <code>Properties</code> object
+ * contains any keys or values that are not <code>Strings</code>.
+ */
+ public synchronized void store(OutputStream out, String header)
+ throws IOException {
+ BufferedWriter awriter;
+
+ awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
+ if (header != null)
+ writeln(awriter, "#" + header);
+ writeln(awriter, "#" + new Date().toString());
+ for (Enumeration e = keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = (String) get(key);
+
+ // key = saveConvert(key);
+ // val = saveConvert(val);
+ writeln(awriter, key + "=" + val);
+ }
+ awriter.flush();
+ }
+
+ private static void writeln(BufferedWriter bw, String s) throws IOException {
+ bw.write(s);
+ bw.newLine();
+ }
+
+ /**
+ * Searches for the property with the specified key in this property list.
+ * If the key is not found in this property list, the default property list,
+ * and its defaults, recursively, are then checked. The method returns
+ * <code>null</code> if the property is not found.
+ *
+ * @param key the property key.
+ * @return the value in this property list with the specified key value.
+ * @see java.util.Properties#defaults
+ */
+ public String getProperty(String key) {
+ Object oval = super.get(key);
+ String sval = (oval instanceof String) ? (String) oval : null;
+
+ return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
+ }
+
+ /**
+ * Searches for the property with the specified key in this property list.
+ * If the key is not found in this property list, the default property list,
+ * and its defaults, recursively, are then checked. The method returns the
+ * default value argument if the property is not found.
+ *
+ * @param key the hashtable key.
+ * @param defaultValue a default value.
+ *
+ * @return the value in this property list with the specified key value.
+ * @see java.util.Properties#defaults
+ */
+ public String getProperty(String key, String defaultValue) {
+ String val = getProperty(key);
+
+ return (val == null) ? defaultValue : val;
+ }
+
+ /**
+ * Returns an enumeration of all the keys in this property list, including
+ * the keys in the default property list.
+ *
+ * @return an enumeration of all the keys in this property list, including
+ * the keys in the default property list.
+ * @see java.util.Enumeration
+ * @see java.util.Properties#defaults
+ */
+ public Enumeration propertyNames() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h.keys();
+ }
+
+ /**
+ * Prints this property list out to the specified output stream.
+ * This method is useful for debugging.
+ *
+ * @param out an output stream.
+ */
+ public void list(PrintStream out) {
+ out.println("-- listing properties --");
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ for (Enumeration e = h.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = (String) h.get(key);
+
+ if (val.length() > 40) {
+ val = val.substring(0, 37) + "...";
+ }
+ out.println(key + "=" + val);
+ }
+ }
+
+ /**
+ * Prints this property list out to the specified output stream.
+ * This method is useful for debugging.
+ *
+ * @param out an output stream.
+ * @since JDK1.1
+ */
+
+ /*
+ * Rather than use an anonymous inner class to share common code, this
+ * method is duplicated in order to ensure that a non-1.1 compiler can
+ * compile this file.
+ */
+ public void list(PrintWriter out) {
+ out.println("-- listing properties --");
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ for (Enumeration e = h.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = (String) h.get(key);
+
+ if (val.length() > 40) {
+ val = val.substring(0, 37) + "...";
+ }
+ out.println(key + "=" + val);
+ }
+ }
+
+ /**
+ * Enumerates all key/value pairs in the specified hastable.
+ * @param h the hashtable
+ */
+ private synchronized void enumerate(Hashtable h) {
+ if (defaults != null) {
+ defaults.enumerate(h);
+ }
+ for (Enumeration e = keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+
+ h.put(key, get(key));
+ }
+ }
+
+ /**
+ * Convert a nibble to a hex character
+ * @param nibble the nibble to convert.
+ */
+ private static char toHex(int nibble) {
+ return hexDigit[(nibble & 0xF)];
+ }
+
+ /** A table of hex digits */
+ private static final char[] hexDigit = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java b/pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java
new file mode 100644
index 000000000..9b192905f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java
@@ -0,0 +1,55 @@
+// --- 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.base;
+
+
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * This class is is a wrapper to hide the Properties methods from
+ * the PropConfigStore. Lucky for us, Properties already implements
+ * almost every thing ISourceConfigStore requires.
+ *
+ * @version $Revision$, $Date$
+ * @see java.util.Properties
+ */
+public class SourceConfigStore extends SimpleProperties implements ISourceConfigStore {
+
+ /**
+ * Retrieves a property from the config store
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ public Object get(String name) {
+ return super.get(name); // from Properties->Hashtable
+ }
+
+ /**
+ * Puts a property into the config store.
+ * <P>
+ *
+ * @param name property name
+ * @param value property value
+ */
+ public void put(String name, Object value) {
+ super.put(name, value); // from Properties->Hashtable
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java b/pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java
new file mode 100644
index 000000000..442a93671
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java
@@ -0,0 +1,74 @@
+// --- 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.base;
+
+
+import com.netscape.certsrv.apps.CMS;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * A class represents a subsystem loader.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class SubsystemLoader {
+
+ private static final String PROP_SUBSYSTEM = "subsystem";
+ private static final String PROP_CLASSNAME = "class";
+ private static final String PROP_ID = "id";
+
+ public static Vector load(IConfigStore config) throws EBaseException {
+ Vector v = new Vector();
+
+ // load a list of installable subsystems (services)
+ for (int i = 0;; i++) {
+ IConfigStore c = config.getSubStore(PROP_SUBSYSTEM + i);
+
+ if (c == null)
+ break;
+ String id = null;
+
+ try {
+ id = c.getString(PROP_ID, null);
+ if (id == null)
+ break;
+ } catch (EBaseException e) {
+ break;
+ }
+ String className = c.getString(PROP_CLASSNAME, null);
+
+ if (className == null)
+ break;
+ try {
+ ISubsystem sub = (ISubsystem) Class.forName(
+ className).newInstance();
+
+ sub.setId(id);
+ v.addElement(sub);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_FAILED", className));
+ }
+ }
+ return v;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java b/pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java
new file mode 100644
index 000000000..f95a61610
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java
@@ -0,0 +1,43 @@
+// --- 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.base;
+
+
+import java.util.Hashtable;
+import com.netscape.certsrv.base.*;
+
+
+public class SubsystemRegistry extends Hashtable {
+ private static SubsystemRegistry mInstance = null;
+
+ public static SubsystemRegistry getInstance() {
+ if (mInstance == null) {
+ mInstance = new SubsystemRegistry();
+ }
+ return mInstance;
+ }
+
+ private SubsystemRegistry() {
+ super();
+ }
+
+ public ISubsystem get(String key) {
+ return (ISubsystem) super.get(key);
+ }
+
+}