151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util.logging;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ArrayList;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.HashMap;
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.List;
30ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmeraimport java.util.Locale;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map;
32ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmeraimport java.util.MissingResourceException;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ResourceBundle;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmeraimport dalvik.system.VMStack;
36ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Level class defines a set of standard logging levels that
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * can be used to control logging output.  The logging Level objects
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are ordered and are specified by ordered integers.  Enabling logging
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * at a given level also enables logging at all higher levels.
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Clients should normally use the predefined Level constants such
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as Level.SEVERE.
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The levels in descending order are:
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul>
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>SEVERE (highest value)
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>WARNING
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>INFO
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>CONFIG
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>FINE
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>FINER
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>FINEST  (lowest value)
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul>
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In addition there is a level OFF that can be used to turn
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * off logging, and a level ALL that can be used to enable
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * logging of all messages.
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It is possible for third parties to define additional logging
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * levels by subclassing Level.  In such cases subclasses should
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * take care to chose unique integer level values and to ensure that
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * they maintain the Object uniqueness property across serialization
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by defining a suitable readResolve method.
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class Level implements java.io.Serializable {
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static String defaultBundle = "sun.util.logging.resources.logging";
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial  The non-localized name of the level.
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final String name;
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial  The integer value of the level.
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final int value;
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial The resource bundle name to be used in localizing the level name.
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final String resourceBundleName;
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // localized level name
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String localizedLevelName;
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
90ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera    private transient  ResourceBundle rb;
91ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * OFF is a special level that can be used to turn off logging.
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * SEVERE is a message level indicating a serious failure.
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * In general SEVERE messages should describe events that are
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * of considerable importance and which will prevent normal
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * program execution.   They should be reasonably intelligible
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to end users and to system administrators.
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>1000</CODE>.
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * WARNING is a message level indicating a potential problem.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * In general WARNING messages should describe events that will
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be of interest to end users or system managers, or which
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * indicate potential problems.
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>900</CODE>.
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * INFO is a message level for informational messages.
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Typically INFO messages will be written to the console
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * or its equivalent.  So the INFO level should only be
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * used for reasonably significant messages that will
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * make sense to end users and system administrators.
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>800</CODE>.
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level INFO = new Level("INFO", 800, defaultBundle);
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * CONFIG is a message level for static configuration messages.
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * CONFIG messages are intended to provide a variety of static
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * configuration information, to assist in debugging problems
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * that may be associated with particular configurations.
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For example, CONFIG message might include the CPU type,
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the graphics depth, the GUI look-and-feel, etc.
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>700</CODE>.
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * FINE is a message level providing tracing information.
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * All of FINE, FINER, and FINEST are intended for relatively
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * detailed tracing.  The exact meaning of the three levels will
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * vary between subsystems, but in general, FINEST should be used
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for the most voluminous detailed output, FINER for somewhat
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * less detailed output, and FINE for the  lowest volume (and
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * most important) messages.
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * In general the FINE level should be used for information
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * that will be broadly interesting to developers who do not have
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a specialized interest in the specific subsystem.
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * FINE messages might include things like minor (recoverable)
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * failures.  Issues indicating potential performance problems
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * are also worth logging as FINE.
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>500</CODE>.
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level FINE = new Level("FINE", 500, defaultBundle);
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * FINER indicates a fairly detailed tracing message.
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * By default logging calls for entering, returning, or throwing
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * an exception are traced at this level.
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>400</CODE>.
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level FINER = new Level("FINER", 400, defaultBundle);
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * FINEST indicates a highly detailed tracing message.
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>300</CODE>.
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ALL indicates that all messages should be logged.
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>.
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Create a named Level with a given integer value.
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Note that this constructor is "protected" to allow subclassing.
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * In general clients of logging should use one of the constant Level
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * objects such as SEVERE or FINEST.  However, if clients need to
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * add new logging levels, they may subclass Level and define new
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * constants.
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param name  the name of the Level, for example "SEVERE".
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param value an integer value for the level.
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if the name is null
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected Level(String name, int value) {
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(name, value, null);
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Create a named Level with a given integer value and a
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * given localization resource name.
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param name  the name of the Level, for example "SEVERE".
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param value an integer value for the level.
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param resourceBundleName name of a resource bundle to use in
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *    localizing the given name. If the resourceBundleName is null
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *    or an empty string, it is ignored.
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if the name is null
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected Level(String name, int value, String resourceBundleName) {
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name == null) {
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.name = name;
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.value = value;
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.resourceBundleName = resourceBundleName;
217ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera        if (resourceBundleName != null) {
218ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera            try {
219ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                ClassLoader cl = VMStack.getCallingClassLoader();
220ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                if (cl != null) {
221ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                    rb = ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(), cl);
222ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                } else {
223ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                    rb = ResourceBundle.getBundle(resourceBundleName);
224ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                }
225ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera            } catch (MissingResourceException ex) {
226ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera                rb = null;
227ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera            }
228ed0a7b5290c302f8c58fdb3fb4ed8df5e0d32bd4Shubham Ajmera        }
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.localizedLevelName = resourceBundleName == null ? name : null;
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        KnownLevel.add(this);
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return the level's localization resource bundle name, or
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * null if no localization bundle is defined.
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return localization resource bundle name
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getResourceBundleName() {
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return resourceBundleName;
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return the non-localized string name of the Level.
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return non-localized name
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getName() {
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return name;
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return the localized string name of the Level, for
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the current default locale.
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If no localization information is available, the
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * non-localized name is returned.
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return localized name
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getLocalizedName() {
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getLocalizedLevelName();
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // package-private getLevelName() is used by the implementation
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // instead of getName() to avoid calling the subclass's version
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    final String getLevelName() {
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return this.name;
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    final synchronized String getLocalizedLevelName() {
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (localizedLevelName != null) {
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return localizedLevelName;
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            localizedLevelName = rb.getString(name);
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception ex) {
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            localizedLevelName = name;
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return localizedLevelName;
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Returns a mirrored Level object that matches the given name as
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // specified in the Level.parse method.  Returns null if not found.
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // It returns the same Level object as the one returned by Level.parse
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // method if the given name is a non-localized name or integer.
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // If the name is a localized name, findLevel and parse method may
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // return a different level value if there is a custom Level subclass
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // that overrides Level.getLocalizedName() to return a different string
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // than what's returned by the default implementation.
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static Level findLevel(String name) {
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name == null) {
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        KnownLevel level;
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Look for a known Level with the given non-localized name.
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        level = KnownLevel.findByName(name);
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (level != null) {
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.mirroredLevel;
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Now, check if the given name is an integer.  If so,
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // first look for a Level with the given value and then
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if necessary create one.
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int x = Integer.parseInt(name);
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            level = KnownLevel.findByValue(x);
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (level == null) {
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // add new Level
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Level levelObject = new Level(name, x);
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                level = KnownLevel.findByValue(x);
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.mirroredLevel;
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (NumberFormatException ex) {
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Not an integer.
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Drop through.
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        level = KnownLevel.findByLocalizedLevelName(name);
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (level != null) {
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.mirroredLevel;
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a string representation of this Level.
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the non-localized name of the Level, for example "INFO".
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final String toString() {
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return name;
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get the integer value for this level.  This integer value
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * can be used for efficient ordering comparisons between
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Level objects.
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the integer value for this level.
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final int intValue() {
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return value;
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final long serialVersionUID = -8176160795706313070L;
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Serialization magic to prevent "doppelgangers".
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // This is a performance optimization.
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object readResolve() {
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        KnownLevel o = KnownLevel.matches(this);
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (o != null) {
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return o.levelObject;
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Woops.  Whoever sent us this object knows
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // about a new log level.  Add it to our list.
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Level level = new Level(this.name, this.value, this.resourceBundleName);
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return level;
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Parse a level name string into a Level.
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The argument string may consist of either a level name
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * or an integer value.
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For example:
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <ul>
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li>     "SEVERE"
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li>     "1000"
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </ul>
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  name   string to be parsed
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if the name is null
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IllegalArgumentException if the value is not valid.
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * appropriate package access, or new levels defined or created
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * by subclasses.
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return The parsed value. Passing an integer that corresponds to a known name
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Passing an integer that does not (e.g., 1) will return a new level name
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * initialized to that value.
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static synchronized Level parse(String name) throws IllegalArgumentException {
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Check that name is not null.
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        name.length();
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        KnownLevel level;
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Look for a known Level with the given non-localized name.
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        level = KnownLevel.findByName(name);
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (level != null) {
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.levelObject;
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Now, check if the given name is an integer.  If so,
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // first look for a Level with the given value and then
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if necessary create one.
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int x = Integer.parseInt(name);
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            level = KnownLevel.findByValue(x);
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (level == null) {
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // add new Level
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Level levelObject = new Level(name, x);
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                level = KnownLevel.findByValue(x);
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.levelObject;
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (NumberFormatException ex) {
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Not an integer.
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Drop through.
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Finally, look for a known level with the given localized name,
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // in the current default locale.
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // This is relatively expensive, but not excessively so.
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        level = KnownLevel.findByLocalizedName(name);
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (level != null) {
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.levelObject;
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // OK, we've tried everything and failed
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new IllegalArgumentException("Bad level \"" + name + "\"");
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compare two objects for value equality.
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return true if and only if the two objects have the same level value.
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean equals(Object ox) {
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Level lx = (Level)ox;
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (lx.value == this.value);
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception ex) {
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Generate a hashcode.
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a hashcode based on the level value
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int hashCode() {
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return this.value;
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // KnownLevel class maintains the global list of all known levels.
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // The API allows multiple custom Level instances of the same name/value
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // be created. This class provides convenient methods to find a level
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // by a given name, by a given value, or by a given localized name.
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // KnownLevel wraps the following Level objects:
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // 1. levelObject:   standard Level object or custom Level object
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // 2. mirroredLevel: Level object representing the level specified in the
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //                   logging configuration.
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // are non-final but the name and resource bundle name are parameters to
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the Level constructor.  Use the mirroredLevel object instead of the
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // levelObject to prevent the logging framework to execute foreign code
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // implemented by untrusted Level subclass.
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Implementation Notes:
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // were final, the following KnownLevel implementation can be removed.
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Future API change should take this into consideration.
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final class KnownLevel {
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static Map<String, List<KnownLevel>> nameToLevels = new HashMap<>();
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static Map<Integer, List<KnownLevel>> intToLevels = new HashMap<>();
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Level levelObject;     // instance of Level class or Level subclass
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Level mirroredLevel;   // instance of Level class
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        KnownLevel(Level l) {
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.levelObject = l;
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (l.getClass() == Level.class) {
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.mirroredLevel = l;
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName);
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static synchronized void add(Level l) {
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // the mirroredLevel object is always added to the list
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // before the custom Level instance
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            KnownLevel o = new KnownLevel(l);
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<KnownLevel> list = nameToLevels.get(l.name);
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (list == null) {
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                list = new ArrayList<>();
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameToLevels.put(l.name, list);
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            list.add(o);
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            list = intToLevels.get(l.value);
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (list == null) {
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                list = new ArrayList<>();
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                intToLevels.put(l.value, list);
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            list.add(o);
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Returns a KnownLevel with the given non-localized name.
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static synchronized KnownLevel findByName(String name) {
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<KnownLevel> list = nameToLevels.get(name);
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (list != null) {
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return list.get(0);
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Returns a KnownLevel with the given value.
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static synchronized KnownLevel findByValue(int value) {
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<KnownLevel> list = intToLevels.get(value);
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (list != null) {
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return list.get(0);
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Returns a KnownLevel with the given localized name matching
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // by calling the Level.getLocalizedLevelName() method (i.e. found
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // from the resourceBundle associated with the Level object).
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // This method does not call Level.getLocalizedName() that may
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // be overridden in a subclass implementation
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static synchronized KnownLevel findByLocalizedLevelName(String name) {
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (List<KnownLevel> levels : nameToLevels.values()) {
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (KnownLevel l : levels) {
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String lname = l.levelObject.getLocalizedLevelName();
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (name.equals(lname)) {
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return l;
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Returns a KnownLevel with the given localized name matching
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // by calling the Level.getLocalizedName() method
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static synchronized KnownLevel findByLocalizedName(String name) {
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (List<KnownLevel> levels : nameToLevels.values()) {
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (KnownLevel l : levels) {
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String lname = l.levelObject.getLocalizedName();
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (name.equals(lname)) {
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return l;
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static synchronized KnownLevel matches(Level l) {
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<KnownLevel> list = nameToLevels.get(l.name);
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (list != null) {
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (KnownLevel level : list) {
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Level other = level.mirroredLevel;
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (l.value == other.value &&
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                           (l.resourceBundleName == other.resourceBundleName ||
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               (l.resourceBundleName != null &&
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                l.resourceBundleName.equals(other.resourceBundleName)))) {
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return level;
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
577