blob: 287bf976b56c022134c1e923f12d3c835f78dba7 [file] [log] [blame]
package org.eclipse.core.internal.runtime;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.*;
import java.util.*;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IStatus;
/**
* A log writer that writes log entries in XML format.
* See PlatformLogReader for reading logs back into memory.
*/
public class PlatformLogWriter implements ILogListener {
protected File logFile = null;
protected Writer log = null;
protected int tabDepth;
protected static final String LINE_SEPARATOR;
protected static final String TAB_STRING = " ";
protected static final String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
protected static final String ATTRIBUTE_DATE = "date";
protected static final String ATTRIBUTE_SEVERITY = "sev";
protected static final String ATTRIBUTE_PLUGIN_ID = "id";
protected static final String ATTRIBUTE_CODE = "code";
protected static final String ATTRIBUTE_MESSAGE = "msg";
protected static final String ATTRIBUTE_TRACE = "trace";
protected static final String ELEMENT_LOG = "log";
protected static final String ELEMENT_LOG_ENTRY = "entry";
protected static final String ELEMENT_STATUS = "status";
protected static final String ELEMENT_EXCEPTION = "exception";
static {
String s = System.getProperty("line.separator");
LINE_SEPARATOR = s == null ? "\n" : s;
}
public PlatformLogWriter(File file) {
this.logFile = file;
// remove old log file
logFile.delete();
}
/**
* This constructor should only be used to pass System.out .
*/
public PlatformLogWriter(OutputStream out) {
log = new OutputStreamWriter(out);
}
protected static void appendEscapedChar(StringBuffer buffer, char c) {
String replacement = getReplacement(c);
if (replacement != null) {
buffer.append('&');
buffer.append(replacement);
buffer.append(';');
} else {
buffer.append(c);
}
}
protected static String getEscaped(String s) {
StringBuffer result = new StringBuffer(s.length() + 10);
for (int i = 0; i < s.length(); ++i)
appendEscapedChar(result, s.charAt(i));
return result.toString();
}
protected static String getReplacement(char c) {
// Encode special XML characters into the equivalent character references.
// These five are defined by default for all XML documents.
switch (c) {
case '<' :
return "lt";
case '>' :
return "gt";
case '"' :
return "quot";
case '\'' :
return "apos";
case '&' :
return "amp";
}
return null;
}
protected void closeLogFile() throws IOException {
try {
log.flush();
log.close();
} finally {
log = null;
}
}
/**
* Returns a string representation of the given severity.
*/
protected String encodeSeverity(int severity) {
switch (severity) {
case IStatus.ERROR :
return "ERROR";
case IStatus.INFO :
return "INFO";
case IStatus.OK:
return "OK";
case IStatus.WARNING :
return "WARNING";
}
//unknown severity, just print the integer
return Integer.toString(severity);
}
protected String encodeStackTrace(Throwable t) {
StringWriter sWriter = new StringWriter();
PrintWriter pWriter = new PrintWriter(sWriter);
pWriter.println();
t.printStackTrace(pWriter);
pWriter.flush();
return sWriter.toString();
}
protected void endTag(String name) throws IOException {
tabDepth--;
printTag('/' + name, null);
}
/**
* @see ILogListener#logging.
*/
public synchronized void logging(IStatus status, String plugin) {
// thread safety: (Concurrency003)
if (logFile != null)
openLogFile();
if (log == null)
log = new OutputStreamWriter(System.err);
try {
try {
writeLogEntry(status);
} finally {
if (logFile != null)
closeLogFile();
}
} catch (Exception e) {
System.err.println("An exception occurred while writing to the platform log:");
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.err.println("Logging to the console instead.");
//we failed to write, so dump log entry to console instead
try {
log = new OutputStreamWriter(System.err);
writeLogEntry(status);
log.flush();
} catch (Exception e2) {
System.err.println("An exception occurred while logging to the console:");
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
} finally {
log = null;
}
}
protected void openLogFile() {
try {
boolean newLog = !logFile.exists();
log =new BufferedWriter(new FileWriter(logFile.getAbsolutePath(), true));
if (newLog) {
println(XML_VERSION);
startTag(ELEMENT_LOG, null);
}
} catch (IOException e) {
// there was a problem opening the log file so log to the console
log = new OutputStreamWriter(System.err);
}
}
/**
* Writes the given string to the log, followed by the line terminator string.
*/
protected void println(String s) throws IOException {
log.write(s);
log.write(LINE_SEPARATOR);
}
protected void printTabulation() throws IOException {
for (int i = 0; i < tabDepth; i++)
log.write(TAB_STRING);
}
protected void printTag(String name, HashMap parameters) throws IOException {
printTabulation();
log.write('<');
log.write(name);
tabDepth++;
if (parameters != null)
for (Enumeration enum = Collections.enumeration(parameters.keySet()); enum.hasMoreElements();) {
//new line for each attribute if there's more than one
if (parameters.size() > 1) {
log.write(LINE_SEPARATOR);
printTabulation();
}
log.write(" ");
String key = (String) enum.nextElement();
log.write(key);
log.write("=\"");
log.write(getEscaped(String.valueOf(parameters.get(key))));
log.write("\"");
}
tabDepth--;
println(">");
}
/**
* Shuts down the platform log.
*/
public synchronized void shutdown() {
try {
if (logFile != null) {
try {
openLogFile();
endTag(ELEMENT_LOG);
} finally {
closeLogFile();
logFile = null;
}
} else {
if (log != null) {
Writer old = log;
log = null;
old.flush();
old.close();
}
}
} catch (Exception e) {
//we've shutdown the log, so not much else we can do!
e.printStackTrace();
}
}
protected void startTag(String name, HashMap parameters) throws IOException {
printTag(name, parameters);
tabDepth++;
}
protected void write(Throwable throwable) throws IOException {
if (throwable == null)
return;
HashMap attributes = new HashMap();
attributes.put(ATTRIBUTE_MESSAGE, throwable.getMessage());
attributes.put(ATTRIBUTE_TRACE, encodeStackTrace(throwable));
startTag(ELEMENT_EXCEPTION, attributes);
endTag(ELEMENT_EXCEPTION);
}
protected void write(IStatus status) throws IOException {
HashMap attributes = new HashMap();
attributes.put(ATTRIBUTE_SEVERITY, encodeSeverity(status.getSeverity()));
attributes.put(ATTRIBUTE_PLUGIN_ID, status.getPlugin());
attributes.put(ATTRIBUTE_CODE, Integer.toString(status.getCode()));
attributes.put(ATTRIBUTE_MESSAGE, status.getMessage());
startTag(ELEMENT_STATUS, attributes); {
write(status.getException());
if (status.isMultiStatus()) {
IStatus[] children = status.getChildren();
for (int i = 0; i < children.length; i++) {
write(children[i]);
}
}
}
endTag(ELEMENT_STATUS);
}
protected void writeLogEntry(IStatus status) throws IOException {
tabDepth = 0;
HashMap attributes = new HashMap();
attributes.put(ATTRIBUTE_DATE, new Date());
startTag(ELEMENT_LOG_ENTRY, attributes);
write(status);
endTag(ELEMENT_LOG_ENTRY);
}
}