From 26b4ed670b319a5922d479e156ef9ab2acf86913 Mon Sep 17 00:00:00 2001 From: David Dykstal Date: Mon, 10 Apr 2006 20:17:09 +0000 Subject: [PATCH] initial population --- .../org.eclipse.rse.logging/.classpath | 7 + .../org.eclipse.rse.logging/.cvsignore | 1 + rse/plugins/org.eclipse.rse.logging/.project | 28 + .../org.eclipse.rse.logging/HelpContexts.xml | 26 + .../META-INF/MANIFEST.MF | 14 + .../RemoteSystemsLogging.properties | 32 + .../org.eclipse.rse.logging/about.html | 22 + .../org.eclipse.rse.logging/build.properties | 24 + .../org.eclipse.rse.logging/plugin.properties | 26 + .../org.eclipse.rse.logging/plugin.xml | 37 + .../rse/internal/logging/LabelUtil.java | 162 ++++ .../internal/logging/LoggerController.java | 60 ++ .../logging/RemoteSystemLogListener.java | 191 +++++ .../org/eclipse/rse/logging/Activator.java | 70 ++ .../rse/logging/IRemoteSystemsLogging.java | 79 ++ .../src/org/eclipse/rse/logging/Logger.java | 273 +++++++ .../eclipse/rse/logging/LoggerFactory.java | 66 ++ .../logging/LoggingPreferenceInitializer.java | 39 + .../rse/logging/LoggingPreferencePage.java | 354 +++++++++ .../logging/RemoteSystemsLoggingPlugin.java | 128 +++ .../performance/PerformanceLogger.java | 739 ++++++++++++++++++ .../style/performancelogtohtml.xsl | 36 + 22 files changed, 2414 insertions(+) create mode 100644 rse/plugins/org.eclipse.rse.logging/.classpath create mode 100644 rse/plugins/org.eclipse.rse.logging/.cvsignore create mode 100644 rse/plugins/org.eclipse.rse.logging/.project create mode 100644 rse/plugins/org.eclipse.rse.logging/HelpContexts.xml create mode 100644 rse/plugins/org.eclipse.rse.logging/META-INF/MANIFEST.MF create mode 100644 rse/plugins/org.eclipse.rse.logging/RemoteSystemsLogging.properties create mode 100644 rse/plugins/org.eclipse.rse.logging/about.html create mode 100644 rse/plugins/org.eclipse.rse.logging/build.properties create mode 100644 rse/plugins/org.eclipse.rse.logging/plugin.properties create mode 100644 rse/plugins/org.eclipse.rse.logging/plugin.xml create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LabelUtil.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LoggerController.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/RemoteSystemLogListener.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Activator.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/IRemoteSystemsLogging.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Logger.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggerFactory.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferenceInitializer.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferencePage.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/RemoteSystemsLoggingPlugin.java create mode 100644 rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/performance/PerformanceLogger.java create mode 100644 rse/plugins/org.eclipse.rse.logging/style/performancelogtohtml.xsl diff --git a/rse/plugins/org.eclipse.rse.logging/.classpath b/rse/plugins/org.eclipse.rse.logging/.classpath new file mode 100644 index 00000000000..751c8f2e504 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/rse/plugins/org.eclipse.rse.logging/.cvsignore b/rse/plugins/org.eclipse.rse.logging/.cvsignore new file mode 100644 index 00000000000..ba077a4031a --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/rse/plugins/org.eclipse.rse.logging/.project b/rse/plugins/org.eclipse.rse.logging/.project new file mode 100644 index 00000000000..993758daff0 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/.project @@ -0,0 +1,28 @@ + + + org.eclipse.rse.logging + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/rse/plugins/org.eclipse.rse.logging/HelpContexts.xml b/rse/plugins/org.eclipse.rse.logging/HelpContexts.xml new file mode 100644 index 00000000000..44abfd5c409 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/HelpContexts.xml @@ -0,0 +1,26 @@ + + + + + + + + Settings for the logging of messages. + + + + \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.logging/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..8e739811f25 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/META-INF/MANIFEST.MF @@ -0,0 +1,14 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %plugin.name +Bundle-SymbolicName: org.eclipse.rse.logging;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: org.eclipse.rse.logging.RemoteSystemsLoggingPlugin +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime +Eclipse-LazyStart: true +Export-Package: org.eclipse.rse.logging, + org.eclipse.rse.logging.performance +Bundle-Vendor: Eclipse.org +Bundle-ClassPath: systemslogging.jar diff --git a/rse/plugins/org.eclipse.rse.logging/RemoteSystemsLogging.properties b/rse/plugins/org.eclipse.rse.logging/RemoteSystemsLogging.properties new file mode 100644 index 00000000000..02c1b15ebc5 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/RemoteSystemsLogging.properties @@ -0,0 +1,32 @@ +################################################################################ +# Copyright (c) 2006 IBM Corporation. All rights reserved. +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License v1.0 which accompanies this distribution, and is +# available at http://www.eclipse.org/legal/epl-v10.html +# +# Initial Contributors: +# The following IBM employees contributed to the Remote System Explorer +# component that contains this file: David McKnight, Kushal Munir, +# Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, +# Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. +# +# Contributors: +# {Name} (company) - description of contribution. +################################################################################ + +# ===================================== +# Remote System Logging properties file +# ===================================== +# NLS_MESSAGEFORMAT_NONE + +# Preference Page +# ---------------- +LoggingPreferencePage.topLabel1 = Specify the logging options for {0} +LoggingPreferencePage.topLabel2 = Logging Level: +LoggingPreferencePage.errors_only = Errors only +LoggingPreferencePage.warnings_errors = Warnings and errors +LoggingPreferencePage.info_debug = Warnings, errors and information messages +LoggingPreferencePage.full_debug = Full debug +LoggingPreferencePage.logging_location = Logging Location: +LoggingPreferencePage.log_to_file = Log to file (default) +LoggingPreferencePage.log_to_stdout = Log to Standard Out \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/about.html b/rse/plugins/org.eclipse.rse.logging/about.html new file mode 100644 index 00000000000..6f6b96c4c87 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/about.html @@ -0,0 +1,22 @@ + + + +About + + + +

About This Content

+ +

February 24, 2005

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content.

