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