// --- 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.ByteArrayOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.math.BigInteger; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.util.Base64OutputStream; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.EPropertyNotDefined; import com.netscape.certsrv.base.EPropertyNotFound; import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.ISourceConfigStore; /** * 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 * *
* cms.ca0.http.service0 -> mSource=PropConfigStore -> * cms.ca0.http -> mSource=PropConfigStore -> * cms.ca0 -> mSource=PropConfigStore -> * cms -> mSource=SourceConfigStore -> Properties ** * The chain ends when the store name is reduced down to it's original * value. *
* * @version $Revision$, $Date$ */ public class PropConfigStore implements IConfigStore, Cloneable { /** * */ private static final long serialVersionUID = 4714108964096659077L; 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. *
* * @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. *
* * @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. *
* * @return store name */ public String getName() { return mStoreName; } /** * Retrieves a property from the configuration file. *
* * @param name property name * @return property value */ public String 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. *
* * @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. *
* * @param name property name * @param value property value */ public String put(String name, String value) { return 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 *
*
* @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), "
*
* @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.
*
*
* @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), "
*
* @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),
"
*
* @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.
*
*
* @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,
*
*
*
* @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.
*
*
* @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.
*
*
* @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 {
}
}
* cms.ldap.host=ds.netscape.com
* cms.ldap.port=389
*
*
* "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,
*
*
* cms.ldap = kms.ldap
*
*