src/java.rmi/share/classes/sun/rmi/runtime/Log.java
author rehn
Fri, 29 Nov 2019 12:09:25 +0100
changeset 59325 3636bab5e81e
parent 57866 1e85670cb9ee
permissions -rw-r--r--
8234086: VM operation can be simplified Reviewed-by: kbarrett, dholmes, dcubed
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
19211
32a04c562026 8022440: suppress deprecation warnings in sun.rmi
smarks
parents: 5506
diff changeset
     2
 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.rmi.runtime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.ByteArrayOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.PrintStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.OutputStream;
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
    31
import java.lang.StackWalker.StackFrame;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.rmi.server.LogStream;
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 21278
diff changeset
    33
import java.security.PrivilegedAction;
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
    34
import java.util.Set;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.util.logging.Handler;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.util.logging.SimpleFormatter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.util.logging.Level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.util.logging.Logger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.util.logging.LogRecord;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.util.logging.StreamHandler;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * Utility which provides an abstract "logger" like RMI internal API
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * which can be directed to use one of two types of logging
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * infrastructure: the java.util.logging API or the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * java.rmi.server.LogStream API.  The default behavior is to use the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * java.util.logging API.  The LogStream API may be used instead by
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * setting the system property sun.rmi.log.useOld to true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * For backwards compatibility, supports the RMI system logging
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * properties which pre-1.4 comprised the only way to configure RMI
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * logging.  If the java.util.logging API is used and RMI system log
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * properties are set, the system properties override initial RMI
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * logger values as appropriate. If the java.util.logging API is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * turned off, pre-1.4 logging behavior is used.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * @author Laird Dornin
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * @since 1.4
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 */
19211
32a04c562026 8022440: suppress deprecation warnings in sun.rmi
smarks
parents: 5506
diff changeset
    60
