You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/15 15:57:17 UTC

svn commit: r386087 [21/45] - in /incubator/harmony/enhanced/classlib/trunk: make/ make/patternsets/ modules/jndi/ modules/jndi/META-INF/ modules/jndi/make/ modules/jndi/make/common/ modules/jndi/src/ modules/jndi/src/main/ modules/jndi/src/main/java/ ...

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/api/javax/naming/util/Util.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/api/javax/naming/util/Util.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/api/javax/naming/util/Util.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/api/javax/naming/util/Util.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,269 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 tests.api.javax.naming.util;
+
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchResult;
+
+public final class Util {
+
+	/**
+	 * Only entry to obtain an InitialContext instance.
+	 * 
+	 * @return a new InitialContext instance
+	 */
+	public static InitialContext getInitialContext() {
+		try {
+			Properties p = new Properties();
+			p.load(Util.class.getClassLoader().getResourceAsStream(
+					"jndi.properties"));
+			/*
+			 * Hashtable ht = new Hashtable(); ht.put(
+			 * Context.INITIAL_CONTEXT_FACTORY,
+			 * "dazzle.jndi.testing.spi.DazzleContextFactory");
+			 */
+			return new InitialContext(p);
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	/**
+	 * Clean up, opposite to getInitialContext().
+	 * 
+	 * @param ctx
+	 *            the InitialContext to clean up
+	 */
+	public static void cleanUpInitialContext(InitialContext ctx) {
+
+	}
+
+	/**
+	 * Only entry to obtain an InitialDirContext instance.
+	 * 
+	 * @return a new InitialDirContext instance
+	 */
+	public static InitialDirContext getInitialDirContext() {
+		try {
+			Properties p = new Properties();
+			p.load(Util.class.getClassLoader().getResourceAsStream(
+					"jndi.properties"));
+			Hashtable ht = new Hashtable();
+			ht.put(Context.INITIAL_CONTEXT_FACTORY,
+					"dazzle.jndi.testing.spi.DazzleContextFactory");
+			return new InitialDirContext(p);
+		} catch (Exception e) {
+			// e.printStackTrace();
+			return null;
+		}
+	}
+
+	/**
+	 * Clean up, opposite to getInitialDirContext().
+	 * 
+	 * @param ctx
+	 *            the InitialDirContext to clean up
+	 */
+	public static void cleanUpInitialDirContext(InitialDirContext ctx) {
+
+	}
+
+	/**
+	 * Format an Attribute to String
+	 * 
+	 * @param a
+	 * @return the string representation
+	 */
+	public static String toString(Attribute a) {
+		if (a == null) {
+			return "NULL";
+		}
+
+		try {
+			StringBuffer buf = new StringBuffer();
+			buf.append(a.getID());
+			if (a.isOrdered()) {
+				buf.append("+o");
+			}
+			buf.append("=");
+			if (a.size() == 0) {
+				buf.append("null");
+			} else if (a.size() == 1) {
+				buf.append(a.get());
+			} else {
+				buf.append("[");
+				for (int i = 0; i < a.size(); i++) {
+					if (i != 0) {
+						buf.append(",");
+					}
+					buf.append(a.get(i) == null ? "null" : a.get(i));
+				}
+				buf.append("]");
+			}
+			return buf.toString();
+		} catch (Throwable e) {
+			e.printStackTrace();
+			return "NULL";
+		}
+	}
+
+	/**
+	 * Format an Attributes to String
+	 * 
+	 * @param as
+	 * @return the string representation
+	 */
+	public static String toString(Attributes as) {
+		if (as == null) {
+			return "NULL";
+		}
+
+		try {
+			if (as.size() == 0) {
+				return "{}";
+			} else {
+				StringBuffer buf = new StringBuffer();
+				buf.append("{ ");
+				NamingEnumeration enumeration = as.getAll();
+				int i = 0;
+				while (enumeration.hasMoreElements()) {
+					Attribute a = (Attribute) enumeration.nextElement();
+					if (i != 0) {
+						buf.append(", ");
+					}
+					buf.append(toString(a));
+					i++;
+				}
+				buf.append(" }");
+				return buf.toString();
+			}
+		} catch (Throwable e) {
+			e.printStackTrace();
+			return "NULL";
+		}
+	}
+
+	/**
+	 * Format a SearchResult to String
+	 * 
+	 * @param r
+	 * @return the string representation
+	 */
+	public static String toString(SearchResult r) {
+		StringBuffer buf = new StringBuffer();
+		buf.append(r.getName());
+		buf.append(" ");
+		buf.append(toString(r.getAttributes()));
+		buf.append(" = ");
+		buf.append(r.getObject());
+		return buf.toString();
+	}
+
+	/**
+	 * Format a Context to String
+	 * 
+	 * @param ctx
+	 * @return the string representation
+	 */
+	public static String toString(Context ctx) {
+		if (ctx == null) {
+			return "NULL";
+		}
+
+		try {
+			StringBuffer buf = new StringBuffer();
+			return toString(buf, 0, ctx);
+		} catch (Throwable e) {
+			e.printStackTrace();
+			return "NULL";
+		}
+	}
+
+	/**
+	 * Format a DirContext to String
+	 * 
+	 * @param ctx
+	 * @return the string representation
+	 */
+	public static String toString(DirContext ctx) {
+		if (ctx == null) {
+			return "NULL";
+		}
+
+		try {
+			StringBuffer buf = new StringBuffer();
+			return toString(buf, 0, ctx);
+		} catch (Throwable e) {
+			e.printStackTrace();
+			return "NULL";
+		}
+	}
+
+	private static String toString(StringBuffer buf, int i, Context ctx)
+			throws NamingException {
+
+		int j = i + 4;
+		space(buf, i);
+		buf.append(ctx + " {").append("\n");
+
+		NamingEnumeration enumeration = ctx.listBindings("");
+		while (enumeration.hasMoreElements()) {
+			Binding r = (Binding) enumeration.nextElement();
+			space(buf, j);
+			if (r.getName() != null) {
+				buf.append(r.getName());
+				if (ctx instanceof DirContext) {
+					buf.append(" ");
+					buf.append(toString(((DirContext) ctx).getAttributes(r
+							.getName())));
+				}
+			}
+			buf.append(" = ");
+			if (r.getObject() instanceof Context) {
+				toString(buf, j, (Context) r.getObject());
+			} else {
+				buf.append(r.getObject() == null ? "" : r.getObject());
+			}
+			buf.append("\n");
+		}
+
+		space(buf, i);
+		buf.append("}");
+		return buf.toString();
+	}
+
+	private static void space(StringBuffer buf, int n) {
+		for (int i = 0; i < n; i++) {
+			buf.append(' ');
+		}
+	}
+
+	public static void main(String[] args) throws Exception {
+		Context ctx = Util.getInitialContext();
+		ctx.bind("test", new Integer(200));
+	}
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/jndi/AllTests.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/jndi/AllTests.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/jndi/AllTests.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/tests/jndi/AllTests.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,41 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 tests.jndi;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all tests for the JNDI project.
+ */
+public class AllTests {
+
+	public static void main(String[] args) {
+		junit.textui.TestRunner.run(AllTests.suite());
+	}
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite("All JNDI test suites");
+		// $JUnit-BEGIN$
+		suite.addTest(tests.api.javax.naming.AllTests.suite());
+		suite.addTest(tests.api.javax.naming.directory.AllTests.suite());
+		suite.addTest(tests.api.javax.naming.event.AllTests.suite());
+		suite.addTest(tests.api.javax.naming.ldap.AllTests.suite());
+		suite.addTest(tests.api.javax.naming.spi.AllTests.suite());
+		// $JUnit-END$
+		return suite;
+	}
+}
\ No newline at end of file

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/resources/libs/jnditesthelper.zip
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/resources/libs/jnditesthelper.zip?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/resources/libs/jnditesthelper.zip
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/META-INF/MANIFEST.MF?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/META-INF/MANIFEST.MF (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/META-INF/MANIFEST.MF Wed Mar 15 06:55:38 2006
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Harmony Logging
+Bundle-SymbolicName: org.apache.harmony.logging
+Bundle-Version: 1.0.0
+Bundle-ClassPath: .
+Eclipse-JREBundle: true
+Export-Package: java.util.logging
+Import-Package: java.lang,
+ java.beans,
+ java.io,
+ java.security,
+ java.util,
+ java.nio.channels,
+ java.text,
+ java.nio.charset,
+ java.net
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/make/build.xml
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/make/build.xml?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/make/build.xml (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/make/build.xml Wed Mar 15 06:55:38 2006
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+  
+    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.
+-->
+
+<project name="LOGGING Build" default="build" basedir="..">
+	<description>Build for LOGGING component</description>
+
+	<!-- set global properties for this build. -->
+	<xmlproperty file="make/common/hyproperties.xml" semanticAttributes="true"/>
+	<property environment="env"/>
+
+	<!-- Determine the (normalized) operating system family -->
+	<condition property="if.win">
+		<os family="Windows" />
+	</condition>
+	<condition property="hy.os_family" value="windows">
+		<isset property="if.win"/>
+	</condition>
+
+	<condition property="if.linux">
+		<and>
+			<os name="linux" />
+			<os family="unix" />
+		</and>
+	</condition>
+	<condition property="hy.os_family" value="linux">
+		<isset property="if.linux"/>
+	</condition>
+
+
+	<!-- Determine the (normalized) processor family -->
+	<condition property="if.x86_64">
+		<contains string="${os.arch}" substring="x86_64"/>
+	</condition>
+	<condition property="hy.cpu_family" value="x86_64">
+		<isset property="if.x86_64"/>
+	</condition>
+	
+	<condition property="if.x86">
+		<and>
+			<contains string="${os.arch}" substring="86"/>
+			<not>
+				<isset property="if.x86_64"/>
+			</not>
+		</and>
+	</condition>
+	<condition property="hy.cpu_family" value="x86">
+		<isset property="if.x86"/>
+	</condition>
+	
+	<condition property="if.ipf">
+		<contains string="${os.arch}" substring="ia64"/>
+	</condition>
+	<condition property="hy.cpu_family" value="ipf">
+		<isset property="if.ipf"/>
+	</condition>
+
+	<!-- Define the platform property dependant upon the OS and platform -->
+	<property name="hy.platform" value="${hy.os_family}.${hy.cpu_family}"/>
+
+	<!-- Set the java compiler to be the Eclipse Java compiler -->
+	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter" />
+
+
+	<target name="init">
+		<tstamp>
+			<format property="build-date" pattern="yyyyMMdd" locale="en" />
+		</tstamp>
+		<tstamp>
+			<format property="build-time" pattern="yyyyMMdd_HHmm" />
+		</tstamp>
+		<echo message="build-date=${build-date}" />
+		<echo message="build-time=${build-time}" />
+		<echo message="on platform=${os.name} version=${os.version} arch=${os.arch}" />
+
+		<property name="java.debug.option" value="on" />
+		<property name="native.debug.option" value="on" />
+
+		<property name="source.ver" value="1.4" />
+	</target>
+	
+	<!-- LOGGING TARGETS -->
+
+	<target name="build" depends="init">
+		<ant dir="make/common" target="compile.java" />
+		<ant dir="make/common" target="build.jar" />
+	<!--	<ant dir="make/platform/${hy.platform}" target="compile.native" /> -->
+		<ant dir="make/common" target="copy.resources" />
+	</target>
+
+
+	<target name="test" depends="build">
+		<ant dir="make/common" target="compile.tests" />
+		<ant dir="make/common" target="run.tests" />
+	</target>
+
+	<target name="clean">
+		<delete dir="${hy.logging.bin.main}"/>
+		<delete dir="${hy.logging.bin.test}"/>
+	</target>
+
+</project>

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/build.xml
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/build.xml?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/build.xml (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/build.xml Wed Mar 15 06:55:38 2006
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+  
+    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.
+-->
+
+<project name="Common_LOGGING_Build">
+	
+	<target name="compile.java" description="Compile LOGGING java code">
+		<echo message="Compiling LOGGING classes from ${hy.logging.src.main.java}" />
+		
+		<mkdir dir="${hy.logging.bin.main}" />
+
+		<javac sourcepath=""
+			srcdir="${hy.logging.src.main.java}"
+			destdir="${hy.logging.bin.main}"
+			source="${source.ver}"
+			debug="${java.debug.option}">
+
+			<bootclasspath>
+				<fileset dir="${hy.target}/jre/lib/boot">
+					<include name="*.jar" />
+				</fileset>
+			</bootclasspath>
+		</javac>
+	</target>
+	
+	<target name="build.jar">
+		<jar destfile="${hy.target}/jre/lib/boot/logging.jar"
+			manifest="${hy.logging}/META-INF/MANIFEST.MF">
+			<fileset dir="${hy.logging.bin.main}" />
+		</jar>
+	</target>
+
+	
+	<target name="compile.tests">
+		<echo message="Compiling LOGGING tests from ${hy.logging.src.test.java}" />
+
+		<mkdir dir="${hy.logging.bin.test}" />
+
+		<javac srcdir="${hy.logging.src.test.java}"
+			destdir="${hy.logging.bin.test}"
+			sourcepath=""
+			source="${source.ver}"
+			debug="${java.debug.option}">
+
+			<bootclasspath>
+				<fileset dir="${hy.target}/jre/lib/boot">
+					<include name="*.jar" />
+				</fileset>
+			</bootclasspath>
+                        <classpath location="../../../../build/tests" />
+		</javac>
+	</target>
+
+
+	<target name="run.tests">
+		
+	        <mkdir dir="${hy.tests.reports}" />
+
+	        <junit fork="yes"
+			forkmode="once"
+			printsummary="withOutAndErr"
+			errorproperty="test.error"
+			showoutput="on"
+			dir="${hy.logging.bin.test}"
+			jvm="${hy.target}/jre/bin/java">
+
+			<jvmarg value="-showversion"/>
+
+			<env key="JAVA_HOME" value="${hy.target}/jre"/>
+
+			<classpath>
+				<pathelement path="${hy.logging.bin.test}"/>
+			</classpath>
+                        <classpath location="../../../../build/tests" />
+
+			<formatter type="xml" />
+
+			<batchtest todir="${hy.tests.reports}" haltonfailure="no">
+				<fileset dir="${hy.logging.src.test.java}">
+					<include name="**/*Test.java"/>
+                                        <exclude name="**/JarFileTest.java"/>
+                                        <exclude name="**/JarOutputStreamTest.java"/>
+                                        <exclude name="**/GZIPInputStreamTest.java"/>
+                                        <exclude name="**/InflaterInputStreamTest.java"/>
+                                        <exclude name="**/InflaterTest.java"/>
+
+				</fileset>
+			</batchtest>
+		</junit>
+	</target>
+	
+	
+	<target name="copy.resources">
+		<!-- Nothing for LOGGING -->
+	</target>
+</project>
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/hyproperties.xml
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/hyproperties.xml?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/hyproperties.xml (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/make/common/hyproperties.xml Wed Mar 15 06:55:38 2006
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+  
+    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.
+-->
+
+<hy>
+   <logging location=".">
+      <src>
+         <main>
+            <java location="src/main/java" />
+        	<resources location="src/main/resources" />
+         </main>
+         <test>
+            <java location="src/test/java" />
+            <resources location="src/main/resources" />
+         </test>
+         <natives location="src/natives" />
+      </src>
+      <bin>
+        <main location="bin/main" />
+        <test location="bin/test" />
+      </bin>
+      <packaging>
+      </packaging>
+   </logging>
+
+   <target location="../../deploy" />
+
+   <tests>
+      <reports location="../../build/test_report" />
+   </tests>
+</hy>

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ConsoleHandler.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ConsoleHandler.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ConsoleHandler.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ConsoleHandler.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,89 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+/**
+ * A handler that writes log messages to the standard output stream
+ * <code>System.err</code>.
+ * <p>
+ * This handler reads the following properties from the log manager to
+ * initialize itself:
+ * <ul>
+ * <li>java.util.logging.ConsoleHandler.level specifies the logging level,
+ * defaults to <code>Level.INFO</code> if this property is not found or has an
+ * invalid value;
+ * <li>java.util.logging.ConsoleHandler.filter specifies the name of the filter
+ * class to be associated with this handler, defaults to <code>null</code> if
+ * this property is not found or has an invalid value;
+ * <li>java.util.logging.ConsoleHandler.formatter specifies the name of the
+ * formatter class to be associated with this handler, defaults to
+ * <code>java.util.logging.SimpleFormatter</code> if this property is not
+ * found or has an invalid value;
+ * <li>java.util.logging.ConsoleHandler.encoding specifies the encoding this
+ * handler will use to encode log messages, defaults to <code>null</code> if
+ * this property is not found or has an invalid value.
+ * </ul>
+ * </p>
+ * <p>
+ * This class is not thread-safe.
+ * </p>
+ * 
+ */
+public class ConsoleHandler extends StreamHandler {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Constructs a <code>ConsoleHandler</code> object.
+     */
+    public ConsoleHandler() {
+        super(System.err);
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Closes this handler. The <code>System.err</code> is flushed but not
+     * closed.
+     */
+    public void close() {
+        super.close(false);
+    }
+
+    /**
+     * Logs a record if necessary. A flush operation will be done.
+     * 
+     * @param record
+     *            the log record to be logged
+     */
+    public void publish(LogRecord record) {
+        super.publish(record);
+        super.flush();
+
+    }
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ErrorManager.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ErrorManager.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ErrorManager.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/ErrorManager.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,147 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+/**
+ * <code>Handler</code> objects can report errors to the
+ * <code>ErrorManager</code> instance attached to them when they encounter any
+ * exceptions or errors.
+ * <p>
+ * Callers of a logger are unlikely to be interested in the exceptions occured
+ * during logging. Use an <code>ErrorManager</code> object to report these
+ * exceptions.
+ * </p>
+ * 
+ */
+public class ErrorManager {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * The error code indicating a failure that does not fit in any of the
+     * specific types of failures that follow.
+     */
+    public static final int GENERIC_FAILURE = 0;
+
+    /**
+     * The error code indicating a failure when writting to an output stream.
+     */
+    public static final int WRITE_FAILURE = 1;
+
+    /**
+     * The error code indicating a failure when flushing an output stream.
+     */
+    public static final int FLUSH_FAILURE = 2;
+
+    /**
+     * The error code indicating a failure when closing an output stream.
+     */
+    public static final int CLOSE_FAILURE = 3;
+
+    /**
+     * The error code indicating a failure when opening an output stream.
+     */
+    public static final int OPEN_FAILURE = 4;
+
+    /**
+     * The error code indicating a failure when formatting the error messages.
+     */
+    public static final int FORMAT_FAILURE = 5;
+
+    /*
+     * -------------------------------------------------------------------
+     * Instance variables
+     * -------------------------------------------------------------------
+     */
+
+    // Used to synchronize calls to the error method.
+    private Object lock;
+
+    // Indicating whether the current call is the first call.
+    private boolean firstCall;
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Constructs an instance of <code>ErrorManager</code>.
+     */
+    public ErrorManager() {
+        lock = new Object();
+        firstCall = true;
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Reports an error.
+     * <p>
+     * This method can be called by a <code>Handler</code> object when it
+     * encounters an exception or error. The first call to this method will do
+     * the exact error-reporting as desired. Subsequent calls are ignored.
+     * 
+     * @param msg
+     *            the error message which may be <code>null</code>
+     * @param ex
+     *            the exception which may be <code>null</code>
+     * @param errorCode
+     *            the error code indicating the type of the failure
+     */
+    public void error(String msg, Exception ex, int errorCode) {
+        if (firstCall) {
+            // Synchronize concurrent "first" calls
+            synchronized (lock) {
+                if (firstCall) {
+                    outputError(msg, ex, errorCode);
+                }
+            }
+        }
+    }
+
+    //if it is the first time to call error, output it
+    private void outputError(String msg, Exception ex, int errorCode) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(this.getClass().getName());
+        sb.append(": the error code is "); //$NON-NLS-1$
+        sb.append(errorCode);
+        sb.append("."); //$NON-NLS-1$
+        sb.append(LogManager.getSystemLineSeparator());
+        if (null != msg) {
+            sb.append("The error message is: "); //$NON-NLS-1$
+            sb.append(msg);
+            sb.append(LogManager.getSystemLineSeparator());
+        }
+        if (null != ex) {
+            sb.append(ex.toString());
+        }
+        System.err.println(sb);
+        firstCall = false;
+    }
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/FileHandler.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/FileHandler.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/FileHandler.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/FileHandler.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,605 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Hashtable;
+
+/**
+ * A <code>Handler</code> writes description of logging event into a specified
+ * file or a rotating set of files.
+ * <p>
+ * If a set of files are used, when a given amount of data has been written to
+ * one file, this file is closed, and another file is opened. The name of these
+ * files are generated by given name pattern, see below for details.
+ * </p>
+ * <p>
+ * By default the IO buffering mechanism is enabled, but when each log record is
+ * complete, it is flushed out.
+ * </p>
+ * <p>
+ * <code>XMLFormatter</code> is default formatter for <code>FileHandler</code>.
+ * </p>
+ * <p>
+ * <code>MemoryHandler</code> will read following <code>LogManager</code>
+ * properties for initialization, if given propeties are not defined or has
+ * invalid values, default value will be used.
+ * <ul>
+ * <li>java.util.logging.FileHandler.level specifies the level for this
+ * <code>Handler</code>, defaults to <code>Level.ALL</code>.</li>
+ * <li>java.util.logging.FileHandler.filter specifies the <code>Filter</code>
+ * class name, defaults to no <code>Filter</code>.</li>
+ * <li>java.util.logging.FileHandler.formatter specifies the
+ * <code>Formatter</code> class, defaults to
+ * <code>java.util.logging.XMLFormatter</code>.</li>
+ * <li>java.util.logging.FileHandler.encoding specifies the character set
+ * encoding name, defaults to the default platform encoding.</li>
+ * <li>java.util.logging.FileHandler.limit specifies an maximum bytes to write
+ * to any one file, defaults to zero, which means no limit.</li>
+ * <li>java.util.logging.FileHandler.count specifies how many output files to
+ * rotate, defaults to 1.</li>
+ * <li>java.util.logging.FileHandler.pattern specifies name pattern for the
+ * output files. See below for details. Defaults to "%h/java%u.log".</li>
+ * <li>java.util.logging.FileHandler.append specifies whether this
+ * <code>FileHandler</code> should append onto existing files, defaults to
+ * false.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Name pattern is a string that may includes some special sub-strings, which
+ * will be replaced to generate output files:
+ * <ul>
+ * <li>"/" represents the local pathname separator</li>
+ * <li>"%t" represents the system temporary directory</li>
+ * <li>"%h" represents the home directory of current user, which is specified
+ * by "user.home" system property</li>
+ * <li>"%g" represents the generation number to distinguish rotated logs</li>
+ * <li>"%u" represents a unique number to resolve conflicts</li>
+ * <li>"%%" represents percent sign character '%'</li>
+ * </ul>
+ * </p>
+ * Normally, the generation numbers are not larger than given file count and
+ * follow the sequence 0, 1, 2.... If the file count is larger than one, but the
+ * generation field("%g") has not been specifed in the pattern, then the
+ * generation number after a dot will be added to the end of the file name,
+ * </p>
+ * <p>
+ * The "%u" unique field is used to avoid conflicts and set to 0 at first. If
+ * one <code>FileHandler</code> tries to open the filename which is currently
+ * in use by another process, it will repeatly increment the unique number field
+ * and try again. If the "%u" component has not been included in the file name
+ * pattern and some contention on a file does occur then a unique numerical
+ * value will be added to the end of the filename in question immediately to the
+ * right of a dot. The unique ids to avoid conflicts is only guaranteed to work
+ * reliably when using a local disk file system.
+ * </p>
+ * 
+ */
+public class FileHandler extends StreamHandler {
+
+    /*
+     * ---------------------------------------------
+     * constants
+     * ---------------------------------------------
+     */
+    private static final int DEFAULT_COUNT = 1;
+
+    private static final int DEFAULT_LIMIT = 0;
+
+    private static final boolean DEFAULT_APPEND = false;
+
+    private static final String DEFAULT_PATTERN = "%h/java%u.log"; //$NON-NLS-1$
+
+    /*
+     * ---------------------------------------------
+     * class variables
+     * ---------------------------------------------
+     */
+    //maintain all file locks hold by this process
+    private static Hashtable allLocks = new Hashtable();
+
+    /*
+     * ---------------------------------------------
+     * instance variables
+     * ---------------------------------------------
+     */
+
+    //the count of files which the output cycle through
+    private int count;
+
+    //the size limitation in byte of log file
+    private int limit;
+
+    //whether the FileHandler should open a existing file for output in append mode
+    private boolean append;
+
+    //the pattern for output file name
+    private String pattern;
+
+    //maintain a LogManager instance for convenience
+    private LogManager manager;
+
+    //output stream, which can measure the output file length
+    private MeasureOutputStream output;
+
+    //used output file
+    private File[] files;
+
+    //output file lock
+    FileLock lock = null;
+
+    //current output file name
+    String fileName = null;
+
+    //current generation
+    int generation = 0;
+
+    /*
+     * ---------------------------------------------
+     * constructors
+     * ---------------------------------------------
+     */
+    /**
+     * Construct a <code>FileHandler</code> using <code>LogManager</code> 
+     * properties or their default value
+     * 
+     * @throws IOException			
+     * 				if any IO exception happened
+     * @throws SecurityException	
+     * 				if security manager exists and it determines that caller 
+     * 				does not have the required permissions to control this handler,
+     * 				required permissions include <code>LogPermission("control")</code>
+     * 				and other permission like <code>FilePermission("write")</code>, 
+     * 				etc.
+     * 								
+     */
+    public FileHandler() throws IOException {
+        init(null, null, null, null);
+    }
+
+    //init properties
+    private void init(String p, Boolean a, Integer l, Integer c)
+            throws IOException {
+        //check access
+        manager = LogManager.getLogManager();
+        manager.checkAccess();
+        initProperties(p, a, l, c);
+        initOutputFiles();
+    }
+
+    private void initOutputFiles() throws FileNotFoundException, IOException {
+        int uniqueID = -1;
+        FileOutputStream fileStream = null;
+        FileChannel channel = null;
+        while (true) {
+            //try to find a unique file which is not locked by other process
+            fileName = parseFileName(generation, ++uniqueID);
+            synchronized (allLocks) {
+                //if current process has held lock for this fileName
+                //continue to find next file
+                if (null != allLocks.get(fileName)) {
+                    continue;
+                }
+                try {
+                    fileStream = new FileOutputStream(fileName, true);
+                    channel = fileStream.getChannel();
+                } catch(FileNotFoundException e){
+                    //invalid path name, throw exception
+                    throw e;
+                }
+                //if lock is unsupported and IOException throwed, just let the 
+                //IOException throws out and exit
+                //otherwise it will go into an undead cycle
+                lock = channel.tryLock();
+                if (null == lock) {
+                    continue;
+                }
+				files[0] = new File(fileName);
+				allLocks.put(fileName, lock);
+				break;
+            }
+        }
+        for (generation = 1; generation < count; generation++) {
+            //cache all file names for rotation use
+            files[generation] = new File(parseFileName(generation, uniqueID));
+        }
+        output = new MeasureOutputStream(new BufferedOutputStream(fileStream),
+                files[0].length());
+        if (append && output.getLength() < limit) {
+            setOutputStream(output);
+        } else {
+            setOutputStream(output);
+            findNextGeneration();
+        }
+    }
+
+    private void initProperties(String p, Boolean a, Integer l, Integer c) {
+        super.initProperties("ALL", null, "java.util.logging.XMLFormatter",  //$NON-NLS-1$//$NON-NLS-2$
+                null);
+        String className = this.getClass().getName();
+        pattern = (null == p) ? getStringProperty(className + ".pattern", //$NON-NLS-1$
+                DEFAULT_PATTERN) : p;
+        if (null == pattern || "".equals(pattern)) { //$NON-NLS-1$
+            throw new NullPointerException("Pattern cannot be empty"); //$NON-NLS-1$
+        }
+        append = (null == a) ? getBooleanProperty(className + ".append", //$NON-NLS-1$
+                DEFAULT_APPEND) : a.booleanValue();
+        count = (null == c) ? getIntProperty(className + ".count", //$NON-NLS-1$
+                DEFAULT_COUNT) : c.intValue();
+        limit = (null == l) ? getIntProperty(className + ".limit", //$NON-NLS-1$
+                DEFAULT_LIMIT) : l.intValue();
+        count = count < 1 ? DEFAULT_COUNT : count;
+        limit = limit < 0 ? DEFAULT_LIMIT : limit;
+        files = new File[count];
+    }
+
+    private void findNextGeneration() {
+        super.close();
+        for (int i = count - 1; i > 0; i--) {
+            if (files[i].exists()) {
+                files[i].delete();
+            }
+            files[i - 1].renameTo(files[i]);
+        }
+        try {
+            output = new MeasureOutputStream(new BufferedOutputStream(
+                    new FileOutputStream(files[0])));
+        } catch (FileNotFoundException e1) {
+            this.getErrorManager().error("Error happened when open log file.", //$NON-NLS-1$
+                    e1, ErrorManager.OPEN_FAILURE);
+        }
+        setOutputStream(output);
+
+    }
+
+    //apply settings, parse pattern and open files
+    private String parseFileName(int gen, int uniqueID) {
+        int cur = 0;
+        int next = 0;
+        boolean hasUniqueID = false;
+        boolean hasGeneration = false;
+        //TODO privilege code?
+        String tempPath = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$
+        String homePath = System.getProperty("user.home"); //$NON-NLS-1$
+        StringBuffer sb = new StringBuffer();
+        pattern = pattern.replace('/', File.separatorChar);
+        char[] value = pattern.toCharArray();
+        while ((next = pattern.indexOf('%', cur)) >= 0) {
+            if (++next < pattern.length()) {
+                switch (value[next]) {
+                case 'g':
+                    sb.append(value, cur, next - cur - 1).append(gen);
+                    hasGeneration = true;
+                    break;
+                case 'u':
+                    sb.append(value, cur, next - cur - 1).append(uniqueID);
+                    hasUniqueID = true;
+                    break;
+                case 't':
+                    sb.append(value, cur, next - cur - 1).append(tempPath);
+                    break;
+                case 'h':
+                    sb.append(value, cur, next - cur - 1).append(homePath);
+                    break;
+                case '%':
+                    sb.append(value, cur, next - cur - 1).append('%');
+                    break;
+                default:
+                    sb.append(value, cur, next - cur);
+                }
+                cur = ++next;
+            } else {
+
+            }
+        }
+        sb.append(value, cur, value.length - cur);
+        if (!hasGeneration && count > 1) {
+            sb.append(".").append(gen); //$NON-NLS-1$
+        }
+        if (!hasUniqueID && uniqueID > 0) {
+            sb.append(".").append(uniqueID); //$NON-NLS-1$
+        }
+        return sb.toString();
+    }
+
+    //get boolean LogManager property, if invalid value got, using default value
+    private boolean getBooleanProperty(String key, boolean defaultValue) {
+        String property = manager.getProperty(key);
+        if (null == property) {
+            return defaultValue;
+        }
+        boolean result = defaultValue;
+        if ("true".equalsIgnoreCase(property)) { //$NON-NLS-1$
+            result = true;
+        } else if ("false".equalsIgnoreCase(property)) { //$NON-NLS-1$
+            result = false;
+        }
+        return result;
+    }
+
+    //get String LogManager property, if invalid value got, using default value
+    private String getStringProperty(String key, String defaultValue) {
+        String property = manager.getProperty(key);
+        return property == null ? defaultValue : property;
+    }
+
+    //get int LogManager property, if invalid value got, using default value
+    private int getIntProperty(String key, int defaultValue) {
+        String property = manager.getProperty(key);
+        int result = defaultValue;
+        if (null != property) {
+            try {
+                result = Integer.parseInt(property);
+            } catch (Exception e) {//ignore
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Construct a <code>FileHandler</code>, the given name pattern is used as
+     * output filename, the file limit is set to zero(no limit), and the file 
+     * count is set to one, other configuration using <code>LogManager</code> 
+     * properties or their default value
+     * 
+     * This handler write to only one file and no amount limit.
+     *
+     * @param  pattern
+     * 				the name pattern of output file 
+     * @throws IOException			
+     * 				if any IO exception happened
+     * @throws SecurityException	
+     * 				if security manager exists and it determines that caller 
+     * 				does not have the required permissions to control this handler,
+     * 				required permissions include <code>LogPermission("control")</code>
+     * 				and other permission like <code>FilePermission("write")</code>, 
+     * 				etc.
+     * 								
+     */
+    public FileHandler(String pattern) throws IOException {
+        if(null == pattern || "".equals(pattern)){ //$NON-NLS-1$
+            throw new NullPointerException("Pattern cannot be empty"); //$NON-NLS-1$
+        }
+        init(pattern, null, new Integer(DEFAULT_LIMIT), new Integer(
+                DEFAULT_COUNT));
+    }
+
+    /**
+	 * Construct a <code>FileHandler</code>, the given name pattern is used
+	 * as output filename, the file limit is set to zero(i.e. no limit applies),
+	 * the file count is initialized to one, and the value of
+	 * <code>append</code> becomes the new instance's append mode. Other
+	 * configuration is done using <code>LogManager</code> properties.
+	 * 
+	 * This handler write to only one file and no amount limit.
+	 * 
+	 * @param pattern
+	 *            the name pattern of output file
+	 * @param append
+	 *            the append mode
+	 * @throws IOException
+	 *             if any IO exception happened
+	 * @throws SecurityException
+	 *             if security manager exists and it determines that caller does
+	 *             not have the required permissions to control this handler,
+	 *             required permissions include
+	 *             <code>LogPermission("control")</code> and other permission
+	 *             like <code>FilePermission("write")</code>, etc.
+	 * 
+	 */
+    public FileHandler(String pattern, boolean append) throws IOException {
+        if(null == pattern || "".equals(pattern)){ //$NON-NLS-1$
+            throw new NullPointerException("Pattern cannot be empty"); //$NON-NLS-1$
+        }        
+        init(pattern, Boolean.valueOf(append), new Integer(DEFAULT_LIMIT),
+                new Integer(DEFAULT_COUNT));
+    }
+
+    /**
+     * Construct a <code>FileHandler</code>, the given name pattern is used as
+     * output filename, the file limit is set to given limit argument, and 
+     * the file count is set to given count argument, other configuration using 
+     * <code>LogManager</code> properties  or their default value
+     * 
+     * This handler is configured to write to a rotating set of count files, 
+     * when the limit of bytes has been written to one output file, another file 
+     * will be opened instead.  
+     *
+     * @param  pattern
+     * 				the name pattern of output file
+     * @param  limit
+     * 				the data amount limit in bytes of one ouput file, cannot less
+     * 				than one
+     * @param  count
+     * 				the maximum number of files can be used, cannot less than one 
+     * @throws IOException			
+     * 				if any IO exception happened
+     * @throws SecurityException	
+     * 				if security manager exists and it determines that caller 
+     * 				does not have the required permissions to control this handler,
+     * 				required permissions include <code>LogPermission("control")</code>
+     * 				and other permission like <code>FilePermission("write")</code>, 
+     * 				etc.
+     * @throws IllegalArgumentException
+     * 				if count<1, or limit<0 								
+     */
+    public FileHandler(String pattern, int limit, int count) throws IOException {
+        if(null == pattern || "".equals(pattern)){ //$NON-NLS-1$
+            throw new NullPointerException("Pattern cannot be empty"); //$NON-NLS-1$
+        }        
+        if (limit < 1 || count < 0) {
+            throw new IllegalArgumentException(
+                    "The limit and count property must larger than 0 and 1, respctively"); //$NON-NLS-1$
+        }
+        init(pattern, null, new Integer(limit), new Integer(count));
+    }
+
+    /**
+     * Construct a <code>FileHandler</code>, the given name pattern is used as
+     * output filename, the file limit is set to given limit argument, the file 
+     * count is set to given count argument, and the append mode is set to given
+     * append argument, other configuration using <code>LogManager</code> 
+     * properties  or their default value
+     * 
+     * This handler is configured to write to a rotating set of count files, 
+     * when the limit of bytes has been written to one output file, another file 
+     * will be opened instead. 
+     * 
+     * @param  pattern
+     * 				the name pattern of output file
+     * @param  limit
+     * 				the data amount limit in bytes of one ouput file, cannot less
+     * 				than one
+     * @param  count
+     * 				the maximum number of files can be used, cannot less than one 
+     * @param  append
+     * 				the append mode
+     * @throws IOException			
+     * 				if any IO exception happened
+     * @throws SecurityException	
+     * 				if security manager exists and it determines that caller 
+     * 				does not have the required permissions to control this handler,
+     * 				required permissions include <code>LogPermission("control")</code>
+     * 				and other permission like <code>FilePermission("write")</code>, 
+     * 				etc.
+     * @throws IllegalArgumentException
+     * 				if count<1, or limit<0
+     * 								
+     */
+    public FileHandler(String pattern, int limit, int count, boolean append)
+            throws IOException {
+        if(null == pattern || "".equals(pattern)){ //$NON-NLS-1$
+            throw new NullPointerException("Pattern cannot be empty"); //$NON-NLS-1$
+        }        
+        if (limit < 1 || count < 0) {
+            throw new IllegalArgumentException(
+                    "The limit and count property must larger than 0 and 1, respectively"); //$NON-NLS-1$
+        }
+        init(pattern, Boolean.valueOf(append), new Integer(limit), new Integer(
+                count));
+    }
+
+    /*
+     * ---------------------------------------------
+     * Methods overrides StreamHandler
+     * ---------------------------------------------
+     */
+    /**
+     * Flush and close all opened files.
+     * 
+     * @throws SecurityException	
+     * 				if security manager exists and it determines that caller 
+     * 				does not have the required permissions to control this handler,
+     * 				required permissions include <code>LogPermission("control")</code>
+     * 				and other permission like <code>FilePermission("write")</code>, 
+     * 				etc.
+     */
+    public void close() {
+        //release locks
+        super.close();
+        //        //FIXME: delete this
+        //        System.out.println("close:"+fileName);
+        allLocks.remove(fileName);
+        try {
+            lock.release();
+        } catch (IOException e) {
+            //ignore
+        }
+    }
+
+    /**
+     * Publish a <code>LogRecord</code>
+     * 
+     * @param record the log record to be published
+     */
+    public void publish(LogRecord record) {
+        super.publish(record);
+        flush();
+        if (limit > 0 && output.getLength() >= limit) {
+            AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    findNextGeneration();
+                    return null;
+                }
+            });
+        }
+    }
+
+    /*
+     * This output stream use decorator pattern to add measure feature to OutputStream
+     * which can detect the total size(in bytes) of output, the initial size can be set
+     */
+    class MeasureOutputStream extends OutputStream {
+
+        OutputStream wrapped;
+
+        long length;
+
+        public MeasureOutputStream(OutputStream stream, long currentLength) {
+            wrapped = stream;
+            length = currentLength;
+        }
+
+        public MeasureOutputStream(OutputStream stream) {
+            this(stream, 0);
+        }
+
+        public void write(int oneByte) throws IOException {
+            wrapped.write(oneByte);
+            length++;
+        }
+
+        public void write(byte[] bytes) throws IOException {
+            wrapped.write(bytes);
+            length += bytes.length;
+        }
+
+        public void write(byte[] b, int off, int len) throws IOException {
+            wrapped.write(b, off, len);
+            length += len;
+        }
+
+        public void close() throws IOException {
+            wrapped.close();
+        }
+
+        public void flush() throws IOException {
+            wrapped.flush();
+        }
+
+        public long getLength() {
+            return length;
+        }
+
+        public void setLength(long newLength) {
+            length = newLength;
+        }
+
+    }
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Filter.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Filter.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Filter.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Filter.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,43 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+/**
+ * <code>Filter</code> objects are used to filter loggings that are not
+ * desired. <code>Handler</code> or <code>Logger</code> objects can be
+ * attached with a filter to get finer grain control over what should be logged.
+ * 
+ */
+public interface Filter {
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Checks whether the supplied log record needs to be logged.
+     * 
+     * @param record
+     *            the log record to be checked
+     * @return <code>true</code> if the supplied log record needs to be
+     *         logged, otherwise <code>false</code>
+     */
+    boolean isLoggable(LogRecord record);
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Formatter.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Formatter.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Formatter.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Formatter.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,129 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+/**
+ * <code>Formatter</code> objects are used to format <code>LogRecord</code>
+ * objects into a string representation. Head and tail strings are sometime used
+ * to wrap a set of records. The <code>getHead</code> and <code>getTail</code>
+ * methods are presented for this purpose.
+ * 
+ */
+public abstract class Formatter {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Constructs a <code>Formatter</code> object.
+     */
+    protected Formatter() {
+        super();
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Formats a <code>LogRecord</code> object into a string representation.
+     * The resulted string is usually localized and includes the message field
+     * of the supplied <code>LogRecord</code> object.
+     * 
+     * @param r
+     *            the log record to be formatted into a string
+     * @return the string resulted from the formatting
+     */
+    public abstract String format(LogRecord r);
+
+    /**
+     * Formats a <code>LogRecord</code> object into a localized string
+     * representation. This method can be regarded as a convenience for
+     * subclasses of <code>Formatter</code> to use.
+     * <p>
+     * The message string is firstly localized using the
+     * <code>ResourceBundle</code> object associated with the supplied
+     * <code>LogRecord</code>.
+     * </p>
+     * 
+     * @param r
+     *            the log record to be formatted
+     * @return the string resulted from the formatting
+     */
+    public String formatMessage(LogRecord r) {
+        String pattern = r.getMessage();
+        ResourceBundle rb = null;
+        // try to localize the message string first
+        if (null != (rb = r.getResourceBundle())) {
+            try {
+                pattern = rb.getString(pattern);
+            } catch (Exception e) {
+                pattern = r.getMessage();
+            }
+        }
+        if (null != pattern) {
+            Object[] params = r.getParameters();
+            /*
+             * if the message contains "{0", use java.text.MessageFormat to
+             * format the string
+             */
+            if (pattern.indexOf("{0") >= 0 && null != params //$NON-NLS-1$
+                    && params.length > 0) {
+                try {
+                    pattern = MessageFormat.format(pattern, params);
+                } catch (IllegalArgumentException e) {
+                    pattern = r.getMessage();
+                }
+            }
+        }
+        return pattern;
+    }
+
+    /**
+     * Gets the head string used to wrap a set of log records. This base class
+     * always returns the empty string.
+     * 
+     * @param h
+     *            the target handler
+     * @return the head string used to wrap a set of log records
+     */
+    public String getHead(Handler h) {
+        return ""; //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the tail string used to wrap a set of log records. This base class
+     * always returns the empty string.
+     * 
+     * @param h
+     *            the target handler
+     * @return the tail string used to wrap a set of log records
+     */
+    public String getTail(Handler h) {
+        return ""; //$NON-NLS-1$
+    }
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Handler.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Handler.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Handler.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Handler.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,414 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+import java.nio.charset.Charset;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A <code>Handler</code> object accepts a logging request and exports the
+ * desired messages to a target, for example, a file, the console, etc. It can
+ * be disabled by setting its logging level to <code>Level.OFF</code>.
+ * 
+ */
+public abstract class Handler {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+    private static final Level DEFAULT_LEVEL = Level.ALL;
+
+    /*
+     * -------------------------------------------------------------------
+     * Instance variables
+     * -------------------------------------------------------------------
+     */
+
+    // the error manager to report errors during logging
+    private ErrorManager errorMan;
+
+    // the character encoding used by this handler
+    private String encoding;
+
+    // the logging level
+    private Level level;
+
+    // the formatter used to export messages
+    private Formatter formatter;
+
+    // the filter used to filter undesired messages
+    private Filter filter;
+
+    // class name, used for property reading
+    private String prefix;
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Constructs a <code>Handler</code> object with a default error manager,
+     * the default encoding, and the default logging level
+     * <code>Level.ALL</code>. It has no filter and no formatter.
+     */
+    protected Handler() {
+        this.errorMan = new ErrorManager();
+        this.level = DEFAULT_LEVEL;
+        this.encoding = null;
+        this.filter = null;
+        this.formatter = null;
+        this.prefix = this.getClass().getName();
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    // get a instance from given class name, using Class.forName()
+    private Object getDefaultInstance(String className) {
+        Object result = null;
+        if (null == className) {
+            return result;
+        }
+        try {
+            result = Class.forName(className).newInstance();
+        } catch (Exception e) {
+            //ignore
+        }
+        return result;
+    }
+
+    // get a instance from given class name, using context classloader
+    private Object getCustomizeInstance(final String className)
+            throws Exception {
+        Class c = (Class) AccessController
+                .doPrivileged(new PrivilegedExceptionAction() {
+                    public Object run() throws Exception {
+                        ClassLoader loader = Thread.currentThread()
+                                .getContextClassLoader();
+                        if (null == loader)
+                            loader = ClassLoader.getSystemClassLoader();
+                        return loader.loadClass(className);
+                    }
+                });
+        return c.newInstance();
+    }
+
+    // print error message in some format
+    void printInvalidPropMessage(String key, String value, Exception e) {
+        String msg = new StringBuffer().append("Invalid property value for ") //$NON-NLS-1$
+                .append(prefix).append(".").append(key).append(":").append( //$NON-NLS-1$//$NON-NLS-2$
+                        value).toString();
+        errorMan.error(msg, e, ErrorManager.GENERIC_FAILURE);
+    }
+
+    /*
+     * init the common properties, including filter, level, formatter, and
+     * encoding
+     */
+    void initProperties(String defaultLevel, String defaultFilter,
+            String defaultFormatter, String defaultEncoding) {
+        LogManager manager = LogManager.getLogManager();
+
+        //set filter
+        final String filterName = manager.getProperty(prefix + ".filter"); //$NON-NLS-1$
+        if (null != filterName) {
+            try {
+                filter = (Filter) getCustomizeInstance(filterName);
+            } catch (Exception e1) {
+                printInvalidPropMessage("filter", filterName, e1); //$NON-NLS-1$
+                filter = (Filter) getDefaultInstance(defaultFilter);
+            }
+        } else {
+            filter = (Filter) getDefaultInstance(defaultFilter);
+        }
+
+        //set level
+        String levelName = manager.getProperty(prefix + ".level"); //$NON-NLS-1$
+        if (null != levelName) {
+            try {
+                level = Level.parse(levelName);
+            } catch (Exception e) {
+                printInvalidPropMessage("level", levelName, e); //$NON-NLS-1$
+                level = Level.parse(defaultLevel);
+            }
+        } else {
+            level = Level.parse(defaultLevel);
+        }
+
+        //set formatter
+        final String formatterName = manager.getProperty(prefix + ".formatter"); //$NON-NLS-1$
+        if (null != formatterName) {
+            try {
+                formatter = (Formatter) getCustomizeInstance(formatterName);
+            } catch (Exception e) {
+                printInvalidPropMessage("formatter", formatterName, e); //$NON-NLS-1$
+                formatter = (Formatter) getDefaultInstance(defaultFormatter);
+            }
+        } else {
+            formatter = (Formatter) getDefaultInstance(defaultFormatter);
+        }
+
+        //set encoding
+        final String encodingName = manager.getProperty(prefix + ".encoding"); //$NON-NLS-1$
+        try {
+            internalSetEncoding(encodingName);
+        } catch (UnsupportedEncodingException e) {
+            printInvalidPropMessage("encoding", encodingName, e); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Closes this handler. A flush operation will usually be performed and all
+     * the associated resources will be freed. Client applications should not
+     * use a handler after closing it.
+     * 
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     */
+    public abstract void close();
+
+    /**
+     * Flushes any buffered output.
+     */
+    public abstract void flush();
+
+    /**
+     * Accepts an actual logging request.
+     * 
+     * @param record
+     *            the log record to be logged
+     */
+    public abstract void publish(LogRecord record);
+
+    /**
+     * Gets the character encoding used by this handler.
+     * 
+     * @return the character encoding used by this handler
+     */
+    public String getEncoding() {
+        return this.encoding;
+    }
+
+    /**
+     * Gets the error manager used by this handler to report errors during
+     * logging.
+     * 
+     * @return the error manager used by this handler
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     */
+    public ErrorManager getErrorManager() {
+        LogManager.getLogManager().checkAccess();
+        return this.errorMan;
+    }
+
+    /**
+     * Gets the filter used by this handler.
+     * 
+     * @return the filter used by this handler
+     */
+    public Filter getFilter() {
+        return this.filter;
+    }
+
+    /**
+     * Gets the fomatter used by this handler to format the logging messages.
+     * 
+     * @return the fomatter used by this handler
+     */
+    public Formatter getFormatter() {
+        return this.formatter;
+    }
+
+    /**
+     * Gets the logging level of this handler.
+     * 
+     * @return the logging level of this handler
+     */
+    public Level getLevel() {
+        return this.level;
+    }
+
+    /**
+     * Determines whether the supplied log record need to be logged. The logging
+     * levels will be checked as well as the filter.
+     * 
+     * @param record
+     *            the log record to be checked
+     * @return <code>true</code> if the supplied log record need to be logged,
+     *         otherwise <code>false</code>
+     */
+    public boolean isLoggable(LogRecord record) {
+        if (null == record) {
+            reportError(
+                    "Null pointer of LogRecord", new NullPointerException("null"), ErrorManager.GENERIC_FAILURE); //$NON-NLS-1$ //$NON-NLS-2$
+            return false;
+        }
+        if (this.level.intValue() == Level.OFF.intValue()) {
+            return false;
+        } else if (record.getLevel().intValue() >= this.level.intValue()) {
+            return null == this.filter ? true : this.filter.isLoggable(record);
+        }
+        return false;
+    }
+
+    /**
+     * Report an error to the error manager associated with this handler.
+     * 
+     * @param msg
+     *            the error message
+     * @param ex
+     *            the associated exception
+     * @param code
+     *            the error code
+     */
+    protected void reportError(String msg, Exception ex, int code) {
+        this.errorMan.error(msg, ex, code);
+    }
+
+    /**
+     * Sets the character encoding used by this handler. A <code>null</code>
+     * value indicates the using of the default encoding. This internal method
+     * does not check security.
+     * 
+     * @param newEncoding
+     *            the character encoding to set
+     * @throws UnsupportedEncodingException
+     *             If the specified encoding is not supported by the runtime.
+     */
+    void internalSetEncoding(String newEncoding)
+            throws UnsupportedEncodingException {
+        // accepts "null" because it indicates using default encoding
+        if (null == newEncoding) {
+            this.encoding = null;
+        } else {
+            if (Charset.isSupported(newEncoding)) {
+                this.encoding = newEncoding;
+            } else {
+                throw new UnsupportedEncodingException("The encoding \"" //$NON-NLS-1$
+                        + newEncoding + "\" is not supported."); //$NON-NLS-1$
+            }
+
+        }
+    }
+
+    /**
+     * Sets the character encoding used by this handler. A <code>null</code>
+     * value indicates the using of the default encoding.
+     * 
+     * @param encoding
+     *            the character encoding to set
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     * @throws UnsupportedEncodingException
+     *             If the specified encoding is not supported by the runtime.
+     */
+    public void setEncoding(String encoding) throws SecurityException,
+            UnsupportedEncodingException {
+        LogManager.getLogManager().checkAccess();
+        internalSetEncoding(encoding);
+    }
+
+    /**
+     * Sets the error manager for this handler.
+     * 
+     * @param em
+     *            the error manager to set
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     */
+    public void setErrorManager(ErrorManager em) {
+        LogManager.getLogManager().checkAccess();
+        if (null == em) {
+            throw new NullPointerException("null"); //$NON-NLS-1$
+        }
+        this.errorMan = em;
+    }
+
+    /**
+     * Sets the filter to be used by this handler.
+     * 
+     * @param newFilter
+     *            the filter to set
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     */
+    public void setFilter(Filter newFilter) {
+        LogManager.getLogManager().checkAccess();
+        this.filter = newFilter;
+    }
+
+    /**
+     * Sets the formatter to be used by this handler. This internal method does
+     * not check security.
+     * 
+     * @param newFormatter
+     *            the fomatter to set
+     */
+    void internalSetFormatter(Formatter newFormatter) {
+        if (null == newFormatter) {
+            throw new NullPointerException("null"); //$NON-NLS-1$
+        }
+        this.formatter = newFormatter;
+    }
+
+    /**
+     * Sets the formatter to be used by this handler.
+     * 
+     * @param newFormatter
+     *            the fomatter to set
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     */
+    public void setFormatter(Formatter newFormatter) {
+        LogManager.getLogManager().checkAccess();
+        internalSetFormatter(newFormatter);
+    }
+
+    /**
+     * Sets the logging level of this handler.
+     * 
+     * @param newLevel
+     *            the logging level to set
+     * @throws SecurityException
+     *             If a security manager determines that the caller does not
+     *             have the required permission.
+     */
+    public void setLevel(Level newLevel) {
+        if (null == newLevel) {
+            throw new NullPointerException("null"); //$NON-NLS-1$
+        }
+        LogManager.getLogManager().checkAccess();
+        this.level = newLevel;
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Level.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Level.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Level.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/logging/src/main/java/java/util/logging/Level.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,359 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * 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 java.util.logging;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/**
+ * <code>Level</code> 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.
+ * </p>
+ * 
+ */
+public class Level implements Serializable {
+    
+    
+    //for serialization compability
+    private static final long serialVersionUID = -8176160795706313070L;    
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+
+	/*
+     * -------------------------------------------------------------------
+     * Class variables
+     * -------------------------------------------------------------------
+     */
+    private static Map levels = new HashMap();
+	
+    // The following string constants define the name of all predefined levels.
+    private static final String SEVERESTR = "SEVERE"; //$NON-NLS-1$
+
+    private static final String WARNINGSTR = "WARNING"; //$NON-NLS-1$
+
+    private static final String INFOSTR = "INFO"; //$NON-NLS-1$
+
+    private static final String CONFIGSTR = "CONFIG"; //$NON-NLS-1$
+
+    private static final String FINESTR = "FINE"; //$NON-NLS-1$
+
+    private static final String FINERSTR = "FINER"; //$NON-NLS-1$
+
+    private static final String FINESTSTR = "FINEST"; //$NON-NLS-1$
+
+    private static final String OFFSTR = "OFF"; //$NON-NLS-1$
+
+    private static final String ALLSTR = "ALL"; //$NON-NLS-1$
+
+    /**
+     * The SEVERE level indicates a severe failure.
+     */
+    public static final Level SEVERE = new Level(SEVERESTR, 1000);
+
+    /**
+     * The WARNING level indicates a warning.
+     */
+    public static final Level WARNING = new Level(WARNINGSTR, 900);
+
+    /**
+     * The INFO level indicates an informative message.
+     */
+    public static final Level INFO = new Level(INFOSTR, 800);
+
+    /**
+     * The CONFIG level indicates a static configuration message.
+     */
+    public static final Level CONFIG = new Level(CONFIGSTR, 700);
+
+    /**
+     * The FINE level provides tracing messages.
+     */
+    public static final Level FINE = new Level(FINESTR, 500);
+
+    /**
+     * The FINER level provides more detailed tracing messages.
+     */
+    public static final Level FINER = new Level(FINERSTR, 400);
+
+    /**
+     * The FINEST level provides highly detailed tracing messages.
+     */
+    public static final Level FINEST = new Level(FINESTSTR, 300);
+
+    /**
+     * The OFF level provides no logging messages.
+     */
+    public static final Level OFF = new Level(OFFSTR, Integer.MAX_VALUE);
+
+    /**
+     * The ALL level provides all logging messages.
+     */
+    public static final Level ALL = new Level(ALLSTR, Integer.MIN_VALUE);
+
+
+    /*
+     * -------------------------------------------------------------------
+     * Global initialization
+     * -------------------------------------------------------------------
+     */
+
+    static {
+		levels.remove(null);
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Instance variables
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * 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;
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Constructs an instance of <code>Level</code> taking the supplied name
+     * and level value.
+     * 
+     * @param name
+     *            name of the level
+     * @param level
+     *            an integer value indicating the level
+     */
+    protected Level(String name, int level) {
+        this(name, level, null);
+    }
+
+    /**
+     * Constructs an instance of <code>Level</code> taking the supplied name
+     * and level value.
+     * 
+     * @param name
+     *            name of the level
+     * @param level
+     *            an integer value indicating the level
+     * @param resourceBundleName
+     *            the name of the resource bundle to use
+     */
+    protected Level(String name, int level, String resourceBundleName) {
+        this.name = name;
+        this.value = level;
+        this.resourceBundleName = resourceBundleName;
+		//put value into known values list in Constructor
+		if(null==levels.get(name)){
+			levels.put(name,this);
+		}
+		if(null==levels.get(String.valueOf(level))){
+			levels.put(String.valueOf(this.intValue()), this);
+		}
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Gets the name of this <code>Level</code>.
+     * 
+     * @return the name of this <code>Level</code>
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Gets the name of the resource bundle associated with this
+     * <code>Level</code>.
+     * 
+     * @return the name of the resource bundle associated with this
+     *         <code>Level</code>
+     */
+    public String getResourceBundleName() {
+        return this.resourceBundleName;
+    }
+
+    /**
+     * Gets the integer value indicating this <code>Level</code>.
+     * 
+     * @return the integer value indicating this <code>Level</code>
+     */
+    public final int intValue() {
+        return this.value;
+    }
+
+    /**
+     * Parses a level name into a <code>Level</code> object.
+     * 
+     * @param name
+     *            the name of the desired level, which cannot be null
+     * @return a <code>Level</code> object with the specified name
+     * @throws NullPointerException
+     *             If <code>name</code> is null.
+     * @throws IllegalArgumentException
+     *             When <code>name</code> cannot be parsed.
+     */
+    public static final Level parse(String name) {
+        if (null == name)
+            throw new NullPointerException("null"); //$NON-NLS-1$
+        // Check if the name is a predefined one
+        Level result = (Level) levels.get(name);
+        if (null != result) {
+            return result;
+        }
+        // Try to parse the name as an integer
+        try {
+            int v = Integer.parseInt(name);
+            result = new Level(name, v);
+            return result;
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("Cannot parse this name: " //$NON-NLS-1$
+                    + name);
+        }
+    }
+
+    /**
+     * Gets the localized name of this level. The default locale is used. If no
+     * resource bundle is associated with this <code>Level</code>, the
+     * original level name is returned.
+     * 
+     * @return the localized name of this level
+     */
+    public String getLocalizedName() {
+        String result = name;
+        if (null != resourceBundleName && null == rb) {
+            try {
+                rb = ResourceBundle.getBundle(resourceBundleName);
+            } catch (Exception e) {
+                rb = null;
+            }
+        }
+        if (null != rb) {
+            try {
+                result = rb.getString(name);
+            } catch (Exception e) {
+                result = name;
+            }
+        }
+        return result;
+    }
+
+    /*
+     * Maintains the Object uniqueness property across serialization.
+     */
+    private Object readResolve() {
+        String levelName = this.getName();
+        Level result = (Level) levels.get(levelName);
+
+        if (null != result) {
+            boolean sameResourceBundle = (this.resourceBundleName == null ? result
+                    .getResourceBundleName() == null
+                    : this.resourceBundleName.equals(result
+                            .getResourceBundleName()));
+            if (result.intValue() == this.value && sameResourceBundle) {
+                return result;
+            }
+        }
+        return this;
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods overriding parent class Object
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Compares two <code>Level</code> objects for equality. They are
+     * considered to be equal if they have the same value.
+     * 
+     * @param o
+     *            the other object to be compared with
+     * @return <code>true</code> if this object equals to the supplied object,
+     *         otherwise <code>false</code>
+     */
+    public boolean equals(Object o) {
+        if (!(o instanceof Level)) {
+            return false;
+        }
+        return ((Level) o).intValue() == this.value;
+    }
+
+    /**
+     * Returns the hash code of this <code>Level</code> object.
+     * 
+     * @return the hash code of this <code>Level</code> object
+     */
+    public int hashCode() {
+        return this.value;
+    }
+
+    /**
+     * Returns the string representation of this <code>Level</code> object.
+     * Usually this will include its name.
+     * 
+     * @return the string representation of this <code>Level</code> object
+     */
+    public final String toString() {
+        return this.name;
+    }
+
+}
+