OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [util/] [logging/] [XMLFormatter.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* XMLFormatter.java --
2
   A class for formatting log messages into a standard XML format
3
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package java.util.logging;
41
 
42
import java.text.SimpleDateFormat;
43
import java.util.Date;
44
import java.util.ResourceBundle;
45
 
46
/**
47
 * An <code>XMLFormatter</code> formats LogRecords into
48
 * a standard XML format.
49
 *
50
 * @author Sascha Brawer (brawer@acm.org)
51
 */
52
public class XMLFormatter
53
  extends Formatter
54
{
55
  /**
56
   * Constructs a new XMLFormatter.
57
   */
58
  public XMLFormatter()
59
  {
60
  }
61
 
62
 
63
  /**
64
   * The character sequence that is used to separate lines in the
65
   * generated XML stream. Somewhat surprisingly, the Sun J2SE 1.4
66
   * reference implementation always uses UNIX line endings, even on
67
   * platforms that have different line ending conventions (i.e.,
68
   * DOS). The GNU Classpath implementation does not replicates this
69
   * bug.
70
   *
71
   * See also the Sun bug parade, bug #4462871,
72
   * "java.util.logging.SimpleFormatter uses hard-coded line separator".
73
   */
74
  private static final String lineSep = SimpleFormatter.lineSep;
75
 
76
 
77
  /**
78
   * A DateFormat for emitting time in the ISO 8601 format.
79
   * Since the API specification of SimpleDateFormat does not talk
80
   * about its thread-safety, we cannot share a singleton instance.
81
   */
82
  private final SimpleDateFormat iso8601
83
    = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
84
 
85
 
86
  /**
87
   * Appends a line consisting of indentation, opening element tag,
88
   * element content, closing element tag and line separator to
89
   * a StringBuffer, provided that the element content is
90
   * actually existing.
91
   *
92
   * @param buf the StringBuffer to which the line will be appended.
93
   *
94
   * @param indent the indentation level.
95
   *
96
   * @param tag the element tag name, for instance <code>method</code>.
97
   *
98
   * @param content the element content, or <code>null</code> to
99
   *        have no output whatsoever appended to <code>buf</code>.
100
   */
101
  private static void appendTag(StringBuffer buf, int indent,
102
                                String tag, String content)
103
  {
104
    int i;
105
 
106
    if (content == null)
107
      return;
108
 
109
    for (i = 0; i < indent * 2; i++)
110
      buf.append(' ');
111
 
112
    buf.append("<");
113
    buf.append(tag);
114
    buf.append('>');
115
 
116
    /* Append the content, but escape for XML by replacing
117
     * '&', '<', '>' and all non-ASCII characters with
118
     * appropriate escape sequences.
119
     * The Sun J2SE 1.4 reference implementation does not
120
     * escape non-ASCII characters. This is a bug in their
121
     * implementation which has been reported in the Java
122
     * bug parade as bug number (FIXME: Insert number here).
123
     */
124
    for (i = 0; i < content.length(); i++)
125
    {
126
      char c = content.charAt(i);
127
      switch (c)
128
      {
129
      case '&':
130
        buf.append("&amp;");
131
        break;
132
 
133
      case '<':
134
        buf.append("&lt;");
135
        break;
136
 
137
      case '>':
138
        buf.append("&gt;");
139
        break;
140
 
141
      default:
142
        if (((c >= 0x20) && (c <= 0x7e))
143
            || (c == /* line feed */ 10)
144
            || (c == /* carriage return */ 13))
145
          buf.append(c);
146
        else
147
        {
148
          buf.append("&#");
149
          buf.append((int) c);
150
          buf.append(';');
151
        }
152
        break;
153
      } /* switch (c) */
154
    } /* for i */
155
 
156
    buf.append("</");
157
    buf.append(tag);
158
    buf.append(">");
159
    buf.append(lineSep);
160
  }
161
 
162
 
163
  /**
164
   * Appends a line consisting of indentation, opening element tag,
165
   * numeric element content, closing element tag and line separator
166
   * to a StringBuffer.
167
   *
168
   * @param buf the StringBuffer to which the line will be appended.
169
   *
170
   * @param indent the indentation level.
171
   *
172
   * @param tag the element tag name, for instance <code>method</code>.
173
   *
174
   * @param content the element content.
175
   */
176
  private static void appendTag(StringBuffer buf, int indent,
177
                                String tag, long content)
178
  {
179
    appendTag(buf, indent, tag, Long.toString(content));
180
  }
181
 
182
 
183
  public String format(LogRecord record)
184
  {
185
    StringBuffer    buf = new StringBuffer(400);
186
    Level           level = record.getLevel();
187
    long            millis = record.getMillis();
188
    Object[]        params = record.getParameters();
189
    ResourceBundle  bundle = record.getResourceBundle();
190
    String          message;
191
 
192
    buf.append("<record>");
193
    buf.append(lineSep);
194
 
195
 
196
    appendTag(buf, 1, "date", iso8601.format(new Date(millis)));
197
    appendTag(buf, 1, "millis", record.getMillis());
198
    appendTag(buf, 1, "sequence", record.getSequenceNumber());
199
    appendTag(buf, 1, "logger", record.getLoggerName());
200
 
201
    if (level.isStandardLevel())
202
      appendTag(buf, 1, "level", level.toString());
203
    else
204
      appendTag(buf, 1, "level", level.intValue());
205
 
206
    appendTag(buf, 1, "class", record.getSourceClassName());
207
    appendTag(buf, 1, "method", record.getSourceMethodName());
208
    appendTag(buf, 1, "thread", record.getThreadID());
209
 
210
    /* The Sun J2SE 1.4 reference implementation does not emit the
211
     * message in localized form. This is in violation of the API
212
     * specification. The GNU Classpath implementation intentionally
213
     * replicates the buggy behavior of the Sun implementation, as
214
     * different log files might be a big nuisance to users.
215
     */
216
    try
217
    {
218
      record.setResourceBundle(null);
219
      message = formatMessage(record);
220
    }
221
    finally
222
    {
223
      record.setResourceBundle(bundle);
224
    }
225
    appendTag(buf, 1, "message", message);
226
 
227
    /* The Sun J2SE 1.4 reference implementation does not
228
     * emit key, catalog and param tags. This is in violation
229
     * of the API specification.  The Classpath implementation
230
     * intentionally replicates the buggy behavior of the
231
     * Sun implementation, as different log files might be
232
     * a big nuisance to users.
233
     *
234
     * FIXME: File a bug report with Sun. Insert bug number here.
235
     *
236
     *
237
     * key = record.getMessage();
238
     * if (key == null)
239
     *   key = "";
240
     *
241
     * if ((bundle != null) && !key.equals(message))
242
     * {
243
     *   appendTag(buf, 1, "key", key);
244
     *   appendTag(buf, 1, "catalog", record.getResourceBundleName());
245
     * }
246
     *
247
     * if (params != null)
248
     * {
249
     *   for (int i = 0; i < params.length; i++)
250
     *     appendTag(buf, 1, "param", params[i].toString());
251
     * }
252
     */
253
 
254
    /* FIXME: We have no way to obtain the stacktrace before free JVMs
255
     * support the corresponding method in java.lang.Throwable.  Well,
256
     * it would be possible to parse the output of printStackTrace,
257
     * but this would be pretty kludgy. Instead, we postpose the
258
     * implementation until Throwable has made progress.
259
     */
260
    Throwable thrown = record.getThrown();
261
    if (thrown != null)
262
    {
263
      buf.append("  <exception>");
264
      buf.append(lineSep);
265
 
266
      /* The API specification is not clear about what exactly
267
       * goes into the XML record for a thrown exception: It
268
       * could be the result of getMessage(), getLocalizedMessage(),
269
       * or toString(). Therefore, it was necessary to write a
270
       * Mauve testlet and run it with the Sun J2SE 1.4 reference
271
       * implementation. It turned out that the we need to call
272
       * toString().
273
       *
274
       * FIXME: File a bug report with Sun, asking for clearer
275
       * specs.
276
       */
277
      appendTag(buf, 2, "message", thrown.toString());
278
 
279
      /* FIXME: The Logging DTD specifies:
280
       *
281
       * <!ELEMENT exception (message?, frame+)>
282
       *
283
       * However, java.lang.Throwable.getStackTrace() is
284
       * allowed to return an empty array. So, what frame should
285
       * be emitted for an empty stack trace? We probably
286
       * should file a bug report with Sun, asking for the DTD
287
       * to be changed.
288
       */
289
 
290
      buf.append("  </exception>");
291
      buf.append(lineSep);
292
    }
293
 
294
 
295
    buf.append("</record>");
296
    buf.append(lineSep);
297
 
298
    return buf.toString();
299
  }
300
 
301
 
302
  /**
303
   * Returns a string that handlers are supposed to emit before
304
   * the first log record.  The base implementation returns an
305
   * empty string, but subclasses such as {@link XMLFormatter}
306
   * override this method in order to provide a suitable header.
307
   *
308
   * @return a string for the header.
309
   *
310
   * @param h the handler which will prepend the returned
311
   *     string in front of the first log record.  This method
312
   *     will inspect certain properties of the handler, for
313
   *     example its encoding, in order to construct the header.
314
   */
315
  public String getHead(Handler h)
316
  {
317
    StringBuffer  buf;
318
    String        encoding;
319
 
320
    buf = new StringBuffer(80);
321
    buf.append("<?xml version=\"1.0\" encoding=\"");
322
 
323
    encoding = h.getEncoding();
324
 
325
    /* file.encoding is a system property with the Sun JVM, indicating
326
     * the platform-default file encoding. Unfortunately, the API
327
     * specification for java.lang.System.getProperties() does not
328
     * list this property.
329
     */
330
    if (encoding == null)
331
      encoding = System.getProperty("file.encoding");
332
 
333
    /* Since file.encoding is not listed with the API specification of
334
     * java.lang.System.getProperties(), there might be some VMs that
335
     * do not define this system property.  Therefore, we use UTF-8 as
336
     * a reasonable default. Please note that if the platform encoding
337
     * uses the same codepoints as US-ASCII for the US-ASCII character
338
     * set (e.g, 65 for A), it does not matter whether we emit the
339
     * wrong encoding into the XML header -- the GNU Classpath will
340
     * emit XML escape sequences like &#1234; for any non-ASCII
341
     * character.  Virtually all character encodings use the same code
342
     * points as US-ASCII for ASCII characters.  Probably, EBCDIC is
343
     * the only exception.
344
     */
345
    if (encoding == null)
346
      encoding = "UTF-8";
347
 
348
    /* On Windows XP localized for Swiss German (this is one of
349
     * my [Sascha Brawer's] test machines), the default encoding
350
     * has the canonical name "windows-1252". The "historical" name
351
     * of this encoding is "Cp1252" (see the Javadoc for the class
352
     * java.nio.charset.Charset for the distinction). Now, that class
353
     * does have a method for mapping historical to canonical encoding
354
     * names. However, if we used it here, we would be come dependent
355
     * on java.nio.*, which was only introduced with J2SE 1.4.
356
     * Thus, we do this little hack here. As soon as Classpath supports
357
     * java.nio.charset.CharSet, this hack should be replaced by
358
     * code that correctly canonicalizes the encoding name.
359
     */
360
    if ((encoding.length() > 2) && encoding.startsWith("Cp"))
361
      encoding = "windows-" + encoding.substring(2);
362
 
363
    buf.append(encoding);
364
 
365
    buf.append("\" standalone=\"no\"?>");
366
    buf.append(lineSep);
367
 
368
    /* SYSTEM is not a fully qualified URL so that validating
369
     * XML parsers do not need to connect to the Internet in
370
     * order to read in a log file.  See also the Sun Bug Parade,
371
     * bug #4372790, "Logging APIs: need to use relative URL for XML
372
     * doctype".
373
     */
374
    buf.append("<!DOCTYPE log SYSTEM \"logger.dtd\">");
375
    buf.append(lineSep);
376
    buf.append("<log>");
377
    buf.append(lineSep);
378
 
379
    return buf.toString();
380
  }
381
 
382
 
383
  public String getTail(Handler h)
384
  {
385
    return "</log>" + lineSep;
386
  }
387
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.