rt/emul/compact/src/main/java/java/util/logging/LogRecord.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 10 Sep 2013 15:39:33 +0200
changeset 1277 853245102164
parent 1259 d257b7a37635
permissions -rw-r--r--
Convert the Level names to names of methods on console object
     1 /*
     2  * Copyright (c) 2000, 2010, 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 java.util.logging;
    27 import java.io.*;
    28 
    29 /**
    30  * LogRecord objects are used to pass logging requests between
    31  * the logging framework and individual log Handlers.
    32  * <p>
    33  * When a LogRecord is passed into the logging framework it
    34  * logically belongs to the framework and should no longer be
    35  * used or updated by the client application.
    36  * <p>
    37  * Note that if the client application has not specified an
    38  * explicit source method name and source class name, then the
    39  * LogRecord class will infer them automatically when they are
    40  * first accessed (due to a call on getSourceMethodName or
    41  * getSourceClassName) by analyzing the call stack.  Therefore,
    42  * if a logging Handler wants to pass off a LogRecord to another
    43  * thread, or to transmit it over RMI, and if it wishes to subsequently
    44  * obtain method name or class name information it should call
    45  * one of getSourceClassName or getSourceMethodName to force
    46  * the values to be filled in.
    47  * <p>
    48  * <b> Serialization notes:</b>
    49  * <ul>
    50  * <li>The LogRecord class is serializable.
    51  *
    52  * <li> Because objects in the parameters array may not be serializable,
    53  * during serialization all objects in the parameters array are
    54  * written as the corresponding Strings (using Object.toString).
    55  *
    56  * <li> The ResourceBundle is not transmitted as part of the serialized
    57  * form, but the resource bundle name is, and the recipient object's
    58  * readObject method will attempt to locate a suitable resource bundle.
    59  *
    60  * </ul>
    61  *
    62  * @since 1.4
    63  */
    64 
    65 public class LogRecord implements java.io.Serializable {
    66     private static long globalSequenceNumber = 0;
    67 
    68     /**
    69      * The default value of threadID will be the current thread's
    70      * thread id, for ease of correlation, unless it is greater than
    71      * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
    72      * our promise to keep threadIDs unique by avoiding collisions due
    73      * to 32-bit wraparound.  Unfortunately, LogRecord.getThreadID()
    74      * returns int, while Thread.getId() returns long.
    75      */
    76     private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
    77 
    78     /**
    79      * @serial Logging message level
    80      */
    81     private Level level;
    82 
    83     /**
    84      * @serial Sequence number
    85      */
    86     private long sequenceNumber;
    87 
    88     /**
    89      * @serial Class that issued logging call
    90      */
    91     private String sourceClassName;
    92 
    93     /**
    94      * @serial Method that issued logging call
    95      */
    96     private String sourceMethodName;
    97 
    98     /**
    99      * @serial Non-localized raw message text
   100      */
   101     private String message;
   102 
   103     /**
   104      * @serial Thread ID for thread that issued logging call.
   105      */
   106     private int threadID;
   107 
   108     /**
   109      * @serial Event time in milliseconds since 1970
   110      */
   111     private long millis;
   112 
   113     /**
   114      * @serial The Throwable (if any) associated with log message
   115      */
   116     private Throwable thrown;
   117 
   118     /**
   119      * @serial Name of the source Logger.
   120      */
   121     private String loggerName;
   122 
   123     /**
   124      * @serial Resource bundle name to localized log message.
   125      */
   126     private String resourceBundleName;
   127 
   128     private transient boolean needToInferCaller;
   129     private transient Object parameters[];
   130 
   131     /**
   132      * Returns the default value for a new LogRecord's threadID.
   133      */
   134     private int defaultThreadID() {
   135         return 0;
   136     }
   137 
   138     /**
   139      * Construct a LogRecord with the given level and message values.
   140      * <p>
   141      * The sequence property will be initialized with a new unique value.
   142      * These sequence values are allocated in increasing order within a VM.
   143      * <p>
   144      * The millis property will be initialized to the current time.
   145      * <p>
   146      * The thread ID property will be initialized with a unique ID for
   147      * the current thread.
   148      * <p>
   149      * All other properties will be initialized to "null".
   150      *
   151      * @param level  a logging level value
   152      * @param msg  the raw non-localized logging message (may be null)
   153      */
   154     public LogRecord(Level level, String msg) {
   155         // Make sure level isn't null, by calling random method.
   156         level.getClass();
   157         this.level = level;
   158         message = msg;
   159         // Assign a thread ID and a unique sequence number.
   160         sequenceNumber = globalSequenceNumber++;
   161         threadID = defaultThreadID();
   162         millis = System.currentTimeMillis();
   163         needToInferCaller = true;
   164    }
   165 
   166     /**
   167      * Get the source Logger's name.
   168      *
   169      * @return source logger name (may be null)
   170      */
   171     public String getLoggerName() {
   172         return loggerName;
   173     }
   174 
   175     /**
   176      * Set the source Logger's name.
   177      *
   178      * @param name   the source logger name (may be null)
   179      */
   180     public void setLoggerName(String name) {
   181         loggerName = name;
   182     }
   183 
   184     /**
   185      * Get the localization resource bundle
   186      * <p>
   187      * This is the ResourceBundle that should be used to localize
   188      * the message string before formatting it.  The result may
   189      * be null if the message is not localizable, or if no suitable
   190      * ResourceBundle is available.
   191      */
   192 //    public ResourceBundle getResourceBundle() {
   193 //        return resourceBundle;
   194 //    }
   195 
   196     /**
   197      * Set the localization resource bundle.
   198      *
   199      * @param bundle  localization bundle (may be null)
   200      */
   201 //    public void setResourceBundle(ResourceBundle bundle) {
   202 //        resourceBundle = bundle;
   203 //    }
   204 
   205     /**
   206      * Get the localization resource bundle name
   207      * <p>
   208      * This is the name for the ResourceBundle that should be
   209      * used to localize the message string before formatting it.
   210      * The result may be null if the message is not localizable.
   211      */
   212     public String getResourceBundleName() {
   213         return resourceBundleName;
   214     }
   215 
   216     /**
   217      * Set the localization resource bundle name.
   218      *
   219      * @param name  localization bundle name (may be null)
   220      */
   221     public void setResourceBundleName(String name) {
   222         resourceBundleName = name;
   223     }
   224 
   225     /**
   226      * Get the logging message level, for example Level.SEVERE.
   227      * @return the logging message level
   228      */
   229     public Level getLevel() {
   230         return level;
   231     }
   232 
   233     /**
   234      * Set the logging message level, for example Level.SEVERE.
   235      * @param level the logging message level
   236      */
   237     public void setLevel(Level level) {
   238         if (level == null) {
   239             throw new NullPointerException();
   240         }
   241         this.level = level;
   242     }
   243 
   244     /**
   245      * Get the sequence number.
   246      * <p>
   247      * Sequence numbers are normally assigned in the LogRecord
   248      * constructor, which assigns unique sequence numbers to
   249      * each new LogRecord in increasing order.
   250      * @return the sequence number
   251      */
   252     public long getSequenceNumber() {
   253         return sequenceNumber;
   254     }
   255 
   256     /**
   257      * Set the sequence number.
   258      * <p>
   259      * Sequence numbers are normally assigned in the LogRecord constructor,
   260      * so it should not normally be necessary to use this method.
   261      */
   262     public void setSequenceNumber(long seq) {
   263         sequenceNumber = seq;
   264     }
   265 
   266     /**
   267      * Get the  name of the class that (allegedly) issued the logging request.
   268      * <p>
   269      * Note that this sourceClassName is not verified and may be spoofed.
   270      * This information may either have been provided as part of the
   271      * logging call, or it may have been inferred automatically by the
   272      * logging framework.  In the latter case, the information may only
   273      * be approximate and may in fact describe an earlier call on the
   274      * stack frame.
   275      * <p>
   276      * May be null if no information could be obtained.
   277      *
   278      * @return the source class name
   279      */
   280     public String getSourceClassName() {
   281         return sourceClassName;
   282     }
   283 
   284     /**
   285      * Set the name of the class that (allegedly) issued the logging request.
   286      *
   287      * @param sourceClassName the source class name (may be null)
   288      */
   289     public void setSourceClassName(String sourceClassName) {
   290         this.sourceClassName = sourceClassName;
   291         needToInferCaller = false;
   292     }
   293 
   294     /**
   295      * Get the  name of the method that (allegedly) issued the logging request.
   296      * <p>
   297      * Note that this sourceMethodName is not verified and may be spoofed.
   298      * This information may either have been provided as part of the
   299      * logging call, or it may have been inferred automatically by the
   300      * logging framework.  In the latter case, the information may only
   301      * be approximate and may in fact describe an earlier call on the
   302      * stack frame.
   303      * <p>
   304      * May be null if no information could be obtained.
   305      *
   306      * @return the source method name
   307      */
   308     public String getSourceMethodName() {
   309         return sourceMethodName;
   310     }
   311 
   312     /**
   313      * Set the name of the method that (allegedly) issued the logging request.
   314      *
   315      * @param sourceMethodName the source method name (may be null)
   316      */
   317     public void setSourceMethodName(String sourceMethodName) {
   318         this.sourceMethodName = sourceMethodName;
   319         needToInferCaller = false;
   320     }
   321 
   322     /**
   323      * Get the "raw" log message, before localization or formatting.
   324      * <p>
   325      * May be null, which is equivalent to the empty string "".
   326      * <p>
   327      * This message may be either the final text or a localization key.
   328      * <p>
   329      * During formatting, if the source logger has a localization
   330      * ResourceBundle and if that ResourceBundle has an entry for
   331      * this message string, then the message string is replaced
   332      * with the localized value.
   333      *
   334      * @return the raw message string
   335      */
   336     public String getMessage() {
   337         return message;
   338     }
   339 
   340     /**
   341      * Set the "raw" log message, before localization or formatting.
   342      *
   343      * @param message the raw message string (may be null)
   344      */
   345     public void setMessage(String message) {
   346         this.message = message;
   347     }
   348 
   349     /**
   350      * Get the parameters to the log message.
   351      *
   352      * @return the log message parameters.  May be null if
   353      *                  there are no parameters.
   354      */
   355     public Object[] getParameters() {
   356         return parameters;
   357     }
   358 
   359     /**
   360      * Set the parameters to the log message.
   361      *
   362      * @param parameters the log message parameters. (may be null)
   363      */
   364     public void setParameters(Object parameters[]) {
   365         this.parameters = parameters;
   366     }
   367 
   368     /**
   369      * Get an identifier for the thread where the message originated.
   370      * <p>
   371      * This is a thread identifier within the Java VM and may or
   372      * may not map to any operating system ID.
   373      *
   374      * @return thread ID
   375      */
   376     public int getThreadID() {
   377         return threadID;
   378     }
   379 
   380     /**
   381      * Set an identifier for the thread where the message originated.
   382      * @param threadID  the thread ID
   383      */
   384     public void setThreadID(int threadID) {
   385         this.threadID = threadID;
   386     }
   387 
   388     /**
   389      * Get event time in milliseconds since 1970.
   390      *
   391      * @return event time in millis since 1970
   392      */
   393     public long getMillis() {
   394         return millis;
   395     }
   396 
   397     /**
   398      * Set event time.
   399      *
   400      * @param millis event time in millis since 1970
   401      */
   402     public void setMillis(long millis) {
   403         this.millis = millis;
   404     }
   405 
   406     /**
   407      * Get any throwable associated with the log record.
   408      * <p>
   409      * If the event involved an exception, this will be the
   410      * exception object. Otherwise null.
   411      *
   412      * @return a throwable
   413      */
   414     public Throwable getThrown() {
   415         return thrown;
   416     }
   417 
   418     /**
   419      * Set a throwable associated with the log event.
   420      *
   421      * @param thrown  a throwable (may be null)
   422      */
   423     public void setThrown(Throwable thrown) {
   424         this.thrown = thrown;
   425     }
   426 
   427     private static final long serialVersionUID = 5372048053134512534L;
   428 
   429     /**
   430      * @serialData Default fields, followed by a two byte version number
   431      * (major byte, followed by minor byte), followed by information on
   432      * the log record parameter array.  If there is no parameter array,
   433      * then -1 is written.  If there is a parameter array (possible of zero
   434      * length) then the array length is written as an integer, followed
   435      * by String values for each parameter.  If a parameter is null, then
   436      * a null String is written.  Otherwise the output of Object.toString()
   437      * is written.
   438      */
   439     private void writeObject(ObjectOutputStream out) throws IOException {
   440         // We have to call defaultWriteObject first.
   441         out.defaultWriteObject();
   442 
   443         // Write our version number.
   444         out.writeByte(1);
   445         out.writeByte(0);
   446         if (parameters == null) {
   447             out.writeInt(-1);
   448             return;
   449         }
   450         out.writeInt(parameters.length);
   451         // Write string values for the parameters.
   452         for (int i = 0; i < parameters.length; i++) {
   453             if (parameters[i] == null) {
   454                 out.writeObject(null);
   455             } else {
   456                 out.writeObject(parameters[i].toString());
   457             }
   458         }
   459     }
   460 
   461 
   462     private boolean isLoggerImplFrame(String cname) {
   463         // the log record could be created for a platform logger
   464         return (cname.equals("java.util.logging.Logger") ||
   465                 cname.startsWith("java.util.logging.LoggingProxyImpl") ||
   466                 cname.startsWith("sun.util.logging."));
   467     }
   468 }