Save This Page
Home » openjdk-7 » java » util » logging » [javadoc | source]
    1   /*
    2    * Copyright 2000-2004 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.util.logging;
   27   import java.util;
   28   import java.io;
   29   
   30   /**
   31    * LogRecord objects are used to pass logging requests between
   32    * the logging framework and individual log Handlers.
   33    * <p>
   34    * When a LogRecord is passed into the logging framework it
   35    * logically belongs to the framework and should no longer be
   36    * used or updated by the client application.
   37    * <p>
   38    * Note that if the client application has not specified an
   39    * explicit source method name and source class name, then the
   40    * LogRecord class will infer them automatically when they are
   41    * first accessed (due to a call on getSourceMethodName or
   42    * getSourceClassName) by analyzing the call stack.  Therefore,
   43    * if a logging Handler wants to pass off a LogRecord to another
   44    * thread, or to transmit it over RMI, and if it wishes to subsequently
   45    * obtain method name or class name information it should call
   46    * one of getSourceClassName or getSourceMethodName to force
   47    * the values to be filled in.
   48    * <p>
   49    * <b> Serialization notes:</b>
   50    * <ul>
   51    * <li>The LogRecord class is serializable.
   52    *
   53    * <li> Because objects in the parameters array may not be serializable,
   54    * during serialization all objects in the parameters array are
   55    * written as the corresponding Strings (using Object.toString).
   56    *
   57    * <li> The ResourceBundle is not transmitted as part of the serialized
   58    * form, but the resource bundle name is, and the recipient object's
   59    * readObject method will attempt to locate a suitable resource bundle.
   60    *
   61    * </ul>
   62    *
   63    * @since 1.4
   64    */
   65   
   66   public class LogRecord implements java.io.Serializable {
   67       private static long globalSequenceNumber;
   68       private static int nextThreadId=10;
   69       private static ThreadLocal<Integer> threadIds = new ThreadLocal<Integer>();
   70   
   71       /**
   72        * @serial Logging message level
   73        */
   74       private Level level;
   75   
   76       /**
   77        * @serial Sequence number
   78        */
   79       private long sequenceNumber;
   80   
   81       /**
   82        * @serial Class that issued logging call
   83        */
   84       private String sourceClassName;
   85   
   86       /**
   87        * @serial Method that issued logging call
   88        */
   89       private String sourceMethodName;
   90   
   91       /**
   92        * @serial Non-localized raw message text
   93        */
   94       private String message;
   95   
   96       /**
   97        * @serial Thread ID for thread that issued logging call.
   98        */
   99       private int threadID;
  100   
  101       /**
  102        * @serial Event time in milliseconds since 1970
  103        */
  104       private long millis;
  105   
  106       /**
  107        * @serial The Throwable (if any) associated with log message
  108        */
  109       private Throwable thrown;
  110   
  111       /**
  112        * @serial Name of the source Logger.
  113        */
  114       private String loggerName;
  115   
  116       /**
  117        * @serial Resource bundle name to localized log message.
  118        */
  119       private String resourceBundleName;
  120   
  121       private transient boolean needToInferCaller;
  122       private transient Object parameters[];
  123       private transient ResourceBundle resourceBundle;
  124   
  125       /**
  126        * Construct a LogRecord with the given level and message values.
  127        * <p>
  128        * The sequence property will be initialized with a new unique value.
  129        * These sequence values are allocated in increasing order within a VM.
  130        * <p>
  131        * The millis property will be initialized to the current time.
  132        * <p>
  133        * The thread ID property will be initialized with a unique ID for
  134        * the current thread.
  135        * <p>
  136        * All other properties will be initialized to "null".
  137        *
  138        * @param level  a logging level value
  139        * @param msg  the raw non-localized logging message (may be null)
  140        */
  141       public LogRecord(Level level, String msg) {
  142           // Make sure level isn't null, by calling random method.
  143           level.getClass();
  144           this.level = level;
  145           message = msg;
  146           // Assign a thread ID and a unique sequence number.
  147           synchronized (LogRecord.class) {
  148               sequenceNumber = globalSequenceNumber++;
  149               Integer id = threadIds.get();
  150               if (id == null) {
  151                   id = new Integer(nextThreadId++);
  152                   threadIds.set(id);
  153               }
  154               threadID = id.intValue();
  155           }
  156           millis = System.currentTimeMillis();
  157           needToInferCaller = true;
  158      }
  159   
  160       /**
  161        * Get the source Logger name's
  162        *
  163        * @return source logger name (may be null)
  164        */
  165       public String getLoggerName() {
  166           return loggerName;
  167       }
  168   
  169       /**
  170        * Set the source Logger name.
  171        *
  172        * @param name   the source logger name (may be null)
  173        */
  174       public void setLoggerName(String name) {
  175           loggerName = name;
  176       }
  177   
  178       /**
  179        * Get the localization resource bundle
  180        * <p>
  181        * This is the ResourceBundle that should be used to localize
  182        * the message string before formatting it.  The result may
  183        * be null if the message is not localizable, or if no suitable
  184        * ResourceBundle is available.
  185        */
  186       public ResourceBundle getResourceBundle() {
  187           return resourceBundle;
  188       }
  189   
  190       /**
  191        * Set the localization resource bundle.
  192        *
  193        * @param bundle  localization bundle (may be null)
  194        */
  195       public void setResourceBundle(ResourceBundle bundle) {
  196           resourceBundle = bundle;
  197       }
  198   
  199       /**
  200        * Get the localization resource bundle name
  201        * <p>
  202        * This is the name for the ResourceBundle that should be
  203        * used to localize the message string before formatting it.
  204        * The result may be null if the message is not localizable.
  205        */
  206       public String getResourceBundleName() {
  207           return resourceBundleName;
  208       }
  209   
  210       /**
  211        * Set the localization resource bundle name.
  212        *
  213        * @param name  localization bundle name (may be null)
  214        */
  215       public void setResourceBundleName(String name) {
  216           resourceBundleName = name;
  217       }
  218   
  219       /**
  220        * Get the logging message level, for example Level.SEVERE.
  221        * @return the logging message level
  222        */
  223       public Level getLevel() {
  224           return level;
  225       }
  226   
  227       /**
  228        * Set the logging message level, for example Level.SEVERE.
  229        * @param level the logging message level
  230        */
  231       public void setLevel(Level level) {
  232           if (level == null) {
  233               throw new NullPointerException();
  234           }
  235           this.level = level;
  236       }
  237   
  238       /**
  239        * Get the sequence number.
  240        * <p>
  241        * Sequence numbers are normally assigned in the LogRecord
  242        * constructor, which assigns unique sequence numbers to
  243        * each new LogRecord in increasing order.
  244        * @return the sequence number
  245        */
  246       public long getSequenceNumber() {
  247           return sequenceNumber;
  248       }
  249   
  250       /**
  251        * Set the sequence number.
  252        * <p>
  253        * Sequence numbers are normally assigned in the LogRecord constructor,
  254        * so it should not normally be necessary to use this method.
  255        */
  256       public void setSequenceNumber(long seq) {
  257           sequenceNumber = seq;
  258       }
  259   
  260       /**
  261        * Get the  name of the class that (allegedly) issued the logging request.
  262        * <p>
  263        * Note that this sourceClassName is not verified and may be spoofed.
  264        * This information may either have been provided as part of the
  265        * logging call, or it may have been inferred automatically by the
  266        * logging framework.  In the latter case, the information may only
  267        * be approximate and may in fact describe an earlier call on the
  268        * stack frame.
  269        * <p>
  270        * May be null if no information could be obtained.
  271        *
  272        * @return the source class name
  273        */
  274       public String getSourceClassName() {
  275           if (needToInferCaller) {
  276               inferCaller();
  277           }
  278           return sourceClassName;
  279       }
  280   
  281       /**
  282        * Set the name of the class that (allegedly) issued the logging request.
  283        *
  284        * @param sourceClassName the source class name (may be null)
  285        */
  286       public void setSourceClassName(String sourceClassName) {
  287           this.sourceClassName = sourceClassName;
  288           needToInferCaller = false;
  289       }
  290   
  291       /**
  292        * Get the  name of the method that (allegedly) issued the logging request.
  293        * <p>
  294        * Note that this sourceMethodName is not verified and may be spoofed.
  295        * This information may either have been provided as part of the
  296        * logging call, or it may have been inferred automatically by the
  297        * logging framework.  In the latter case, the information may only
  298        * be approximate and may in fact describe an earlier call on the
  299        * stack frame.
  300        * <p>
  301        * May be null if no information could be obtained.
  302        *
  303        * @return the source method name
  304        */
  305       public String getSourceMethodName() {
  306           if (needToInferCaller) {
  307               inferCaller();
  308           }
  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       private void readObject(ObjectInputStream in)
  462                           throws IOException, ClassNotFoundException {
  463           // We have to call defaultReadObject first.
  464           in.defaultReadObject();
  465   
  466           // Read version number.
  467           byte major = in.readByte();
  468           byte minor = in.readByte();
  469           if (major != 1) {
  470               throw new IOException("LogRecord: bad version: " + major + "." + minor);
  471           }
  472           int len = in.readInt();
  473           if (len == -1) {
  474               parameters = null;
  475           } else {
  476               parameters = new Object[len];
  477               for (int i = 0; i < parameters.length; i++) {
  478                   parameters[i] = in.readObject();
  479               }
  480           }
  481           // If necessary, try to regenerate the resource bundle.
  482           if (resourceBundleName != null) {
  483               try {
  484                   resourceBundle = ResourceBundle.getBundle(resourceBundleName);
  485               } catch (MissingResourceException ex) {
  486                   // This is not a good place to throw an exception,
  487                   // so we simply leave the resourceBundle null.
  488                   resourceBundle = null;
  489               }
  490           }
  491   
  492           needToInferCaller = false;
  493       }
  494   
  495       // Private method to infer the caller's class and method names
  496       private void inferCaller() {
  497           needToInferCaller = false;
  498           // Get the stack trace.
  499           StackTraceElement stack[] = (new Throwable()).getStackTrace();
  500           // First, search back to a method in the Logger class.
  501           int ix = 0;
  502           while (ix < stack.length) {
  503               StackTraceElement frame = stack[ix];
  504               String cname = frame.getClassName();
  505               if (cname.equals("java.util.logging.Logger")) {
  506                   break;
  507               }
  508               ix++;
  509           }
  510           // Now search for the first frame before the "Logger" class.
  511           while (ix < stack.length) {
  512               StackTraceElement frame = stack[ix];
  513               String cname = frame.getClassName();
  514               if (!cname.equals("java.util.logging.Logger")) {
  515                   // We've found the relevant frame.
  516                   setSourceClassName(cname);
  517                   setSourceMethodName(frame.getMethodName());
  518                   return;
  519               }
  520               ix++;
  521           }
  522           // We haven't found a suitable frame, so just punt.  This is
  523           // OK as we are only committed to making a "best effort" here.
  524       }
  525   }

Save This Page
Home » openjdk-7 » java » util » logging » [javadoc | source]