summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cmscore/util
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/util')
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/Assert.java49
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/AssertionException.java32
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/Debug.java363
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java91
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/FileAsString.java123
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java146
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java488
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java162
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java294
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java210
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java179
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/UtilResources.java74
12 files changed, 2211 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/util/Assert.java b/pki/base/common/src/com/netscape/cmscore/util/Assert.java
new file mode 100644
index 000000000..afc38f49b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/Assert.java
@@ -0,0 +1,49 @@
+// --- 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.util;
+
+
+public class Assert {
+ public static final boolean ON = true;
+
+ public static void Assertion(boolean e) {
+ if (!e) {
+ throw new AssertionException("assertion");
+ }
+ }
+
+ public static void NotReached(String msg) {
+ throw new AssertionException("not reached: " + msg);
+ }
+
+ public static void NotYetImplemented(String msg) {
+ throw new AssertionException("not yet implemented: " + msg);
+ }
+
+ public static void PreCondition(boolean e) {
+ if (!e) {
+ throw new AssertionException("precondition");
+ }
+ }
+
+ public static void PostCondition(boolean e) {
+ if (!e) {
+ throw new AssertionException("precondition");
+ }
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/AssertionException.java b/pki/base/common/src/com/netscape/cmscore/util/AssertionException.java
new file mode 100644
index 000000000..7b0675b12
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/AssertionException.java
@@ -0,0 +1,32 @@
+// --- 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.util;
+
+
+/**
+ * Assertion exceptions are thrown when assertion code is invoked
+ * and fails to operate properly.
+ */
+public class AssertionException extends Error {
+ public AssertionException() {
+ }
+
+ public AssertionException(String msg) {
+ super(msg);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/Debug.java b/pki/base/common/src/com/netscape/cmscore/util/Debug.java
new file mode 100644
index 000000000..b9b794e9c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/Debug.java
@@ -0,0 +1,363 @@
+// --- 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.util;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.cmsutil.util.*;
+
+import java.lang.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+
+public class Debug
+ implements ISubsystem {
+
+ private static Debug mInstance = new Debug();
+ private static boolean mShowCaller = false;
+
+
+ /* This dateformatter is used to put the date on each
+ debug line. But the DateFormatter is not thread safe,
+ so I create a thread-local DateFormatter for each thread
+ */
+ private static String DATE_PATTERN = "dd/MMM/yyyy:HH:mm:ss";
+ private static ThreadLocal mFormatObject = new ThreadLocal() {
+ protected synchronized Object initialValue() {
+ return new SimpleDateFormat(DATE_PATTERN);
+ }
+ };
+
+ /* the dateformatter should be accessed with this function */
+ private static SimpleDateFormat getDateFormatter() {
+ return ((SimpleDateFormat)(mFormatObject.get()));
+ }
+
+ public static final boolean ON = false;
+ public static final int OBNOXIOUS = 10;
+ public static final int VERBOSE = 5;
+ public static final int INFORM = 1;
+
+ // the difference between this and 'ON' is that this is always
+ // guaranteed to log to 'mOut', whereas other parts of the server
+ // may do:
+ // if (Debug.ON) {
+ // System.out.println("..");
+ // }
+ // I want to make sure that any Debug.trace() is not logged to
+ // System.out if the server is running under watchdog
+
+ private static boolean TRACE_ON = false;
+
+ private static int mDebugLevel = VERBOSE;
+
+ private static PrintStream mOut = null;
+ private static Hashtable mHK = null;
+
+ static {
+ if (TRACE_ON == true) {
+ mOut = System.out;
+ }
+ }
+
+ public static void trace(int level, String t) {
+ trace(level, t, null, true);
+ }
+
+ /**
+ * Output a debug message at the output stream sepcified in the init()
+ * method. This method is very lightweight if debugging is turned off, since
+ * it will return immediately. However, the caller should be aware that
+ * if the argument to Debug.trace() is an object whose toString() is
+ * expensive, that this toString() will still be called in any case.
+ * In such a case, it is wise to wrap the Debug.trace like this: <pre>
+ * if (Debug.on()) { Debug.trace("obj is: "+obj); }
+ * </pre>
+ * @param level the message level. If this is >= than the currently set
+ * level (set with setLevel() ), the message is printed
+ * @param t the message to print
+ * @param ignoreStack when walking the stack to determine the
+ * location of the method that called the trace() method,
+ * ignore any classes with this string in. Can be null
+ * @param printCaller if true, (and if static mShowCaller is true)
+ * dump caller information in this format:
+ * (source-file:line) methodname():
+ */
+ public static void trace(int level, String t, String ignoreStack, boolean printCaller) {
+ String callerinfo = "";
+ if (!TRACE_ON) return;
+ if (level >= mDebugLevel) {
+ if (mShowCaller && printCaller) {
+ String method = "";
+ String fileAndLine = "";
+
+ try {
+ Throwable tr = new Throwable();
+ StackTraceElement ste[] = tr.getStackTrace();
+ int i=0;
+ while ((i < ste.length) &&
+ (ste[i].getMethodName().toLowerCase().indexOf("debug") >-1) ||
+ (ste[i].getMethodName().toLowerCase().indexOf("hashkey") >-1) ||
+ (ste[i].getClassName().toLowerCase().indexOf("propconfigstore") >-1) ||
+ (ste[i].getClassName().toLowerCase().indexOf("argblock") >-1) ||
+ (ste[i].getClassName().toLowerCase().indexOf("debug") >-1) ||
+ (ste[i].getMethodName().toLowerCase().indexOf("trace") >-1)) i++;
+
+ if (i < ste.length) {
+ fileAndLine = ste[i].getFileName()+":"+
+ ste[i].getLineNumber();
+ method = ste[i].getMethodName()+"()";
+ }
+
+ callerinfo = fileAndLine +":"+ method + " ";
+ } catch (Exception f) {
+ }
+ }
+
+ outputTraceMessage(callerinfo + t);
+ }
+ }
+
+ private static void outputTraceMessage(String t)
+ {
+ if (!TRACE_ON) return;
+ SimpleDateFormat d = getDateFormatter();
+ if (mOut != null && d != null) {
+ mOut.println("[" + d.format(new Date()) + "][" + Thread.currentThread().getName() + "]: " + t);
+ mOut.flush();
+ }
+ }
+
+ private static boolean hkdotype(String type)
+ {
+ if (mHK!= null && mHK.get(type) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void traceHashKey(String type, String key) {
+ if (hkdotype(type)) {
+ trace("GET r=" + type+ ",k=" + key);
+ }
+ }
+
+ public static void traceHashKey(String type, String key, String val) {
+ if (hkdotype(type)) {
+ trace("GET r=" + type+ ",k=" + key + ",v=" + val);
+ }
+ }
+
+ public static void traceHashKey(String type, String key, String val, String def) {
+ if (hkdotype(type)) {
+ trace("GET r=" + type+ ",k=" +
+ key + ",v=" + val +",d="+def);
+ }
+ }
+
+ public static void putHashKey(String type, String key, String value) {
+ if (hkdotype(type)) {
+ outputTraceMessage("PUT r=" + type+ ",k=" + key + ",v=" + value);
+ }
+ }
+
+ public static void trace(String t) {
+ trace(VERBOSE, t);
+ }
+
+ public static void print(int level, String t) {
+ if (!TRACE_ON) return;
+ if (mOut != null) {
+ if (level >= mDebugLevel)
+ mOut.print(t);
+ }
+ }
+
+ public static void print(String t) {
+ print(VERBOSE, t);
+ }
+
+ private static void printNybble(byte b) {
+ if (mOut == null) return;
+ if (b < 10) mOut.write('0' + b);
+ else mOut.write('a' + b - 10);
+ }
+
+ /**
+ * If tracing enabled, dump a byte array to debugging printstream
+ * as hex, colon-seperated bytes, 16 bytes to a line
+ */
+ public static void print(byte[] b) {
+ if (!TRACE_ON) return;
+ if (mOut == null) return;
+
+ for (int i = 0; i < b.length; i++) {
+ printNybble((byte) ((b[i] & 0xf0) >> 4));
+ printNybble((byte) (b[i] & 0x0f));
+ mOut.print(" ");
+ if (((i % 16) == 15) && i != b.length) mOut.println("");
+ }
+ mOut.println("");
+ mOut.flush();
+ }
+
+ /**
+ * Print the current stack trace to the debug printstream
+ */
+ public static void printStackTrace() {
+ if (!TRACE_ON) return;
+ Exception e = new Exception("Debug");
+
+ printStackTrace(e);
+ }
+
+ /**
+ * Print the stack trace of the named exception
+ * to the debug printstream
+ */
+ public static void printStackTrace(Throwable e) {
+ if (!TRACE_ON) return;
+ if (mOut == null) return;
+
+ e.printStackTrace(mOut);
+ }
+
+ /**
+ * Set the current debugging level. You can use: <pre>
+ * OBNOXIOUS = 10
+ * VERBOSE = 5
+ * INFORM = 1
+ * </pre> Or another value
+ */
+
+ public static void setLevel(int level) {
+ mDebugLevel = level;
+ }
+
+ public static int getLevel(int level) {
+ return mDebugLevel;
+ }
+
+ /**
+ * Test if debugging is on. Do NOT write to System.out in your debug code
+ */
+ public static boolean on() {
+ return TRACE_ON;
+ }
+
+ /* ISubsystem methods: */
+
+ public static String ID = "debug";
+ private static IConfigStore mConfig = null;
+
+ public String getId() {
+ return ID;
+ }
+
+ public void setId(String id) {
+ ID = id;
+ }
+
+ private static final String PROP_ENABLED = "enabled";
+ private static final String PROP_FILENAME = "filename";
+ private static final String PROP_HASHKEYS = "hashkeytypes";
+ private static final String PROP_SHOWCALLER = "showcaller";
+ private static final String PROP_LEVEL = "level";
+ private static final String PROP_APPEND = "append";
+
+ /**
+ * Debug subsystem initialization. This subsystem is usually
+ * given the following parameters: <pre>
+ * debug.enabled : (true|false) default false
+ * debug.filename : can be a pathname, or STDOUT
+ * debug.hashkeytypes: comma-separated list of hashkey types
+ * possible values: "CS.cfg"
+ * debug.showcaller: (true|false) default false [show caller method name for Debug.trace()]
+ * </pre>
+ */
+ public void init(ISubsystem owner, IConfigStore config) {
+ mConfig = config;
+ String filename = null;
+ String hashkeytypes = null;
+ boolean append=true;
+
+ try {
+ TRACE_ON = mConfig.getBoolean(PROP_ENABLED, false);
+ if (TRACE_ON) {
+ filename = mConfig.getString(PROP_FILENAME, null);
+ if (filename == null) {
+ TRACE_ON = false;
+ }
+ hashkeytypes = mConfig.getString(PROP_HASHKEYS, null);
+ mShowCaller = mConfig.getBoolean(PROP_SHOWCALLER, false);
+ append = mConfig.getBoolean(PROP_APPEND, true);
+ }
+ if (TRACE_ON) {
+ if (filename.equals("STDOUT")) {
+ mOut = System.out;
+ } else {
+ if( !Utils.isNT() ) {
+ // Always insure that a physical file exists!
+ Utils.exec( "touch " + filename );
+ Utils.exec( "chmod 00640 " + filename );
+ }
+ OutputStream os = new FileOutputStream(filename, append);
+ mOut = new PrintStream(os, true); /* true == autoflush */
+ }
+ if (hashkeytypes != null) {
+ StringTokenizer st = new StringTokenizer(hashkeytypes,
+ ",", false);
+ mHK = new Hashtable();
+ while (st.hasMoreElements()) {
+ String hkr = st.nextToken();
+ mHK.put(hkr, "true");
+ }
+ }
+ }
+ outputTraceMessage("============================================");
+ outputTraceMessage("===== DEBUG SUBSYSTEM INITIALIZED =======");
+ outputTraceMessage("============================================");
+ int level = mConfig.getInteger(PROP_LEVEL, VERBOSE);
+ setLevel(level);
+ } catch (Exception e) {
+ // Don't do anything. Logging is not set up yet, and
+ // we can't write to STDOUT.
+ }
+ }
+
+ public void startup() {
+ }
+
+ public void shutdown() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ // for singleton
+
+ public static Debug getInstance() {
+ return mInstance;
+ }
+
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java b/pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java
new file mode 100644
index 000000000..61f6f49ec
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java
@@ -0,0 +1,91 @@
+// --- 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.util;
+
+
+import java.io.*;
+
+
+public class ExceptionFormatter {
+
+ /**
+ * Routines for pretty-printing java exceptions
+ * prints okay in a single-line.
+ */
+ /*
+ * Take an exception stacktrace, and reformat it so that is
+ * prints okay in a single-line.
+ */
+
+ public static String getStackTraceAsString(Throwable e) {
+ String returnvalue = e.toString();
+
+ try {
+ PipedOutputStream po = new PipedOutputStream();
+ PipedInputStream pi = new PipedInputStream(po);
+
+ PrintWriter ps = new PrintWriter(po);
+
+ e.printStackTrace(ps);
+ ps.flush();
+
+ int avail = pi.available();
+ byte[] b = new byte[avail];
+
+ pi.read(b, 0, avail);
+ returnvalue = new String(b);
+ } catch (Exception ex) {
+ }
+ return returnvalue;
+
+ }
+
+ /* test code below */
+
+ public static void test()
+ throws TestException {
+ throw new TestException("** testexception **");
+ }
+
+ public static void main(String[] argv) {
+ try {
+ test();
+ } catch (Exception e) {
+ System.out.println("\n------- Exception.toString() ------");
+ System.out.println(e.toString());
+ System.out.println("\n------- Exception.printStackTrace() ------");
+ e.printStackTrace();
+ System.out.println("\n------- ExceptionFormatter.format() ------");
+ System.out.println(ExceptionFormatter.getStackTraceAsString(e));
+ }
+ }
+
+}
+
+
+class TestException extends Exception {
+
+ public TestException() {
+ }
+
+ public TestException(String s) {
+ super(s);
+ }
+
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/util/FileAsString.java b/pki/base/common/src/com/netscape/cmscore/util/FileAsString.java
new file mode 100644
index 000000000..968f9cb80
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/FileAsString.java
@@ -0,0 +1,123 @@
+// --- 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.util;
+
+
+import java.io.*;
+import java.lang.StringBuffer;
+
+
+public class FileAsString {
+
+ protected String mFilename;
+ protected long mLastRead = 0;
+
+ private String fileContents = null;
+ private Object userObject = null;
+
+ /**
+ * This class enables you to get treat a file as a string
+ * If the file changes underneath you, it will automatically
+ * be read
+ */
+ public FileAsString(String filename) throws IOException {
+ mFilename = filename;
+ readFile();
+ }
+
+ public boolean fileHasChanged() throws IOException {
+ File file = new File(mFilename);
+ long lastmodified = file.lastModified();
+
+ return (lastmodified != mLastRead);
+ }
+
+ private void readFile()
+ throws IOException {
+ BufferedReader br = createBufferedReader(mFilename);
+ StringBuffer buf = new StringBuffer("");
+ int bytesread = 0;
+
+ do {
+ char cbuf[] = new char[16];
+
+ bytesread = br.read(cbuf, 0, cbuf.length);
+ if (bytesread > 0) {
+ buf.append(cbuf, 0, bytesread);
+ }
+ String s = new String(buf);
+ }
+ while (bytesread != -1);
+ br.close();
+
+ fileContents = new String(buf);
+ }
+
+ private BufferedReader createBufferedReader(String filename)
+ throws IOException {
+ Debug.trace("createBufferedReader(filename=" + filename + ")");
+ BufferedReader br = null;
+ FileReader fr = null;
+
+ try {
+ File file = new File(filename);
+
+ mLastRead = file.lastModified();
+ fr = new FileReader(file);
+ br = new BufferedReader(fr);
+ mFilename = filename;
+ } catch (IOException e) {
+ try {
+ if (fr != null) {
+ fr.close();
+ }
+ } catch (Exception f) {
+ }
+ throw e;
+ }
+ return br;
+ }
+
+ public String getAsString()
+ throws IOException {
+ if (fileHasChanged()) {
+ readFile();
+ }
+ return fileContents;
+ }
+
+ public Object getUserObject() {
+ try {
+ if (fileHasChanged()) {
+ userObject = null;
+ }
+ } catch (Exception e) {
+ userObject = null;
+ }
+ return userObject;
+ }
+
+ public void setUserObject(Object x) {
+ userObject = x;
+ }
+
+ public String getFilename() {
+ return mFilename;
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java b/pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java
new file mode 100644
index 000000000..98a2e8422
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java
@@ -0,0 +1,146 @@
+// --- 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.util;
+
+
+import java.io.*;
+
+
+/**
+ * checks the filename and directory with the specified filter
+ * checks with multiple "*".
+ * the filter has to start with a '*' character.
+ * this to keep the search the same as in the motif version
+ * <P>
+ * Copied verbatium from sun.awt.tiny.TinyFileDialogPeer. Used by
+ * RollingLogFile expiration code
+ * <P>
+ * @author mikep
+ * @version $Revision$, $Date$
+ */
+public class FileDialogFilter implements FilenameFilter {
+
+ String filter;
+
+ public FileDialogFilter(String f) {
+ filter = f;
+ }
+
+ public String toString() {
+ return filter;
+ }
+
+ /**
+ * return true if match
+ */
+ public boolean accept(File dir, String fileName) {
+
+ File f = new File(dir, fileName);
+
+ if (f.isDirectory()) {
+ return true;
+ } else {
+ return searchPattern(fileName, filter);
+ }
+ }
+
+ /**
+ * start searching
+ */
+ boolean searchPattern(String fileName, String filter) {
+ int filterCursor = 0;
+ int fileNameCursor = 0;
+
+ int filterChar = filter.charAt(filterCursor);
+
+ if (filterCursor == 0 && filterChar != '*') {
+ return false;
+ }
+ String ls = filter.substring(filterCursor + 1);
+
+ return handleStar(fileName, ls);
+ }
+
+ /**
+ * call this method when character was an *
+ */
+ boolean handleStar(String fileName, String filter) {
+ int ftLen = filter.length();
+ int flLen = fileName.length();
+ char ftChar;
+ char flChar;
+ int ftCur = 0;
+ int flCur = 0;
+ int c = 0;
+
+ if (ftLen == 0) {
+ return true;
+ }
+
+ while (c < flLen) {
+ ftChar = filter.charAt(ftCur);
+
+ if (ftChar == '*') {
+ String ls = filter.substring(ftCur + 1);
+ String fs = fileName.substring(flCur);
+
+ if (handleStar(fs, ls)) {
+ return true;
+ }
+ c++;
+ flCur = c;
+ ftCur = 0;
+ continue;
+ }
+ flChar = fileName.charAt(flCur);
+
+ if (ftChar == flChar) {
+ ftCur++;
+ flCur++;
+
+ if (flCur == flLen && ftCur == ftLen) {
+ return true;
+ }
+
+ if (flCur < flLen && ftCur == ftLen) {
+ return false;
+ }
+
+ if (flCur == flLen) {
+ c = flLen;
+ }
+ } else {
+ c++;
+ flCur = c;
+ ftCur = 0;
+ if (c == flLen) {
+ return false;
+ }
+ }
+ }
+
+ for (int i = ftCur; i < ftLen; i++) {
+ ftChar = filter.charAt(i);
+ if (ftChar != '*') {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java b/pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java
new file mode 100644
index 000000000..a3cdcbdef
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java
@@ -0,0 +1,488 @@
+// --- 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.util;
+
+
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.osutil.*;
+
+
+/**
+ * This object contains the OS independent interfaces. It's currently
+ * used for Unix signal and user handling, but could eventually be extended
+ * for NT interfaces.
+ * <P>
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ */
+public final class OsSubsystem implements ISubsystem {
+
+ public static final String ID = "os";
+ protected IConfigStore mConfig;
+ protected String mInstanceDir;
+ protected ISubsystem mOwner;
+ protected ILogger mLogger = null;
+ protected static SignalThread mSignalThread = null;
+
+ private static final String PROP_OS = "os";
+ private static final String PROP_USERID = "userid";
+
+ // singleton enforcement
+
+ private static OsSubsystem mInstance = new OsSubsystem();
+
+ public static OsSubsystem getInstance() {
+ return mInstance;
+ }
+
+ // end singleton enforcement.
+
+ /**
+ * Constructor for an OS subsystem
+ */
+ private OsSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem name.
+ */
+ public String getId() {
+ return ID;
+ }
+
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ /**
+ * Initializes this subsystem with the given configuration
+ * store.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ * @exception EBaseException failed to initialize
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+
+ mOwner = owner;
+ mConfig = config;
+ mLogger = CMS.getLogger();
+
+ mInstanceDir = CMS.getConfigStore().getString("instanceRoot");
+
+ // We currently only deal with Unix and NT
+ if (isUnix()) {
+ //initUnix();
+ } else {
+ initNT();
+ }
+ try {
+ //System.out.println(" The dir I'm seeing is " + mInstanceDir);
+ String pidName = mInstanceDir + File.separator + "config" + File.separator + "cert-pid";
+ BufferedWriter pidOut = new BufferedWriter(new FileWriter(pidName));
+ int pid = OsSubsystem.getpid();
+
+ pidOut.write(Integer.toString(pid));
+ pidOut.close();
+ OSUtil.getFileWriteLock(pidName);
+ } catch (Exception e) {
+ //XX to stderr XXXXXX
+ //e.printStackTrace();
+ }
+ }
+
+ /**
+ * Starts up OS
+ */
+ public void startup() throws EBaseException {
+ if (isUnix()) {
+ String pf = mConfig.getString("pidFile", null);
+
+ if (pf == null) {
+ return; // development environment does not rely on this
+ }
+ // dont ever call detach in Java environment,
+ // it does a fork()
+ // LibC.detach();
+
+ // need to do pid here, pid will be changed after detach
+ int pid = LibC.getpid();
+ String pidStr = Integer.toString(pid);
+
+ try {
+ FileOutputStream fos = new FileOutputStream(pf);
+
+ fos.write(pidStr.getBytes());
+ fos.close();
+ } catch (IOException e) {
+
+ /*LogDoc
+ *
+ * @phase start OS subsystem
+ * @message OS: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, "OS: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * Returns the process ID of the Certificate Server process. Works
+ * on Unix and NT.
+ */
+ public static int getpid() {
+ if (isUnix()) {
+ return LibC.getpid();
+ } else {
+ return OSUtil.getNTpid();
+ }
+ }
+
+ /**
+ * Hooks up unix signals.
+ */
+ private void initUnix() throws EBaseException {
+ // Set up signal handling. We pretty much exit on anything
+ // Signal.watch(Signal.SIGHUP);
+ // Signal.watch(Signal.SIGTERM);
+ // Signal.watch(Signal.SIGINT);
+ // mSignalThread = new SignalThread();
+ // mSignalThread.setDaemon(true);
+ // mSignalThread.start();
+
+ Signal.addSignalListener(Signal.SIGHUP, new SIGHUPListener(this));
+ Signal.addSignalListener(Signal.SIGTERM, new SIGTERMListener(this));
+ Signal.addSignalListener(Signal.SIGINT, new SIGINTListener(this));
+
+ /* Increase the maximum number of file descriptors */
+ int i = mConfig.getInteger("maxFiles",
+ ResourceLimit.getHardLimit(ResourceLimit.RLIMIT_NOFILE));
+
+ ResourceLimit.setLimits(ResourceLimit.RLIMIT_NOFILE,
+ i, ResourceLimit.getHardLimit(ResourceLimit.RLIMIT_NOFILE));
+
+ // write current pid to specified file
+ String pf = mConfig.getString("pidFile", null);
+
+ if (pf == null) {
+ return; // development environment does not rely on this
+ }
+ File pidFile = new File(pf);
+
+ if (pidFile.exists()) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PID_EXIST"));
+ }
+ }
+
+ /**
+ * Used to change the process user id usually called after the appropriate
+ * network ports have been opened.
+ */
+ public void setUserId() throws EBaseException {
+ if (!isUnix())
+ return;
+
+ String userid;
+
+ userid = mConfig.getString(PROP_USERID, null);
+ String id = String.valueOf(UserID.get());
+
+ // Change the userid to the prefered Unix user
+ if (userid == null) {
+
+ /*LogDoc
+ *
+ * @phase set user id
+ * @arg0 default user id
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ "OS: No user id in config file. Running as {0}", id);
+ } else {
+ Object[] params = {userid, id};
+
+ try {
+ UserID.set(userid);
+ } catch (IllegalArgumentException e) {
+
+ /*LogDoc
+ *
+ * @phase set user id
+ * @arg0 supplied user id in config
+ * @arg1 default user id
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ "OS: No such user as {0}. Running as {1}", params);
+ } catch (SecurityException e) {
+
+ /*LogDoc
+ *
+ * @phase set user id
+ * @arg0 supplied user id in config
+ * @arg1 default user id
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ "OS: Can't change process uid to {0}. Running as {1}",
+ params);
+ }
+ }
+ }
+
+ private void initNT() {
+ }
+
+ /**
+ * Stops the watchdog. You need to call this if you want the
+ * server to really shutdown, otherwise the watchdog will just
+ * restart us.
+ * <P>
+ */
+ public static void stop() {
+ if (isUnix()) {
+ shutdownUnix();
+ Signal.send(LibC.getppid(), Signal.SIGTERM);
+ } else {
+
+ /*LogDoc
+ *
+ * @phase stop watchdog
+ */
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: stop the NT watchdog!");
+ }
+ }
+
+ /**
+ * Stops this system.
+ * <P>
+ */
+ public void shutdown() {
+ if (isUnix()) {
+ shutdownUnix();
+ } else {
+ shutdownNT();
+ }
+ }
+
+ /**
+ * Shutdown the unix system handlers
+ * <P>
+ */
+ private static void shutdownUnix() {
+
+ // Don't accidentally stop this thread
+ //if (Thread.currentThread() != mSignalThread && mSignalThread != null) {
+ // mSignalThread.stop();
+ // mSignalThread = null;
+ //}
+
+ /* Don't release this signals to protect the process
+ Signal.release(Signal.SIGHUP);
+ Signal.release(Signal.SIGTERM);
+ Signal.release(Signal.SIGINT);
+ */
+ }
+
+ /**
+ * Shutdown the NT system handlers
+ * <P>
+ */
+ private void shutdownNT() {
+ }
+
+ /**
+ * Restart the server
+ * <P>
+ */
+ public void restart() {
+
+ /**
+ if (isUnix()) {
+ restartUnix();
+ } else {
+ restartNT();
+ }
+ **/
+ }
+
+ /**
+ * Unix restart
+ * <P>
+ */
+ private void restartUnix() {
+ // Tell watch dog to restart us
+ int ppid = LibC.getppid();
+
+ Signal.send(ppid, Signal.SIGHUP);
+ }
+
+ /**
+ * NT restart
+ * <P>
+ */
+ private void restartNT() {
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * A universal routine to decide if we are Unix or something else.
+ * This is mostly used for signal handling and uids.
+ *
+ * <P>
+ * @return true if these OS the JavaVM is running on is some Unix varient
+ */
+ public static boolean isUnix() {
+ // XXX What about MacOS?
+ return (File.separatorChar == '/');
+ }
+
+ /**
+ * Unix signal thread. Sleep for a second and then check on the
+ * signals we're interested in. If one is set, do the right stuff
+ */
+ final class SignalThread extends Thread {
+
+ /**
+ * Signal thread constructor
+ */
+ public SignalThread() {
+ super();
+ super.setName("OsSignal-" + (Thread.activeCount() + 1));
+ }
+
+ /**
+ * Check for signal changes every second
+ */
+ public void run() {
+ while (true) {
+ // Sleep for the interval and then check for caught signals
+ // synchronized (Thread.this) {
+ synchronized (this) {
+ try {
+ // Thread.this.wait(1000);
+ this.wait(1000);
+ } catch (InterruptedException e) {
+ // Not very interesting...
+ }
+ }
+
+ // wants us to exit?
+ if (Signal.caught(Signal.SIGINT) > 0 ||
+ Signal.caught(Signal.SIGTERM) > 0) {
+
+ /*LogDoc
+ *
+ * @phase watchdog check
+ */
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: Received shutdown signal");
+ SubsystemRegistry.getInstance().get("MAIN").shutdown();
+ return;
+ }
+
+ // Tell to restart us
+ if (Signal.caught(Signal.SIGHUP) > 0) {
+
+ /*LogDoc
+ *
+ * @phase watchdog check
+ */
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: Received restart signal");
+ restart();
+ return;
+ }
+
+ }
+ }
+
+ }
+}
+
+
+class SIGTERMListener extends SignalListener {
+ private OsSubsystem mOS;
+ public SIGTERMListener(OsSubsystem os) {
+ mOS = os;
+ }
+
+ public void process() {
+ System.out.println("SIGTERMListener process");
+ // XXX - temp, should call shutdown
+ System.exit(0);
+ //PKIServer.getPKIServer().shutdown();
+ }
+}
+
+
+class SIGINTListener extends SignalListener {
+ private OsSubsystem mOS;
+ public SIGINTListener(OsSubsystem os) {
+ mOS = os;
+ }
+
+ public void process() {
+ System.out.println("SIGINTListener process");
+ // XXX - temp, should call shutdown
+ System.exit(0);
+ //PKIServer.getPKIServer().shutdown();
+ }
+}
+
+
+class SIGHUPListener extends SignalListener {
+ private OsSubsystem mOS;
+ public SIGHUPListener(OsSubsystem os) {
+ mOS = os;
+ }
+
+ public void process() {
+ System.out.println("SIGHUPListener process");
+ // XXX - temp, should call shutdown
+ // System.exit(0);
+ //PKIServer.getPKIServer().shutdown();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java b/pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java
new file mode 100644
index 000000000..ed268df46
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java
@@ -0,0 +1,162 @@
+// --- 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.util;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import java.security.*;
+import java.security.cert.*;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.crypto.PBEAlgorithm;
+import org.mozilla.jss.pkcs12.*;
+import org.mozilla.jss.pkix.primitive.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.*;
+
+
+public class PFXUtils {
+
+ /**
+ * Creates a PKCS12 package.
+ */
+ public static byte[] createPFX(String pwd, X509Certificate x509cert,
+ byte privateKeyInfo[]) throws EBaseException {
+ try {
+ // add certificate
+ SEQUENCE encSafeContents = new SEQUENCE();
+ ASN1Value cert = new OCTET_STRING(
+ x509cert.getEncoded());
+ byte localKeyId[] = createLocalKeyId(x509cert);
+ SET certAttrs = createBagAttrs(
+ x509cert.getSubjectDN().toString(), localKeyId);
+ // attributes: user friendly name, Local Key ID
+ SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
+ new CertBag(CertBag.X509_CERT_TYPE, cert),
+ certAttrs);
+
+ encSafeContents.addElement(certBag);
+
+ // add key
+ org.mozilla.jss.util.Password pass = new
+ org.mozilla.jss.util.Password(
+ pwd.toCharArray());
+
+ SEQUENCE safeContents = new SEQUENCE();
+ PasswordConverter passConverter = new
+ PasswordConverter();
+
+ // XXX - should generate salt
+ byte salt[] = {0x01, 0x01, 0x01, 0x01};
+ PrivateKeyInfo pki = (PrivateKeyInfo)
+ ASN1Util.decode(PrivateKeyInfo.getTemplate(),
+ privateKeyInfo);
+ ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
+ PBEAlgorithm.PBE_SHA1_DES3_CBC,
+ pass, salt, 1, passConverter, pki);
+ SET keyAttrs = createBagAttrs(
+ x509cert.getSubjectDN().toString(),
+ localKeyId);
+ SafeBag keyBag = new SafeBag(
+ SafeBag.PKCS8_SHROUDED_KEY_BAG, key,
+ keyAttrs); // ??
+
+ safeContents.addElement(keyBag);
+
+ // build contents
+ AuthenticatedSafes authSafes = new
+ AuthenticatedSafes();
+
+ authSafes.addSafeContents(safeContents);
+ authSafes.addSafeContents(encSafeContents);
+
+ // authSafes.addEncryptedSafeContents(
+ // authSafes.DEFAULT_KEY_GEN_ALG,
+ // pass, null, 1,
+ // encSafeContents);
+ PFX pfx = new PFX(authSafes);
+
+ pfx.computeMacData(pass, null, 5); // ??
+ ByteArrayOutputStream fos = new
+ ByteArrayOutputStream();
+
+ pfx.encode(fos);
+ pass.clear();
+
+ // put final PKCS12 into volatile request
+ return fos.toByteArray();
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Failed to create PKCS12 - " + e.toString()));
+ }
+ }
+
+ /**
+ * Creates local key identifier.
+ */
+ public static byte[] createLocalKeyId(X509Certificate cert)
+ throws EBaseException {
+ try {
+ byte certDer[] = cert.getEncoded();
+ MessageDigest md = MessageDigest.getInstance("SHA");
+
+ md.update(certDer);
+ return md.digest();
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Failed to create Key ID - " + e.toString()));
+ }
+ }
+
+ /**
+ * Creates bag attributes.
+ */
+ public static SET createBagAttrs(String nickName, byte localKeyId[])
+ throws EBaseException {
+ try {
+ SET attrs = new SET();
+ SEQUENCE nickNameAttr = new SEQUENCE();
+
+ nickNameAttr.addElement(SafeBag.FRIENDLY_NAME);
+ SET nickNameSet = new SET();
+
+ nickNameSet.addElement(new BMPString(nickName));
+ nickNameAttr.addElement(nickNameSet);
+ attrs.addElement(nickNameAttr);
+ SEQUENCE localKeyAttr = new SEQUENCE();
+
+ localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
+ SET localKeySet = new SET();
+
+ localKeySet.addElement(new OCTET_STRING(localKeyId));
+ localKeyAttr.addElement(localKeySet);
+ attrs.addElement(localKeyAttr);
+ return attrs;
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Failed to create Key Bag - " + e.toString()));
+ }
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java b/pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java
new file mode 100644
index 000000000..d7ba11c02
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java
@@ -0,0 +1,294 @@
+// --- 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.util;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * A class represents a internal subsystem. This subsystem
+ * can be loaded into cert server kernel to perform
+ * run time system profiling.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class ProfileSubsystem extends Frame implements ISubsystem, Runnable {
+
+ private String mId = null;
+ private Thread mMonitoring = new Thread(this);
+ private TextArea mTextArea = null;
+ private JScrollPane mThreads = null;
+ private JTable mThreadTable = null;
+ private JButton mGC = null;
+ private ThreadTableModel mThreadModel = null;
+
+ /**
+ * Constructs a certificate server.
+ */
+ public ProfileSubsystem() {
+ super();
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * Initializes this subsystem with the given
+ * configuration store.
+ * It first initializes resident subsystems,
+ * and it loads and initializes loadable
+ * subsystem specified in the configuration
+ * store.
+ * <P>
+ * Note that individual subsystem should be
+ * initialized in a separated thread if
+ * it has dependency on the initialization
+ * of other subsystems.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ JTabbedPane tabPane = new JTabbedPane();
+
+ // general panel
+ JPanel pane = new JPanel();
+
+ mTextArea = new TextArea();
+ // mTextArea.setSize(500, 180);
+ //mGC = new JButton("GC");
+ // pane.setLayout(new GridLayout(2, 1));
+ pane.add(mTextArea);
+ // pane.add(mGC);
+ mTextArea.setEditable(false);
+ tabPane.addTab("General", mTextArea);
+ tabPane.setSelectedIndex(0);
+
+ // thread panel
+ mThreadModel = new ThreadTableModel();
+ updateThreadPanel();
+ mThreadTable = new JTable(mThreadModel);
+ // table.setEditable(false);
+ mThreads = JTable.createScrollPaneForTable(mThreadTable);
+ tabPane.addTab("Threads", mThreads);
+
+ mThreadTable.addMouseListener(new ThreadTableEvent(mThreadTable));
+
+ add(tabPane);
+ setSize(500, 200);
+ setVisible(true);
+ mMonitoring.start();
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return null;
+ }
+
+ public void updateGeneralPanel() {
+ Runtime.getRuntime().gc();
+ String text =
+ "JDK VM Information " + "\n" +
+ "Total Memory: " +
+ Runtime.getRuntime().totalMemory() + "\n" +
+ "Used Memory: " +
+ (Runtime.getRuntime().totalMemory() -
+ Runtime.getRuntime().freeMemory()) + "\n" +
+ "Free Memory: " +
+ Runtime.getRuntime().freeMemory() + "\n" +
+ "Number of threads: " +
+ Thread.activeCount() + "\n";
+
+ mTextArea.setText(text);
+ }
+
+ public void updateThreadPanel() {
+ Thread currentThread = Thread.currentThread();
+ Vector data = new Vector();
+ Thread threads[] = new Thread[100];
+ int numThreads = Thread.enumerate(threads);
+
+ for (int i = 0; i < numThreads; i++) {
+ Vector row = new Vector();
+
+ row.addElement(threads[i].getName());
+ row.addElement(threads[i].getThreadGroup().getName());
+ row.addElement(Integer.toString(threads[i].getPriority()));
+ if (currentThread.getName().equals(threads[i].getName())) {
+ row.addElement("true");
+ } else {
+ row.addElement("false");
+ }
+ row.addElement(Boolean.toString(threads[i].isInterrupted()));
+ row.addElement(Boolean.toString(threads[i].isDaemon()));
+ data.addElement(row);
+ }
+
+ Vector colNames = new Vector();
+
+ colNames.addElement("Name");
+ colNames.addElement("Group");
+ colNames.addElement("Priority");
+ colNames.addElement("isCurrent");
+ colNames.addElement("isInterrupted");
+ colNames.addElement("isDaemon");
+
+ mThreadModel.setInfo(data, colNames);
+ if (mThreadTable != null) {
+ mThreadTable.setModel(mThreadModel);
+ mThreadTable.updateUI();
+ }
+ }
+
+ public void run() {
+ while (true) {
+ // To get exact memory statistics
+ try {
+ updateGeneralPanel();
+ updateThreadPanel();
+ // update every second
+ mMonitoring.sleep(1000);
+ } catch (Exception e) {
+ }
+ }
+ }
+}
+
+
+class ThreadTableModel extends AbstractTableModel {
+ Vector rowData;
+ Vector columnNames;
+
+ public ThreadTableModel() {
+ }
+
+ public void setInfo(Vector _rowData, Vector _columnNames) {
+ rowData = _rowData;
+ columnNames = _columnNames;
+ }
+
+ public String getColumnName(int column) {
+ return columnNames.elementAt(column).toString();
+ }
+
+ public int getRowCount() {
+ return rowData.size();
+ }
+
+ public int getColumnCount() {
+ return columnNames.size();
+ }
+
+ public Object getValueAt(int row, int column) {
+ return ((Vector) rowData.elementAt(row)).elementAt(column);
+ }
+
+ public boolean isCellEditable(int row, int column) {
+ return false;
+ }
+
+ public void setValueAt(Object value, int row, int column) {
+ ((Vector) rowData.elementAt(row)).setElementAt(value, column);
+ fireTableCellUpdated(row, column);
+ }
+}
+
+
+class ThreadTableEvent extends MouseAdapter {
+
+ private JTable mThreadTable = null;
+
+ public ThreadTableEvent(JTable table) {
+ mThreadTable = table;
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ int row = mThreadTable.getSelectedRow();
+
+ if (row != -1) {
+ String name = (String) mThreadTable.getValueAt(row, 0);
+ JDialog dialog = new JDialog();
+ JTextArea field = new JTextArea();
+ JScrollPane pane = new JScrollPane(field);
+
+ field.setEditable(false);
+
+ // get stack trace
+ Thread threads[] = new Thread[100];
+ int numThreads = Thread.enumerate(threads);
+
+ ByteArrayOutputStream outArray = new ByteArrayOutputStream();
+
+ for (int i = 0; i < numThreads; i++) {
+ if (!threads[i].getName().equals(name))
+ continue;
+ PrintStream err = System.err;
+
+ System.setErr(new PrintStream(outArray));
+ threads[i].dumpStack(); // not working, print only current thread
+ System.setErr(err);
+ }
+
+ String str = outArray.toString();
+
+ field.setText(str);
+ dialog.setTitle(name);
+ dialog.setSize(500, 400);
+ dialog.setVisible(true);
+
+ dialog.setContentPane(pane);
+ dialog.show();
+ }
+ }
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java b/pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java
new file mode 100644
index 000000000..ba07b2ca0
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java
@@ -0,0 +1,210 @@
+// --- 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.util;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.util.*;
+import com.netscape.certsrv.apps.*;
+
+/**
+ * A class represents a internal subsystem. This subsystem
+ * can be loaded into cert server kernel to perform
+ * statistics collection.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class StatsSubsystem implements IStatsSubsystem
+{
+ private String mId = null;
+ private StatsEvent mAllTrans = new StatsEvent(null);
+ private Date mStartTime = new Date();
+ private Hashtable mHashtable = new Hashtable();
+
+ /**
+ * Constructs a certificate server.
+ */
+ public StatsSubsystem() {
+ super();
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * Initializes this subsystem with the given
+ * configuration store.
+ * It first initializes resident subsystems,
+ * and it loads and initializes loadable
+ * subsystem specified in the configuration
+ * store.
+ * <P>
+ * Note that individual subsystem should be
+ * initialized in a separated thread if
+ * it has dependency on the initialization
+ * of other subsystems.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException
+ {
+ }
+
+ public Date getStartTime()
+ {
+ return mStartTime;
+ }
+
+ public void startTiming(String id)
+ {
+ startTiming(id, false /* not the main */);
+ }
+
+ public void startTiming(String id, boolean mainAction)
+ {
+ Thread t = Thread.currentThread();
+ Vector milestones = null;
+ if (mHashtable.containsKey(t.toString())) {
+ milestones = (Vector)mHashtable.get(t.toString());
+ } else {
+ milestones = new Vector();
+ mHashtable.put(t.toString(), milestones);
+ }
+ long startTime = CMS.getCurrentDate().getTime();
+ StatsEvent currentST = null;
+ for (int i = 0; i < milestones.size(); i++) {
+ StatsMilestone se = (StatsMilestone)milestones.elementAt(i);
+ if (currentST == null) {
+ currentST = mAllTrans.getSubEvent(se.getId());
+ } else {
+ currentST = currentST.getSubEvent(se.getId());
+ }
+ }
+ if (currentST == null) {
+ if (!mainAction) {
+ return; /* ignore none main action */
+ }
+ currentST = mAllTrans;
+ }
+ StatsEvent newST = currentST.getSubEvent(id);
+ if (newST == null) {
+ newST = new StatsEvent(currentST);
+ newST.setName(id);
+ currentST.addSubEvent(newST);
+ }
+ milestones.addElement(new StatsMilestone(id, startTime, newST));
+ }
+
+ public void endTiming(String id)
+ {
+ long endTime = CMS.getCurrentDate().getTime();
+ Thread t = Thread.currentThread();
+ if (!mHashtable.containsKey(t.toString())) {
+ return; /* error */
+ }
+ Vector milestones = (Vector)mHashtable.get(t.toString());
+ if (milestones.size() == 0) {
+ return; /* error */
+ }
+ StatsMilestone last = (StatsMilestone)milestones.remove(milestones.size() - 1);
+ StatsEvent st = last.getStatsEvent();
+ st.incNoOfOperations(1);
+ st.incTimeTaken(endTime - last.getStartTime());
+ if (milestones.size() == 0) {
+ mHashtable.remove(t.toString());
+ }
+ }
+
+ public void resetCounters()
+ {
+ mStartTime = CMS.getCurrentDate();
+ mAllTrans.resetCounters();
+ }
+
+ public StatsEvent getMainStatsEvent()
+ {
+ return mAllTrans;
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return null;
+ }
+}
+
+class StatsMilestone
+{
+ private String mId = null;
+ private long mStartTime = 0;
+ private StatsEvent mST = null;
+
+ public StatsMilestone(String id, long startTime, StatsEvent st)
+ {
+ mId = id;
+ mStartTime = startTime;
+ mST = st;
+ }
+
+ public String getId()
+ {
+ return mId;
+ }
+
+ public long getStartTime()
+ {
+ return mStartTime;
+ }
+
+ public StatsEvent getStatsEvent()
+ {
+ return mST;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java b/pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java
new file mode 100644
index 000000000..e9b2a6cdd
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java
@@ -0,0 +1,179 @@
+// --- 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.util;
+
+
+import com.netscape.certsrv.base.MessageFormatter;
+import java.util.Locale;
+
+
+/**
+ * This object is used to easily create I18N messages for utility
+ * classes and standalone programs.
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.base.MessageFormatter
+ * @see com.netscape.cmscore.util.UtilResources
+ */
+public class UtilMessage {
+
+ protected Object mParams[] = null;
+
+ private String mMessage = null;
+
+ /**
+ * The bundle name for this event.
+ */
+ static String mBundleName = UtilResources.class.getName();
+
+ /**
+ * Constructs a message event
+ * <P>
+ *
+ * @param msgFormat the message string
+ */
+ public UtilMessage(String msgFormat) {
+ mMessage = msgFormat;
+ mParams = null;
+ }
+
+ /**
+ * Constructs a message with a parameter. For example,
+ * <PRE>
+ * new UtilMessage("failed to load {0}", fileName);
+ * </PRE>
+ * <P>
+ *
+ * @param msgFormat details in message string format
+ * @param param message string parameter
+ */
+ public UtilMessage(String msgFormat, String param) {
+ this(msgFormat);
+ mParams = new String[1];
+ mParams[0] = param;
+ }
+
+ /**
+ * Constructs a message from an exception. It can be used to carry
+ * a system exception that may contain information about
+ * the context. For example,
+ * <PRE>
+ * try {
+ * ...
+ * } catch (IOExeption e) {
+ * out.println(new UtilMessage("Encountered System Error {0}", e);
+ * }
+ * </PRE>
+ * <P>
+ *
+ * @param msgFormat exception details in message string format
+ * @param exception system exception
+ */
+ public UtilMessage(String msgFormat, Exception exception) {
+ this(msgFormat);
+ mParams = new Exception[1];
+ mParams[0] = exception;
+ }
+
+ /**
+ * Constructs a message from a base exception. This will use the msgFormat
+ * from the exception itself.
+ * <PRE>
+ * try {
+ * ...
+ * } catch (Exception e) {
+ * System.out.println(new UtilMessage(e));
+ * }
+ * </PRE>
+ * <P>
+ *
+ * @param exception CMS exception
+ */
+ public UtilMessage(Exception e) {
+ this(e.getMessage());
+ mParams = new Exception[1];
+ mParams[0] = e;
+ }
+
+ /**
+ * Constructs a message event with a list of parameters
+ * that will be substituted into the message format.
+ * <P>
+ *
+ * @param msgFormat message string format
+ * @param params list of message format parameters
+ */
+ public UtilMessage(String msgFormat, Object params[]) {
+ this(msgFormat);
+ mParams = params;
+ }
+
+ /**
+ * Returns the current message format string.
+ * <P>
+ *
+ * @return details message
+ */
+ public String getMessage() {
+ return mMessage;
+ }
+
+ /**
+ * Returns a list of parameters.
+ * <P>
+ *
+ * @return list of message format parameters
+ */
+ public Object[] getParameters() {
+ return mParams;
+ }
+
+ /**
+ * Returns localized message string. This method should
+ * only be called if a localized string is necessary.
+ * <P>
+ *
+ * @return details message
+ */
+ public String toString() {
+ return toString(Locale.getDefault());
+ }
+
+ /**
+ * Returns the string based on the given locale.
+ * <P>
+ *
+ * @param locale locale
+ * @return details message
+ */
+ public String toString(Locale locale) {
+ return MessageFormatter.getLocalizedString(locale, getBundleName(),
+ getMessage(),
+ getParameters());
+ }
+
+ /**
+ * Gets the resource bundle name for this class instance. This should
+ * be overridden by subclasses who have their own resource bundles.
+ */
+ protected String getBundleName() {
+ return mBundleName;
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/UtilResources.java b/pki/base/common/src/com/netscape/cmscore/util/UtilResources.java
new file mode 100644
index 000000000..8114413b0
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/UtilResources.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.util;
+
+
+import java.util.*;
+
+
+/**
+ * A class represents a resource bundle for miscellanous utilities
+ * <P>
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ * @see java.util.ListResourceBundle
+ */
+public class UtilResources extends ListResourceBundle {
+
+ /**
+ * Returns the content of this resource.
+ */
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ /**
+ * Constants. The suffix represents the number of
+ * possible parameters.
+ */
+ public final static String HASH_FILE_CHECK_USAGE = "hashFileCheckUsage";
+ public final static String BAD_ARG_COUNT = "badArgCount";
+ public final static String NO_SUCH_FILE_1 = "noSuchFile";
+ public final static String DIGEST_MATCH_1 = "digestMatch";
+ public final static String DIGEST_DONT_MATCH_1 = "digestDontMatch";
+ public final static String FILE_TRUNCATED = "fileTruncated";
+ public final static String EXCEPTION_1 = "exception";
+ public final static String LOG_PASSWORD = "logPassword";
+ public final static String NO_USERID = "noUserId";
+ public final static String NO_SUCH_USER_2 = "noSuchUser";
+ public final static String NO_UID_PERMISSION_2 = "noUidPermission";
+ public final static String SHUTDOWN_SIG = "shutdownSignal";
+ public final static String RESTART_SIG = "restartSignal";
+
+ static final Object[][] contents = {
+ {HASH_FILE_CHECK_USAGE, "usage: HashFileCheck <filename>"},
+ {BAD_ARG_COUNT, "incorrect number of arguments"},
+ {NO_SUCH_FILE_1, "can''t find file {0}"},
+ {FILE_TRUNCATED, "Log file has been truncated."},
+ {DIGEST_MATCH_1, "Hash digest matches log file. {0} OK"},
+ {DIGEST_DONT_MATCH_1, "Hash digest does NOT match log file. {0} and/or hash file is corrupt or the password is incorrect."},
+ {EXCEPTION_1, "Caught unexpected exception {0}"},
+ {LOG_PASSWORD, "Please enter the log file hash digest password: "},
+ {NO_USERID, "No user id in config file. Running as {0}"},
+ {NO_SUCH_USER_2, "No such user as {0}. Running as {1}"},
+ {NO_UID_PERMISSION_2, "Can''t change process uid to {0}. Running as {1}"},
+ {SHUTDOWN_SIG, "Received shutdown signal"},
+ {RESTART_SIG, "Received restart signal"},
+ };
+}