+ + + \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/build.properties b/rse/plugins/org.eclipse.rse.logging/build.properties new file mode 100644 index 00000000000..aecd1815b53 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/build.properties @@ -0,0 +1,24 @@ +bin.includes = HelpContexts.xml,\ + RemoteSystemsLogging.properties,\ + plugin.properties,\ + plugin.xml,\ + style/,\ + systemslogging.jar,\ + about.ini,\ + about.htm,\ + about.mappings,\ + about.properties,\ + about.html,\ + about.mappings,\ + about.properties,\ + META-INF/ +jars.compile.order = systemslogging.jar +source.systemslogging.jar = src/ +output.systemslogging.jar = bin/ +src.includes = HelpContexts.xml,\ + META-INF/,\ + RemoteSystemsLogging.properties,\ + about.html,\ + plugin.properties,\ + plugin.xml,\ + style/ diff --git a/rse/plugins/org.eclipse.rse.logging/plugin.properties b/rse/plugins/org.eclipse.rse.logging/plugin.properties new file mode 100644 index 00000000000..895b4fc982e --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/plugin.properties @@ -0,0 +1,26 @@ +################################################################################ +# Copyright (c) 2006 IBM Corporation. All rights reserved. +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License v1.0 which accompanies this distribution, and is +# available at http://www.eclipse.org/legal/epl-v10.html +# +# Initial Contributors: +# The following IBM employees contributed to the Remote System Explorer +# component that contains this file: David McKnight, Kushal Munir, +# Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, +# Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. +# +# Contributors: +# {Name} (company) - description of contribution. +################################################################################ + +# ================================================= +# Remote Systems logging plugin.xml properties file +# ================================================= + +# NLS_MESSAGEFORMAT_VAR + +plugin.name = RSE Logging + +Remote_Systems_Logging = Remote Systems Logging + diff --git a/rse/plugins/org.eclipse.rse.logging/plugin.xml b/rse/plugins/org.eclipse.rse.logging/plugin.xml new file mode 100644 index 00000000000..0a291c6a8f3 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/plugin.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LabelUtil.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LabelUtil.java new file mode 100644 index 00000000000..b990ebec946 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LabelUtil.java @@ -0,0 +1,162 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.internal.logging; + +import java.util.HashSet; +import java.util.Set; + +/** + * Provides a set of utility routines for processing mnemonics for labels that are + * to be used in dialogs and menus. + */ +public class LabelUtil { + + private final static String upperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private final static String lowerLetters = "abcdefghijklmnopqrstuvwxyz"; + private final static char lpar = '('; + private final static char rpar = ')'; + private final static char trigger = '&'; + + /** + * The Assignment class contains the result of a mnemonic assignment. + */ + private static class Assignment { + private String label; + private Character mnemonic; + Assignment(String label, Character mnemonic) { + this.label = label; + this.mnemonic = mnemonic; + } + String getLabel() { + return label; + } + Character getMnemonic() { + return mnemonic; + } + boolean hasMnemonic() { + return mnemonic != null; + } + } + + /** + * Assigns a mnemonic to a label and adds it to the set of used mnemonic characters. + * Used mnemonics are ignored in the search for a valid mnemonic. + * If there are no characters in the label that can be used as mnemonics then a + * valid mnemonic is appended to the label in parentheses. + * If the label already has a mnemonic, its mnemonic is added to the set of used + * mnemonics, but the label itself is unchanged. + * @param label the label in which the mnemonic is to be discovered + * @param used the set of Characters that cannot be used as mnemonics. This set is modified + * by the operation if a mnemonic could be found. + * @return the label with the mnemonic identified or the original label if a mnemonic could + * not be found. + */ + public static String assignMnemonic(String label, Set used) { + Assignment result = null; + Character c = findMnemonic(label); + if (c != null) { + used.add(c); + return label; + } + result = assignMnemonic(label, upperLetters, used); + if (!result.hasMnemonic()) { + result = assignMnemonic(label, lowerLetters, used); + if (!result.hasMnemonic()) { + Assignment temp = assignMnemonic(upperLetters, upperLetters, used); + if (temp.hasMnemonic()) { + c = temp.getMnemonic(); + StringBuffer b = new StringBuffer(label.length() + 4); + b.append(label); + b.append(lpar); + b.append(trigger); + b.append(c); + b.append(rpar); + result = new Assignment(b.toString(), c); + } + } + } + if (result.hasMnemonic()) { + Character mnemonic = result.getMnemonic(); + Character lower = new Character(Character.toLowerCase(mnemonic.charValue())); + Character upper = new Character(Character.toUpperCase(mnemonic.charValue())); + used.add(lower); + used.add(upper); + + } + return result.getLabel(); + } + + /** + * This is a convenience method for constucting a "used set" by taking + * the individual characters of a string + * in both lower and upper cases and adding them to the set. Mnemonics are + * not case sensitive. + * @param s the String from which to construct the set. + * @return the set. + */ + public static Set usedFromString(String s) { + Set result = new HashSet(); + char[] characters = s.toLowerCase().toCharArray(); + for (int i = 0; i < characters.length; i++) { + result.add(new Character(characters[i])); + } + characters = s.toUpperCase().toCharArray(); + for (int i = 0; i < characters.length; i++) { + result.add(new Character(characters[i])); + } + return result; + } + + /** + * Assigns a mnemonic to a label from a List of candidate mnemonics. + * @param label the label in which the mnemonic is to be discovered. + * @param candidates the String of valid candidates to use as mnemonics. + * @param used The Set of Characters that have already been used. + * @return the Assignment containing the new string with the mnemonic identified. If no + * mnemonic could be assigned then the Assignment will have no mnemonic specified. + */ + private static Assignment assignMnemonic(String label, String candidates, Set used) { + char[] characters = label.toCharArray(); + Assignment result = new Assignment(label, null); + for (int i = 0; i < characters.length && !result.hasMnemonic(); i++) { + Character c = new Character(characters[i]); + if (!used.contains(c) && candidates.indexOf(c.charValue()) >= 0) { + StringBuffer b = new StringBuffer(label.length() + 1); + b.append(label.substring(0, i)); + b.append(trigger); + b.append(label.substring(i)); + result = new Assignment(b.toString(), c); + } + } + return result; + } + + /** + * Finds the Character used as a mnemonic in a label + * @param label the label to search + * @return the Character used as the mnemonic, null if none exists. + */ + private static Character findMnemonic(String label) { + Character result = null; + int i = label.indexOf(trigger); + if (i >=0 && i < label.length() - 1) { + result = new Character(label.charAt(i + 1)); + } + return result; + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LoggerController.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LoggerController.java new file mode 100644 index 00000000000..e1d6b22cde1 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/LoggerController.java @@ -0,0 +1,60 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.internal.logging; + +import java.util.Hashtable; + +import org.eclipse.rse.logging.Logger; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +public class LoggerController { + + public static final String Copyright = + "(C) Copyright IBM Corp. 2002, 2003. All Rights Reserved."; + + private static Hashtable pluginTable = new Hashtable(); + + /** + * Return an previously cached Logger instance.
+ * It will return null if no Logger instance has been created + * for this plugin before. + */ + public static Logger getInst(AbstractUIPlugin plugin) { + if (pluginTable.containsKey(plugin)) + return (Logger) pluginTable.get(plugin); + else + return null; + } + + public static void registerInst(AbstractUIPlugin plugin, Logger logger) { + pluginTable.put(plugin, logger); + return; + } + + public static void freeInst(AbstractUIPlugin plugin) { + // get cached instance if one exists. + Logger logger = getInst(plugin); + // no luck, this means we have an incorrect free, do nothing. + if (logger == null) + return; + logger.freeResources(); + pluginTable.remove(plugin); + return; + + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/RemoteSystemLogListener.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/RemoteSystemLogListener.java new file mode 100644 index 00000000000..52d7fc12b3e --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/internal/logging/RemoteSystemLogListener.java @@ -0,0 +1,191 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.internal.logging; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.util.Date; + +import org.eclipse.core.runtime.ILogListener; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.rse.logging.IRemoteSystemsLogging; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +/** + * Log Listener is a sink for messages coming from Logger. + */ +public class RemoteSystemLogListener + implements ILogListener, IPropertyChangeListener { + + public static final String Copyright = + "(C) Copyright IBM Corp. 2002, 2003. All Rights Reserved."; + + private PrintWriter log = null; + private File outputFile = null; + private boolean log_to_stdout = false; + private AbstractUIPlugin plugin = null; + + public RemoteSystemLogListener(AbstractUIPlugin plugin) { + this.plugin = plugin; + IPath path = + plugin.getStateLocation().addTrailingSeparator().append(".log"); + + outputFile = path.toFile(); + + // make sure to delete old log file. + if ((outputFile != null) && (outputFile.exists())) { + outputFile.delete(); + } + + initialize(); + } + + private void initialize() { + try { + // Initialize log file location here. Check to see + // if we need to log to file or View. + IPreferenceStore store = plugin.getPreferenceStore(); + String log_location = + store.getString( + IRemoteSystemsLogging.LOG_LOCATION); + + if ((log_location != null) + && (log_location + .equalsIgnoreCase(IRemoteSystemsLogging.LOG_TO_STDOUT))) { + doLogToView(); + } else { + doLogToFile(); + } + } catch (Exception e) { + // can not log anything. + log = null; + System.err.println("Exception in RemoteSystemLogListener.initialize(): "+e.getMessage()); + e.printStackTrace(); + } + } + + private void doLogToView() { + // make sure we free resources first + freeResources(); + // log + log = new PrintWriter(System.out, true); + // cach last state + log_to_stdout = true; + } + + private void doLogToFile() throws Exception { + // make sure we free resources first + freeResources(); + // log + log = + new PrintWriter( + new BufferedWriter(new FileWriter(outputFile.toString(), true)), + true); + // cache last state + log_to_stdout = false; + } + + public void logging(IStatus status) { + if (log == null) + return; + else { + // Need a to string here, because we need to be able to compate dates. + String date = new Date().toString(); + log.println(date); + int severity = status.getSeverity(); + if (severity == IStatus.ERROR) { + log.print("ERROR"); + } else if (severity == IStatus.WARNING) { + log.print("WARNING"); + } else if (severity == IStatus.INFO) { + log.print("INFO"); + } else if (severity == IStatus.OK) { + log.print("DEBUG"); + } + + log.print(" "); + log.print(status.getPlugin()); + // removed for now because we do not use Error codes. + //log.print(" "); + //log.print(status.getCode()); + log.print(" "); + log.println(status.getMessage()); + if (status.getException() != null) + status.getException().printStackTrace(log); + if (status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for (int i = 0; i < children.length; i++) + loggingChild(children[i]); + } + log.println("--------------------------------------------"); + } + + } + + public void logging(IStatus status, String plugin) { + logging(status); + } + + /** + * @param tmp org.eclipse.core.runtime.IStatus + */ + private void loggingChild(IStatus status) { + if (log == null) + return; + else { + int severity = status.getSeverity(); + log.print("\t\t"); + log.println(status.getMessage()); + if (status.getException() != null) + status.getException().printStackTrace(log); + if (status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for (int i = 0; i < children.length; i++) + logging(children[i]); + } + } + } + + /** + * Handle changes from Preferences page. + */ + public synchronized void propertyChange(PropertyChangeEvent event) { + // refresh the log location from plugin Preference store + initialize(); + } + + public void freeResources() { + if (log == null) + return; + + // make sure to not close std_out. A closed stream can *not* + // br re-opened! + if (log_to_stdout) + return; + + log.flush(); + log.close(); + log = null; + + } +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Activator.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Activator.java new file mode 100644 index 00000000000..c61191dba11 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Activator.java @@ -0,0 +1,70 @@ +/******************************************************************************** + * Copyright (c) 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The main plugin class to be used in the desktop. + */ +public class Activator extends AbstractUIPlugin { + + //The shared instance. + private static Activator plugin; + + /** + * The constructor. + */ + public Activator() { + plugin = this; + } + + /** + * This method is called upon plug-in activation + */ + public void start(BundleContext context) throws Exception { + super.start(context); + } + + /** + * This method is called when the plug-in is stopped + */ + public void stop(BundleContext context) throws Exception { + super.stop(context); + plugin = null; + } + + /** + * Returns the shared instance. + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path. + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.rse.logging", path); + } +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/IRemoteSystemsLogging.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/IRemoteSystemsLogging.java new file mode 100644 index 00000000000..44e19560d5f --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/IRemoteSystemsLogging.java @@ -0,0 +1,79 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + +/** + * Defines all logging constants. + */ +public interface IRemoteSystemsLogging { + + + // All attributes here are static final. + /** + * Name of the key that controls the logging level.
+ */ + String PLUGIN_ID = "org.eclipse.rse.logging"; + + /** + * Name of the key that controls the logging level.
+ * (value is "debug_level"). + */ + String DEBUG_LEVEL = "debug_level"; + + /** + * Name of the key that controls the log location.
+ * (value is "log_location"). + */ + String LOG_LOCATION = "log_location"; + + /** + * Set debug_level to this value to get Error messages.
+ * (value is 0). + */ + int LOG_ERROR = 0; + + /** + * Set debug_level to this value to get Warning messages.
+ * (value is 1). + */ + int LOG_WARNING = 1; + + /** + * Set debug_level to this value to get Information messages.
+ * (value is 2). + */ + int LOG_INFO = 2; + + /** + * Set debug_level to this value to get Debug messages.
+ * (value is 3). + */ + int LOG_DEBUG = 3; + + /** + * Set log_location to this value to log to a file.
+ * (value is "Log_To_File"). + */ + String LOG_TO_FILE = "Log_To_File"; + + /** + * Set log_location to this value to log to a Std out.
+ * (value is "Log_To_StdOut"). + */ + String LOG_TO_STDOUT = "Log_To_StdOut"; + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Logger.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Logger.java new file mode 100644 index 00000000000..3264186064a --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/Logger.java @@ -0,0 +1,273 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.rse.internal.logging.RemoteSystemLogListener; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; + + +/** + * Generic Logger class for handling Remote Systems logging and tracing.
+ *
+ * The debug level is determined by a "debug_level" key in the preferences store + * of the plugin that owns this Logger instance.
+ *
+ * The debug location is determined by a "log_location" key in the preferences store + * of the plugin that owns this Logger instance.
+ *
+ * The valid values for these keys can be found in the javadocs for IRemoteSystemsLogging.
. + * This means that these keys could have been defined through hardcoding in your + * plugin startup code, through preferences.ini in the plugin install directory, + * OR from pref_store.ini in the plugin read/write metadata area.
+ * The default behavior is to log to file, and to log only errors. + *
+ * A typical usage of this class is as follows:
+ *
+ * public class myPlugin extends AbstractUIPlugin {
+ *
+ * // a cached Logger inst for convenience.
+ * public static Logger out = null;
+ *
+ * public myPlugin(IPluginDescriptor descriptor) {
+ * super(descriptor);
+ * ......
+ * ......
+ * out = LoggerFactory.getInst(this);
+ * out.logInfo("loading myPlugin class.");
+ * //out.logWarning("This is a warning message.");
+ * //out.logError("This is an error.", new Exception());
+ * //if (Logger.DEBUG)
+ * // out.logDebugMessage(
+ * // "myPlugin",
+ * // "this is a debug message from class myPlugin.");
+ * ......
+ * ......
+ * }
+ *
+ *
+ * public void shutdown() throws CoreException {
+ * super.shutdown();
+ * LoggerFactory.freeInst(this);
+ * }
+ *
+ * + */ +public class Logger implements IPropertyChangeListener { + + public static final String Copyright = + "(C) Copyright IBM Corp. 2002, 2003. All Rights Reserved."; + + /** + * This SHOULD be set to false in production.
+ * Used to compile out developement debug messages.
+ */ + public final static boolean DEBUG = false; + + // Cashed workbenchPlugin Log, LogListener instances + private ILog systemsPluginLog = null; + private RemoteSystemLogListener logListener = null; + + // Cashed Plugin ID, and plugin + private String pluginId = null; + AbstractUIPlugin systemPlugin = null; + + // Controls logging level + private int debug_level = 0; + + // Captures initialization errors + private boolean init_ok = true; + + protected Logger(AbstractUIPlugin systemPlugin) { + this.systemPlugin = systemPlugin; + this.pluginId = systemPlugin.getBundle().getSymbolicName(); + initialize(); + } + + private void initialize() { + try { + + systemsPluginLog = systemPlugin.getLog(); + if (logListener == null) + logListener = new RemoteSystemLogListener(systemPlugin); + systemsPluginLog.addLogListener(logListener); + + // get the debug level from plugin Preference store. + // note: logListener must be initialized before calling getPreference store! + IPreferenceStore store = systemPlugin.getPreferenceStore(); + debug_level = store.getInt(IRemoteSystemsLogging.DEBUG_LEVEL); + + systemPlugin.getPreferenceStore().addPropertyChangeListener(this); + systemPlugin.getPreferenceStore().addPropertyChangeListener(logListener); + + } catch (Exception e) { + // Errors occured during initialize, disable logging. + // should never be here. Use Platform logger instead. + Bundle bundle = Platform.getBundle(Platform.PI_RUNTIME); + Platform.getLog(bundle).log( + new Status( + IStatus.ERROR, + IRemoteSystemsLogging.PLUGIN_ID, + IStatus.OK, + "could not create Logger for " + pluginId, + e)); + init_ok = false; + } + } + + /** + * Log a Debug message. This is intended to be wrapped as follows:
+ * if (Logger.DEBUG)
+ * Logger.logDebugMessage("someClassName", "someMessage");
+ *
+ * and the output will be:
+ *
+ * ---------------------------------------------------------------
+ * DEBUG com.ibm.etools.systems.logging someClassName
+ * someMessage
+ * ---------------------------------------------------------------
+ *
+ *
+ * Note that since this message is only for developer debugging, it does not + * need to be localized to proper local.
+ */ + + public synchronized void logDebugMessage( + String className, + String message) { + if ((init_ok) && (debug_level >= IRemoteSystemsLogging.LOG_DEBUG)) { + // ie: print all INFO, WARNING and ERROR messages + MultiStatus debugStatus = + new MultiStatus(pluginId, IStatus.OK, className, null); + Status infoStatus = + new Status(IStatus.OK, pluginId, IStatus.OK, message, null); + debugStatus.add(infoStatus); + systemsPluginLog.log(debugStatus); + } + } + + /** + * Log an Error message with an exception. Note that the message should already + * be localized to proper local.
+ * ie: Resource.getString() should already have been called + */ + + public synchronized void logError(String message, Throwable ex) { + if ((init_ok) && (debug_level >= IRemoteSystemsLogging.LOG_ERROR)) { + // ie: print only ERROR messages + if (message == null) + message = ""; + Status errorStatus = + new Status(IStatus.ERROR, pluginId, IStatus.OK, message, ex); + systemsPluginLog.log(errorStatus); + + } + } + + /** + * Log an Information message. Note that the message should already + * be localized to proper local.
+ * ie: Resource.getString() should already have been called + */ + public synchronized void logInfo(String message) + { + logInfo(message, null); + } + + /** + * Log an Information message. Note that the message should already + * be localized to proper local.
+ * ie: Resource.getString() should already have been called + */ + + public synchronized void logInfo(String message, Throwable ex) { + if ((init_ok) && (debug_level >= IRemoteSystemsLogging.LOG_INFO)) { + if (message == null) + message = ""; + // ie: print all INFO, WARNING and ERROR messages + Status infoStatus = + new Status(IStatus.INFO, pluginId, IStatus.OK, message, ex); + systemsPluginLog.log(infoStatus); + + } + + } + + /** + * Log a Warning message. Note that the message should already + * be localized to proper local.
+ * ie: Resource.getString() should already have been called + */ + public synchronized void logWarning(String message) + { + logWarning(message, null); + } + + /** + * Log a Warning message. Note that the message should already + * be localized to proper local.
+ * ie: Resource.getString() should already have been called + */ + public synchronized void logWarning(String message, Throwable ex) { + if ((init_ok) && (debug_level >= IRemoteSystemsLogging.LOG_WARNING)) { + if (message == null) + message = ""; + // ie: print all WARNING and ERROR messages + Status warningStatus = + new Status( + IStatus.WARNING, + pluginId, + IStatus.OK, + message, + ex); + systemsPluginLog.log(warningStatus); + } + + } + + public synchronized void setDebugLevel(int level) { + debug_level = level; + } + + public synchronized int getDebugLevel() { + return debug_level; + } + + public synchronized void freeResources() { + logListener.freeResources(); + } + + /** + * Handle changes from Preferences page. + */ + public synchronized void propertyChange(PropertyChangeEvent event) { + // refresh the debug level from plugin Preference store + debug_level = + systemPlugin.getPreferenceStore().getInt( + IRemoteSystemsLogging.DEBUG_LEVEL); + + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggerFactory.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggerFactory.java new file mode 100644 index 00000000000..b879ba58786 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggerFactory.java @@ -0,0 +1,66 @@ +/******************************************************************************** + * Copyright (c) 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + +import org.eclipse.rse.internal.logging.LoggerController; +import org.eclipse.ui.plugin.AbstractUIPlugin; + + +/** + * Factory class for creating Logger instances.
+ * Keep in mind that this factory class follows the singleton model.
+ * ie: once an instance of a Logger class for a given plugin is created, + * it will always be reused. + */ +public class LoggerFactory { + + + /** + * Returns a Logger instance for the given plugin.
Note that there is only + * a singelton instance of the Logger class per plugin. You are guarenteed the + * same instance if one has previously been created. + */ + public static Logger getInst(AbstractUIPlugin plugin) { + + // get cached instance from controller if one exists. + Logger inst = LoggerController.getInst(plugin); + // no luck, create it and register it with the controller, and create + // preference page. + if (inst == null) { + inst = new Logger(plugin); + LoggerController.registerInst(plugin, inst); + // Check to see if the Logging plugin out instance has been created yet. + // If it has, use it to log + if (RemoteSystemsLoggingPlugin.out != null) + RemoteSystemsLoggingPlugin.out.logInfo( + "Created Logger instance for " + + plugin.getBundle().getSymbolicName()); + } + + return inst; + } + + /** + * Frees resources used by the Logger instance for the given plugin.
+ * This methods must be called as part of the the plugin shutdown life cycle. + */ + public static void freeInst(AbstractUIPlugin plugin) { + // delegate to controller + LoggerController.freeInst(plugin); + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferenceInitializer.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferenceInitializer.java new file mode 100644 index 00000000000..ff06d0c574d --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferenceInitializer.java @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; + +/** + * This class initializes logging preferences. + */ +public class LoggingPreferenceInitializer extends AbstractPreferenceInitializer { + + /** + * Constructor. + */ + public LoggingPreferenceInitializer() { + super(); + } + + /** + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + public void initializeDefaultPreferences() { + RemoteSystemsLoggingPlugin.getDefault().initializeDefaultPreferences(); + } +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferencePage.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferencePage.java new file mode 100644 index 00000000000..072c09c6b27 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/LoggingPreferencePage.java @@ -0,0 +1,354 @@ +/******************************************************************************** + * Copyright (c) 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + + +import java.text.MessageFormat; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.preference.PreferenceStore; +import org.eclipse.rse.internal.logging.LabelUtil; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; + + +/** + * An abstract preference page for all remote system logging.
+ * Use a subclass of this page if you need a preference page to control + * logging. + */ +public abstract class LoggingPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IExecutableExtension { + + + private Button radioButton0; + private Button radioButton1; + private Button radioButton2; + private Button radioButton3; + private Button radioButtonLogFile; + private Button radioButtonLogView; + + /** + * This is the plugin instance who's preference store will be used + * to control the settings on this page. Also, when this page is closed + * the settings are restored in the preference store of the above plugin. + */ + private Bundle bundle = null; + + /** + * Creates composite control and sets the default layout data. + * + * @param parent the parent of the new composite + * @param numColumns the number of columns for the new composite + * @return the newly-created coposite + */ + private Composite createComposite(Composite parent, int numColumns) { + Composite composite = new Composite(parent, SWT.NONE); + //GridLayout + GridLayout layout = new GridLayout(); + layout.numColumns = numColumns; + composite.setLayout(layout); + + //GridData + GridData data = new GridData(); + data.verticalAlignment = GridData.FILL; + data.horizontalAlignment = GridData.FILL; + composite.setLayoutData(data); + return composite; + } + + /** + * Method declared on PreferencePage + */ + protected Control createContents(Composite parent) { + Composite composite_tab = createComposite(parent, 2); + String bundleName = (String)(bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_NAME)); + String topLabel1 = RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.topLabel1"); + topLabel1 = MessageFormat.format(topLabel1, new Object[] {bundleName}); + Label label1 = createLabel(composite_tab, topLabel1); + forceSpace(composite_tab); + String topLabel2 = RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.topLabel2"); + Label label2 = createLabel(composite_tab, topLabel2); + tabForward(composite_tab); + Composite composite1_radioButton = createComposite(composite_tab, 1); + String text = RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.errors_only"); + Set used = LabelUtil.usedFromString("ad"); // the mnemonics already used on preference page (in English) + radioButton0 = createRadioButton(composite1_radioButton, LabelUtil.assignMnemonic(text, used)); + text = RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.warnings_errors"); + radioButton1 = createRadioButton(composite1_radioButton, LabelUtil.assignMnemonic(text, used)); + text = RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.info_debug"); + radioButton2 = createRadioButton(composite1_radioButton, LabelUtil.assignMnemonic(text, used)); + // now add debug stuff, that only shows up in a debug build. + if (Logger.DEBUG) { + radioButton3 = createRadioButton(composite1_radioButton, RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.full_debug")); + Composite composite_tab2 = createComposite(parent, 2); + Label label3 = createLabel(composite_tab2, RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.logging_location")); + tabForward(composite_tab2); + Composite composite_radioButton2 = createComposite(composite_tab2, 1); + radioButtonLogFile = createRadioButton(composite_radioButton2, RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.log_to_file")); + radioButtonLogView = createRadioButton(composite_radioButton2, RemoteSystemsLoggingPlugin.getResourceString("LoggingPreferencePage.log_to_stdout")); + WorkbenchHelp.setHelp(composite_tab2, "com.ibm.etools.systems.logging.pref0000"); + } + initializeValues(); + RemoteSystemsLoggingPlugin.out.logInfo("created LoggingPreferencePage"); + WorkbenchHelp.setHelp(composite_tab, "com.ibm.etools.systems.logging.pref0000"); + return new Composite(parent, SWT.NULL); + } + + /** + * Utility method that creates a label instance + * and sets the default layout data. + * + * @param parent the parent for the new label + * @param text the text for the new label + * @return the new label + */ + private Label createLabel(Composite parent, String text) { + Label label = new Label(parent, SWT.LEFT); + label.setText(text); + GridData data = new GridData(); + data.horizontalSpan = 2; + data.horizontalAlignment = GridData.FILL; + label.setLayoutData(data); + return label; + } + + /** + * Utility method that creates a radio button instance + * and sets the default layout data. + * + * @param parent the parent for the new button + * @param label the label for the new button + * @return the newly-created button + */ + private Button createRadioButton(Composite parent, String label) { + Button button = new Button(parent, SWT.RADIO | SWT.LEFT); + button.setText(label); + GridData data = new GridData(); + button.setLayoutData(data); + return button; + } + + /** + * + */ + protected IPreferenceStore doGetPreferenceStore() { + + if (bundle != null) { + AbstractUIPlugin plugin = getPlugin(); + + if (plugin != null) { + return plugin.getPreferenceStore(); + } + else { + return new PreferenceStore(); + } + } + else { + return new PreferenceStore(); + } + } + + protected abstract AbstractUIPlugin getPlugin(); + + /** + * Method declared on IWorkbenchPreferencePage + */ + public void init(IWorkbench workbench) { + } + + /** + * Initializes states of the controls using current values + * in the preference store. + */ + private void initializeValues() { + IPreferenceStore store = getPreferenceStore(); + radioButton0.setSelection(false); + radioButton1.setSelection(false); + radioButton2.setSelection(false); + if (null != radioButton3) + radioButton3.setSelection(false); + if (Logger.DEBUG) { + radioButtonLogFile.setSelection(false); + radioButtonLogView.setSelection(false); + } + int choice = store.getInt(IRemoteSystemsLogging.DEBUG_LEVEL); + switch (choice) { + case 0 : + radioButton0.setSelection(true); + break; + case 1 : + radioButton1.setSelection(true); + break; + case 2 : + radioButton2.setSelection(true); + break; + case 3 : + if (null != radioButton3) + radioButton3.setSelection(true); + else + radioButton2.setSelection(true); + break; + } + if (Logger.DEBUG) { + String log_location = store.getString(IRemoteSystemsLogging.LOG_LOCATION); + if (log_location.equalsIgnoreCase(IRemoteSystemsLogging.LOG_TO_STDOUT)) + radioButtonLogView.setSelection(true); + else + radioButtonLogFile.setSelection(true); + } + } + + /** + * Initializes states of the controls using default values + * in the preference store. + */ + private void initializeDefaults() { + IPreferenceStore store = getPreferenceStore(); + radioButton0.setSelection(false); + radioButton1.setSelection(false); + radioButton2.setSelection(false); + if (null != radioButton3) + radioButton3.setSelection(false); + if (Logger.DEBUG) { + radioButtonLogFile.setSelection(false); + radioButtonLogView.setSelection(false); + } + int choice = store.getDefaultInt(IRemoteSystemsLogging.DEBUG_LEVEL); + switch (choice) { + case 0 : + radioButton0.setSelection(true); + break; + case 1 : + radioButton1.setSelection(true); + break; + case 2 : + radioButton2.setSelection(true); + break; + case 3 : + if (null != radioButton3) + radioButton3.setSelection(true); + else + radioButton2.setSelection(true); + break; + } + if (Logger.DEBUG) { + String log_location = store.getDefaultString(IRemoteSystemsLogging.LOG_LOCATION); + if (log_location.equalsIgnoreCase(IRemoteSystemsLogging.LOG_TO_STDOUT)) + radioButtonLogView.setSelection(true); + else + radioButtonLogFile.setSelection(true); + } + } + + /** + * Method declared on PreferencePage + */ + protected void performDefaults() { + super.performDefaults(); + initializeDefaults(); + } + + /** + * Method declared on PreferencePage + */ + public boolean performOk() { + storeValues(); + return true; + } + + /** + * Stores the values of the controls back to the preference store. + */ + private void storeValues() { + IPreferenceStore store = getPreferenceStore(); + int choice = 0; + if (radioButton1.getSelection()) + choice = 1; + else if (radioButton2.getSelection()) + choice = 2; + else if (null != radioButton3 && radioButton3.getSelection()) + choice = 3; + store.setValue(IRemoteSystemsLogging.DEBUG_LEVEL, choice); + if (Logger.DEBUG) { + String log_location = ""; + if (radioButtonLogFile.getSelection()) + log_location = IRemoteSystemsLogging.LOG_TO_FILE; + else + log_location = IRemoteSystemsLogging.LOG_TO_STDOUT; + store.setValue(IRemoteSystemsLogging.LOG_LOCATION, log_location); + } + } + + /** + * Creates a tab of one horizontal span. + * + * @param parent the parent in which the tab should be created + */ + private void tabForward(Composite parent) { + Label vfiller = new Label(parent, SWT.LEFT); + GridData gridData = new GridData(); + gridData = new GridData(); + gridData.horizontalAlignment = GridData.BEGINNING; + gridData.grabExcessHorizontalSpace = false; + gridData.verticalAlignment = GridData.CENTER; + gridData.grabExcessVerticalSpace = false; + vfiller.setLayoutData(gridData); + } + + /** + * Create a horizontal space line. + */ + private void forceSpace(Composite parent) { + Label label = new Label(parent, SWT.NONE); + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.BEGINNING; + data.horizontalSpan = 2; + label.setLayoutData(data); + } + + /** + * This is needed to get to the plugin id, and then plugin instance. + */ + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + // we are assuming here that only AbstractUIPlugins will be used. + try { + String nameSpace = config.getDeclaringExtension().getNamespace(); + this.bundle = Platform.getBundle(nameSpace); + } catch (Exception e) { + // log error. plugin remains null. + RemoteSystemsLoggingPlugin.out.logError("Failed to create LoggingPreferencePage.", e); + } + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/RemoteSystemsLoggingPlugin.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/RemoteSystemsLoggingPlugin.java new file mode 100644 index 00000000000..2f88a36990c --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/RemoteSystemsLoggingPlugin.java @@ -0,0 +1,128 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging; + +import java.net.URL; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + + +/** + * Remote Systems Logging plugin. + */ +public class RemoteSystemsLoggingPlugin extends AbstractUIPlugin { + + + //The shared instance. + private static RemoteSystemsLoggingPlugin inst; + + //Resource bundle. + private ResourceBundle resourceBundle; + + // The cached Logger inst. + public static Logger out = null; + + /** + * Constructor. + */ + public RemoteSystemsLoggingPlugin() { + super(); + + if (inst == null) { + inst = this; + } + } + + /** + * Returns the shared plugin instance. + */ + public static RemoteSystemsLoggingPlugin getDefault() { + return inst; + } + + /** + * Returns the string from the plugin's resource bundle, + * or 'key' if not found. + */ + public static String getResourceString(String key) { + try { + ResourceBundle bundle = RemoteSystemsLoggingPlugin.getDefault().getResourceBundle(); + return bundle.getString(key); + } catch (Exception e) { + out.logError("could not get resource string for: " + key, e); + return key; + } + } + + /** + * Returns the plugin's resource bundle. + */ + public ResourceBundle getResourceBundle() { + + if (resourceBundle == null) { + + try { + IPath path = new Path("$nl$/RemoteSystemsLogging.properties"); + URL url = Platform.find(getBundle(), path); + resourceBundle = new PropertyResourceBundle(url.openStream()); + } catch (Exception x) { + resourceBundle = null; + out.logInfo("RemoteSystemsLoggingPlugin - unable to log resourcebundle"); + } + } + + return resourceBundle; + } + + /** + * Sets default preference values. These values will be used + * until some preferences are actually set using Preference dialog. + */ + public void initializeDefaultPreferences() { + getPreferenceStore().setDefault( + IRemoteSystemsLogging.DEBUG_LEVEL, + IRemoteSystemsLogging.LOG_ERROR); + getPreferenceStore().setDefault( + IRemoteSystemsLogging.LOG_LOCATION, + IRemoteSystemsLogging.LOG_TO_FILE); + } + + /** + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + + // don't need a preference page for this plugin. + out = LoggerFactory.getInst(this); + out.logInfo("loading RemoteSystemsLoggingPlugin class."); + } + + /** + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + LoggerFactory.freeInst(this); + super.stop(context); + } +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/performance/PerformanceLogger.java b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/performance/PerformanceLogger.java new file mode 100644 index 00000000000..2cf25c76a95 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/src/org/eclipse/rse/logging/performance/PerformanceLogger.java @@ -0,0 +1,739 @@ +/******************************************************************************** + * Copyright (c) 2002, 2006 IBM Corporation. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Initial Contributors: + * The following IBM employees contributed to the Remote System Explorer + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. + * + * Contributors: + * {Name} (company) - description of contribution. + ********************************************************************************/ + +package org.eclipse.rse.logging.performance; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.util.Calendar; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.Stack; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Comment; +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + + +/** +* A performance measurement class for benchmarking. +* This performance framework provides stopwatch functions +* for calculating elapsed time for an operation. +* +* Usuage example +* Method_A { +* String key = PerformanceLogger.register("RSE","WDSC","5120"); +* PerformanceLogger.start(key, "OP1"); //CallerID is OP1 +* Method_B(); +* PerformanceLogger.stop(key); +* } +* +* Method_B { +* PerformanceLogger.start("RSE"); //"RSE" component, CalleID="class.method" +* // Do something +* PerformanceLogger.stop("RSE"); +* } +* +* Method_C { +* PerformanceLogger.start(); //Use the default component for recording +* // Do something +* PerformanceLogger.stop(); +* } +*/ + +public class PerformanceLogger +{ + + public final static boolean _ENABLE_PERFORMANCE_LOGGING_IBM_INTERNAL_ = false; + + public final static int OPTION_GET_ALL = 1; + public final static int OPTION_GET_FEATURE = 2; + public final static int OPTION_GET_VERSION = 3; + + + + final static String ELEMENT_TASK = "Task"; + final static String ATTRIBUTE_NAME_TASKID = "CallerID"; + final static String DEFAULT_COMPONENT = "_PERFORMANCELOGGER_"; + + static boolean ENABLE_PERFORMANCE_LOGGING = false; /*for user logging enabling*/ + //static long currentAssignedID = -1; + static long samplingTime = -1; /* Elapsed time for normalization operatin */ + static boolean _initialized = false; + static HashMap perfLogRegistry = new HashMap(); + + static class StartData + { + long startTime = -1; + long stopTime = -1; + String userID = null; + String startThread = null; + String startMethod = null; + String stopThread = null; + String stopMethod = null; + Element node = null; + } + class ComponentData + { + String component = null; + String timeStamp = null; + String feature = null; + String version = null; + String XMLFileID = null; + File XMLFile = null; + Document doc = null; + Stack taskStack = new Stack(); + ComponentData(String comp_id) { + component = comp_id; + } + } + + + /** + * PerformanceLogger(): class constructor + * @return + * - Normalization time generated + * - XML file for default component created + */ + private PerformanceLogger() { + init(); + } + + /** + * public static void enablePerformanceLogging(boolean enable) : enable performance logging + * @param + * enable : true or false + * @return + * The flag ENABLE_PERFORMANCE_LOGGING is enable(true or false) + */ + public static void enablePerformanceLogging(boolean enable){ + if (enable) + ENABLE_PERFORMANCE_LOGGING = true; + else + ENABLE_PERFORMANCE_LOGGING = false; + } + + /** + * public static boolean isPerformanceLoggingEnabled() : check if logging enabled + * @return + * boolean ENABLE_PERFORMANCE_LOGGING + */ + public static boolean isPerformanceLoggingEnabled(){ + return ENABLE_PERFORMANCE_LOGGING; + } + + /* public static String register(String comp_id) : registering a component using default + * @parm + * - comp_id: Component to be registered + * @return + * compont comp_id registered with no product info + */ + public static String register(String comp_id) { + return register(comp_id,"",""); + } + + /* public static String register(String feature, String version) : method for registering a component using default + * @parm + * - feature: Identifier for Product Feature attribute in XML + * - version: Identifier for Product Version attribute in XML + * @return + * - return default component key + * - Default component XML file created + * + */ + public static String register(String feature, String version) { + return register(DEFAULT_COMPONENT,feature,version); + } + + /** + * public static String register(String comp_id, String feature, String version) : Registering a component + * @parm + * - comp_id: Component to be registered + * - feature: Identifier for Product Feature attribute in XML + * - version: Identifier for Product Version attribute in XML + * @return + * - comp_id as the registered key + * - An XML file is created by concatenating comp_id, feature and version with time stamp appended + */ + public static String register(String comp_id, String feature, String version){ + + if ( (comp_id == null) || (comp_id.length() == 0) ) { + System.out.println("PerformanceLogger:register(): Cannot register null component id."); + return comp_id; + } + + if (perfLogRegistry.containsKey(comp_id)) { + System.out.println("PerformanceLogger:register(): component \"" + comp_id + "\" already registered"); + return comp_id; + } + + ComponentData compData = new PerformanceLogger().new ComponentData(comp_id); + + Calendar time = Calendar.getInstance(); + compData.timeStamp = time.getTime().toString(); + String userID = System.getProperty("user.name"); + compData.XMLFileID = comp_id+"_" + userID + "_" + feature.replace(' ', '_') + "_"+version.replace(' ', '_') + "_perf." + compData.timeStamp.replace(' ', '_').replace(':', '_') + ".xml"; + compData.XMLFile = new File(compData.XMLFileID); + compData.feature = feature; + compData.version = version; + generateXMLFile(compData); + compData.taskStack = new Stack(); + perfLogRegistry.put(comp_id, compData); + _initialized = true; + System.out.println("SystemPerformanceLogger: XML file created is \"" + compData.XMLFile.getAbsolutePath() + "\"."); + return comp_id; + } + + /** + * public static void deRegister(): De-register the default component + * @return + * Default component "_PERFORMANCELOGGER_" removed + * start() will be disabled + */ + public static void deRegister() { + perfLogRegistry.remove(DEFAULT_COMPONENT); + System.out.println("SystemPerformanceLogger: default component de-registered"); + } + + /** + * public static void deRegister(String key): De-register a component + * @parm + * key : component to be removed + * @return + * component identified by key removed + * start(comp_id) will be disabled + */ + public static void deRegister(String key) { + perfLogRegistry.remove(key); + System.out.println("SystemPerformanceLogger: component \"" + key + "\" de-registered"); + } + + /** + * private void init() : method for class instance initialization. + * @return + * Normalization value generated + */ + private void init() { + if (samplingTime == -1) { + + /*Set normalization values*/ + + long startTime = System.currentTimeMillis(); + + /*Trying to make sure it is not optimized by the compiler? */ + /* Excute some standard instruction sets, such that a reasonably elapsed time can be obtained */ + double val = 0; + Double q = null; + int i = 0; + int n = 1000000; + for ( i = 0; i < n; i++) { /* increment operation for 1000 times */ + Double dd = new Double(n); + Double dr = new Double(n+i); + q = new Double(dd.doubleValue()/dr.doubleValue()); + } + val = q.doubleValue()/i; + + long stopTime = System.currentTimeMillis(); + samplingTime = stopTime-startTime; + System.out.println("SystemPerformanceLogger::Normalization Elapsed time = " + samplingTime); + } + + } + + /** + * public static long start(): start timer using default component + * The Task values will be recorded in the default component XML file + * @return + * - started time milliseconds + */ + public static long start() { + if (_initialized == false) { + register(DEFAULT_COMPONENT,"",""); + } + /*Use the class method name for CallerID*/ + /* + * Sample method name retruned by getMethodName(): + * " com.ibm.etools.iseries.core.resources.ISeriesEditableSrcPhysicalFileMember.doDownload(ISeriesEditableSrcPhysicalFileMember.java:558)" + * + */ + String methodPath = getMethodName(true); + + return start(DEFAULT_COMPONENT, methodPath); + } + + /** + * public static long start(String comp_id): start timer for component comp_id using default TaskID + * @parm : + * comp_id : component registered previously by register(comp_id,..) + * @return + * - started time in milliseconds. + */ + public static long start(String comp_id) { + String methodPath = getMethodName(true); + return start(comp_id, methodPath); + + } + + /** + * public long start(String comp_id, String call_id): start the timer for registered component comp_id + * @parm + * comp_id is the registered component + * call_id is the "CallID" attribute value for the XML tag "Task" + * @return + * - started time in milliseconds. + */ + public static long start(String comp_id, String call_id) { + + if (perfLogRegistry.containsKey(comp_id) == false) { + System.out.println("PerformanceLogger:start(): component \"" + comp_id + "\" not registered"); + return -1; + } + + ComponentData cd = (ComponentData)perfLogRegistry.get(comp_id); + StartData td = new StartData(); + + td.userID = call_id; + td.startThread = Thread.currentThread().toString(); + td.startMethod = getMethodName(false); + + /* Create the new Task Element in the DOC */ + try { + + //BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cd.XMLFile), "UTF8")); + Element root = cd.doc.getDocumentElement(); + Element task = cd.doc.createElement(ELEMENT_TASK); + task.setAttribute(ATTRIBUTE_NAME_TASKID, td.userID); + task.setAttribute("StartAt", td.startMethod); + task.setAttribute("StartThread", td.startThread); + + td.node = task; + + /* Check if start() is nested by checking if the TaskStack is empty */ + if ( cd.taskStack.isEmpty() ) { /*Empty==>not a nested start()*/ + root.appendChild(task); + } + else { /*Not empty ==> this start() is nested*/ + + StartData sd = (StartData)cd.taskStack.peek(); /*Peek the parent CallID on the stack*/ + sd.node.appendChild(task); + } + } + catch (DOMException e) + { + System.out.println("PerformanceLogger::updateXMLFileatStart DOM Error:" + e.toString()); + } + + /*Read the current time save it on stack */ + td.startTime = System.currentTimeMillis(); + cd.taskStack.push(td); + return td.startTime; + } + + /** + * public static long stop(): stop timer for default component + * The Task values will be recorded in the default component XML file + * @return + * - started time milliseconds + */ + public static long stop() { + return stop(DEFAULT_COMPONENT); + } + + /** + * public long stop(String comp_id): Stopping the timer for component comp_id + * @return + * - stopped time in milliseconds. + */ + public static long stop(String comp_id) { + + long st = System.currentTimeMillis(); + ComponentData cd = (ComponentData)perfLogRegistry.get(comp_id); + if (cd == null) { + System.out.println("SystemPerformanceLogger::stop(): invalid registration key"); + return 0; + } + StartData td = null; + try { + td = (StartData)cd.taskStack.pop(); + td.stopTime = st; + td.stopThread = Thread.currentThread().toString(); + td.stopMethod = getMethodName(false); + updateXMLFileAtStop(cd,td); + + //System.out.println("SystemPerformanceLogger::stop(): timer \"" + td.userID + "\" stopped. Elapsed time = " + + // (td.stopTime-td.startTime) + " millis."); + } + catch (EmptyStackException e) { + System.out.println("SystemPerformanceLogger:: Probably too many stop() function calls. - " + e); + } + return td.stopTime; + } + + + /** + * private void generateXMLFile(ComponentData cd): create XML file + * @param + * cd is the component data for creating the XML + * @return + * - An XML file is created with "Product" and "System" tags. + */ + private static void generateXMLFile(ComponentData cd){ + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cd.XMLFile), "UTF8")); +// DOMImplementation impl = new DOMImplementationImpl(); +// cd.doc = impl.createDocument(null, "Benchmark", null); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = null; + try { + builder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e1) { + } + DOMImplementation impl = builder.getDOMImplementation(); + cd.doc = impl.createDocument(null, "Benchmark", null); + // get root element and set attributes + Element root = cd.doc.getDocumentElement(); + root.setAttribute("BenchmarkID", cd.XMLFileID); + root.setAttribute("TimeStamp", cd.timeStamp); + + Element system = cd.doc.createElement("System"); + Element product = cd.doc.createElement("Product"); + + product.setAttribute("Feature", cd.feature); + product.setAttribute("Version", cd.version); + root.appendChild(product); + + system.setAttribute("OSName",System.getProperty("os.name")); + system.setAttribute("OSVersion",System.getProperty("os.version")); + system.setAttribute("JavaVersion",System.getProperty("java.version")); + system.setAttribute("JavaVMVersion",System.getProperty("java.vm.version")); + system.setAttribute("JavaClassPath",System.getProperty("java.class.path")); + system.setAttribute("JavaLibraryPath",System.getProperty("java.library.path")); + root.appendChild(system); + + Element norm = cd.doc.createElement("_NORMALIZATION_VALUES"); + Long ems = new Long(samplingTime); + norm.setAttribute("ElapsedTime",ems.toString()); + root.appendChild(norm); + + /* Insert comments for Task tag */ + Comment cmt1 = cd.doc.createComment("Each Task element represents one start/stop timer operation"); + Comment cmt2 = cd.doc.createComment("Time recorded is in milliseconds"); + Comment cmt3 = cd.doc.createComment("NormalizedFactor is the performance indicator. A larger value than the previous run might indicate performance degradation."); + root.appendChild(cmt1); + root.appendChild(cmt2); + root.appendChild(cmt3); + + try { + Source source = new DOMSource(cd.doc); + Result result = new StreamResult(writer); + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.setOutputProperty(OutputKeys.INDENT, "yes"); + t.transform(source, result); + } catch (TransformerConfigurationException e2) { + } catch (TransformerFactoryConfigurationError e2) { + } catch (TransformerException e2) { + } + +// OutputFormat fmt = new OutputFormat(cd.doc); +// fmt.setLineSeparator(LineSeparator.Windows); +// fmt.setIndenting(true); +// fmt.setPreserveSpace(false); +// //writer.flush(); +// XMLSerializer serializer = new XMLSerializer(writer, fmt); +// serializer.serialize(cd.doc); +// writer.close(); + + } + catch (java.io.IOException e) + { + System.out.println("PerformanceLogger::updateXML IO Error:" + e.toString()); + } + catch (DOMException e) + { + System.out.println("PerformanceLogger::updateXML DOM Error:" + e.toString()); + } + } + + /** + * private void updateXMLFileAtStop(ComponentData cd, StartData td): update XML file with performance measurement info + * @return + * - A "Task" tag is created in the XML file with the current start and stop timer information. + */ + private static void updateXMLFileAtStop(ComponentData cd, StartData td ){ + + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cd.XMLFile), "UTF8")); + Element root = cd.doc.getDocumentElement(); + Element task = td.node; + + /* Construct Long class insatnce for string manipulation */ + Long ems = new Long(td.stopTime-td.startTime); + Long sms = new Long(td.startTime); + Long tms = new Long(td.stopTime); + /*Calculate the normalization factor*/ + String normalizedFactor = "invalid"; + if (samplingTime > 0) { + Long sam = new Long(samplingTime); + Double val = new Double(ems.doubleValue()/sam.doubleValue()); + normalizedFactor = val.toString(); + } + + /* Update the document */ + task.setAttribute("ElapsedTime",ems.toString()); + task.setAttribute("NormalizedFactor",normalizedFactor); + task.setAttribute("StartTime",sms.toString()); + task.setAttribute("StopTime",tms.toString()); + task.setAttribute("StartAt", td.startMethod); + task.setAttribute("StartThread", td.startThread); + task.setAttribute("StopAt", td.stopMethod); + task.setAttribute("StopThread", td.stopThread); + + try { + Source source = new DOMSource(cd.doc); + Result result = new StreamResult(writer); + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.setOutputProperty(OutputKeys.INDENT, "yes"); + t.transform(source, result); + } catch (TransformerConfigurationException e2) { + } catch (TransformerFactoryConfigurationError e2) { + } catch (TransformerException e2) { + } + + /*Now save the DOM*/ +// OutputFormat fmt = new OutputFormat(cd.doc); +// fmt.setLineSeparator(LineSeparator.Windows); +// fmt.setIndenting(true); +// fmt.setPreserveSpace(false); +// //writer.flush(); +// XMLSerializer serializer = new XMLSerializer(writer, fmt); +// serializer.serialize(cd.doc); +// writer.close(); + } + catch (java.io.IOException e) + { + System.out.println("PerformanceLogger::updateXMLFileAtStop IO Error:" + e.toString()); + } + catch (DOMException e) + { + System.out.println("PerformanceLogger::updateXMLFileAtStop DOM Error:" + e.toString()); + } + + } + + /** + * public String geCurrentProductInfo(int req, String comp_id) : retrieve the product information. + * @param + * req : OPTION_GET_FEATURE/OPTION_GET_VERSION + * comp_id : the component id + * @return + * "OPTION_GET_FEATURE":product feature as specified in register() + * "OPTION_GET_VERSION": product version as specified in register() + * no match: null + */ + public static String getCurrentProductInfo(int req, String comp_id) { + ComponentData cd = (ComponentData)perfLogRegistry.get(comp_id); + if (cd == null) { + System.out.println("PerformanceLogger::getCurrentProductInfo invalid comp_id"); + return null; + } + + if (req == OPTION_GET_FEATURE) + return cd.feature; + else if (req == OPTION_GET_VERSION) + return cd.version; + return null; + } + + /** + * public String getXMLFileName(String comp_id) : get the XML file pathname + * @return + * The XML file fullpath name. + */ + public static String getXMLFileName(String comp_id) { + ComponentData cd = (ComponentData)perfLogRegistry.get(comp_id); + return cd.XMLFile.getAbsolutePath(); + } + + /** + * public String getMethodName(boolean parsed) : get the method name + * @param + * parsed : true or false + * @return + * if true method name is returned as class.method. + */ + private static String getMethodName(boolean parsed) { + + String methodPath = null; + Throwable e = new Throwable(); + StringWriter strwriter = new StringWriter(100); + e.printStackTrace(new java.io.PrintWriter(strwriter)); + String stack = strwriter.toString(); + java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(stack, "\r\n"); + /* + * Here to parse the exception string to get the caller which is the current method location + * to be obtained. The Exception stack should show the PerformanceLogger start() in the satck first: + * -java.lang.Exception + * -at com.ibm.etools.systems.logging.performance.PerformanceLogger.start(PerformanceLogger.java:151) + * -at com.ibm.etools.systems.logging.performance.PerformanceLogger.start(PerformanceLogger.java:135) + * Depending if the caller is using default task ID or not, so the caller is the 3rd or the 4th in the stack. + */ + + for (int i = 0; tokenizer.hasMoreTokens(); i++) + { + methodPath = tokenizer.nextToken(); + if ( (methodPath.indexOf("java.lang.Throwable") == -1) && + (methodPath.indexOf("logging.performance.PerformanceLogger") == -1) ) + break; + } + methodPath = methodPath.substring(4); + if (parsed) { + try + { + /* The method name obtained looks like this: + * " com.ibm.etools.iseries.core.resources.ISeriesEditableSrcPhysicalFileMember.doDownload(ISeriesEditableSrcPhysicalFileMember.java:558)" + */ + int i = methodPath.indexOf('('); + if ( i != -1) + methodPath = methodPath.substring(0,i); //strip of the substring enclosed in () + //Now we have "com.ibm.etools.systems.logging.performance.PerformanceLogger.start" + i = methodPath.lastIndexOf('.'); //Get the method name after the last period (.) + String methodName =methodPath.substring(i+1); //Now we have the method name "start" + String className = methodPath.substring(0,i); //remove method name from the string + //We are left with "com.ibm.etools.systems.logging.performance.PerformanceLogger" + i = className.lastIndexOf('.'); + if ( i != -1) + className = className.substring(i+1); //Now we have the class name "PerformanceLogger" + methodPath = className+"."+methodName; + } + catch ( IndexOutOfBoundsException ex ) + { + System.out.println("PerformanceLogger:getMethodName exception" + ex.toString()); + } + } + return methodPath; /*delete " at" in the beginning of the string */ + } + + /** + * public static void listSystemProfile(): retrieve the system information. + * @return + * These values will be retrieved and printed in stdout: + * java.version + * java.vm.version + * java.class.version + * java.class.path + * java.library.path + * os.name + * os.version + */ + public static void listSystemProfile() { + String java_version = System.getProperty("java.version"); + System.out.println("java version : " + System.getProperty("java.version")); + String java_vm_version = System.getProperty("java.vm.version"); + String java_class_version = System.getProperty("java.class.version"); + String java_class_path = System.getProperty("java.class.path"); + String java_library_path = System.getProperty("java.library.path"); + String os_name = System.getProperty("os.name"); + System.out.println("OS name : " + System.getProperty("os.name")); + String os_version = System.getProperty("os.version"); + System.out.println("OS version : " + System.getProperty("os.version")); + String user_dir = System.getProperty("user.dir"); + System.out.println("working dir : " + System.getProperty("user.dir")); + String home_dir = System.getProperty("home.dir"); + System.out.println("home dir : " + System.getProperty("home.dir")); + } + + /** + * public static void main() : This main is used for testing this PerformanceLogger functions. + * The objective is to check the XML output format for nested start() calls. + */ + public static void main(String[] args) { + + int i = 0; + + if (isPerformanceLoggingEnabled()) { + PerformanceLogger.start(); //Start timer using default component + } + for ( i = 0; i < 1000000; i++); + if (isPerformanceLoggingEnabled()) { + PerformanceLogger.stop(); + } + + PerformanceLogger.enablePerformanceLogging(true); + String key = PerformanceLogger.register("","WDSC","5120"); + key = PerformanceLogger.register("RSE","WDSC","5120"); + PerformanceLogger.deRegister("XXX"); //not registered key previously + System.out.println("Product info : " + + PerformanceLogger.getCurrentProductInfo(PerformanceLogger.OPTION_GET_FEATURE, key) + + " " + + PerformanceLogger.getCurrentProductInfo(PerformanceLogger.OPTION_GET_VERSION, key)); + PerformanceLogger.start(key, "NOT_NESTED_1"); + for ( i = 0; i < 1000000; i++); + PerformanceLogger.stop(key); + + PerformanceLogger.start(key,"NESTED_ONE"); + for ( i = 0; i < 500; i++); + PerformanceLogger.start(key,"NESTED_ONE_CHILD"); + for ( i = 0; i < 300; i++); + PerformanceLogger.stop(key); + PerformanceLogger.stop(key); + + PerformanceLogger.start(key, "NOT_NESTED_2"); + for ( i = 0; i < 2000000; i++); + PerformanceLogger.stop(key); + + PerformanceLogger.start(key, "NESTED_THREE"); + for ( i = 0; i < 300; i++); + PerformanceLogger.start(key, "NESTED_TWO_CHILD1"); + PerformanceLogger.start(key, "NESTED_TWO_CHILD2"); + for ( i = 0; i < 4000; i++); + PerformanceLogger.start(key, "NESTED_TWO_CHILD3"); + for ( i = 0; i < 6000; i++); + PerformanceLogger.stop(key); + PerformanceLogger.stop(key); + PerformanceLogger.stop(key); + PerformanceLogger.stop(key); + + PerformanceLogger.start("ABC"); //Expect error: not registered + PerformanceLogger.start(key); //record timer in the previous registered component + for ( i = 0; i < 3000000; i++); + PerformanceLogger.stop(key); + key = PerformanceLogger.register(key); // Expect error: already registered + PerformanceLogger.deRegister(key); + key = PerformanceLogger.register(key); + + String val = "i = " + i; + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.logging/style/performancelogtohtml.xsl b/rse/plugins/org.eclipse.rse.logging/style/performancelogtohtml.xsl new file mode 100644 index 00000000000..629fd7a8341 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.logging/style/performancelogtohtml.xsl @@ -0,0 +1,36 @@ + + + + + + +

+

+ + Operating system:
+
+ + Normalization value: + +

+ + + + + + + + + + + + + +
CallerIDElapsedTimeNormalizedFactor
+ + +
+ +