![JAR search and dependency download from the Maven repository](/logo.png)
org.openide.ErrorManager Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.openide;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.openide.util.Enumerations;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.WeakSet;
/**
* A more or less deprecated system of managing, annotating, and classifying errors
* and log messages. Instead of ErrorManager
use
* {@link Logger} as described in NetBeans logging guide.
*
* Rather then using the {@link ErrorManager} consider using JDK's {@link Logger}
* for reporting log events, unwanted exceptions, etc. The methods
* in this class which are deprecated are annotated with a description
* how to use use the {@link Logger} methods to achieve the same goal.
*
*
* The levels in descending order are:
*
* - ERROR (highest value)
*
- EXCEPTION
*
- USER
*
- WARNING
*
- INFORMATIONAL
*
- UNKNOWN (lowest value)
*
*
*
*
* How to...
*
*
* - Handle an exception
* -
*
If it might be an important error (show the user):
*
* try {
* foo.doSomething();
* } catch (IOException ioe) {
*
* ErrorManager.getDefault().notify(ioe);
*
*
* If it is not very important but should be sent to the log file:
*
* try {
* foo.doSomething();
* } catch (IOException ioe) {
* Logger.getLogger(YourClass.class.getName()).log(Level.CONFIG, "msg", ioe);
* // used to be:
* // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
* }
*
* If it is the normal outcome of a user action
* and there is no need to show stack traces to the user:
*
* try {
* foo.doSomething();
* } catch (IOException ioe) {
*
* ErrorManager.getDefault().notify(ErrorManager.USER, ioe);
* }
*
* You can also specify the severity when you are creating the
* exception (by annotating it), rather than relying on the notifier
* to do this. In that case, if the notifier just use the plain form
* of notify
(i.e. UNKNOWN
severity), the
* annotated severity is used.
*
*
* - Retain nested stacktraces / change exception type
* -
*
* public void doSomething() throws IOException {
* try {
* doSomethingElse();
* } catch (IllegalArgumentException iae) {
* IOException ioe = new IOException("did not work: " + iae);
* ioe.initCause(iae);
* // used to be: ErrorManager.getDefault().annotate(ioe, iae);
* throw ioe;
* }
* }
*
* You can also just use JDK 1.4 causes:
*
* public void doSomething() throws IOException {
* try {
* doSomethingElse();
* } catch (IllegalArgumentException iae) {
* IOException ioe = new IOException("did not work: " + iae);
* ioe.initCause(iae);
* throw ioe;
* }
* }
* // ...
* try {
* foo.doSomething();
* } catch (IOException ioe) {
* // The IllegalArgumentException is still available here:
* ErrorManager.getDefault().notify(ioe);
* // or use logging
* Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ioe);
* }
*
*
*
* - Provide a user-visible (localized) message
* -
*
* public void doSomething(File f) throws IOException {
* if (!f.isFile()) {
* IOException e = new IOException("Not a file: " + f); // NOI18N
* // For what the user actually sees:
* ErrorManager.getDefault().annotate(e,
* NbBundle.getMessage(This.class, "EXC_not_a_file", f));
* throw e;
* }
* }
*
* You can also add the message when the exception is caught rather
* than when it is thrown. You could even have one piece of code throw
* an exception, another annotate it, and yet another notify it.
*
*
* - Collecting several exceptions and wrapping them in one
* -
*
* IOException all = null;
* for (int i = 0; i < things.length; i++) {
* try {
* things[i].process();
* } catch (ThingProcessingException e) {
* if (all == null) {
* all = new IOException("Could not process one or more things"); // NOI18N
* }
* ErrorManager.getDefault().annotate(all, e);
* }
* }
* if (all != null) {
* throw all;
* }
*
* -
*
*
- Logging a warning message just simply uses the JDK's logging API
* -
*
* public void doSomething(String arg) {
* if (arg.length() == 0) {
* Logger.getLogger(YourClass.class.getName()).log(Leverl.WARNING,
* "Warning: doSomething called on empty string");
* return;
* }
* // ...
* }
*
*
*
* - Logging messages for some subcomponent can be done easily with JDK's logging API
* -
*
* package org.netbeans.modules.foo;
* class FooModule {
* public static final Logger ERR =
* Logger.getLogger("org.netbeans.modules.foo");
* }
* // ...
* class Something {
* public void doSomething(String arg) {
* LogRecord rec = new LogRecord(Level.FINE, "MSG_Key");
* // where in the Bundle.properties one has:
* // MSG_Key=Called doSomething with arg {0}
* rec.setResourceBundle(NbBundle.getBundle(Something.class));
* rec.setParameters(new Object[] { arg });
* ERR.log(rec);
* }
* }
*
*
*
*
*
* @author Jaroslav Tulach, Jesse Glick
*/
public abstract class ErrorManager extends Object {
// XXX deprecate error manager after phase II and III are done. See:
// http://openide.netbeans.org/tutorial/reviews/opinions_35067.html
/**
* Undefined severity.
* May be used only in {@link #notify(int, Throwable)}
* and {@link #annotate(Throwable, int, String, String, Throwable, Date)}.
*/
public static final int UNKNOWN = 0x00000000;
/** Message that would be useful for tracing events but which need not be a problem. */
public static final int INFORMATIONAL = 0x00000001;
/** Something went wrong in the software, but it is continuing and the user need not be bothered. */
public static final int WARNING = 0x00000010;
/** Something the user should be aware of. */
public static final int USER = 0x00000100;
/** Something went wrong, though it can be recovered. */
public static final int EXCEPTION = 0x00001000;
/** Serious problem, application may be crippled. */
public static final int ERROR = 0x00010000;
/** We keep a reference to our proxy ErrorManager here. */
private static DelegatingErrorManager current;
/** Getter for the default version of error manager.
* @return the error manager installed in the system
* @since 2.1
*/
public static ErrorManager getDefault() {
synchronized (ErrorManager.class) {
if (current != null) {
return current;
}
}
return getDefaultDelegate();
}
private static DelegatingErrorManager getDefaultDelegate() {
DelegatingErrorManager c = new DelegatingErrorManager(""); // NOI18N
try {
c.initialize();
synchronized (ErrorManager.class) {
if (current == null) {
current = c;
// r is not null after c.initialize();
current.r.addLookupListener(current);
}
}
} catch (RuntimeException e) {
// #20467
e.printStackTrace();
current = c;
} catch (LinkageError e) {
// #20467
e.printStackTrace();
current = c;
}
return current;
}
/** Associates annotations with an exception.
*
* @param t the exception
* @param arr array of annotations (or null
)
* @return the same exception t
(as a convenience)
*/
public abstract Throwable attachAnnotations(Throwable t, Annotation[] arr);
/** Finds annotations associated with a given exception.
* @param t the exception
* @return array of annotations or null
*/
public abstract Annotation[] findAnnotations(Throwable t);
/** Annotates given exception with given values. All the
* previous annotations are kept and this new one is added at
* the top of the annotation stack (index 0 of the annotation
* array).
*
* @param t the exception
* @param severity integer describing severity, e.g. {@link #EXCEPTION}
* @param message message to attach to the exception or null
* @param localizedMessage localized message for the user or null
* @param stackTrace exception representing the stack trace or null
* @param date date or null
* @return the same exception t
(as a convenience)
*/
public abstract Throwable annotate(
Throwable t, int severity, String message, String localizedMessage, Throwable stackTrace, java.util.Date date
);
/** Prints the exception to the log file and (possibly) notifies the user.
* Use of {@link #UNKNOWN} severity means that the error manager should automatically
* select an appropriate severity level, for example based on the contents of
* annotations in the throwable.
* @param severity the severity to be applied to the exception (overrides default), e.g. {@link #EXCEPTION}
* @param t the exception to notify
*/
public abstract void notify(int severity, Throwable t);
/** Prints the exception to the log file and (possibly) notifies the user.
* Guesses at the severity.
* @param t the exception to notify
* @see #UNKNOWN
* @see #notify(int, Throwable)
*/
public final void notify(Throwable t) {
notify(UNKNOWN, t);
}
/** Logs the message to a file and (possibly) tells the user.
* @param severity the severity to be applied (overrides default)
* @param s the log message
*/
public abstract void log(int severity, String s);
// not yet: after phase III: * @deprecated use {@link Logger#log}
/** Logs the message to log file and (possibly) tells the user.
* Uses a default severity.
* @param s the log message
*/
public final void log(String s) {
// not yet: after phase III: * @deprecated {@link Logger#log}
log(INFORMATIONAL, s);
}
/** Test whether a messages with given severity will be logged in advance.
* Can be used to avoid the construction of complicated and expensive
* logging messages.
* The default implementation just returns true. Subclasses
* should override to be more precise - treat this method as abstract.
* @param severity the severity to check, e.g. {@link #EXCEPTION}
* @return false
if the next call to {@link #log(int,String)} with this severity will
* discard the message
*/
public boolean isLoggable(int severity) {
// not yet: after phase III: * @deprecated Use {@link Logger#isLoggable}
return true;
}
/**
* Test whether a throwable, if {@link #notify(int, Throwable) notified} at the given
* level, will actually be displayed in any way (even to a log file etc.).
* If not, there is no point in constructing it.
*
This method is distinct from {@link #isLoggable} because an error manager
* implementation may choose to notify stack traces at a level where it would
* not log messages. See issue #24056 for justification.
*
The default implementation just calls {@link #isLoggable}. Subclasses
* should override to be more precise - treat this method as abstract.
* @param severity a notification severity
* @return true if a throwable notified at this severity will be used; false if it will be ignored
* @since 3.18
*/
public boolean isNotifiable(int severity) {
return isLoggable(severity);
}
/** Returns an instance with given name.
*
By convention, you can name error managers the same as packages (or classes)
* they are designed to report information from.
* For example, org.netbeans.modules.mymodule.ComplicatedParser
.
*
The error manager implementation should provide some way of configuring e.g.
* the logging level for error managers of different names. For example, in the basic
* NetBeans core implementation, you can define a system property with the same name
* as the future error manager (or a package prefix of it) whose value is the numeric
* logging level (e.g. -J-Dorg.netbeans.modules.mymodule.ComplicatedParser=0
* to log everything). Other implementations may have quite different ways of configuring
* the error managers.
* @param name the desired identifying name
* @return a new error manager keyed off of that name
*/
public abstract ErrorManager getInstance(String name);
//
// Helper methods
//
/** Annotates given exception with given values. All the
* previous annotations are kept and this new is added at
* the top of the annotation stack (index 0 of the annotation
* array).
*
* @param t the exception
* @param localizedMessage localized message for the user or null
* @return the same exception t
(as a convenience)
*/
public final Throwable annotate(Throwable t, String localizedMessage) {
return annotate(t, UNKNOWN, null, localizedMessage, null, null);
}
/** Annotates target exception with given exception. All the
* previous annotations are kept and this new is added at
* the top of the annotation stack (index 0 of the annotation
* array).
*
Consider using {@link Throwable#initCause} instead; this
* will be correctly reported by the NetBeans error manager, and
* also works properly with {@link Throwable#printStackTrace()}.
* @param target the exception to be annotated
* @param t the exception that will be added
* @return the same exception target
(as a convenience)
*/
public final Throwable annotate(Throwable target, Throwable t) {
return annotate(target, UNKNOWN, null, null, t, null);
}
/** Takes annotations from one exception and associates
* them with another one.
*
* @param t the exception to annotate
* @param copyFrom exception to take annotations from
* @return the same exception t
(as a convenience)
* @deprecated Now does the same thing as {@link #annotate(Throwable,Throwable)}
* except marks the annotation {@link #UNKNOWN} severity. Otherwise
* you used to have inadvertent data loss when copyFrom
* had annotations of its own: the subannotations were kept but the
* main stack trace in copyFrom
was discarded. In practice
* you usually want to keep all of copyFrom
; if for some
* reason you just want to keep annotations, please do so explicitly
* using {@link #findAnnotations} and {@link #attachAnnotations}.
*/
@Deprecated
public final Throwable copyAnnotation(Throwable t, Throwable copyFrom) {
// Cf. #17874 for the change in behavior.
/*
Annotation[] arr = findAnnotations (copyFrom);
if (arr != null) {
return attachAnnotations (
t, arr
);
} else {
*/
return annotate(t, UNKNOWN, null, null, copyFrom, null);
/*
}
*/
}
/** Annotation that can be attached to an error.
*/
public static interface Annotation {
/** Non-localized message.
* @return associated message or null
*/
public abstract String getMessage();
/** Localized message.
* @return message to be presented to the user or null
*/
public abstract String getLocalizedMessage();
/** Stack trace. The stack trace should locate the method
* and position in the method where the error occurred.
*
* @return exception representing the location of the error or null
*/
public abstract Throwable getStackTrace();
/** Time at which the exception occurred.
* @return the time or null
*/
public abstract java.util.Date getDate();
/** Severity of the exception.
* {@link #UNKNOWN} serves as the default.
* @return number representing the severity, e.g. {@link ErrorManager#EXCEPTION}
*/
public abstract int getSeverity();
}
// end of Annotation
/**
* Implementation of ErrorManager that delegates to the ones found by
* lookup.
*/
private static class DelegatingErrorManager extends ErrorManager implements LookupListener {
private String name = null;
/**
* The set of instances we delegate to.
*/
private Set delegates = new HashSet();
/** fallback logger to send messages to */
private Logger logger;
/**
* A set that has to be updated when the list of delegates
* changes. All instances created by getInstance are held here.
*/
private WeakSet createdByMe = new WeakSet();
/** If we are the "central" delagate this is not null and
* we listen on the result. On newly created delegates this
* is null.
*/
Lookup.Result r;
public DelegatingErrorManager(String name) {
this.name = name;
}
/** Initializes the logger.
*/
Logger logger() {
if (logger == null) {
logger = Logger.getLogger(this.name);
}
return logger;
}
/** If the name is not empty creates new instance of
* DelegatingErrorManager. Adds it to createdByMe.
*/
public ErrorManager getInstance(String name) {
if ((name == null) || ("".equals(name))) { // NOI18N
return this;
}
DelegatingErrorManager dem = new DelegatingErrorManager(name);
synchronized (this) {
attachNewDelegates(dem, name);
createdByMe.add(dem);
}
return dem;
}
/** Calls all delegates. */
public Throwable attachAnnotations(Throwable t, Annotation[] arr) {
for (ErrorManager em : delegates) {
em.attachAnnotations(t, arr);
}
return t;
}
/** Calls all delegates. */
public Annotation[] findAnnotations(Throwable t) {
for (ErrorManager em : delegates) {
Annotation[] res = em.findAnnotations(t);
if ((res != null) && (res.length > 0)) {
return res;
}
}
return new Annotation[0];
}
/** Calls all delegates. */
public Throwable annotate(
Throwable t, int severity, String message, final String localizedMessage, Throwable stackTrace,
java.util.Date date
) {
if (delegates.isEmpty()) {
LogRecord rec = new LogRecord(convertSeverity(severity, true, Level.ALL), message);
if (stackTrace != null) {
rec.setThrown(stackTrace);
}
if (date != null) {
rec.setMillis(date.getTime());
}
if (localizedMessage != null) {
ResourceBundle rb = new ResourceBundle() {
public Object handleGetObject(String key) {
if ("msg".equals(key)) { // NOI18N
return localizedMessage;
} else {
return null;
}
}
public Enumeration getKeys() {
return Enumerations.singleton("msg"); // NOI18N
}
};
rec.setResourceBundle(rb);
rec.setMessage("msg"); // NOI18N
}
AnnException ann = AnnException.findOrCreate(t, true);
if (ann != null) { //#148778 - Although ann should not be null, it was reported it can happen.
ann.addRecord(rec);
}
return t;
}
for (ErrorManager em : delegates) {
em.annotate(t, severity, message, localizedMessage, stackTrace, date);
}
return t;
}
/** Calls all delegates. */
public void notify(int severity, Throwable t) {
if (delegates.isEmpty()) {
if (enterLogger()) return;
try {
AnnException ext = AnnException.extras.get(t);
if (ext != null) {
t = ext;
}
logger().log(convertSeverity(severity, true, OwnLevel.UNKNOWN), t.getMessage(), t);
} finally {
exitLogger();
}
return;
}
try {
for (ErrorManager em : delegates) {
em.notify(severity, t);
}
} catch (RuntimeException e) {
// #20467
e.printStackTrace();
t.printStackTrace();
} catch (LinkageError e) {
// #20467
e.printStackTrace();
t.printStackTrace();
}
}
/** Calls all delegates. */
public void log(int severity, String s) {
if (severity == UNKNOWN) {
throw new IllegalArgumentException("ErrorManager.log(UNKNOWN, ...) is not permitted"); // NOI18N
}
if (delegates.isEmpty()) {
Level sev = convertSeverity(severity, false, Level.FINE);
if (enterLogger()) return;
try {
logger().log(sev, s);
} finally {
exitLogger();
}
return;
}
for (ErrorManager em : delegates) {
em.log(severity, s);
}
}
private static Level convertSeverity(final int severity, boolean forException, Level def) {
Level sev = def;
if (severity >= ERROR) {
sev = Level.SEVERE;
} else if (severity >= EXCEPTION) {
sev = Level.SEVERE;
} else if (severity >= USER) {
sev = OwnLevel.USER;
} else if (severity >= WARNING) {
sev = Level.WARNING;
} else if (severity >= INFORMATIONAL) {
sev = forException ? Level.INFO: Level.FINE;
}
return sev;
}
/** Calls all delegates. */
public boolean isLoggable(int severity) {
if (severity == UNKNOWN) {
throw new IllegalArgumentException("ErrorManager.isLoggable(UNKNOWN) is not permitted"); // NOI18N
}
if (delegates.isEmpty()) {
return logger().isLoggable(convertSeverity(severity, false, null));
}
for (ErrorManager em : delegates) {
if (em.isLoggable(severity)) {
return true;
}
}
return false;
}
/** Calls all delegates. */
public boolean isNotifiable(int severity) {
if (severity == UNKNOWN) {
throw new IllegalArgumentException("ErrorManager.isNotifiable(UNKNOWN) is not permitted"); // NOI18N
}
if (delegates.isEmpty()) {
return logger().isLoggable(convertSeverity(severity, true, null));
}
for (ErrorManager em : delegates) {
if (em.isNotifiable(severity)) {
return true;
}
}
return false;
}
/**
* Updates the list of delegates. Also updates all instances created
* by ourselves.
*/
public synchronized void setDelegates(Collection extends ErrorManager> newDelegates) {
delegates = new LinkedHashSet(newDelegates);
for (DelegatingErrorManager dem : createdByMe) {
attachNewDelegates(dem, dem.getName());
}
}
private String getName() {
return name;
}
/**
* Takes all our delegates, asks them for an instance identified by
* name and adds those results as new delegates for dem.
* @param String name
* @param DelagatingErrorManager d the instance to which we will attach
*/
private void attachNewDelegates(DelegatingErrorManager dem, String name) {
Set newDelegatesForDem = new HashSet();
for (ErrorManager e : delegates) {
newDelegatesForDem.add(e.getInstance(name));
}
dem.setDelegates(newDelegatesForDem);
}
/** Blocks on lookup and after the lookup returns updates
* delegates and adds a listener.
*/
public void initialize() {
r = Lookup.getDefault().lookupResult(ErrorManager.class);
setDelegates(r.allInstances());
}
/** Updates the delegates.*/
public void resultChanged(LookupEvent ev) {
if (r != null) {
setDelegates(r.allInstances());
}
}
private static volatile Thread lastThread;
private static boolean enterLogger() {
if (lastThread == Thread.currentThread()) {
new Exception("using error manager from inside a logger").printStackTrace(); // NOI18N
return true;
}
lastThread = Thread.currentThread();
return false;
}
private static void exitLogger() {
lastThread = null;
}
}
/** An exception that has a log record associated with itself, so
* the NbErrorManager can extract info about the annotation.
*/
private static final class AnnException extends Exception implements Callable {
private List records;
/** additional mapping from throwables that refuse initCause call */
private static Map extras = new WeakHashMap();
public String getMessage() {
StringBuilder sb = new StringBuilder();
String sep = "";
for (LogRecord r : records) {
if (r.getMessage() != null) {
sb.append(sep);
sb.append(r.getMessage());
sep = "\n";
}
}
return sb.toString();
}
static AnnException findOrCreate(Throwable t, boolean create) {
AnnException ann;
try {
ann = findOrCreate0(t, create);
} catch (IllegalStateException x) {
assert create;
ann = extras.get(t);
if (ann == null) {
ann = new AnnException();
ann.initCause(t);
Logger.getLogger(ErrorManager.class.getName()).log(Level.FINE, "getCause was null yet initCause failed for " + t, x);
extras.put(t, ann);
}
}
return ann;
}
private static AnnException findOrCreate0(Throwable t, boolean create) {
if (t instanceof AnnException) {
return (AnnException) t;
}
if (t.getCause() == null) {
if (create) {
t.initCause(new AnnException());
}
return (AnnException) t.getCause();
}
return findOrCreate0(t.getCause(), create);
}
private AnnException() {
}
public synchronized void addRecord(LogRecord rec) {
if (records == null) {
records = new ArrayList();
}
records.add(rec);
}
public LogRecord[] call() {
List r = records;
LogRecord[] empty = new LogRecord[0];
return r == null ? empty : r.toArray(empty);
}
public void printStackTrace(PrintStream s) {
super.printStackTrace(s);
logRecords(s);
}
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
logRecords(s);
}
public void printStackTrace() {
printStackTrace(System.err);
}
private void logRecords(Appendable a) {
List r = records;
if (r == null) {
return;
}
try {
for (LogRecord log : r) {
if (log.getMessage() != null) {
a.append(log.getMessage()).append("\n");;
}
if (log.getThrown() != null) {
StringWriter w = new StringWriter();
log.getThrown().printStackTrace(new PrintWriter(w));
a.append(w.toString()).append("\n");
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
} // end AnnException
private static final class OwnLevel extends Level {
public static final Level USER = new OwnLevel("USER", 1973); // NOI18N
public static final Level UNKNOWN = new OwnLevel("SEVERE", Level.SEVERE.intValue() + 1); // NOI18N
private OwnLevel(String s, int i) {
super(s, i);
}
} // end of UserLevel
}