History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/rmi/runtime/Log.java (1 of 18352 files). Show all

Unified · Split

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