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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* StreamHandler.java --
2
   A class for publishing log messages to instances of java.io.OutputStream
3
   Copyright (C) 2002 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.io.OutputStream;
43
import java.io.OutputStreamWriter;
44
import java.io.UnsupportedEncodingException;
45
import java.io.Writer;
46
 
47
/**
48
 * A <code>StreamHandler</code> publishes <code>LogRecords</code> to
49
 * a instances of <code>java.io.OutputStream</code>.
50
 *
51
 * @author Sascha Brawer (brawer@acm.org)
52
 */
53
public class StreamHandler
54
  extends Handler
55
{
56
  private OutputStream  out;
57
  private Writer        writer;
58
 
59
 
60
 /**
61
  * Indicates the current state of this StreamHandler.  The value
62
  * should be one of STATE_FRESH, STATE_PUBLISHED, or STATE_CLOSED.
63
  */
64
  private int streamState = STATE_FRESH;
65
 
66
 
67
  /**
68
   * streamState having this value indicates that the StreamHandler
69
   * has been created, but the publish(LogRecord) method has not been
70
   * called yet.  If the StreamHandler has been constructed without an
71
   * OutputStream, writer will be null, otherwise it is set to a
72
   * freshly created OutputStreamWriter.
73
   */
74
  private static final int STATE_FRESH = 0;
75
 
76
 
77
  /**
78
   * streamState having this value indicates that the publish(LocRecord)
79
   * method has been called at least once.
80
   */
81
  private static final int STATE_PUBLISHED = 1;
82
 
83
 
84
  /**
85
   * streamState having this value indicates that the close() method
86
   * has been called.
87
   */
88
  private static final int STATE_CLOSED = 2;
89
 
90
 
91
  /**
92
   * Creates a <code>StreamHandler</code> without an output stream.
93
   * Subclasses can later use {@link
94
   * #setOutputStream(java.io.OutputStream)} to associate an output
95
   * stream with this StreamHandler.
96
   */
97
  public StreamHandler()
98
  {
99
    this(null, null);
100
  }
101
 
102
 
103
  /**
104
   * Creates a <code>StreamHandler</code> that formats log messages
105
   * with the specified Formatter and publishes them to the specified
106
   * output stream.
107
   *
108
   * @param out the output stream to which the formatted log messages
109
   *     are published.
110
   *
111
   * @param formatter the <code>Formatter</code> that will be used
112
   *     to format log messages.
113
   */
114
  public StreamHandler(OutputStream out, Formatter formatter)
115
  {
116
    this(out, "java.util.logging.StreamHandler", Level.INFO,
117
         formatter, SimpleFormatter.class);
118
  }
119
 
120
 
121
  StreamHandler(
122
    OutputStream out,
123
    String propertyPrefix,
124
    Level defaultLevel,
125
    Formatter formatter, Class defaultFormatterClass)
126
  {
127
    this.level = LogManager.getLevelProperty(propertyPrefix + ".level",
128
                                             defaultLevel);
129
 
130
    this.filter = (Filter) LogManager.getInstanceProperty(
131
      propertyPrefix + ".filter",
132
      /* must be instance of */       Filter.class,
133
      /* default: new instance of */  null);
134
 
135
    if (formatter != null)
136
      this.formatter = formatter;
137
    else
138
      this.formatter = (Formatter) LogManager.getInstanceProperty(
139
        propertyPrefix + ".formatter",
140
        /* must be instance of */       Formatter.class,
141
        /* default: new instance of */  defaultFormatterClass);
142
 
143
    try
144
    {
145
      String enc = LogManager.getLogManager().getProperty(propertyPrefix
146
                                                          + ".encoding");
147
 
148
      /* make sure enc actually is a valid encoding */
149
      if ((enc != null) && (enc.length() > 0))
150
        new String(new byte[0], enc);
151
 
152
      this.encoding = enc;
153
    }
154
    catch (Exception _)
155
    {
156
    }
157
 
158
    if (out != null)
159
    {
160
      try
161
      {
162
        changeWriter(out, getEncoding());
163
      }
164
      catch (UnsupportedEncodingException uex)
165
      {
166
        /* This should never happen, since the validity of the encoding
167
         * name has been checked above.
168
         */
169
        throw new RuntimeException(uex.getMessage());
170
      }
171
    }
172
  }
173
 
174
 
175
  private void checkOpen()
176
  {
177
    if (streamState == STATE_CLOSED)
178
      throw new IllegalStateException(this.toString() + " has been closed");
179
  }
180
 
181
  private void checkFresh()
182
  {
183
    checkOpen();
184
    if (streamState != STATE_FRESH)
185
      throw new IllegalStateException("some log records have been published to " + this);
186
  }
187
 
188
 
189
  private void changeWriter(OutputStream out, String encoding)
190
    throws UnsupportedEncodingException
191
  {
192
    OutputStreamWriter writer;
193
 
194
    /* The logging API says that a null encoding means the default
195
     * platform encoding. However, java.io.OutputStreamWriter needs
196
     * another constructor for the default platform encoding,
197
     * passing null would throw an exception.
198
     */
199
    if (encoding == null)
200
      writer = new OutputStreamWriter(out);
201
    else
202
      writer = new OutputStreamWriter(out, encoding);
203
 
204
    /* Closing the stream has side effects -- do this only after
205
     * creating a new writer has been successful.
206
     */
207
    if ((streamState != STATE_FRESH) || (this.writer != null))
208
      close();
209
 
210
    this.writer = writer;
211
    this.out = out;
212
    this.encoding = encoding;
213
    streamState = STATE_FRESH;
214
  }
215
 
216
 
217
  /**
218
   * Sets the character encoding which this handler uses for publishing
219
   * log records.  The encoding of a <code>StreamHandler</code> must be
220
   * set before any log records have been published.
221
   *
222
   * @param encoding the name of a character encoding, or <code>null</code>
223
   *            for the default encoding.
224
   *
225
   * @throws SecurityException if a security manager exists and
226
   *     the caller is not granted the permission to control the
227
   *     the logging infrastructure.
228
   *
229
   * @exception IllegalStateException if any log records have been
230
   *     published to this <code>StreamHandler</code> before.  Please
231
   *     be aware that this is a pecularity of the GNU implementation.
232
   *     While the API specification indicates that it is an error
233
   *     if the encoding is set after records have been published,
234
   *     it does not mandate any specific behavior for that case.
235
   */
236
  public void setEncoding(String encoding)
237
    throws SecurityException, UnsupportedEncodingException
238
  {
239
    /* The inherited implementation first checks whether the invoking
240
     * code indeed has the permission to control the logging infra-
241
     * structure, and throws a SecurityException if this was not the
242
     * case.
243
     *
244
     * Next, it verifies that the encoding is supported and throws
245
     * an UnsupportedEncodingExcpetion otherwise. Finally, it remembers
246
     * the name of the encoding.
247
     */
248
    super.setEncoding(encoding);
249
 
250
    checkFresh();
251
 
252
    /* If out is null, setEncoding is being called before an output
253
     * stream has been set. In that case, we need to check that the
254
     * encoding is valid, and remember it if this is the case.  Since
255
     * this is exactly what the inherited implementation of
256
     * Handler.setEncoding does, we can delegate.
257
     */
258
    if (out != null)
259
    {
260
      /* The logging API says that a null encoding means the default
261
       * platform encoding. However, java.io.OutputStreamWriter needs
262
       * another constructor for the default platform encoding, passing
263
       * null would throw an exception.
264
       */
265
      if (encoding == null)
266
        writer = new OutputStreamWriter(out);
267
      else
268
        writer = new OutputStreamWriter(out, encoding);
269
    }
270
  }
271
 
272
 
273
  /**
274
   * Changes the output stream to which this handler publishes
275
   * logging records.
276
   *
277
   * @throws SecurityException if a security manager exists and
278
   *         the caller is not granted the permission to control
279
   *         the logging infrastructure.
280
   *
281
   * @throws NullPointerException if <code>out</code>
282
   *         is <code>null</code>.
283
   */
284
  protected void setOutputStream(OutputStream out)
285
    throws SecurityException
286
  {
287
    LogManager.getLogManager().checkAccess();
288
 
289
    /* Throw a NullPointerException if out is null. */
290
    out.getClass();
291
 
292
    try
293
    {
294
      changeWriter(out, getEncoding());
295
    }
296
    catch (UnsupportedEncodingException ex)
297
    {
298
      /* This seems quite unlikely to happen, unless the underlying
299
       * implementation of java.io.OutputStreamWriter changes its
300
       * mind (at runtime) about the set of supported character
301
       * encodings.
302
       */
303
      throw new RuntimeException(ex.getMessage());
304
    }
305
  }
306
 
307
 
308
  /**
309
   * Publishes a <code>LogRecord</code> to the associated output
310
   * stream, provided the record passes all tests for being loggable.
311
   * The <code>StreamHandler</code> will localize the message of the
312
   * log record and substitute any message parameters.
313
   *
314
   * <p>Most applications do not need to call this method directly.
315
   * Instead, they will use use a {@link Logger}, which will create
316
   * LogRecords and distribute them to registered handlers.
317
   *
318
   * <p>In case of an I/O failure, the <code>ErrorManager</code>
319
   * of this <code>Handler</code> will be informed, but the caller
320
   * of this method will not receive an exception.
321
   *
322
   * <p>If a log record is being published to a
323
   * <code>StreamHandler</code> that has been closed earlier, the Sun
324
   * J2SE 1.4 reference can be observed to silently ignore the
325
   * call. The GNU implementation, however, intentionally behaves
326
   * differently by informing the <code>ErrorManager</code> associated
327
   * with this <code>StreamHandler</code>.  Since the condition
328
   * indicates a programming error, the programmer should be
329
   * informed. It also seems extremely unlikely that any application
330
   * would depend on the exact behavior in this rather obscure,
331
   * erroneous case -- especially since the API specification does not
332
   * prescribe what is supposed to happen.
333
   *
334
   * @param record the log event to be published.
335
   */
336
  public void publish(LogRecord record)
337
  {
338
    String formattedMessage;
339
 
340
    if (!isLoggable(record))
341
      return;
342
 
343
    if (streamState == STATE_FRESH)
344
    {
345
      try
346
      {
347
        writer.write(formatter.getHead(this));
348
      }
349
      catch (java.io.IOException ex)
350
      {
351
        reportError(null, ex, ErrorManager.WRITE_FAILURE);
352
        return;
353
      }
354
      catch (Exception ex)
355
      {
356
        reportError(null, ex, ErrorManager.GENERIC_FAILURE);
357
        return;
358
      }
359
 
360
      streamState = STATE_PUBLISHED;
361
    }
362
 
363
    try
364
    {
365
      formattedMessage = formatter.format(record);
366
    }
367
    catch (Exception ex)
368
    {
369
      reportError(null, ex, ErrorManager.FORMAT_FAILURE);
370
      return;
371
    }
372
 
373
    try
374
    {
375
      writer.write(formattedMessage);
376
    }
377
    catch (Exception ex)
378
    {
379
      reportError(null, ex, ErrorManager.WRITE_FAILURE);
380
    }
381
  }
382
 
383
 
384
  /**
385
   * Checks whether or not a <code>LogRecord</code> would be logged
386
   * if it was passed to this <code>StreamHandler</code> for publication.
387
   *
388
   * <p>The <code>StreamHandler</code> implementation first checks
389
   * whether a writer is present and the handler's level is greater
390
   * than or equal to the severity level threshold.  In a second step,
391
   * if a {@link Filter} has been installed, its {@link
392
   * Filter#isLoggable(LogRecord) isLoggable} method is
393
   * invoked. Subclasses of <code>StreamHandler</code> can override
394
   * this method to impose their own constraints.
395
   *
396
   * @param record the <code>LogRecord</code> to be checked.
397
   *
398
   * @return <code>true</code> if <code>record</code> would
399
   *         be published by {@link #publish(LogRecord) publish},
400
   *         <code>false</code> if it would be discarded.
401
   *
402
   * @see #setLevel(Level)
403
   * @see #setFilter(Filter)
404
   * @see Filter#isLoggable(LogRecord)
405
   *
406
   * @throws NullPointerException if <code>record</code> is
407
   *         <code>null</code>.  */
408
  public boolean isLoggable(LogRecord record)
409
  {
410
    return (writer != null) && super.isLoggable(record);
411
  }
412
 
413
 
414
  /**
415
   * Forces any data that may have been buffered to the underlying
416
   * output device.
417
   *
418
   * <p>In case of an I/O failure, the <code>ErrorManager</code>
419
   * of this <code>Handler</code> will be informed, but the caller
420
   * of this method will not receive an exception.
421
   *
422
   * <p>If a <code>StreamHandler</code> that has been closed earlier
423
   * is closed a second time, the Sun J2SE 1.4 reference can be
424
   * observed to silently ignore the call. The GNU implementation,
425
   * however, intentionally behaves differently by informing the
426
   * <code>ErrorManager</code> associated with this
427
   * <code>StreamHandler</code>.  Since the condition indicates a
428
   * programming error, the programmer should be informed. It also
429
   * seems extremely unlikely that any application would depend on the
430
   * exact behavior in this rather obscure, erroneous case --
431
   * especially since the API specification does not prescribe what is
432
   * supposed to happen.
433
   */
434
  public void flush()
435
  {
436
    try
437
    {
438
      checkOpen();
439
      if (writer != null)
440
        writer.flush();
441
    }
442
    catch (Exception ex)
443
    {
444
      reportError(null, ex, ErrorManager.FLUSH_FAILURE);
445
    }
446
  }
447
 
448
 
449
  /**
450
   * Closes this <code>StreamHandler</code> after having forced any
451
   * data that may have been buffered to the underlying output
452
   * device.
453
   *
454
   * <p>As soon as <code>close</code> has been called,
455
   * a <code>Handler</code> should not be used anymore. Attempts
456
   * to publish log records, to flush buffers, or to modify the
457
   * <code>Handler</code> in any other way may throw runtime
458
   * exceptions after calling <code>close</code>.</p>
459
   *
460
   * <p>In case of an I/O failure, the <code>ErrorManager</code>
461
   * of this <code>Handler</code> will be informed, but the caller
462
   * of this method will not receive an exception.</p>
463
   *
464
   * <p>If a <code>StreamHandler</code> that has been closed earlier
465
   * is closed a second time, the Sun J2SE 1.4 reference can be
466
   * observed to silently ignore the call. The GNU implementation,
467
   * however, intentionally behaves differently by informing the
468
   * <code>ErrorManager</code> associated with this
469
   * <code>StreamHandler</code>.  Since the condition indicates a
470
   * programming error, the programmer should be informed. It also
471
   * seems extremely unlikely that any application would depend on the
472
   * exact behavior in this rather obscure, erroneous case --
473
   * especially since the API specification does not prescribe what is
474
   * supposed to happen.
475
   *
476
   * @throws SecurityException if a security manager exists and
477
   *         the caller is not granted the permission to control
478
   *         the logging infrastructure.
479
   */
480
  public void close()
481
    throws SecurityException
482
  {
483
    LogManager.getLogManager().checkAccess();
484
 
485
    try
486
    {
487
      /* Although  flush also calls checkOpen, it catches
488
       * any exceptions and reports them to the ErrorManager
489
       * as flush failures.  However, we want to report
490
       * a closed stream as a close failure, not as a
491
       * flush failure here.  Therefore, we call checkOpen()
492
       * before flush().
493
       */
494
      checkOpen();
495
      flush();
496
 
497
      if (writer != null)
498
      {
499
        if (formatter != null)
500
        {
501
          /* Even if the StreamHandler has never published a record,
502
           * it emits head and tail upon closing. An earlier version
503
           * of the GNU Classpath implementation did not emitted
504
           * anything. However, this had caused XML log files to be
505
           * entirely empty instead of containing no log records.
506
           */
507
          if (streamState == STATE_FRESH)
508
            writer.write(formatter.getHead(this));
509
          if (streamState != STATE_CLOSED)
510
            writer.write(formatter.getTail(this));
511
        }
512
        streamState = STATE_CLOSED;
513
        writer.close();
514
      }
515
    }
516
    catch (Exception ex)
517
    {
518
      reportError(null, ex, ErrorManager.CLOSE_FAILURE);
519
    }
520
  }
521
}

powered by: WebSVN 2.1.0

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