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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [util/] [logging/] [XMLFormatter.java] - Blame information for rev 778

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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