Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.logging/share/classes/java/util/logging/StreamHandler.java
41159 views
1
/*
2
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
27
package java.util.logging;
28
29
import java.io.*;
30
import java.security.AccessController;
31
import java.security.PrivilegedAction;
32
import java.util.Objects;
33
34
/**
35
* Stream based logging {@code Handler}.
36
* <p>
37
* This is primarily intended as a base class or support class to
38
* be used in implementing other logging {@code Handlers}.
39
* <p>
40
* {@code LogRecords} are published to a given {@code java.io.OutputStream}.
41
* <p>
42
* <b>Configuration:</b>
43
* By default each {@code StreamHandler} is initialized using the following
44
* {@code LogManager} configuration properties where {@code <handler-name>}
45
* refers to the fully-qualified class name of the handler.
46
* If properties are not defined
47
* (or have invalid values) then the specified default values are used.
48
* <ul>
49
* <li> &lt;handler-name&gt;.level
50
* specifies the default level for the {@code Handler}
51
* (defaults to {@code Level.INFO}). </li>
52
* <li> &lt;handler-name&gt;.filter
53
* specifies the name of a {@code Filter} class to use
54
* (defaults to no {@code Filter}). </li>
55
* <li> &lt;handler-name&gt;.formatter
56
* specifies the name of a {@code Formatter} class to use
57
* (defaults to {@code java.util.logging.SimpleFormatter}). </li>
58
* <li> &lt;handler-name&gt;.encoding
59
* the name of the character set encoding to use (defaults to
60
* the default platform encoding). </li>
61
* </ul>
62
* <p>
63
* For example, the properties for {@code StreamHandler} would be:
64
* <ul>
65
* <li> java.util.logging.StreamHandler.level=INFO </li>
66
* <li> java.util.logging.StreamHandler.formatter=java.util.logging.SimpleFormatter </li>
67
* </ul>
68
* <p>
69
* For a custom handler, e.g. com.foo.MyHandler, the properties would be:
70
* <ul>
71
* <li> com.foo.MyHandler.level=INFO </li>
72
* <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
73
* </ul>
74
*
75
* @since 1.4
76
*/
77
78
public class StreamHandler extends Handler {
79
private OutputStream output;
80
private boolean doneHeader;
81
private volatile Writer writer;
82
83
/**
84
* Create a {@code StreamHandler}, with no current output stream.
85
*/
86
public StreamHandler() {
87
// configure with specific defaults for StreamHandler
88
super(Level.INFO, new SimpleFormatter(), null);
89
}
90
91
/**
92
* Create a {@code StreamHandler} with a given {@code Formatter}
93
* and output stream.
94
*
95
* @param out the target output stream
96
* @param formatter Formatter to be used to format output
97
*/
98
public StreamHandler(OutputStream out, Formatter formatter) {
99
// configure with default level but use specified formatter
100
super(Level.INFO, null, Objects.requireNonNull(formatter));
101
102
setOutputStreamPrivileged(out);
103
}
104
105
/**
106
* @see Handler#Handler(Level, Formatter, Formatter)
107
*/
108
StreamHandler(Level defaultLevel,
109
Formatter defaultFormatter,
110
Formatter specifiedFormatter) {
111
super(defaultLevel, defaultFormatter, specifiedFormatter);
112
}
113
114
/**
115
* Change the output stream.
116
* <P>
117
* If there is a current output stream then the {@code Formatter}'s
118
* tail string is written and the stream is flushed and closed.
119
* Then the output stream is replaced with the new output stream.
120
*
121
* @param out New output stream. May not be null.
122
* @throws SecurityException if a security manager exists and if
123
* the caller does not have {@code LoggingPermission("control")}.
124
*/
125
protected synchronized void setOutputStream(OutputStream out) throws SecurityException {
126
if (out == null) {
127
throw new NullPointerException();
128
}
129
flushAndClose();
130
output = out;
131
doneHeader = false;
132
String encoding = getEncoding();
133
if (encoding == null) {
134
writer = new OutputStreamWriter(output);
135
} else {
136
try {
137
writer = new OutputStreamWriter(output, encoding);
138
} catch (UnsupportedEncodingException ex) {
139
// This shouldn't happen. The setEncoding method
140
// should have validated that the encoding is OK.
141
throw new Error("Unexpected exception " + ex);
142
}
143
}
144
}
145
146
/**
147
* Set (or change) the character encoding used by this {@code Handler}.
148
* <p>
149
* The encoding should be set before any {@code LogRecords} are written
150
* to the {@code Handler}.
151
*
152
* @param encoding The name of a supported character encoding.
153
* May be null, to indicate the default platform encoding.
154
* @throws SecurityException if a security manager exists and if
155
* the caller does not have {@code LoggingPermission("control")}.
156
* @throws UnsupportedEncodingException if the named encoding is
157
* not supported.
158
*/
159
@Override
160
public synchronized void setEncoding(String encoding)
161
throws SecurityException, java.io.UnsupportedEncodingException {
162
super.setEncoding(encoding);
163
if (output == null) {
164
return;
165
}
166
// Replace the current writer with a writer for the new encoding.
167
flush();
168
if (encoding == null) {
169
writer = new OutputStreamWriter(output);
170
} else {
171
writer = new OutputStreamWriter(output, encoding);
172
}
173
}
174
175
/**
176
* Format and publish a {@code LogRecord}.
177
* <p>
178
* The {@code StreamHandler} first checks if there is an {@code OutputStream}
179
* and if the given {@code LogRecord} has at least the required log level.
180
* If not it silently returns. If so, it calls any associated
181
* {@code Filter} to check if the record should be published. If so,
182
* it calls its {@code Formatter} to format the record and then writes
183
* the result to the current output stream.
184
* <p>
185
* If this is the first {@code LogRecord} to be written to a given
186
* {@code OutputStream}, the {@code Formatter}'s "head" string is
187
* written to the stream before the {@code LogRecord} is written.
188
*
189
* @param record description of the log event. A null record is
190
* silently ignored and is not published
191
*/
192
@Override
193
public synchronized void publish(LogRecord record) {
194
if (!isLoggable(record)) {
195
return;
196
}
197
String msg;
198
try {
199
msg = getFormatter().format(record);
200
} catch (Exception ex) {
201
// We don't want to throw an exception here, but we
202
// report the exception to any registered ErrorManager.
203
reportError(null, ex, ErrorManager.FORMAT_FAILURE);
204
return;
205
}
206
207
try {
208
if (!doneHeader) {
209
writer.write(getFormatter().getHead(this));
210
doneHeader = true;
211
}
212
writer.write(msg);
213
} catch (Exception ex) {
214
// We don't want to throw an exception here, but we
215
// report the exception to any registered ErrorManager.
216
reportError(null, ex, ErrorManager.WRITE_FAILURE);
217
}
218
}
219
220
221
/**
222
* Check if this {@code Handler} would actually log a given {@code LogRecord}.
223
* <p>
224
* This method checks if the {@code LogRecord} has an appropriate level and
225
* whether it satisfies any {@code Filter}. It will also return false if
226
* no output stream has been assigned yet or the LogRecord is null.
227
*
228
* @param record a {@code LogRecord} (may be null).
229
* @return true if the {@code LogRecord} would be logged.
230
*
231
*/
232
@Override
233
public boolean isLoggable(LogRecord record) {
234
if (writer == null || record == null) {
235
return false;
236
}
237
return super.isLoggable(record);
238
}
239
240
/**
241
* Flush any buffered messages.
242
*/
243
@Override
244
public synchronized void flush() {
245
if (writer != null) {
246
try {
247
writer.flush();
248
} catch (Exception ex) {
249
// We don't want to throw an exception here, but we
250
// report the exception to any registered ErrorManager.
251
reportError(null, ex, ErrorManager.FLUSH_FAILURE);
252
}
253
}
254
}
255
256
private synchronized void flushAndClose() throws SecurityException {
257
checkPermission();
258
if (writer != null) {
259
try {
260
if (!doneHeader) {
261
writer.write(getFormatter().getHead(this));
262
doneHeader = true;
263
}
264
writer.write(getFormatter().getTail(this));
265
writer.flush();
266
writer.close();
267
} catch (Exception ex) {
268
// We don't want to throw an exception here, but we
269
// report the exception to any registered ErrorManager.
270
reportError(null, ex, ErrorManager.CLOSE_FAILURE);
271
}
272
writer = null;
273
output = null;
274
}
275
}
276
277
/**
278
* Close the current output stream.
279
* <p>
280
* The {@code Formatter}'s "tail" string is written to the stream before it
281
* is closed. In addition, if the {@code Formatter}'s "head" string has not
282
* yet been written to the stream, it will be written before the
283
* "tail" string.
284
*
285
* @throws SecurityException if a security manager exists and if
286
* the caller does not have LoggingPermission("control").
287
*/
288
@Override
289
public synchronized void close() throws SecurityException {
290
flushAndClose();
291
}
292
293
// Package-private support for setting OutputStream
294
// with elevated privilege.
295
@SuppressWarnings("removal")
296
final void setOutputStreamPrivileged(final OutputStream out) {
297
AccessController.doPrivileged(new PrivilegedAction<Void>() {
298
@Override
299
public Void run() {
300
setOutputStream(out);
301
return null;
302
}
303
}, null, LogManager.controlPermission);
304
}
305
}
306
307