@SuppressWarnings("deprecation")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
public abstract class Log {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    /** Logger re-definition of old RMI log values */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    public static final Level BRIEF = Level.FINE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    public static final Level VERBOSE = Level.FINER;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
    67
    private static final StackWalker WALKER = StackWalker.getInstance(Set.of(), 4);
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
    68
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    /* selects log implementation */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    private static final LogFactory logFactory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    static {
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 21278
diff changeset
    72
        boolean useOld = java.security.AccessController.doPrivileged(
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 21278
diff changeset
    73
            (PrivilegedAction<Boolean>) () -> Boolean.getBoolean("sun.rmi.log.useOld"));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
        /* set factory to select the logging facility to use */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
        logFactory = (useOld ? (LogFactory) new LogStreamLogFactory() :
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
                      (LogFactory) new LoggerLogFactory());
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    /** "logger like" API to be used by RMI implementation */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    public abstract boolean isLoggable(Level level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    public abstract void log(Level level, String message);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    public abstract void log(Level level, String message, Throwable thrown);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    /** get and set the RMI server call output stream */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    public abstract void setOutputStream(OutputStream stream);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    public abstract PrintStream getPrintStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    /** factory interface enables Logger and LogStream implementations */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    private static interface LogFactory {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        Log createLog(String loggerName, String oldLogName, Level level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    /* access log objects */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
     * Access log for a tri-state system property.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * Need to first convert override value to a log level, taking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     * care to interpret a range of values between BRIEF, VERBOSE and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     * SILENT.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     *
30655
d83f50188ca9 8080422: some docs cleanup for core libs
avstepan
parents: 25859
diff changeset
   103
     * An override {@literal <} 0 is interpreted to mean that the logging
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * configuration should not be overridden. The level passed to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     * factories createLog method will be null in this case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
     * Note that if oldLogName is null and old logging is on, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
     * returned LogStreamLog will ignore the override parameter - the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     * log will never log messages.  This permits new logs that only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
     * write to Loggers to do nothing when old logging is active.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * Do not call getLog multiple times on the same logger name.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * Since this is an internal API, no checks are made to ensure
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * that multiple logs do not exist for the same logger.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    public static Log getLog(String loggerName, String oldLogName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
                             int override)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        Level level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        if (override < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
            level = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        } else if (override == LogStream.SILENT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
            level = Level.OFF;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        } else if ((override > LogStream.SILENT) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                   (override <= LogStream.BRIEF)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            level = BRIEF;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
        } else if ((override > LogStream.BRIEF) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                   (override <= LogStream.VERBOSE))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
            level = VERBOSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
            level = Level.FINEST;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        return logFactory.createLog(loggerName, oldLogName, level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
     * Access logs associated with boolean properties
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
     * Do not call getLog multiple times on the same logger name.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
     * Since this is an internal API, no checks are made to ensure
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     * that multiple logs do not exist for the same logger.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    public static Log getLog(String loggerName, String oldLogName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                             boolean override)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        Level level = (override ? VERBOSE : null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        return logFactory.createLog(loggerName, oldLogName, level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
     * Factory to create Log objects which deliver log messages to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     * java.util.logging API.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    private static class LoggerLogFactory implements LogFactory {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        LoggerLogFactory() {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
         * Accessor to obtain an arbitrary RMI logger with name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
         * loggerName.  If the level of the logger is greater than the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
         * level for the system property with name, the logger level
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
         * will be set to the value of system property.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        public Log createLog(final String loggerName, String oldLogName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                             final Level level)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
            Logger logger = Logger.getLogger(loggerName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
            return new LoggerLog(logger, level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     * Class specialized to log messages to the java.util.logging API
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
    private static class LoggerLog extends Log {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        /* alternate console handler for RMI loggers */
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   179
        private static final Handler alternateConsole =
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                java.security.AccessController.doPrivileged(
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   181
                new java.security.PrivilegedAction<Handler>() {
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   182
                    public Handler run() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                            InternalStreamHandler alternate =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                                new InternalStreamHandler(System.err);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                            alternate.setLevel(Level.ALL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                            return alternate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                        }
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   188
                });
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        /** handler to which messages are copied */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        private InternalStreamHandler copyHandler = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        /* logger to which log messages are written */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        private final Logger logger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        /* used as return value of RemoteServer.getLog */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        private LoggerPrintStream loggerSandwich;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        /** creates a Log which will delegate to the given logger */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        private LoggerLog(final Logger logger, final Level level) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            this.logger = logger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
            if (level != null){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                java.security.AccessController.doPrivileged(
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   205
                    new java.security.PrivilegedAction<Void>() {
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   206
                        public Void run() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                            if (!logger.isLoggable(level)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                                logger.setLevel(level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                            logger.addHandler(alternateConsole);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        public boolean isLoggable(Level level) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            return logger.isLoggable(level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        public void log(Level level, String message) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            if (isLoggable(level)) {
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   224
                StackFrame sourceFrame = getSource();
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   225
                logger.logp(level, sourceFrame.getClassName(), sourceFrame.getMethodName(),
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                           Thread.currentThread().getName() + ": " + message);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        public void log(Level level, String message, Throwable thrown) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            if (isLoggable(level)) {
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   232
                StackFrame sourceFrame = getSource();
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   233
                logger.logp(level, sourceFrame.getClassName(), sourceFrame.getMethodName(),
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                    Thread.currentThread().getName() + ": " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                           message, thrown);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
43211
f264afd5082c 8156802: Better constraint checking
rriggs
parents: 30655
diff changeset
   239
        public String toString() {
f264afd5082c 8156802: Better constraint checking
rriggs
parents: 30655
diff changeset
   240
            return logger.toString() + ", level: " + logger.getLevel() +
f264afd5082c 8156802: Better constraint checking
rriggs
parents: 30655
diff changeset
   241
                    ", name: " + logger.getName();
f264afd5082c 8156802: Better constraint checking
rriggs
parents: 30655
diff changeset
   242
        }
f264afd5082c 8156802: Better constraint checking
rriggs
parents: 30655
diff changeset
   243
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
         * Set the output stream associated with the RMI server call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
         * logger.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
         * Calling code needs LoggingPermission "control".
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        public synchronized void setOutputStream(OutputStream out) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            if (out != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                if (!logger.isLoggable(VERBOSE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                    logger.setLevel(VERBOSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                copyHandler = new InternalStreamHandler(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                copyHandler.setLevel(Log.VERBOSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                logger.addHandler(copyHandler);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
                /* ensure that messages are not logged */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                if (copyHandler != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
                    logger.removeHandler(copyHandler);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                copyHandler = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        public synchronized PrintStream getPrintStream() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            if (loggerSandwich == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                loggerSandwich = new LoggerPrintStream(logger);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            return loggerSandwich;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     * Subclass of StreamHandler for redirecting log output.  flush
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * must be called in the publish and close methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    private static class InternalStreamHandler extends StreamHandler {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        InternalStreamHandler(OutputStream out) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            super(out, new SimpleFormatter());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        public void publish(LogRecord record) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            super.publish(record);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        public void close() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     * PrintStream which forwards log messages to the logger.  Class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * is needed to maintain backwards compatibility with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * RemoteServer.{set|get}Log().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    private static class LoggerPrintStream extends PrintStream {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        /** logger where output of this log is sent */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        private final Logger logger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        /** record the last character written to this stream */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        private int last = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        /** stream used for buffering lines */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        private final ByteArrayOutputStream bufOut;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        private LoggerPrintStream(Logger logger)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            super(new ByteArrayOutputStream());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
            bufOut = (ByteArrayOutputStream) super.out;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            this.logger = logger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        public void write(int b) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
            if ((last == '\r') && (b == '\n')) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                last = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            } else if ((b == '\n') || (b == '\r')) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                    /* write the converted bytes of the log message */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
                    String message =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                        Thread.currentThread().getName() + ": " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                        bufOut.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                    logger.logp(Level.INFO, "LogStream", "print", message);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                    bufOut.reset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                super.write(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            last = b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        public void write(byte b[], int off, int len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            if (len < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                throw new ArrayIndexOutOfBoundsException(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            for (int i = 0; i < len; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                write(b[off + i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
            return "RMI";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     * Factory to create Log objects which deliver log messages to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
     * java.rmi.server.LogStream API
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
    private static class LogStreamLogFactory implements LogFactory {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
        LogStreamLogFactory() {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
        /* create a new LogStreamLog for the specified log */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        public Log createLog(String loggerName, String oldLogName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                             Level level)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
            LogStream stream = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            if (oldLogName != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                stream = LogStream.log(oldLogName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
            return new LogStreamLog(stream, level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     * Class specialized to log messages to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
     * java.rmi.server.LogStream API
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
    private static class LogStreamLog extends Log {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        /** Log stream to which log messages are written */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        private final LogStream stream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        /** the level of the log as set by associated property */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        private int levelValue = Level.OFF.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        private LogStreamLog(LogStream stream, Level level) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            if ((stream != null) && (level != null)) {
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 19211
diff changeset
   383
                /* if the stream or level is null, don't log any
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                 * messages
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                levelValue = level.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
            this.stream = stream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        public synchronized boolean isLoggable(Level level) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            return (level.intValue() >= levelValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        public void log(Level messageLevel, String message) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
            if (isLoggable(messageLevel)) {
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   397
                StackFrame sourceFrame = getSource();
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   398
                stream.println(unqualifiedName(sourceFrame.getClassName()) +
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   399
                               "." + sourceFrame.getMethodName() + ": " + message);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        public void log(Level level, String message, Throwable thrown) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            if (isLoggable(level)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
                 * keep output contiguous and maintain the contract of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                 * RemoteServer.getLog
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                synchronized (stream) {
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   410
                    StackFrame sourceFrame = getSource();
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   411
                    stream.println(unqualifiedName(sourceFrame.getClassName()) + "." +
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   412
                                    sourceFrame.getMethodName() + ": " + message);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                    thrown.printStackTrace(stream);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        public PrintStream getPrintStream() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            return stream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        public synchronized void setOutputStream(OutputStream out) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            if (out != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                if (VERBOSE.intValue() < levelValue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                    levelValue = VERBOSE.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                stream.setOutputStream(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                /* ensure that messages are not logged */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                levelValue = Level.OFF.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
         * Mimic old log messages that only contain unqualified names.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        private static String unqualifiedName(String name) {
24685
215fa91e1b4c 8044461: Cleanup new Boolean and single character strings
rriggs
parents: 23333
diff changeset
   438
            int lastDot = name.lastIndexOf('.');
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            if (lastDot >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                name = name.substring(lastDot + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            name = name.replace('$', '.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
            return name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
    /**
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   448
     * Obtain stack frame of code calling a log method.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
     */
57866
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   450
    private static StackFrame getSource() {
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   451
        return WALKER.walk(s -> s
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   452
                                 .skip(3)
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   453
                                 .findFirst()
1e85670cb9ee 8230058: Replace exception from sun.rmi.runtime.Log#getSource() with StackWalker
rriggs
parents: 47216
diff changeset
   454
                                 .get());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
}