Author: costin Date: Thu Oct 27 19:55:08 2005 New Revision: 329053 URL: http://svn.apache.org/viewcvs?rev=329053&view=rev Log: Implementation of commons-logging that doesn't use any discovery or tricks, just plain java.util.logging.
There is a trick actually - at startup it'll try to load a different handler ( without 2-lines logs ) and a different config ( from classpath like log4j ). I'll probably remove this later, but I can't stand the default handler and behavior Added: tomcat/sandbox/java/ tomcat/sandbox/java/org/ tomcat/sandbox/java/org/apache/ tomcat/sandbox/java/org/apache/commons/ tomcat/sandbox/java/org/apache/commons/logging/ tomcat/sandbox/java/org/apache/commons/logging/DirectJDKLog.java tomcat/sandbox/java/org/apache/commons/logging/Log.java tomcat/sandbox/java/org/apache/commons/logging/LogConfigurationException.java tomcat/sandbox/java/org/apache/commons/logging/LogFactory.java Added: tomcat/sandbox/java/org/apache/commons/logging/DirectJDKLog.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/commons/logging/DirectJDKLog.java?rev=329053&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/commons/logging/DirectJDKLog.java (added) +++ tomcat/sandbox/java/org/apache/commons/logging/DirectJDKLog.java Thu Oct 27 19:55:08 2005 @@ -0,0 +1,185 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * Copyright 2004 Costin Manolache + * + * Licensed 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 org.apache.commons.logging; + +import java.util.logging.ConsoleHandler; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * Hardcoded java.util.logging commons-logging implementation. + * + * In addition, it curr + * + */ +class DirectJDKLog implements Log { + // no reason to hide this - but good reasons to not hide + public Logger logger; + + /** Alternate config reader and console format + */ + private static final String SIMPLE_FMT="org.apache.tomcat.util.log.JdkLoggerFormatter"; + private static final String SIMPLE_CFG="org.apache.tomcat.util.log.JdkLoggerConfig"; + + static { + if( System.getProperty("java.util.logging.config.class") ==null && + System.getProperty("java.util.logging.config.file") ==null ) { + // default configuration - it sucks. Let's override at least the + // formatter for the console + try { + Class.forName(SIMPLE_CFG).newInstance(); + } catch( Throwable t ) { + } + try { + Formatter fmt=(Formatter)Class.forName(SIMPLE_FMT).newInstance(); + // it is also possible that the user modifed jre/lib/logging.properties - + // but that's really stupid in most cases + Logger root=Logger.getLogger(""); + Handler handlers[]=root.getHandlers(); + for( int i=0; i< handlers.length; i++ ) { + // I only care about console - that's what's used in default config anyway + if( handlers[i] instanceof ConsoleHandler ) { + handlers[i].setFormatter(fmt); + } + } + } catch( Throwable t ) { + // maybe it wasn't included - the ugly default will be used. + t.printStackTrace(); + } + + } else { + System.out.println(System.getProperties()); + } + } + + public DirectJDKLog(String name ) { + logger=Logger.getLogger(name); + } + + public final boolean isErrorEnabled() { + return logger.isLoggable(Level.SEVERE); + } + + public final boolean isWarnEnabled() { + return logger.isLoggable(Level.WARNING); + } + + public final boolean isInfoEnabled() { + return logger.isLoggable(Level.INFO); + } + + public final boolean isDebugEnabled() { + return logger.isLoggable(Level.FINE); + } + + public final boolean isFatalEnabled() { + return logger.isLoggable(Level.SEVERE); + } + + public final boolean isTraceEnabled() { + return logger.isLoggable(Level.FINER); + } + + public final void debug(Object message) { + log(Level.FINE, String.valueOf(message), null); + } + + public final void debug(Object message, Throwable t) { + log(Level.FINE, String.valueOf(message), t); + } + + public final void trace(Object message) { + log(Level.FINER, String.valueOf(message), null); + } + + public final void trace(Object message, Throwable t) { + log(Level.FINER, String.valueOf(message), t); + } + + public final void info(Object message) { + log(Level.INFO, String.valueOf(message), null); + } + + public final void info(Object message, Throwable t) { + log(Level.INFO, String.valueOf(message), t); + } + + public final void warn(Object message) { + log(Level.WARNING, String.valueOf(message), null); + } + + public final void warn(Object message, Throwable t) { + log(Level.WARNING, String.valueOf(message), t); + } + + public final void error(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + public final void error(Object message, Throwable t) { + log(Level.SEVERE, String.valueOf(message), t); + } + + public final void fatal(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + public final void fatal(Object message, Throwable t) { + log(Level.SEVERE, String.valueOf(message), t); + } + + // from commons logging. This would be my number one reason why java.util.logging + // is bad - design by comitee can be really bad ! The impact on performance of + // using java.util.logging - and the ugliness if you need to wrap it - is far + // worse than the unfriendly and uncommon default format for logs. + + private void log( Level level, String msg, Throwable ex ) { + if (logger.isLoggable(level)) { + // Hack (?) to get the stack trace. + Throwable dummyException=new Throwable(); + StackTraceElement locations[]=dummyException.getStackTrace(); + // Caller will be the third element + String cname="unknown"; + String method="unknown"; + if( locations!=null && locations.length >2 ) { + StackTraceElement caller=locations[2]; + cname=caller.getClassName(); + method=caller.getMethodName(); + } + if( ex==null ) { + logger.logp( level, cname, method, msg ); + } else { + logger.logp( level, cname, method, msg, ex ); + } + } + } + + // for LogFactory + static void release() { + + } + + static Log getInstance(String name) { + return new DirectJDKLog( name ); + } +} + + Added: tomcat/sandbox/java/org/apache/commons/logging/Log.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/commons/logging/Log.java?rev=329053&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/commons/logging/Log.java (added) +++ tomcat/sandbox/java/org/apache/commons/logging/Log.java Thu Oct 27 19:55:08 2005 @@ -0,0 +1,233 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * Licensed 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 org.apache.commons.logging; + +/** + * <p>A simple logging interface abstracting logging APIs. In order to be + * instantiated successfully by [EMAIL PROTECTED] LogFactory}, classes that implement + * this interface must have a constructor that takes a single String + * parameter representing the "name" of this Log.</p> + * + * <p> The six logging levels used by <code>Log</code> are (in order): + * <ol> + * <li>trace (the least serious)</li> + * <li>debug</li> + * <li>info</li> + * <li>warn</li> + * <li>error</li> + * <li>fatal (the most serious)</li> + * </ol> + * The mapping of these log levels to the concepts used by the underlying + * logging system is implementation dependent. + * The implemention should ensure, though, that this ordering behaves + * as expected.</p> + * + * <p>Performance is often a logging concern. + * By examining the appropriate property, + * a component can avoid expensive operations (producing information + * to be logged).</p> + * + * <p> For example, + * <code><pre> + * if (log.isDebugEnabled()) { + * ... do something expensive ... + * log.debug(theResult); + * } + * </pre></code> + * </p> + * + * <p>Configuration of the underlying logging system will generally be done + * external to the Logging APIs, through whatever mechanism is supported by + * that system.</p> + * + * @author <a href="mailto:[EMAIL PROTECTED]">Scott Sanders</a> + * @author Rod Waldhoff + * @version $Id: Log.java 155426 2005-02-26 13:10:49Z dirkv $ + */ +public interface Log { + + + // ----------------------------------------------------- Logging Properties + + + /** + * <p> Is debug logging currently enabled? </p> + * + * <p> Call this method to prevent having to perform expensive operations + * (for example, <code>String</code> concatenation) + * when the log level is more than debug. </p> + */ + public boolean isDebugEnabled(); + + + /** + * <p> Is error logging currently enabled? </p> + * + * <p> Call this method to prevent having to perform expensive operations + * (for example, <code>String</code> concatenation) + * when the log level is more than error. </p> + */ + public boolean isErrorEnabled(); + + + /** + * <p> Is fatal logging currently enabled? </p> + * + * <p> Call this method to prevent having to perform expensive operations + * (for example, <code>String</code> concatenation) + * when the log level is more than fatal. </p> + */ + public boolean isFatalEnabled(); + + + /** + * <p> Is info logging currently enabled? </p> + * + * <p> Call this method to prevent having to perform expensive operations + * (for example, <code>String</code> concatenation) + * when the log level is more than info. </p> + */ + public boolean isInfoEnabled(); + + + /** + * <p> Is trace logging currently enabled? </p> + * + * <p> Call this method to prevent having to perform expensive operations + * (for example, <code>String</code> concatenation) + * when the log level is more than trace. </p> + */ + public boolean isTraceEnabled(); + + + /** + * <p> Is warn logging currently enabled? </p> + * + * <p> Call this method to prevent having to perform expensive operations + * (for example, <code>String</code> concatenation) + * when the log level is more than warn. </p> + */ + public boolean isWarnEnabled(); + + + // -------------------------------------------------------- Logging Methods + + + /** + * <p> Log a message with trace log level. </p> + * + * @param message log this message + */ + public void trace(Object message); + + + /** + * <p> Log an error with trace log level. </p> + * + * @param message log this message + * @param t log this cause + */ + public void trace(Object message, Throwable t); + + + /** + * <p> Log a message with debug log level. </p> + * + * @param message log this message + */ + public void debug(Object message); + + + /** + * <p> Log an error with debug log level. </p> + * + * @param message log this message + * @param t log this cause + */ + public void debug(Object message, Throwable t); + + + /** + * <p> Log a message with info log level. </p> + * + * @param message log this message + */ + public void info(Object message); + + + /** + * <p> Log an error with info log level. </p> + * + * @param message log this message + * @param t log this cause + */ + public void info(Object message, Throwable t); + + + /** + * <p> Log a message with warn log level. </p> + * + * @param message log this message + */ + public void warn(Object message); + + + /** + * <p> Log an error with warn log level. </p> + * + * @param message log this message + * @param t log this cause + */ + public void warn(Object message, Throwable t); + + + /** + * <p> Log a message with error log level. </p> + * + * @param message log this message + */ + public void error(Object message); + + + /** + * <p> Log an error with error log level. </p> + * + * @param message log this message + * @param t log this cause + */ + public void error(Object message, Throwable t); + + + /** + * <p> Log a message with fatal log level. </p> + * + * @param message log this message + */ + public void fatal(Object message); + + + /** + * <p> Log an error with fatal log level. </p> + * + * @param message log this message + * @param t log this cause + */ + public void fatal(Object message, Throwable t); + + +} Added: tomcat/sandbox/java/org/apache/commons/logging/LogConfigurationException.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/commons/logging/LogConfigurationException.java?rev=329053&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/commons/logging/LogConfigurationException.java (added) +++ tomcat/sandbox/java/org/apache/commons/logging/LogConfigurationException.java Thu Oct 27 19:55:08 2005 @@ -0,0 +1,97 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * Licensed 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 org.apache.commons.logging; + + +/** + * <p>An exception that is thrown only if a suitable <code>LogFactory</code> + * or <code>Log</code> instance cannot be created by the corresponding + * factory methods.</p> + * + * @author Craig R. McClanahan + * @version $Revision: 155426 $ $Date: 2005-02-26 05:10:49 -0800 (Sat, 26 Feb 2005) $ + */ + +public class LogConfigurationException extends RuntimeException { + + + /** + * Construct a new exception with <code>null</code> as its detail message. + */ + public LogConfigurationException() { + + super(); + + } + + + /** + * Construct a new exception with the specified detail message. + * + * @param message The detail message + */ + public LogConfigurationException(String message) { + + super(message); + + } + + + /** + * Construct a new exception with the specified cause and a derived + * detail message. + * + * @param cause The underlying cause + */ + public LogConfigurationException(Throwable cause) { + + this((cause == null) ? null : cause.toString(), cause); + + } + + + /** + * Construct a new exception with the specified detail message and cause. + * + * @param message The detail message + * @param cause The underlying cause + */ + public LogConfigurationException(String message, Throwable cause) { + + super(message + " (Caused by " + cause + ")"); + this.cause = cause; // Two-argument version requires JDK 1.4 or later + + } + + + /** + * The underlying cause of this exception. + */ + protected Throwable cause = null; + + + /** + * Return the underlying cause of this exception (if any). + */ + public Throwable getCause() { + + return (this.cause); + + } + + +} Added: tomcat/sandbox/java/org/apache/commons/logging/LogFactory.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/commons/logging/LogFactory.java?rev=329053&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/commons/logging/LogFactory.java (added) +++ tomcat/sandbox/java/org/apache/commons/logging/LogFactory.java Thu Oct 27 19:55:08 2005 @@ -0,0 +1,361 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * Licensed 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 org.apache.commons.logging; + + +import java.util.Properties; + + + +/** + * Modified LogFactory: removed all discovery, hardcode a specific implementation + * If you like a different logging implementation - use either the discovery-based + * commons-logging, or better - another implementation hardcoded to your favourite + * logging impl. + * + * Why ? Each application and deployment can choose a logging implementation - + * that involves configuration, installing the logger jar and optional plugins, etc. + * As part of this process - they can as well install the commons-logging implementation + * that corresponds to their logger of choice. This completely avoids any discovery + * problem, while still allowing the user to switch. + * + * Note that this implementation is not just a wrapper arround JDK logging ( like + * the original commons-logging impl ). It adds 2 features - a simpler configuration + * ( which is in fact a subset of log4j.properties ) and a formatter that is + * less ugly. + * + * The removal of 'abstract' preserves binary backward compatibility. It is possible + * to preserve the abstract - and introduce another ( hardcoded ) factory - but I + * see no benefit. + * + * Since this class is not intended to be extended - and provides + * no plugin for other LogFactory implementation - all protected methods are removed. + * This can be changed - but again, there is little value in keeping dead code. + * Just take a quick look at the removed code ( and it's complexity) + * + * -------------- + * + * Original comment: + * <p>Factory for creating [EMAIL PROTECTED] Log} instances, with discovery and + * configuration features similar to that employed by standard Java APIs + * such as JAXP.</p> + * + * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is heavily + * based on the SAXParserFactory and DocumentBuilderFactory implementations + * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.</p> + * + * + * @author Craig R. McClanahan + * @author Costin Manolache + * @author Richard A. Sitze + * @version $Revision: 209449 $ $Date: 2005-07-06 05:06:32 -0700 (Wed, 06 Jul 2005) $ + */ +public /* abstract */ class LogFactory { + + // ----------------------------------------------------- Manifest Constants + + /** + * The name of the property used to identify the LogFactory implementation + * class name. + */ + public static final String FACTORY_PROPERTY = + "org.apache.commons.logging.LogFactory"; + + /** + * The fully qualified class name of the fallback <code>LogFactory</code> + * implementation class to use, if no other can be found. + */ + public static final String FACTORY_DEFAULT = + "org.apache.commons.logging.impl.LogFactoryImpl"; + + /** + * The name of the properties file to search for. + */ + public static final String FACTORY_PROPERTIES = + "commons-logging.properties"; + + /** + * <p>Setting this system property value allows the <code>Hashtable</code> used to store + * classloaders to be substituted by an alternative implementation. + * </p> + * <p> + * <strong>Note:</strong> <code>LogFactory</code> will print: + * <code><pre> + * [ERROR] LogFactory: Load of custom hashtable failed</em> + * </code></pre> + * to system error and then continue using a standard Hashtable. + * </p> + * <p> + * <strong>Usage:</strong> Set this property when Java is invoked + * and <code>LogFactory</code> will attempt to load a new instance + * of the given implementation class. + * For example, running the following ant scriplet: + * <code><pre> + * <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}"> + * ... + * <sysproperty + * key="org.apache.commons.logging.LogFactory.HashtableImpl" + * value="org.apache.commons.logging.AltHashtable"/> + * </java> + * </pre></code> + * will mean that <code>LogFactory</code> will load an instance of + * <code>org.apache.commons.logging.AltHashtable</code>. + * </p> + * <p> + * A typical use case is to allow a custom + * Hashtable implementation using weak references to be substituted. + * This will allow classloaders to be garbage collected without + * the need to release them (on 1.3+ JVMs only, of course ;) + * </p> + */ + public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = + "org.apache.commons.logging.LogFactory.HashtableImpl"; + + private static LogFactory singleton=new LogFactory(); + + Properties logConfig; + + // ----------------------------------------------------------- Constructors + + + /** + * Protected constructor that is not available for public use. + */ + private LogFactory() { + logConfig=new Properties(); + } + + // hook for syserr logger - class level + void setLogConfig( Properties p ) { + this.logConfig=p; + } + // --------------------------------------------------------- Public Methods + + // only those 2 methods need to change to use a different direct logger. + + /** + * <p>Construct (if necessary) and return a <code>Log</code> instance, + * using the factory's current set of configuration attributes.</p> + * + * <p><strong>NOTE</strong> - Depending upon the implementation of + * the <code>LogFactory</code> you are using, the <code>Log</code> + * instance you are returned may or may not be local to the current + * application, and may or may not be returned again on a subsequent + * call with the same name argument.</p> + * + * @param name Logical name of the <code>Log</code> instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * + * @exception LogConfigurationException if a suitable <code>Log</code> + * instance cannot be returned + */ + public Log getInstance(String name) + throws LogConfigurationException { + return DirectJDKLog.getInstance(name); + } + + + /** + * Release any internal references to previously created [EMAIL PROTECTED] Log} + * instances returned by this factory. This is useful in environments + * like servlet containers, which implement application reloading by + * throwing away a ClassLoader. Dangling references to objects in that + * class loader would prevent garbage collection. + */ + public void release() { + DirectJDKLog.release(); + } + + /** + * Return the configuration attribute with the specified name (if any), + * or <code>null</code> if there is no such attribute. + * + * @param name Name of the attribute to return + */ + public Object getAttribute(String name) { + return logConfig.get(name); + } + + + /** + * Return an array containing the names of all currently defined + * configuration attributes. If there are no such attributes, a zero + * length array is returned. + */ + public String[] getAttributeNames() { + return (String[])logConfig.keySet().toArray(); + } + + /** + * Remove any configuration attribute associated with the specified name. + * If there is no such attribute, no action is taken. + * + * @param name Name of the attribute to remove + */ + public void removeAttribute(String name) { + logConfig.remove(name); + } + + + /** + * Set the configuration attribute with the specified name. Calling + * this with a <code>null</code> value is equivalent to calling + * <code>removeAttribute(name)</code>. + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or <code>null</code> + * to remove any setting for this attribute + */ + public void setAttribute(String name, Object value) { + logConfig.put(name, value); + } + + + /** + * Convenience method to derive a name from the specified class and + * call <code>getInstance(String)</code> with it. + * + * @param clazz Class for which a suitable Log name will be derived + * + * @exception LogConfigurationException if a suitable <code>Log</code> + * instance cannot be returned + */ + public Log getInstance(Class clazz) + throws LogConfigurationException { + return getInstance( clazz.getName()); + } + + + + + + // ------------------------------------------------------- Static Variables + + + + // --------------------------------------------------------- Static Methods + + + /** + * <p>Construct (if necessary) and return a <code>LogFactory</code> + * instance, using the following ordered lookup procedure to determine + * the name of the implementation class to be loaded.</p> + * <ul> + * <li>The <code>org.apache.commons.logging.LogFactory</code> system + * property.</li> + * <li>The JDK 1.3 Service Discovery mechanism</li> + * <li>Use the properties file <code>commons-logging.properties</code> + * file, if found in the class path of this class. The configuration + * file is in standard <code>java.util.Properties</code> format and + * contains the fully qualified name of the implementation class + * with the key being the system property defined above.</li> + * <li>Fall back to a default implementation class + * (<code>org.apache.commons.logging.impl.LogFactoryImpl</code>).</li> + * </ul> + * + * <p><em>NOTE</em> - If the properties file method of identifying the + * <code>LogFactory</code> implementation class is utilized, all of the + * properties defined in this file will be set as configuration attributes + * on the corresponding <code>LogFactory</code> instance.</p> + * + * @exception LogConfigurationException if the implementation class is not + * available or cannot be instantiated. + */ + public static LogFactory getFactory() throws LogConfigurationException { + return singleton; + } + + + /** + * Convenience method to return a named logger, without the application + * having to care about factories. + * + * @param clazz Class from which a log name will be derived + * + * @exception LogConfigurationException if a suitable <code>Log</code> + * instance cannot be returned + */ + public static Log getLog(Class clazz) + throws LogConfigurationException { + return (getFactory().getInstance(clazz)); + + } + + + /** + * Convenience method to return a named logger, without the application + * having to care about factories. + * + * @param name Logical name of the <code>Log</code> instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * + * @exception LogConfigurationException if a suitable <code>Log</code> + * instance cannot be returned + */ + public static Log getLog(String name) + throws LogConfigurationException { + return (getFactory().getInstance(name)); + + } + + + /** + * Release any internal references to previously created [EMAIL PROTECTED] LogFactory} + * instances that have been associated with the specified class loader + * (if any), after calling the instance method <code>release()</code> on + * each of them. + * + * @param classLoader ClassLoader for which to release the LogFactory + */ + public static void release(ClassLoader classLoader) { + // nothing - we don't use any class loaders + } + + + /** + * Release any internal references to previously created [EMAIL PROTECTED] LogFactory} + * instances, after calling the instance method <code>release()</code> on + * each of them. This is useful in environments like servlet containers, + * which implement application reloading by throwing away a ClassLoader. + * Dangling references to objects in that class loader would prevent + * garbage collection. + */ + public static void releaseAll() { + singleton.release(); + } + + /** + * Returns a string that uniquely identifies the specified object, including + * its class. + * <p> + * The returned string is of form "[EMAIL PROTECTED]", ie is the same as + * the return value of the Object.toString() method, but works even when + * the specified object's class has overidden the toString method. + * + * @param o may be null. + * @return a string of form [EMAIL PROTECTED], or "null" if param o is null. + */ + public static String objectId(Object o) { + if (o == null) { + return "null"; + } else { + return o.getClass().getName() + "@" + System.identityHashCode(o); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]