ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts/*
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the Common Development and Distribution License
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the License). You may not use this file except in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * compliance with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the License at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * opensso/legal/CDDLv1.0.txt
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * permission and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Header Notice in each file and include the License file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * at opensso/legal/CDDLv1.0.txt.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below the CDDL Header,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the fields enclosed by brackets [] replaced by
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * your own identifying information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * $Id: Stats.java,v 1.5 2008/08/08 00:40:59 ww203982 Exp $
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts * Portions Copyrighted 2016 ForgeRock AS.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpackage com.sun.identity.shared.stats;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpottsimport static org.forgerock.openam.utils.Time.*;
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.common.SystemTimer;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.shared.Constants;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.shared.configuration.SystemPropertiesManager;
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Lunaimport org.forgerock.util.thread.listener.ShutdownListener;
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Lunaimport org.forgerock.util.thread.listener.ShutdownManager;
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.BufferedWriter;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.File;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.FileOutputStream;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.IOException;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.OutputStreamWriter;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.PrintWriter;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.StringWriter;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.text.DateFormat;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.text.SimpleDateFormat;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.Date;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.HashMap;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.Map;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.MissingResourceException;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.ResourceBundle;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster// NOTE: Since JVM specs guarantee atomic access/updates to int variables
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster// (actually all variables except double and long), the design consciously
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster// avoids synchronized methods, particularly for message(). This is done to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster// reduce the performance overhead of synchronized message() when statistics
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster// is disabled. This does not have serious side-effects other than an occasional
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster// invocation of message() missing concurrent update of 'statsState'.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster/*******************************************************************************
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Allows a uniform interface to statistics information in a uniform format.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>Stats</code> supports different states of filing stats information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>OFF</code>, <code>FILE</code> and <code>CONSOLE</code>. <BR>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <li> <code>OFF</code> statistics is turned off.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <li> <code>FILE</code> statistics information is written to a file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <li> <code>CONSOLE</code> statistics information is written on console
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Stats service uses the property file, <code>AMConfig.properties</code>, to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * set the default stats level and the output directory where the stats files
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * will be placed. The properties file is located (using
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@link java.util.ResourceBundle} semantics) from one of the directories in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the CLASSPATH.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The following keys are used to configure the Stats service. Possible values
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * for the key 'state' are: off | off | file | console The key 'directory'
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * specifies the output directory where the stats files will be created.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <blockquote>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <pre>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * com.iplanet.services.stats.state
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * com.iplanet.services.stats.directory
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </pre>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </blockquote>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If there is an error reading or loading the properties, all the information
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is redirected to <code>System.out</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If these properties are changed, the server must be restarted for the changes
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * to take effect.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <b>NOTE:</b> Printing Statistics is an IO intensive operation and may hurt
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * application performance when abused. Particularly, note that Java evaluates
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the arguments to <code>message()</code> and <code>warning()</code> even
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * when statistics is turned off. It is recommended that the stats state be
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * checked before invoking any <code>message()</code> or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>warning()</code> methods to avoid unnecessary argument evaluation and
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * to maximize application performance.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @supported.all.api
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpublic class Stats implements ShutdownListener {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /** flags the disabled stats state. */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static final int OFF = 0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Flags the state where all the statistic information is printed to a file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static final int FILE = 1;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Flags the state where printing to a file is disabled. All printing is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * done on System.out.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static final int CONSOLE = 2;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * statsMap is a container of all active Stats objects. Log file name is the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * key and Stats is the value of this map.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static Map statsMap = new HashMap();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /** serviceInitialized indicates if the service is already initialized. */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static boolean serviceInitialized = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static DateFormat dateFormat;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The default stats level for the entire service and the level that is used
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * when a Stats object is first created and before its level is modified.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Don't initialize the following two variables in a static
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * initializer/block because other components may initialize Stats in their
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * static initializers (as opposed to constructors or methods). The order of
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * execution of static blocks is not guaranteed by JVM. So if we set the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * following two static variables to some default values here, then it will
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * interfere with the execution of {@link #initService}.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String defaultStatsLevel;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String outputDirectory;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private final String statsName;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private PrintWriter statsFile = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private int statsState;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static StatsRunner statsListeners = new StatsRunner();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Initializes the Stats service so that Stats objects can be created. At
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * startup (when the first Stats object is ever created in a JVM), this
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * method reads <code>AMConfig.properties</code> file (using
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@link java.util.ResourceBundle} semantics) from one of the directories
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * in the <code>CLASSPATH</code>, and loads the properties. It creates
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the stats directory. If all the directories in output dir don't have
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * adequate permissions then the creation of the stats directory will fail
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * and all the stats files will be located in the "current working
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * directory" of the process running stats code. If there is an error
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * reading or loading the properties, it will set the stats service to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * redirect all stats information to <code>System.out</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static void initService() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /*
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * We will use the double-checked locking pattern. Rarely entered block.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Push synchronization inside it. This is the first check.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!serviceInitialized) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /*
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Only 1 thread at a time gets past the next point. Rarely executed
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * synchronization statement and hence synchronization penalty is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * not paid every time this method is called.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized (Stats.class) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /*
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If a second thread was waiting to get here, it will now find
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * that the instance has already been initialized, and it will
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * not re-initialize the instance variable. This is the (second)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * double-check.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!serviceInitialized) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster dateFormat = new SimpleDateFormat(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "MM/dd/yyyy hh:mm:ss:SSS a zzz");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster defaultStatsLevel = SystemPropertiesManager.get(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Constants.SERVICES_STATS_STATE);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster outputDirectory = SystemPropertiesManager.get(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Constants.SERVICES_STATS_DIRECTORY);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ResourceBundle bundle =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster com.sun.identity.shared.locale.Locale
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster .getInstallResourceBundle("amUtilMsgs");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (outputDirectory != null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster File createDir = new File(outputDirectory);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!createDir.exists()) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!createDir.mkdirs()) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster System.err.println(bundle.getString(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "com.iplanet.services.stats.nodir"));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } catch (MissingResourceException e) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster System.err.println(e.getMessage());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster e.printStackTrace();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // If there is any error in getting the level or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // outputDirectory, defaultStatsLevel will be set to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // ON so that output will go to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // System.out
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster defaultStatsLevel = "console";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster outputDirectory = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } catch (SecurityException se) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster System.err.println(se.getMessage());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SystemTimer.getTimer().schedule(statsListeners, new Date(((
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts currentTimeMillis() +
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts statsListeners.getRunPeriod()) / 1000) * 1000));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster serviceInitialized = true;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This constructor takes as an argument the name of the stats file. The
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * stats file is neither created nor opened until the first time
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>message()</code>, <code>warning()</code> or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>error()</code> is invoked and the stats state is neither
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>OFF</code> nor <code>ON</code>.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <b>NOTE:</b>The recommended and preferred method to create Stats objects
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is <code>getInstance(String)</code>. This constructor may be
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * deprecated in future.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna * @param statsName name of the stats file to create or use
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private Stats(String statsName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Initialize the stats service the first time a Stats object is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // created.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster initService();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Now initialize this instance itself
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster this.statsName = statsName;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster setStats(defaultStatsLevel);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized (statsMap) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // explicitly ignore any duplicate instances.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsMap.put(statsName, this);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna ShutdownManager shutdownMan = com.sun.identity.common.ShutdownManager.getInstance();
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna shutdownMan.addShutdownListener(this);
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns an existing instance of Stats for the specified stats file or a
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * new one if no such instance already exists. If a Stats object has to be
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * created, its level is set to the level defined in the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>AMConfig.properties</code> file. The level can be changed later
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * by using {@link #setStats(int)} or {@link #setStats(String)}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param statsName
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * name of statistic instance.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return an existing instance of Stats for the specified stats file.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static synchronized Stats getInstance(String statsName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Stats statsObj = (Stats) statsMap.get(statsName);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsObj == null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsObj = new Stats(statsName);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return statsObj;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Checks if statistics is enabled.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <b>NOTE:</b> It is recommended that <code>isEnabled()</code> be used
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * instead of <code>isEnabled()</code> as the former is more intuitive.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return <code>true</code> if statistics is enabled <code>false</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * if statistics is disabled
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public boolean isEnabled() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return (statsState > Stats.OFF);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns one of the 3 possible values.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <ul>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <li><code>Stats.OFF</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <li><code>Stats.FILE</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <li><code>Stats.CONSOLE</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </ul>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return state of Stats.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public int getState() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return statsState;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Prints messages only when the stats state is either
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>Stats.FILE</code> or <code>Stats.CONSOLE</code>.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <b>NOTE:</b> Printing Statistics is an IO intensive operation and may
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * hurt application performance when abused. Particularly, note that Java
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * evaluates arguments to <code>message()</code> even when statistics is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * turned off. So when the argument to this method involves the String
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * concatenation operator '+' or any other method invocation,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>isEnabled</code> <b>MUST</b> be used. It is recommended that the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * stats state be checked by invoking <code>isEnabled()</code> before
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * invoking any <code>message()</code> methods to avoid unnecessary
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * argument evaluation and maximize application performance.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param msg
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * message to be recorded.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void record(String msg) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsState > Stats.OFF) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster formatAndWrite(null, msg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void formatAndWrite(String prefix, String msg) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsState == Stats.CONSOLE) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (msg != null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (prefix == null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster System.out.println(msg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster System.out.println(prefix + msg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // The default capacity of StringBuffer in StringWriter is 16, but we
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // know for sure that the minimum header size is about 35. Hence, to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // avoid reallocation allocate at least 160 chars.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String serverInstance = System.getProperty("server.name");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster StringWriter swriter = new StringWriter(160);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster PrintWriter buf = new PrintWriter(swriter, true);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized (dateFormat) {
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts buf.write(dateFormat.format(newDate()));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((serverInstance != null) && (serverInstance != "")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write(": ");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write("Server Instance: " + serverInstance);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write(": ");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write(Thread.currentThread().toString());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write("\n");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (prefix != null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write(prefix);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (msg != null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.write(msg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster buf.flush();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster write(swriter.toString());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Actually writes to the stats file. If it cannot write to the stats file,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * it turn off statistics. The first time this method is invoked on a Stats
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * object, that object's stats file is created/opened in the directory
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * specified by the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>property com.iplanet.services.stats.directory</code> in the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * properties file, <code>AMConfig.properties</code>.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private synchronized void write(String msg) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // statistics is enabled.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // First, see if the statsFile is already open. If not, open it now.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsFile == null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // open file in append mode
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster FileOutputStream fos = new FileOutputStream(outputDirectory
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + File.separator + statsName, true);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsFile = new PrintWriter(new BufferedWriter(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster new OutputStreamWriter(fos, "UTF-8")), true);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsFile.println("*********************************" +
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "*********************");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsFile.println(msg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } catch (IOException e) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster System.err.println(msg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // turn off statistics because statsFile is not accessible
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.OFF;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Sets the stats capabilities based on the values of the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>statsType</code> argument.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param statsType
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is any one of five possible values:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>Stats.OFF</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>Stats.FILE</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>Stats.CONSOLE</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void setStats(int statsType) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster switch (statsType) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case Stats.OFF:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case Stats.FILE:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case Stats.CONSOLE:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = statsType;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster break;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster default:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // ignore invalid statsType values
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster break;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Sets the <code>stats</code> capabilities based on the values of the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>statsType</code> argument.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param statsType
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is any one of the following possible values:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * off - statistics is disabled
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * file - statistics are written to the stats file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>System.out</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * console - statistics are written to the stats to the console
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void setStats(String statsType) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsType == null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (statsType.equalsIgnoreCase("console")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.CONSOLE;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (statsType.equalsIgnoreCase("file")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.FILE;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (statsType.equalsIgnoreCase("off")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.OFF;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (statsType.equals("*")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.CONSOLE;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsType.endsWith("*")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsType = statsType.substring(0, statsType.length() - 1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsName.startsWith(statsType)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.CONSOLE;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Destroys the stats object, closes the stats file and releases any system
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * resources. Note that the stats file will remain open until
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>destroy()</code> is invoked. To conserve file resources, you
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * should invoke <code>destroy()</code> explicitly rather than wait for
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the garbage collector to clean up.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If this object is accessed after <code>destroy()</code> has been
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * invoked, the results are undefined.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * </p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void destroy() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster finalize();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void shutdown() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster finalize();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /** Flushes and then closes the stats file. */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster protected void finalize() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized (statsMap) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsMap.remove(statsName);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized (this) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (statsFile == null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsState = Stats.OFF;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsFile.flush();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsFile.close();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsFile = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void addStatsListener(StatsListener listener) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster statsListeners.addElement(listener);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster}