jdk/src/share/classes/java/util/logging/XMLFormatter.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/logging/XMLFormatter.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+package java.util.logging;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * Format a LogRecord into a standard XML format.
+ * <p>
+ * The DTD specification is provided as Appendix A to the
+ * Java Logging APIs specification.
+ * <p>
+ * The XMLFormatter can be used with arbitrary character encodings,
+ * but it is recommended that it normally be used with UTF-8.  The
+ * character encoding can be set on the output Handler.
+ *
+ * @since 1.4
+ */
+
+public class XMLFormatter extends Formatter {
+    private LogManager manager = LogManager.getLogManager();
+
+    // Append a two digit number.
+    private void a2(StringBuffer sb, int x) {
+        if (x < 10) {
+            sb.append('0');
+        }
+        sb.append(x);
+    }
+
+    // Append the time and date in ISO 8601 format
+    private void appendISO8601(StringBuffer sb, long millis) {
+        Date date = new Date(millis);
+        sb.append(date.getYear() + 1900);
+        sb.append('-');
+        a2(sb, date.getMonth() + 1);
+        sb.append('-');
+        a2(sb, date.getDate());
+        sb.append('T');
+        a2(sb, date.getHours());
+        sb.append(':');
+        a2(sb, date.getMinutes());
+        sb.append(':');
+        a2(sb, date.getSeconds());
+    }
+
+    // Append to the given StringBuffer an escaped version of the
+    // given text string where XML special characters have been escaped.
+    // For a null string we append "<null>"
+    private void escape(StringBuffer sb, String text) {
+        if (text == null) {
+            text = "<null>";
+        }
+        for (int i = 0; i < text.length(); i++) {
+            char ch = text.charAt(i);
+            if (ch == '<') {
+                sb.append("&lt;");
+            } else if (ch == '>') {
+                sb.append("&gt;");
+            } else if (ch == '&') {
+                sb.append("&amp;");
+            } else {
+                sb.append(ch);
+            }
+        }
+    }
+
+    /**
+     * Format the given message to XML.
+     * <p>
+     * This method can be overridden in a subclass.
+     * It is recommended to use the {@link Formatter#formatMessage}
+     * convenience method to localize and format the message field.
+     *
+     * @param record the log record to be formatted.
+     * @return a formatted log record
+     */
+    public String format(LogRecord record) {
+        StringBuffer sb = new StringBuffer(500);
+        sb.append("<record>\n");
+
+        sb.append("  <date>");
+        appendISO8601(sb, record.getMillis());
+        sb.append("</date>\n");
+
+        sb.append("  <millis>");
+        sb.append(record.getMillis());
+        sb.append("</millis>\n");
+
+        sb.append("  <sequence>");
+        sb.append(record.getSequenceNumber());
+        sb.append("</sequence>\n");
+
+        String name = record.getLoggerName();
+        if (name != null) {
+            sb.append("  <logger>");
+            escape(sb, name);
+            sb.append("</logger>\n");
+        }
+
+        sb.append("  <level>");
+        escape(sb, record.getLevel().toString());
+        sb.append("</level>\n");
+
+        if (record.getSourceClassName() != null) {
+            sb.append("  <class>");
+            escape(sb, record.getSourceClassName());
+            sb.append("</class>\n");
+        }
+
+        if (record.getSourceMethodName() != null) {
+            sb.append("  <method>");
+            escape(sb, record.getSourceMethodName());
+            sb.append("</method>\n");
+        }
+
+        sb.append("  <thread>");
+        sb.append(record.getThreadID());
+        sb.append("</thread>\n");
+
+        if (record.getMessage() != null) {
+            // Format the message string and its accompanying parameters.
+            String message = formatMessage(record);
+            sb.append("  <message>");
+            escape(sb, message);
+            sb.append("</message>");
+            sb.append("\n");
+        }
+
+        // If the message is being localized, output the key, resource
+        // bundle name, and params.
+        ResourceBundle bundle = record.getResourceBundle();
+        try {
+            if (bundle != null && bundle.getString(record.getMessage()) != null) {
+                sb.append("  <key>");
+                escape(sb, record.getMessage());
+                sb.append("</key>\n");
+                sb.append("  <catalog>");
+                escape(sb, record.getResourceBundleName());
+                sb.append("</catalog>\n");
+            }
+        } catch (Exception ex) {
+            // The message is not in the catalog.  Drop through.
+        }
+
+        Object parameters[] = record.getParameters();
+        //  Check to see if the parameter was not a messagetext format
+        //  or was not null or empty
+        if ( parameters != null && parameters.length != 0
+                && record.getMessage().indexOf("{") == -1 ) {
+            for (int i = 0; i < parameters.length; i++) {
+                sb.append("  <param>");
+                try {
+                    escape(sb, parameters[i].toString());
+                } catch (Exception ex) {
+                    sb.append("???");
+                }
+                sb.append("</param>\n");
+            }
+        }
+
+        if (record.getThrown() != null) {
+            // Report on the state of the throwable.
+            Throwable th = record.getThrown();
+            sb.append("  <exception>\n");
+            sb.append("    <message>");
+            escape(sb, th.toString());
+            sb.append("</message>\n");
+            StackTraceElement trace[] = th.getStackTrace();
+            for (int i = 0; i < trace.length; i++) {
+                StackTraceElement frame = trace[i];
+                sb.append("    <frame>\n");
+                sb.append("      <class>");
+                escape(sb, frame.getClassName());
+                sb.append("</class>\n");
+                sb.append("      <method>");
+                escape(sb, frame.getMethodName());
+                sb.append("</method>\n");
+                // Check for a line number.
+                if (frame.getLineNumber() >= 0) {
+                    sb.append("      <line>");
+                    sb.append(frame.getLineNumber());
+                    sb.append("</line>\n");
+                }
+                sb.append("    </frame>\n");
+            }
+            sb.append("  </exception>\n");
+        }
+
+        sb.append("</record>\n");
+        return sb.toString();
+    }
+
+    /**
+     * Return the header string for a set of XML formatted records.
+     *
+     * @param   h  The target handler (can be null)
+     * @return  a valid XML string
+     */
+    public String getHead(Handler h) {
+        StringBuffer sb = new StringBuffer();
+        String encoding;
+        sb.append("<?xml version=\"1.0\"");
+
+        if (h != null) {
+            encoding = h.getEncoding();
+        } else {
+            encoding = null;
+        }
+
+        if (encoding == null) {
+            // Figure out the default encoding.
+            encoding = java.nio.charset.Charset.defaultCharset().name();
+        }
+        // Try to map the encoding name to a canonical name.
+        try {
+            Charset cs = Charset.forName(encoding);
+            encoding = cs.name();
+        } catch (Exception ex) {
+            // We hit problems finding a canonical name.
+            // Just use the raw encoding name.
+        }
+
+        sb.append(" encoding=\"");
+        sb.append(encoding);
+        sb.append("\"");
+        sb.append(" standalone=\"no\"?>\n");
+        sb.append("<!DOCTYPE log SYSTEM \"logger.dtd\">\n");
+        sb.append("<log>\n");
+        return sb.toString();
+    }
+
+    /**
+     * Return the tail string for a set of XML formatted records.
+     *
+     * @param   h  The target handler (can be null)
+     * @return  a valid XML string
+     */
+    public String getTail(Handler h) {
+        return "</log>\n";
+    }
+}