Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/rmi/runtime/Log.java
38829 views
1
/*
2
* Copyright (c) 2001, 2013, 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
package sun.rmi.runtime;
27
28
import java.io.ByteArrayOutputStream;
29
import java.io.IOException;
30
import java.io.PrintStream;
31
import java.io.OutputStream;
32
import java.rmi.server.LogStream;
33
import java.util.logging.ConsoleHandler;
34
import java.util.logging.Handler;
35
import java.util.logging.Formatter;
36
import java.util.logging.SimpleFormatter;
37
import java.util.logging.StreamHandler;
38
import java.util.logging.Level;
39
import java.util.logging.Logger;
40
import java.util.logging.LogManager;
41
import java.util.logging.LogRecord;
42
import java.util.logging.StreamHandler;
43
import java.util.Map;
44
import java.util.HashMap;
45
46
/**
47
* Utility which provides an abstract "logger" like RMI internal API
48
* which can be directed to use one of two types of logging
49
* infrastructure: the java.util.logging API or the
50
* java.rmi.server.LogStream API. The default behavior is to use the
51
* java.util.logging API. The LogStream API may be used instead by
52
* setting the system property sun.rmi.log.useOld to true.
53
*
54
* For backwards compatibility, supports the RMI system logging
55
* properties which pre-1.4 comprised the only way to configure RMI
56
* logging. If the java.util.logging API is used and RMI system log
57
* properties are set, the system properties override initial RMI
58
* logger values as appropriate. If the java.util.logging API is
59
* turned off, pre-1.4 logging behavior is used.
60
*
61
* @author Laird Dornin
62
* @since 1.4
63
*/
64
@SuppressWarnings("deprecation")
65
public abstract class Log {
66
67
/** Logger re-definition of old RMI log values */
68
public static final Level BRIEF = Level.FINE;
69
public static final Level VERBOSE = Level.FINER;
70
71
/* selects log implementation */
72
private static final LogFactory logFactory;
73
static {
74
boolean useOld =
75
Boolean.valueOf(java.security.AccessController.
76
doPrivileged(new sun.security.action.GetPropertyAction(
77
"sun.rmi.log.useOld"))).booleanValue();
78
79
/* set factory to select the logging facility to use */
80
logFactory = (useOld ? (LogFactory) new LogStreamLogFactory() :
81
(LogFactory) new LoggerLogFactory());
82
}
83
84
/** "logger like" API to be used by RMI implementation */
85
public abstract boolean isLoggable(Level level);
86
public abstract void log(Level level, String message);
87
public abstract void log(Level level, String message, Throwable thrown);
88
89
/** get and set the RMI server call output stream */
90
public abstract void setOutputStream(OutputStream stream);
91
public abstract PrintStream getPrintStream();
92
93
/** factory interface enables Logger and LogStream implementations */
94
private static interface LogFactory {
95
Log createLog(String loggerName, String oldLogName, Level level);
96
}
97
98
/* access log objects */
99
100
/**
101
* Access log for a tri-state system property.
102
*
103
* Need to first convert override value to a log level, taking
104
* care to interpret a range of values between BRIEF, VERBOSE and
105
* SILENT.
106
*
107
* An override < 0 is interpreted to mean that the logging
108
* configuration should not be overridden. The level passed to the
109
* factories createLog method will be null in this case.
110
*
111
* Note that if oldLogName is null and old logging is on, the
112
* returned LogStreamLog will ignore the override parameter - the
113
* log will never log messages. This permits new logs that only
114
* write to Loggers to do nothing when old logging is active.
115
*
116
* Do not call getLog multiple times on the same logger name.
117
* Since this is an internal API, no checks are made to ensure
118
* that multiple logs do not exist for the same logger.
119
*/
120
public static Log getLog(String loggerName, String oldLogName,
121
int override)
122
{
123
Level level;
124
125
if (override < 0) {
126
level = null;
127
} else if (override == LogStream.SILENT) {
128
level = Level.OFF;
129
} else if ((override > LogStream.SILENT) &&
130
(override <= LogStream.BRIEF)) {
131
level = BRIEF;
132
} else if ((override > LogStream.BRIEF) &&
133
(override <= LogStream.VERBOSE))
134
{
135
level = VERBOSE;
136
} else {
137
level = Level.FINEST;
138
}
139
return logFactory.createLog(loggerName, oldLogName, level);
140
}
141
142
/**
143
* Access logs associated with boolean properties
144
*
145
* Do not call getLog multiple times on the same logger name.
146
* Since this is an internal API, no checks are made to ensure
147
* that multiple logs do not exist for the same logger.
148
*/
149
public static Log getLog(String loggerName, String oldLogName,
150
boolean override)
151
{
152
Level level = (override ? VERBOSE : null);
153
return logFactory.createLog(loggerName, oldLogName, level);
154
}
155
156
/**
157
* Factory to create Log objects which deliver log messages to the
158
* java.util.logging API.
159
*/
160
private static class LoggerLogFactory implements LogFactory {
161
LoggerLogFactory() {}
162
163
/*
164
* Accessor to obtain an arbitrary RMI logger with name
165
* loggerName. If the level of the logger is greater than the
166
* level for the system property with name, the logger level
167
* will be set to the value of system property.
168
*/
169
public Log createLog(final String loggerName, String oldLogName,
170
final Level level)
171
{
172
Logger logger = Logger.getLogger(loggerName);
173
return new LoggerLog(logger, level);
174
}
175
}
176
177
/**
178
* Class specialized to log messages to the java.util.logging API
179
*/
180
private static class LoggerLog extends Log {
181
182
/* alternate console handler for RMI loggers */
183
private static final Handler alternateConsole =
184
java.security.AccessController.doPrivileged(
185
new java.security.PrivilegedAction<Handler>() {
186
public Handler run() {
187
InternalStreamHandler alternate =
188
new InternalStreamHandler(System.err);
189
alternate.setLevel(Level.ALL);
190
return alternate;
191
}
192
});
193
194
/** handler to which messages are copied */
195
private InternalStreamHandler copyHandler = null;
196
197
/* logger to which log messages are written */
198
private final Logger logger;
199
200
/* used as return value of RemoteServer.getLog */
201
private LoggerPrintStream loggerSandwich;
202
203
/** creates a Log which will delegate to the given logger */
204
private LoggerLog(final Logger logger, final Level level) {
205
this.logger = logger;
206
207
if (level != null){
208
java.security.AccessController.doPrivileged(
209
new java.security.PrivilegedAction<Void>() {
210
public Void run() {
211
if (!logger.isLoggable(level)) {
212
logger.setLevel(level);
213
}
214
logger.addHandler(alternateConsole);
215
return null;
216
}
217
}
218
);
219
}
220
}
221
222
public boolean isLoggable(Level level) {
223
return logger.isLoggable(level);
224
}
225
226
public void log(Level level, String message) {
227
if (isLoggable(level)) {
228
String[] source = getSource();
229
logger.logp(level, source[0], source[1],
230
Thread.currentThread().getName() + ": " + message);
231
}
232
}
233
234
public void log(Level level, String message, Throwable thrown) {
235
if (isLoggable(level)) {
236
String[] source = getSource();
237
logger.logp(level, source[0], source[1],
238
Thread.currentThread().getName() + ": " +
239
message, thrown);
240
}
241
}
242
243
/**
244
* Set the output stream associated with the RMI server call
245
* logger.
246
*
247
* Calling code needs LoggingPermission "control".
248
*/
249
public synchronized void setOutputStream(OutputStream out) {
250
if (out != null) {
251
if (!logger.isLoggable(VERBOSE)) {
252
logger.setLevel(VERBOSE);
253
}
254
copyHandler = new InternalStreamHandler(out);
255
copyHandler.setLevel(Log.VERBOSE);
256
logger.addHandler(copyHandler);
257
} else {
258
/* ensure that messages are not logged */
259
if (copyHandler != null) {
260
logger.removeHandler(copyHandler);
261
}
262
copyHandler = null;
263
}
264
}
265
266
public synchronized PrintStream getPrintStream() {
267
if (loggerSandwich == null) {
268
loggerSandwich = new LoggerPrintStream(logger);
269
}
270
return loggerSandwich;
271
}
272
}
273
274
/**
275
* Subclass of StreamHandler for redirecting log output. flush
276
* must be called in the publish and close methods.
277
*/
278
private static class InternalStreamHandler extends StreamHandler {
279
InternalStreamHandler(OutputStream out) {
280
super(out, new SimpleFormatter());
281
}
282
283
public void publish(LogRecord record) {
284
super.publish(record);
285
flush();
286
}
287
288
public void close() {
289
flush();
290
}
291
}
292
293
/**
294
* PrintStream which forwards log messages to the logger. Class
295
* is needed to maintain backwards compatibility with
296
* RemoteServer.{set|get}Log().
297
*/
298
private static class LoggerPrintStream extends PrintStream {
299
300
/** logger where output of this log is sent */
301
private final Logger logger;
302
303
/** record the last character written to this stream */
304
private int last = -1;
305
306
/** stream used for buffering lines */
307
private final ByteArrayOutputStream bufOut;
308
309
private LoggerPrintStream(Logger logger)
310
{
311
super(new ByteArrayOutputStream());
312
bufOut = (ByteArrayOutputStream) super.out;
313
this.logger = logger;
314
}
315
316
public void write(int b) {
317
if ((last == '\r') && (b == '\n')) {
318
last = -1;
319
return;
320
} else if ((b == '\n') || (b == '\r')) {
321
try {
322
/* write the converted bytes of the log message */
323
String message =
324
Thread.currentThread().getName() + ": " +
325
bufOut.toString();
326
logger.logp(Level.INFO, "LogStream", "print", message);
327
} finally {
328
bufOut.reset();
329
}
330
} else {
331
super.write(b);
332
}
333
last = b;
334
}
335
336
public void write(byte b[], int off, int len) {
337
if (len < 0) {
338
throw new ArrayIndexOutOfBoundsException(len);
339
}
340
for (int i = 0; i < len; i++) {
341
write(b[off + i]);
342
}
343
}
344
345
public String toString() {
346
return "RMI";
347
}
348
}
349
350
/**
351
* Factory to create Log objects which deliver log messages to the
352
* java.rmi.server.LogStream API
353
*/
354
private static class LogStreamLogFactory implements LogFactory {
355
LogStreamLogFactory() {}
356
357
/* create a new LogStreamLog for the specified log */
358
public Log createLog(String loggerName, String oldLogName,
359
Level level)
360
{
361
LogStream stream = null;
362
if (oldLogName != null) {
363
stream = LogStream.log(oldLogName);
364
}
365
return new LogStreamLog(stream, level);
366
}
367
}
368
369
/**
370
* Class specialized to log messages to the
371
* java.rmi.server.LogStream API
372
*/
373
private static class LogStreamLog extends Log {
374
/** Log stream to which log messages are written */
375
private final LogStream stream;
376
377
/** the level of the log as set by associated property */
378
private int levelValue = Level.OFF.intValue();
379
380
private LogStreamLog(LogStream stream, Level level) {
381
if ((stream != null) && (level != null)) {
382
/* if the stream or level is null, don't log any
383
* messages
384
*/
385
levelValue = level.intValue();
386
}
387
this.stream = stream;
388
}
389
390
public synchronized boolean isLoggable(Level level) {
391
return (level.intValue() >= levelValue);
392
}
393
394
public void log(Level messageLevel, String message) {
395
if (isLoggable(messageLevel)) {
396
String[] source = getSource();
397
stream.println(unqualifiedName(source[0]) +
398
"." + source[1] + ": " + message);
399
}
400
}
401
402
public void log(Level level, String message, Throwable thrown) {
403
if (isLoggable(level)) {
404
/*
405
* keep output contiguous and maintain the contract of
406
* RemoteServer.getLog
407
*/
408
synchronized (stream) {
409
String[] source = getSource();
410
stream.println(unqualifiedName(source[0]) + "." +
411
source[1] + ": " + message);
412
thrown.printStackTrace(stream);
413
}
414
}
415
}
416
417
public PrintStream getPrintStream() {
418
return stream;
419
}
420
421
public synchronized void setOutputStream(OutputStream out) {
422
if (out != null) {
423
if (VERBOSE.intValue() < levelValue) {
424
levelValue = VERBOSE.intValue();
425
}
426
stream.setOutputStream(out);
427
} else {
428
/* ensure that messages are not logged */
429
levelValue = Level.OFF.intValue();
430
}
431
}
432
433
/*
434
* Mimic old log messages that only contain unqualified names.
435
*/
436
private static String unqualifiedName(String name) {
437
int lastDot = name.lastIndexOf(".");
438
if (lastDot >= 0) {
439
name = name.substring(lastDot + 1);
440
}
441
name = name.replace('$', '.');
442
return name;
443
}
444
}
445
446
/**
447
* Obtain class and method names of code calling a log method.
448
*/
449
private static String[] getSource() {
450
StackTraceElement[] trace = (new Exception()).getStackTrace();
451
return new String[] {
452
trace[3].getClassName(),
453
trace[3].getMethodName()
454
};
455
}
456
}
457
458