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