diff options
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/util')
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..5edc44621 --- /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 00660 " + 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..82a83b6da --- /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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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..0acff36bf --- /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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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..2e595a22d --- /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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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..6bbb8ff08 --- /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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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..353f50012 --- /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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + * @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..912f460a2 --- /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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + * @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"}, + }; +} |