| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.util.logging; |
| |
| import dalvik.system.VMStack; |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| import libcore.base.Objects; |
| |
| /** |
| * {@code Level} objects are used to indicate the level of logging. There are a |
| * set of predefined logging levels, each associated with an integer value. |
| * Enabling a certain logging level also enables all logging levels with larger |
| * values. |
| * <p> |
| * The predefined levels in ascending order are FINEST, FINER, FINE, CONFIG, |
| * INFO, WARNING, SEVERE. There are two additional predefined levels, which are |
| * ALL and OFF. ALL indicates logging all messages, and OFF indicates logging no |
| * messages. |
| */ |
| public class Level implements Serializable { |
| |
| private static final long serialVersionUID = -8176160795706313070L; |
| |
| private static final List<Level> levels = new ArrayList<Level>(9); |
| |
| /** |
| * The OFF level provides no logging messages. |
| */ |
| public static final Level OFF = new Level("OFF", Integer.MAX_VALUE); |
| |
| /** |
| * The SEVERE level provides severe failure messages. |
| */ |
| public static final Level SEVERE = new Level("SEVERE", 1000); |
| |
| /** |
| * The WARNING level provides warnings. |
| */ |
| public static final Level WARNING = new Level("WARNING", 900); |
| |
| /** |
| * The INFO level provides informative messages. |
| */ |
| public static final Level INFO = new Level("INFO", 800); |
| |
| /** |
| * The CONFIG level provides static configuration messages. |
| */ |
| public static final Level CONFIG = new Level("CONFIG", 700); |
| |
| /** |
| * The FINE level provides tracing messages. |
| */ |
| public static final Level FINE = new Level("FINE", 500); |
| |
| /** |
| * The FINER level provides more detailed tracing messages. |
| */ |
| public static final Level FINER = new Level("FINER", 400); |
| |
| /** |
| * The FINEST level provides highly detailed tracing messages. |
| */ |
| public static final Level FINEST = new Level("FINEST", 300); |
| |
| /** |
| * The ALL level provides all logging messages. |
| */ |
| public static final Level ALL = new Level("ALL", Integer.MIN_VALUE); |
| |
| /** |
| * Parses a level name into a {@code Level} object. |
| * |
| * @param name |
| * the name of the desired {@code level}, which cannot be |
| * {@code null}. |
| * @return the level with the specified name. |
| * @throws NullPointerException |
| * if {@code name} is {@code null}. |
| * @throws IllegalArgumentException |
| * if {@code name} is not valid. |
| */ |
| public static Level parse(String name) throws IllegalArgumentException { |
| if (name == null) { |
| throw new NullPointerException("name == null"); |
| } |
| |
| boolean isNameAnInt; |
| int nameAsInt; |
| try { |
| nameAsInt = Integer.parseInt(name); |
| isNameAnInt = true; |
| } catch (NumberFormatException e) { |
| nameAsInt = 0; |
| isNameAnInt = false; |
| } |
| |
| synchronized (levels) { |
| for (Level level : levels) { |
| if (name.equals(level.getName())) { |
| return level; |
| } |
| } |
| |
| if (isNameAnInt) { |
| /* |
| * Loop through levels a second time, so that the returned |
| * instance will be passed on the order of construction. |
| */ |
| for (Level level : levels) { |
| if (nameAsInt == level.intValue()) { |
| return level; |
| } |
| } |
| } |
| } |
| |
| if (!isNameAnInt) { |
| throw new IllegalArgumentException("Cannot parse name '" + name + "'"); |
| } |
| |
| return new Level(name, nameAsInt); |
| } |
| |
| /** |
| * The name of this Level. |
| * |
| * @serial |
| */ |
| private final String name; |
| |
| /** |
| * The integer value indicating the level. |
| * |
| * @serial |
| */ |
| private final int value; |
| |
| /** |
| * The name of the resource bundle used to localize the level name. |
| * |
| * @serial |
| */ |
| private final String resourceBundleName; |
| |
| /** |
| * The resource bundle associated with this level, used to localize the |
| * level name. |
| */ |
| private transient ResourceBundle rb; |
| |
| /** |
| * Constructs an instance of {@code Level} taking the supplied name and |
| * level value. |
| * |
| * @param name |
| * the name of the level. |
| * @param level |
| * an integer value indicating the level. |
| * @throws NullPointerException |
| * if {@code name} is {@code null}. |
| */ |
| protected Level(String name, int level) { |
| this(name, level, null); |
| } |
| |
| /** |
| * Constructs an instance of {@code Level} taking the supplied name, level |
| * value and resource bundle name. |
| * |
| * @param name |
| * the name of the level. |
| * @param level |
| * an integer value indicating the level. |
| * @param resourceBundleName |
| * the name of the resource bundle to use. |
| * @throws NullPointerException |
| * if {@code name} is {@code null}. |
| */ |
| protected Level(String name, int level, String resourceBundleName) { |
| if (name == null) { |
| throw new NullPointerException("name == null"); |
| } |
| this.name = name; |
| this.value = level; |
| this.resourceBundleName = resourceBundleName; |
| if (resourceBundleName != null) { |
| try { |
| rb = ResourceBundle.getBundle(resourceBundleName, |
| // BEGIN android-changed |
| Locale.getDefault(), VMStack.getCallingClassLoader()); |
| // BEGIN android-changed |
| } catch (MissingResourceException e) { |
| rb = null; |
| } |
| } |
| synchronized (levels) { |
| levels.add(this); |
| } |
| } |
| |
| /** |
| * Gets the name of this level. |
| * |
| * @return this level's name. |
| */ |
| public String getName() { |
| return this.name; |
| } |
| |
| /** |
| * Gets the name of the resource bundle associated with this level. |
| * |
| * @return the name of this level's resource bundle. |
| */ |
| public String getResourceBundleName() { |
| return this.resourceBundleName; |
| } |
| |
| /** |
| * Gets the integer value indicating this level. |
| * |
| * @return this level's integer value. |
| */ |
| public final int intValue() { |
| return this.value; |
| } |
| |
| /** |
| * Serialization helper method to maintain singletons and add any new |
| * levels. |
| * |
| * @return the resolved instance. |
| */ |
| private Object readResolve() { |
| synchronized (levels) { |
| for (Level level : levels) { |
| if (value != level.value) { |
| continue; |
| } |
| if (!name.equals(level.name)) { |
| continue; |
| } |
| if (Objects.equal(resourceBundleName, level.resourceBundleName)) { |
| return level; |
| } |
| } |
| // This is a new value, so add it. |
| levels.add(this); |
| return this; |
| } |
| } |
| |
| /** |
| * Serialization helper to setup transient resource bundle instance. |
| * |
| * @param in |
| * the input stream to read the instance data from. |
| * @throws IOException |
| * if an IO error occurs. |
| * @throws ClassNotFoundException |
| * if a class is not found. |
| */ |
| private void readObject(ObjectInputStream in) throws IOException, |
| ClassNotFoundException { |
| in.defaultReadObject(); |
| if (resourceBundleName != null) { |
| try { |
| rb = ResourceBundle.getBundle(resourceBundleName); |
| } catch (MissingResourceException e) { |
| rb = null; |
| } |
| } |
| } |
| |
| /** |
| * Gets the localized name of this level. The default locale is used. If no |
| * resource bundle is associated with this level then the original level |
| * name is returned. |
| * |
| * @return the localized name of this level. |
| */ |
| public String getLocalizedName() { |
| if (rb == null) { |
| return name; |
| } |
| |
| try { |
| return rb.getString(name); |
| } catch (MissingResourceException e) { |
| return name; |
| } |
| } |
| |
| /** |
| * Compares two {@code Level} objects for equality. They are considered to |
| * be equal if they have the same level value. |
| * |
| * @param o |
| * the other object to compare this level to. |
| * @return {@code true} if this object equals to the supplied object, |
| * {@code false} otherwise. |
| */ |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| |
| if (!(o instanceof Level)) { |
| return false; |
| } |
| |
| return ((Level) o).intValue() == this.value; |
| } |
| |
| /** |
| * Returns the hash code of this {@code Level} object. |
| * |
| * @return this level's hash code. |
| */ |
| @Override |
| public int hashCode() { |
| return this.value; |
| } |
| |
| /** |
| * Returns the string representation of this {@code Level} object. In |
| * this case, it is the level's name. |
| * |
| * @return the string representation of this level. |
| */ |
| @Override |
| public final String toString() { |
| return this.name; |
| } |
| } |