diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | fdb2704414a9ed92394ada0d1395e4db86889465 (patch) | |
tree | 9b591a4a50054274a197f02b3ccb51313681879f /logging/src | |
download | libcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2 |
Initial Contribution
Diffstat (limited to 'logging/src')
53 files changed, 16993 insertions, 0 deletions
diff --git a/logging/src/main/java/java/util/logging/ConsoleHandler.java b/logging/src/main/java/java/util/logging/ConsoleHandler.java new file mode 100644 index 0000000..9cea60f --- /dev/null +++ b/logging/src/main/java/java/util/logging/ConsoleHandler.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +/** + * 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 { + + /** + * Constructs a <code>ConsoleHandler</code> object. + */ + public ConsoleHandler() { + super(System.err); + } + + /** + * Closes this handler. The <code>System.err</code> is flushed but not + * closed. + */ + @Override + 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 + */ + @Override + public void publish(LogRecord record) { + super.publish(record); + super.flush(); + + } +} diff --git a/logging/src/main/java/java/util/logging/ErrorManager.java b/logging/src/main/java/java/util/logging/ErrorManager.java new file mode 100644 index 0000000..0b12df1 --- /dev/null +++ b/logging/src/main/java/java/util/logging/ErrorManager.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * <p> + * An error reporting facility for {@link Handler} implementations to record any + * error that may happen during logging. <code>Handlers</code> should report + * errors to an <code>ErrorManager</code>, instead of throwing exceptions, + * which would interfere with the log issuer's execution. + * </p> + */ +public class ErrorManager { + + /** + * 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 writing 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; + + @SuppressWarnings("nls") + private static final String[] FAILURES = new String[] { "GENERIC_FAILURE", + "WRITE_FAILURE", "FLUSH_FAILURE", "CLOSE_FAILURE", "OPEN_FAILURE", + "FORMAT_FAILURE" }; + + /** + * An indicator for determining if the error manager has been called at + * least once before. + */ + private boolean called; + + /** + * Constructs an instance of <code>ErrorManager</code>. + */ + public ErrorManager() { + super(); + } + + /** + * <p> + * Reports an error using the given message, exception and error code. This + * implementation will write out the message to {@link System#err} on the + * first call and all subsequent calls are ignored. A subclass of this class + * should override this method. + * </p> + * + * @param message + * The error message, which may be <code>null</code>. + * @param exception + * The exception associated with the error, which may be + * <code>null</code>. + * @param errorCode + * The error code that identifies the type of error; see the + * constant fields on this class. + */ + public void error(String message, Exception exception, int errorCode) { + synchronized (this) { + if (called) { + return; + } + called = true; + } + System.err.println(this.getClass().getName() + + ": " + FAILURES[errorCode]); //$NON-NLS-1$ + if (message != null) { + // logging.1E=Error message - {0} + System.err.println(Messages.getString("logging.1E", message)); //$NON-NLS-1$ + } + if (exception != null) { + // logging.1F=Exception - {0} + System.err.println(Messages.getString("logging.1F", exception)); //$NON-NLS-1$ + } + } +} diff --git a/logging/src/main/java/java/util/logging/FileHandler.java b/logging/src/main/java/java/util/logging/FileHandler.java new file mode 100644 index 0000000..be21ebc --- /dev/null +++ b/logging/src/main/java/java/util/logging/FileHandler.java @@ -0,0 +1,652 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import 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; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * 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 properties 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 specified 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 repeatedly 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 for avoiding conflicts is only guaranteed to + * work reliably when using a local disk file system. + * </p> + * + */ +public class FileHandler extends StreamHandler { + + private static final String LCK_EXT = ".lck"; //$NON-NLS-1$ + + 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$ + + // maintain all file locks hold by this process + private static final Hashtable<String, FileLock> allLocks = new Hashtable<String, FileLock>(); + + // 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 unique ID + int uniqueID = -1; + + /** + * 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 { + while (true) { + // try to find a unique file which is not locked by other process + uniqueID++; + // FIXME: improve performance here + for (int generation = 0; generation < count; generation++) { + // cache all file names for rotation use + files[generation] = new File(parseFileName(generation)); + } + fileName = files[0].getAbsolutePath(); + synchronized (allLocks) { + /* + * if current process has held lock for this fileName continue + * to find next file + */ + if (null != allLocks.get(fileName)) { + continue; + } + if (files[0].exists() + && (!append || files[0].length() >= limit)) { + for (int i = count - 1; i > 0; i--) { + if (files[i].exists()) { + files[i].delete(); + } + files[i - 1].renameTo(files[i]); + } + } + FileOutputStream fileStream = new FileOutputStream(fileName + + LCK_EXT); + FileChannel channel = fileStream.getChannel(); + /* + * if lock is unsupported and IOException thrown, just let the + * IOException throws out and exit otherwise it will go into an + * undead cycle + */ + lock = channel.tryLock(); + if (null == lock) { + try { + fileStream.close(); + } catch (Exception e) { + // ignore + } + continue; + } + allLocks.put(fileName, lock); + break; + } + } + // BEGIN android-modified + output = new MeasureOutputStream( + new BufferedOutputStream( + new FileOutputStream(fileName, append), 8192), + files[0].length()); + // END android-modified + setOutputStream(output); + } + + 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$ + // logging.19=Pattern cannot be empty + throw new NullPointerException(Messages.getString("logging.19")); //$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]; + } + + 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 { + // BEGIN android-modified + output = new MeasureOutputStream( + new BufferedOutputStream( + new FileOutputStream(files[0]), + 8192)); + // END android-modified + } catch (FileNotFoundException e1) { + // logging.1A=Error happened when open log file. + this.getErrorManager().error(Messages.getString("logging.1A"), //$NON-NLS-1$ + e1, ErrorManager.OPEN_FAILURE); + } + setOutputStream(output); + } + + /** + * Transform the pattern to the valid file name, replacing any patterns, and + * applying generation and uniqueID if present + * + * @param gen + * generation of this file + * @return transformed filename ready for use + */ + private String parseFileName(int gen) { + 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$ + boolean tempPathHasSepEnd = (tempPath == null ? false : tempPath + .endsWith(File.separator)); + + String homePath = System.getProperty("user.home"); //$NON-NLS-1$ + boolean homePathHasSepEnd = (homePath == null ? false : homePath + .endsWith(File.separator)); + + StringBuilder sb = new StringBuilder(); + 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': + /* + * we should probably try to do something cute here like + * lookahead for adjacent '/' + */ + sb.append(value, cur, next - cur - 1).append(tempPath); + if (!tempPathHasSepEnd) { + sb.append(File.separator); + } + break; + case 'h': + sb.append(value, cur, next - cur - 1).append(homePath); + if (!homePathHasSepEnd) { + sb.append(File.separator); + } + break; + case '%': + sb.append(value, cur, next - cur - 1).append('%'); + break; + default: + sb.append(value, cur, next - cur); + } + cur = ++next; + } else { + // fail silently + } + } + + 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. + * @throws NullPointerException + * if the pattern is <code>null</code>. + * @throws IllegalArgumentException + * if the pattern is empty. + */ + public FileHandler(String pattern) throws IOException { + if (pattern.equals("")) { //$NON-NLS-1$ + // logging.19=Pattern cannot be empty + throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ + } + init(pattern, null, Integer.valueOf(DEFAULT_LIMIT), Integer + .valueOf(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. + * @throws NullPointerException + * if the pattern is <code>null</code>. + * @throws IllegalArgumentException + * if the pattern is empty. + */ + public FileHandler(String pattern, boolean append) throws IOException { + if (pattern.equals("")) { //$NON-NLS-1$ + throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ + } + + init(pattern, Boolean.valueOf(append), Integer.valueOf(DEFAULT_LIMIT), + Integer.valueOf(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 output 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 NullPointerException + * if pattern is <code>null</code>. + * @throws IllegalArgumentException + * if count<1, or limit<0 + */ + public FileHandler(String pattern, int limit, int count) throws IOException { + if (pattern.equals("")) { //$NON-NLS-1$ + throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ + } + if (limit < 0 || count < 1) { + // logging.1B=The limit and count property must be larger than 0 and + // 1, respectively + throw new IllegalArgumentException(Messages.getString("logging.1B")); //$NON-NLS-1$ + } + init(pattern, null, Integer.valueOf(limit), Integer.valueOf(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 output 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 NullPointerException + * if pattern is <code>null</code>. + * @throws IllegalArgumentException + * if count<1, or limit<0 + */ + public FileHandler(String pattern, int limit, int count, boolean append) + throws IOException { + if (pattern.equals("")) { //$NON-NLS-1$ + throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ + } + if (limit < 0 || count < 1) { + // logging.1B=The limit and count property must be larger than 0 and + // 1, respectively + throw new IllegalArgumentException(Messages.getString("logging.1B")); //$NON-NLS-1$ + } + init(pattern, Boolean.valueOf(append), Integer.valueOf(limit), Integer + .valueOf(count)); + } + + /** + * 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. + */ + @Override + public void close() { + // release locks + super.close(); + allLocks.remove(fileName); + try { + FileChannel channel = lock.channel(); + lock.release(); + channel.close(); + File file = new File(fileName + LCK_EXT); + file.delete(); + } catch (IOException e) { + // ignore + } + } + + /** + * Publish a <code>LogRecord</code> + * + * @param record + * the log record to be published + */ + @Override + public void publish(LogRecord record) { + super.publish(record); + flush(); + if (limit > 0 && output.getLength() >= limit) { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + 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 + */ + static 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); + } + + @Override + public void write(int oneByte) throws IOException { + wrapped.write(oneByte); + length++; + } + + @Override + public void write(byte[] bytes) throws IOException { + wrapped.write(bytes); + length += bytes.length; + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + wrapped.write(b, off, len); + length += len; + } + + @Override + public void close() throws IOException { + wrapped.close(); + } + + @Override + public void flush() throws IOException { + wrapped.flush(); + } + + public long getLength() { + return length; + } + + public void setLength(long newLength) { + length = newLength; + } + } +} diff --git a/logging/src/main/java/java/util/logging/Filter.java b/logging/src/main/java/java/util/logging/Filter.java new file mode 100644 index 0000000..d96f3ce --- /dev/null +++ b/logging/src/main/java/java/util/logging/Filter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +/** + * <p>A Filter provides a mechanism for exercising fine-grained control over + * what records get logged.</p> + */ +public interface Filter { + + /** + * <p>Checks the {@link LogRecord} to determine if it should be logged.</p> + * + * @param record The {@link LogRecord} to be checked. + * @return <code>true</code> if the supplied log record needs to be + * logged, otherwise <code>false</code> + */ + boolean isLoggable(LogRecord record); +} diff --git a/logging/src/main/java/java/util/logging/Formatter.java b/logging/src/main/java/java/util/logging/Formatter.java new file mode 100644 index 0000000..7321aa2 --- /dev/null +++ b/logging/src/main/java/java/util/logging/Formatter.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import 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 + */ + @SuppressWarnings("unused") + 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 + */ + @SuppressWarnings("unused") + public String getTail(Handler h) { + return ""; //$NON-NLS-1$ + } + +} + diff --git a/logging/src/main/java/java/util/logging/Handler.java b/logging/src/main/java/java/util/logging/Handler.java new file mode 100644 index 0000000..9bad459 --- /dev/null +++ b/logging/src/main/java/java/util/logging/Handler.java @@ -0,0 +1,420 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import java.nio.charset.Charset; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.io.UnsupportedEncodingException; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * 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 = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() { + public Class<?> 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) { + // logging.12=Invalid property value for + String msg = new StringBuilder().append(Messages.getString("logging.12")) //$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 + */ + @SuppressWarnings("unused") + 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 formatter used by this handler to format the logging messages. + * + * @return the formatter 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) { + throw new NullPointerException(); + } + if (this.level.intValue() == Level.OFF.intValue()) { + return false; + } else if (record.getLevel().intValue() >= this.level.intValue()) { + return null == this.filter || 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 { + // logging.13=The encoding "{0}" is not supported. + throw new UnsupportedEncodingException(Messages.getString( + "logging.13", //$NON-NLS-1$ + newEncoding)); + } + + } + } + + /** + * 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(); + } + 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 formatter to set + */ + void internalSetFormatter(Formatter newFormatter) { + if (null == newFormatter) { + throw new NullPointerException(); + } + this.formatter = newFormatter; + } + + /** + * Sets the formatter to be used by this handler. + * + * @param newFormatter + * the formatter 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(); + } + LogManager.getLogManager().checkAccess(); + this.level = newLevel; + } +} + diff --git a/logging/src/main/java/java/util/logging/Level.java b/logging/src/main/java/java/util/logging/Level.java new file mode 100644 index 0000000..bb39d51 --- /dev/null +++ b/logging/src/main/java/java/util/logging/Level.java @@ -0,0 +1,360 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.harmony.logging.internal.nls.Messages; +import org.apache.harmony.kernel.vm.VM; + +/** + * <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 { + + private static final long serialVersionUID = -8176160795706313070L; + + private static final List<Level> levels = new ArrayList<Level>(9); + + /** + * The OFF level provides no logging messages. + */ + public static final Level OFF = new Level("OFF", Integer.MAX_VALUE); //$NON-NLS-1$ + + /** + * The SEVERE level indicates a severe failure. + */ + public static final Level SEVERE = new Level("SEVERE", 1000); //$NON-NLS-1$ + + /** + * The WARNING level indicates a warning. + */ + public static final Level WARNING = new Level("WARNING", 900); //$NON-NLS-1$ + + /** + * The INFO level indicates an informative message. + */ + public static final Level INFO = new Level("INFO", 800); //$NON-NLS-1$ + + /** + * The CONFIG level indicates a static configuration message. + */ + public static final Level CONFIG = new Level("CONFIG", 700); //$NON-NLS-1$ + + /** + * The FINE level provides tracing messages. + */ + public static final Level FINE = new Level("FINE", 500); //$NON-NLS-1$ + + /** + * The FINER level provides more detailed tracing messages. + */ + public static final Level FINER = new Level("FINER", 400); //$NON-NLS-1$ + + /** + * The FINEST level provides highly detailed tracing messages. + */ + public static final Level FINEST = new Level("FINEST", 300); //$NON-NLS-1$ + + /** + * The ALL level provides all logging messages. + */ + public static final Level ALL = new Level("ALL", Integer.MIN_VALUE); //$NON-NLS-1$ + + /** + * 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 <code>null</code>. + * @throws IllegalArgumentException + * if <code>name</code> is not valid. + */ + public static final Level parse(String name) { + if (name == null) { + // logging.1C=The 'name' parameter is null. + throw new NullPointerException(Messages.getString("logging.1C")); //$NON-NLS-1$ + } + + boolean isNameAnInt; + int nameAsInt; + try { + nameAsInt = Integer.parseInt(name); + isNameAnInt = true; + } catch (NumberFormatException e) { + nameAsInt = 0; + isNameAnInt = false; + } + + synchronized (levels) { + for (Level level : levels) { + if (name.equals(level.getName())) { + return level; + } + } + + if (isNameAnInt) { + /* + * Loop through levels a second time, so that the + * returned instance will be passed on the order of construction. + */ + for (Level level : levels) { + if (nameAsInt == level.intValue()) { + return level; + } + } + } + } + + if (!isNameAnInt) { + // logging.1D=Cannot parse this name: {0} + throw new IllegalArgumentException(Messages.getString("logging.1D", name)); //$NON-NLS-1$ + } + + return new Level(name, nameAsInt); + } + + /** + * The name of this Level. + * + * @serial + */ + private final String name; + + /** + * The integer value indicating the level. + * + * @serial + */ + private final int value; + + /** + * The name of the resource bundle used to localize the level name. + * + * @serial + */ + private final String resourceBundleName; + + /** + * The resource bundle associated with this level, used to localize the + * level name. + */ + private transient ResourceBundle rb; + + /** + * Constructs an instance of <code>Level</code> taking the supplied name + * and level value. + * + * @param name name of the level + * @param level an integer value indicating the level + * @throws NullPointerException if <code>name</code> is <code>null</code>. + */ + 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 + * @throws NullPointerException if <code>name</code> is <code>null</code>. + */ + protected Level(String name, int level, String resourceBundleName) { + if (name == null) { + // logging.1C=The 'name' parameter is null. + throw new NullPointerException(Messages.getString("logging.1C")); //$NON-NLS-1$ + } + this.name = name; + this.value = level; + this.resourceBundleName = resourceBundleName; + if (resourceBundleName != null) { + try { + rb = ResourceBundle.getBundle(resourceBundleName, + // TODO Implement kernel.vm.VM.callerClassLoader, or find + // another way to get the caller class loader + // Locale.getDefault(), VM.callerClassLoader()); + Locale.getDefault(), ClassLoader.getSystemClassLoader()); + } catch (MissingResourceException e) { + rb = null; + } + } + synchronized (levels) { + levels.add(this); + } + } + + /** + * 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; + } + + /** + * <p> + * Serialization helper method to maintain singletons and add any new + * levels. + * </p> + * + * @return The resolved instance. + */ + private Object readResolve() { + synchronized (levels) { + for (Level level : levels) { + if (value != level.value) { + continue; + } + if (!name.equals(name)) { + continue; + } + if (resourceBundleName == level.resourceBundleName) { + return level; + } else if (resourceBundleName != null + && resourceBundleName.equals(level.resourceBundleName)) { + return level; + } + } + // This is a new value, so add it. + levels.add(this); + return this; + } + } + + /** + * <p>Serialization helper to setup transient resource bundle instance.</p> + * @param in The input stream to read the instance data from. + * @throws IOException if an IO error occurs. + * @throws ClassNotFoundException if a class is not found. + */ + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + if (resourceBundleName != null) { + try { + rb = ResourceBundle.getBundle(resourceBundleName); + } catch (MissingResourceException e) { + rb = null; + } + } + } + + /** + * Gets the localized name of this level. The default locale is used. If no + * resource bundle is associated with this <code>Level</code>, the + * original level name is returned. + * + * @return the localized name of this level + */ + public String getLocalizedName() { + if (rb == null) { + return name; + } + + try { + return rb.getString(name); + } catch (MissingResourceException e) { + return name; + } + } + + /** + * Compares two <code>Level</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> + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof Level)) { + return false; + } + + return ((Level) o).intValue() == this.value; + } + + /** + * Returns the hash code of this <code>Level</code> object. + * + * @return the hash code of this <code>Level</code> object + */ + @Override + 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 + */ + @Override + public final String toString() { + return this.name; + } + +} diff --git a/logging/src/main/java/java/util/logging/LogManager.java b/logging/src/main/java/java/util/logging/LogManager.java new file mode 100644 index 0000000..462b658 --- /dev/null +++ b/logging/src/main/java/java/util/logging/LogManager.java @@ -0,0 +1,634 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +// BEGIN android-removed +// import java.beans.PropertyChangeListener; +// import java.beans.PropertyChangeSupport; +// END android-removed +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +// BEGIN android-removed +// import java.lang.management.ManagementFactory; +// import java.lang.reflect.Method; +// import javax.management.MBeanServer; +// import javax.management.ObjectName; +// import javax.management.ObjectInstance; +// import javax.management.MalformedObjectNameException; +// END android-removed + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * <code>LogManager</code> is used to maintain configuration properties of the + * logging framework, and to manage a hierarchical namespace of all named + * <code>Logger</code> objects. + * <p> + * There is only one global <code>LogManager</code> instance in the + * application, which can be get by calling static method + * <code>LogManager.getLogManager()</code>. This instance is created and + * initialized during class initialization and cannot be changed. + * </p> + * <p> + * The <code>LogManager</code> class can be specified by + * java.util.logging.manager system property, if the property is unavailable or + * invalid, the default class <code>java.util.logging.LogManager</code> will + * be used. + * </p> + * <p> + * When initialization, <code>LogManager</code> read its configuration from a + * properties file, which by default is the "lib/logging.properties" in the JRE + * directory. + * </p> + * <p> + * However, two optional system properties can be used to customize the initial + * configuration process of <code>LogManager</code>. + * <ul> + * <li>"java.util.logging.config.class"</li> + * <li>"java.util.logging.config.file"</li> + * </ul> + * </p> + * <p> + * These two properties can be set in three ways, by the Preferences API, by the + * "java" command line property definitions, or by system property definitions + * passed to JNI_CreateJavaVM. + * </p> + * <p> + * The "java.util.logging.config.class" should specifies a class name. If it is + * set, this given class will be loaded and instantiated during + * <code>LogManager</code> initialization, so that this object's default + * constructor can read the initial configuration and define properties for + * <code>LogManager</code>. + * </p> + * <p> + * If "java.util.logging.config.class" property is not set, or it is invalid, or + * some exception is thrown during the instantiation, then the + * "java.util.logging.config.file" system property can be used to specify a + * properties file. The <code>LogManager</code> will read initial + * configuration from this file. + * </p> + * <p> + * If neither of these properties is defined, or some exception is thrown + * during these two properties using, the <code>LogManager</code> will read + * its initial configuration from default properties file, as described above. + * </p> + * <p> + * The global logging properties may include: + * <ul> + * <li>"handlers". This property's values should be a list of class names for + * handler classes separated by whitespace, these classes must be subclasses of + * <code>Handler</code> and each must have a default constructor, these + * classes will be loaded, instantiated and registered as handlers on the root + * <code>Logger</code> (the <code>Logger</code> named ""). These + * <code>Handler</code>s maybe initialized lazily.</li> + * <li>"config". The property defines a list of class names separated by + * whitespace. Each class must have a default constructor, in which it can + * update the logging configuration, such as levels, handlers, or filters for + * some logger, etc. These classes will be loaded and instantiated during + * <code>LogManager</code> configuration</li> + * </ul> + * </p> + * <p> + * This class, together with any handler and configuration classes associated + * with it, <b>must</b> be loaded from the system classpath when + * <code>LogManager</code> configuration occurs. + * </p> + * <p> + * Besides global properties, the properties for loggers and Handlers can be + * specified in the property files. The names of these properties will start + * with the complete dot separated names for the handlers or loggers. + * </p> + * <p> + * In the <code>LogManager</code>'s hierarchical namespace, + * <code>Loggers</code> are organized based on their dot separated names. For + * example, "x.y.z" is child of "x.y". + * </p> + * <p> + * Levels for <code>Loggers</code> can be defined by properties whose name end + * with ".level". Thus "alogger.level" defines a level for the logger named as + * "alogger" and for all its children in the naming hierarchy. Log levels + * properties are read and applied in the same order as they are specified in + * the property file. The root logger's level can be defined by the property + * named as ".level". + * </p> + * <p> + * All methods on this type can be taken as being thread safe. + * </p> + * + */ +public class LogManager { + /* + * ------------------------------------------------------------------- + * Class variables + * ------------------------------------------------------------------- + */ + + // The line separator of the underlying OS + // Use privileged code to read the line.separator system property + private static final String lineSeparator = + getPrivilegedSystemProperty("line.separator"); //$NON-NLS-1$ + + // The shared logging permission + private static final LoggingPermission perm = new LoggingPermission( + "control", null); //$NON-NLS-1$ + + // the singleton instance + static LogManager manager; + + /** + * <p>The String value of the {@link LoggingMXBean}'s ObjectName.</p> + */ + public static final String LOGGING_MXBEAN_NAME = + "java.util.logging:type=Logging"; //$NON-NLS-1$ + +// BENGIN android-removed +// /** +// * Get the <code>LoggingMXBean</code> instance +// * +// * @return the <code>LoggingMXBean</code> instance +// */ +// public static LoggingMXBean getLoggingMXBean() { +// try { +// ObjectName loggingMXBeanName = new ObjectName(LOGGING_MXBEAN_NAME); +// MBeanServer platformBeanServer = +// ManagementFactory.getPlatformMBeanServer(); +// Set loggingMXBeanSet = platformBeanServer.queryMBeans( +// loggingMXBeanName, null); +// +// if (loggingMXBeanSet.size() != 1) { +// // logging.21=There Can Be Only One logging MX bean. +// throw new AssertionError(Messages.getString("logging.21")); +// } +// +// Iterator i = loggingMXBeanSet.iterator(); +// ObjectInstance loggingMXBeanOI = (ObjectInstance) i.next(); +// String lmxbcn = loggingMXBeanOI.getClassName(); +// Class lmxbc = Class.forName(lmxbcn); +// Method giMethod = lmxbc.getDeclaredMethod("getInstance"); +// giMethod.setAccessible(true); +// LoggingMXBean lmxb = (LoggingMXBean) +// giMethod.invoke(null, new Object[] {}); +// +// return lmxb; +// } catch (Exception e) { +// //TODO +// //e.printStackTrace(); +// } +// // logging.22=Exception occurred while getting the logging MX bean. +// throw new AssertionError(Messages.getString("logging.22")); //$NON-NLS-1$ +// } +// END android-removed + + /* + * ------------------------------------------------------------------- + * Instance variables + * ------------------------------------------------------------------- + */ + //FIXME: use weak reference to avoid heap memory leak + private Hashtable<String, Logger> loggers; + + // the configuration properties + private Properties props; + + // the property change listener +// BEGIN android-removed +// private PropertyChangeSupport listeners; +// END android-removed + + /* + * ------------------------------------------------------------------- + * Global initialization + * ------------------------------------------------------------------- + */ + + static { + // init LogManager singleton instance + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + String className = System.getProperty( + "java.util.logging.manager"); //$NON-NLS-1$ + + if (null != className) { + manager = (LogManager) getInstanceByClass(className); + } + if (null == manager) { + manager = new LogManager(); + } + + // read configuration + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + + // if global logger has been initialized, set root as its parent + Logger root = new Logger("", null); //$NON-NLS-1$ + root.setLevel(Level.INFO); + Logger.global.setParent(root); + + manager.addLogger(root); + manager.addLogger(Logger.global); + return null; + } + }); + } + + /** + * Default constructor. This is not public because there should be only one + * <code>LogManager</code> instance, which can be get by + * <code>LogManager.getLogManager(</code>. This is protected so that + * application can subclass the object. + */ + protected LogManager() { + loggers = new Hashtable<String, Logger>(); + props = new Properties(); +// BEGIN android-removed +// listeners = new PropertyChangeSupport(this); +// END android-removed + // add shutdown hook to ensure that the associated resource will be + // freed when JVM exits + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + reset(); + } + }); + return null; + } + }); + } + + /* + * ------------------------------------------------------------------- + * Methods + * ------------------------------------------------------------------- + */ + /* + * Package private utilities Returns the line separator of the underlying + * OS. + */ + static String getSystemLineSeparator() { + return lineSeparator; + } + + /** + * Check that the caller has <code>LoggingPermission("control")</code> so + * that it is trusted to modify the configuration for logging framework. If + * the check passes, just return, otherwise <code>SecurityException</code> + * will be thrown. + * + * @throws SecurityException + * if there is a security manager in operation and the invoker + * of this method does not have the required security permission + * <code>LoggingPermission("control")</code> + */ + public void checkAccess() { + if (null != System.getSecurityManager()) { + System.getSecurityManager().checkPermission(perm); + } + } + + /** + * Add a given logger into the hierarchical namespace. The + * <code>Logger.addLogger()</code> factory methods call this method to add + * newly created Logger. This returns false if a logger with the given name + * has existed in the namespace + * <p> + * Note that the <code>LogManager</code> may only retain weak references + * to registered loggers. In order to prevent <code>Logger</code> objects + * from being unexpectedly garbage collected it is necessary for + * <i>applications</i> to maintain references to them. + * </p> + * + * @param logger + * the logger to be added + * @return true if the given logger is added into the namespace + * successfully, false if the logger of given name has existed in + * the namespace + */ + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (null != loggers.get(name)) { + return false; + } + addToFamilyTree(logger, name); + loggers.put(name, logger); + logger.setManager(this); + return true; + } + + + private void addToFamilyTree(Logger logger, String name) { + Logger parent = null; + // find parent + int lastSeparator; + String parentName = name; + while ((lastSeparator = parentName.lastIndexOf('.')) != -1) { + parentName = parentName.substring(0, lastSeparator); + parent = loggers.get(parentName); + if (parent != null) { + logger.internalSetParent(parent); + break; + } else if (getProperty(parentName+".level") != null || //$NON-NLS-1$ + getProperty(parentName+".handlers") != null) { //$NON-NLS-1$ + parent = Logger.getLogger(parentName); + logger.internalSetParent(parent); + break; + } + } + if (parent == null && null != (parent = loggers.get(""))) { //$NON-NLS-1$ + logger.internalSetParent(parent); + } + + // find children + //TODO: performance can be improved here? + Collection<Logger> allLoggers = loggers.values(); + for (Logger child : allLoggers) { + Logger oldParent = child.getParent(); + if (parent == oldParent + && (name.length() == 0 || child.getName().startsWith( + name + '.'))) { + child.setParent(logger); + if (null != oldParent) { + //-- remove from old parent as the parent has been changed + oldParent.removeChild(child); + } + } + } + } + + /** + * Get the logger with the given name + * + * @param name + * name of logger + * @return logger with given name, or null if nothing is found + */ + public synchronized Logger getLogger(String name) { + return loggers.get(name); + } + + /** + * Get a <code>Enumeration</code> of all registered logger names + * + * @return enumeration of registered logger names + */ + public synchronized Enumeration<String> getLoggerNames() { + return loggers.keys(); + } + + /** + * Get the global <code>LogManager</code> instance + * + * @return the global <code>LogManager</code> instance + */ + public static LogManager getLogManager() { + return manager; + } + + /** + * Get the value of property with given name + * + * @param name + * the name of property + * @return the value of property + */ + public String getProperty(String name) { + return props.getProperty(name); + } + + /** + * Re-initialize the properties and configuration. The initialization process + * is same as the <code>LogManager</code> instantiation. + * <p> + * A <code>PropertyChangeEvent</code> must be fired. + * </p> + * + * @throws IOException + * if any IO related problems happened + * @throws SecurityException + * if security manager exists and it determines that caller does + * not have the required permissions to perform this action + */ + public void readConfiguration() throws IOException { + checkAccess(); + // check config class + String configClassName = System.getProperty( + "java.util.logging.config.class"); //$NON-NLS-1$ + if (null == configClassName || null == getInstanceByClass(configClassName)) { + // if config class failed, check config file + String configFile = System.getProperty( + "java.util.logging.config.file"); //$NON-NLS-1$ + + if (null == configFile) { + // if cannot find configFile, use default logging.properties + configFile = new StringBuilder().append( + System.getProperty("java.home")).append(File.separator) //$NON-NLS-1$ + .append("lib").append(File.separator).append( //$NON-NLS-1$ + "logging.properties").toString(); //$NON-NLS-1$ + } + + InputStream input = null; + try { + // BEGIN android-removed + // input = new BufferedInputStream(new FileInputStream(configFile)); + // END android-removed + + // BEGIN android-added + try { + input = new BufferedInputStream(new FileInputStream(configFile), 8192); + } catch (Exception ex) { + // consult fixed resource as a last resort + input = new BufferedInputStream(getClass().getResourceAsStream("logging.properties"), 8192); + } + // END android-added + readConfigurationImpl(input); + } finally { + if (input != null) { + try { + input.close(); + } catch (Exception e) {// ignore + } + } + } + } + } + + // use privilege code to get system property + static String getPrivilegedSystemProperty(final String key) { + return AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return System.getProperty(key); + } + }); + } + + // use SystemClassLoader to load class from system classpath + static Object getInstanceByClass(final String className) { + try { + Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass( + className); + return clazz.newInstance(); + } catch (Exception e) { + try { + Class<?> clazz = Thread.currentThread() + .getContextClassLoader().loadClass(className); + return clazz.newInstance(); + } catch (Exception innerE) { + //logging.20=Loading class "{0}" failed + System.err.println(Messages.getString( + "logging.20", className)); //$NON-NLS-1$ + System.err.println(innerE); + return null; + } + } + + } + + // actual initialization process from a given input stream + private synchronized void readConfigurationImpl(InputStream ins) + throws IOException { + reset(); + props.load(ins); + + // parse property "config" and apply setting + String configs = props.getProperty("config"); //$NON-NLS-1$ + if (null != configs) { + StringTokenizer st = new StringTokenizer(configs, " "); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String configerName = st.nextToken(); + getInstanceByClass(configerName); + } + } + + // set levels for logger + Collection<Logger> allLoggers = loggers.values(); + for(Logger logger : allLoggers){ + String property = props.getProperty( + logger.getName()+".level"); //$NON-NLS-1$ + if(null != property){ + logger.setLevel(Level.parse(property)); + } + } +// BEGIN android-removed +// listeners.firePropertyChange(null, null, null); +// END android-removed + } + + + /** + * Re-initialize the properties and configuration from the given + * <code>InputStream</code> + * <p> + * A <code>PropertyChangeEvent</code> must be fired. + * </p> + * + * @param ins + * the input stream. + * @throws IOException + * if any IO related problems happened + * @throws SecurityException + * if security manager exists and it determines that caller does + * not have the required permissions to perform this action + */ + public void readConfiguration(InputStream ins) throws IOException { + checkAccess(); + readConfigurationImpl(ins); + } + + /** + * Reset configuration. + * <p> + * All handlers are closed and removed from any named loggers. All loggers' + * level is set to null, except the root logger's level is set to + * <code>Level.INFO</code>. + * </p> + * + * @throws SecurityException + * if security manager exists and it determines that caller does + * not have the required permissions to perform this action + */ + public void reset() { + checkAccess(); + props = new Properties(); + Enumeration<String> names = getLoggerNames(); + while(names.hasMoreElements()){ + String name = names.nextElement(); + Logger logger = getLogger(name); + if(logger != null){ + logger.reset(); + } + } + Logger root = loggers.get(""); //$NON-NLS-1$ + if (null != root) { + root.setLevel(Level.INFO); + } + } + + /** + * Add a <code>PropertyChangeListener</code>, which will be invoked when + * the properties are reread. + * + * @param l + * the <code>PropertyChangeListener</code> to be added + * @throws SecurityException + * if security manager exists and it determines that caller does + * not have the required permissions to perform this action + */ +// BEGIN android-removed +// public void addPropertyChangeListener(IPropertyChangeListener l) { +// if(l == null){ +// throw new NullPointerException(); +// } +// checkAccess(); +// listeners.addPropertyChangeListener(l); +// } +// END android-removed + + /** + * Remove a <code>PropertyChangeListener</code>, do nothing if the given + * listener is not found. + * + * @param l + * the <code>PropertyChangeListener</code> to be removed + * @throws SecurityException + * if security manager exists and it determines that caller does + * not have the required permissions to perform this action + */ +// BEGIN android-removed +// public void removePropertyChangeListener(IPropertyChangeListener l) { +// checkAccess(); +// listeners.removePropertyChangeListener(l); +// } +// END android-removed +} diff --git a/logging/src/main/java/java/util/logging/LogRecord.java b/logging/src/main/java/java/util/logging/LogRecord.java new file mode 100644 index 0000000..e133797 --- /dev/null +++ b/logging/src/main/java/java/util/logging/LogRecord.java @@ -0,0 +1,499 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * A <code>LogRecord</code> object represents a logging request. It is passed + * between the logging framework and individual logging handlers. Client + * applications should not modify a <code>LogRecord</code> object that has + * been passed into the logging framework. + * <p> + * The <code>LogRecord</code> class will infer the source method name and + * source class name the first time they are accessed if the client application + * didn't specify them explicitly. This automatic inference is based on the + * analysis of the call stack and is not guaranteed to be precise. Client + * applications should force the initialization of these two fields by calling + * <code>getSourceClassName</code> or <code>getSourceMethodName</code> if + * they expect to use them after passing the <code>LogRecord</code> object to + * another thread or transmitting it over RMI. + * </p> + * + */ +public class LogRecord implements Serializable { + + private static final long serialVersionUID = 5372048053134512534L; + + // The major byte used in serialization. + private static final int MAJOR = 1; + + // The minor byte used in serialization. + private static final int MINOR = 4; + + // Store the current value for the sequence number. + private static long currentSequenceNumber = 0; + + // Store the id for each thread. + private static ThreadLocal<Integer> currentThreadId = new ThreadLocal<Integer>(); + + // The base id as the starting point for thread ID allocation. + private static int initThreadId = 0; + + /** + * The logging level. + * + * @serial + */ + private Level level; + + /** + * The sequence number. + * + * @serial + */ + private long sequenceNumber; + + /** + * The name of the class that issued the logging call. + * + * @serial + */ + private String sourceClassName; + + /** + * The name of the method that issued the logging call. + * + * @serial + */ + private String sourceMethodName; + + /** + * The original message text. + * + * @serial + */ + private String message; + + /** + * The ID of the thread that issued the logging call. + * + * @serial + */ + private int threadID; + + /** + * The time that the event occurred, in milliseconds since 1970. + * + * @serial + */ + private long millis; + + /** + * The associated <code>Throwable</code> object if any. + * + * @serial + */ + private Throwable thrown; + + /** + * The name of the source logger. + * + * @serial + */ + private String loggerName; + + /** + * The name of the resource bundle used to localize the log message. + * + * @serial + */ + private String resourceBundleName; + + // The associated resource bundle if any. + private transient ResourceBundle resourceBundle; + + // The parameters. + private transient Object[] parameters; + + // If the source method and source class has been initialized + private transient boolean sourceInited; + + /** + * Constructs a <code>LogRecord</code> object using the supplied the + * logging level and message. The millis property is set to the current + * time. The sequence property is set to a new unique value, allocated in + * increasing order within a VM. The thread ID is set to a unique value for + * the current thread. All other properties are set to <code>null</code>. + * + * @param level + * the logging level which may not be null + * @param msg + * the raw message + */ + public LogRecord(Level level, String msg) { + if (null == level) { + // logging.4=The 'level' parameter is null. + throw new NullPointerException(Messages.getString("logging.4")); //$NON-NLS-1$ + } + this.level = level; + this.message = msg; + this.millis = System.currentTimeMillis(); + + synchronized (LogRecord.class) { + this.sequenceNumber = currentSequenceNumber++; + Integer id = currentThreadId.get(); + if (null == id) { + this.threadID = initThreadId; + currentThreadId.set(Integer.valueOf(initThreadId++)); + } else { + this.threadID = id.intValue(); + } + } + + this.sourceClassName = null; + this.sourceMethodName = null; + this.loggerName = null; + this.parameters = null; + this.resourceBundle = null; + this.resourceBundleName = null; + this.thrown = null; + } + + /** + * Gets the logging level. + * + * @return the logging level + */ + public Level getLevel() { + return level; + } + + /** + * Sets the logging level. + * + * @param level + * the level to set + */ + public void setLevel(Level level) { + if (null == level) { + // logging.4=The 'level' parameter is null. + throw new NullPointerException(Messages.getString("logging.4")); //$NON-NLS-1$ + } + this.level = level; + } + + /** + * Gets the name of the logger. + * + * @return the logger name + */ + public String getLoggerName() { + return loggerName; + } + + /** + * Sets the name of the logger. + * + * @param loggerName + * the logger name to set + */ + public void setLoggerName(String loggerName) { + this.loggerName = loggerName; + } + + /** + * Gets the raw message. + * + * @return the raw message + */ + public String getMessage() { + return message; + } + + /** + * Sets the raw message. + * + * @param message + * the raw message to set + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * Gets the time that the event occurred, in milliseconds since 1970. + * + * @return the time that the event occurred, in milliseconds since 1970 + */ + public long getMillis() { + return millis; + } + + /** + * Sets the time that the event occurred, in milliseconds since 1970. + * + * @param millis + * the time that the event occurred, in milliseconds since 1970 + */ + public void setMillis(long millis) { + this.millis = millis; + } + + /** + * Gets the parameters. + * + * @return the array of parameters + */ + public Object[] getParameters() { + return parameters; + } + + /** + * Sets the parameters. + * + * @param parameters + * the array of parameters to set + */ + public void setParameters(Object[] parameters) { + this.parameters = parameters; + } + + /** + * Gets the resource bundle used to localize the raw message during + * formatting. + * + * @return the associated resource bundle + */ + public ResourceBundle getResourceBundle() { + return resourceBundle; + } + + /** + * Sets the resource bundle used to localize the raw message during + * formatting. + * + * @param resourceBundle + * the resource bundle to set + */ + public void setResourceBundle(ResourceBundle resourceBundle) { + this.resourceBundle = resourceBundle; + } + + /** + * Gets the name of the resource bundle. + * + * @return the name of the resource bundle + */ + public String getResourceBundleName() { + return resourceBundleName; + } + + /** + * Sets the name of the resource bundle. + * + * @param resourceBundleName + * the name of the resource bundle to set + */ + public void setResourceBundleName(String resourceBundleName) { + this.resourceBundleName = resourceBundleName; + } + + /** + * Gets the sequence number. + * + * @return the sequence number + */ + public long getSequenceNumber() { + return sequenceNumber; + } + + /** + * Sets the sequence number. It is usually unnecessary to call this method + * to change the sequence number because the number is allocated when this + * instance is constructed. + * + * @param sequenceNumber + * the sequence number to set + */ + public void setSequenceNumber(long sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } + + /** + * Gets the name of the class that issued the logging call. + * + * @return the name of the class that issued the logging call + */ + public String getSourceClassName() { + initSource(); + return sourceClassName; + } + + /* + * Init the sourceClass and sourceMethod fields. + */ + private void initSource() { + if (!sourceInited) { + StackTraceElement[] elements = (new Throwable()).getStackTrace(); + int i = 0; + String current = null; + FINDLOG: for (; i < elements.length; i++) { + current = elements[i].getClassName(); + if (current.equals(Logger.class.getName())) { + break FINDLOG; + } + } + while(++i<elements.length && elements[i].getClassName().equals(current)) { + // do nothing + } + if (i < elements.length) { + this.sourceClassName = elements[i].getClassName(); + this.sourceMethodName = elements[i].getMethodName(); + } + sourceInited = true; + } + } + + /** + * Sets the name of the class that issued the logging call. + * + * @param sourceClassName + * the name of the class that issued the logging call + */ + public void setSourceClassName(String sourceClassName) { + sourceInited = true; + this.sourceClassName = sourceClassName; + } + + /** + * Gets the name of the method that issued the logging call. + * + * @return the name of the method that issued the logging call + */ + public String getSourceMethodName() { + initSource(); + return sourceMethodName; + } + + /** + * Sets the name of the method that issued the logging call. + * + * @param sourceMethodName + * the name of the method that issued the logging call + */ + public void setSourceMethodName(String sourceMethodName) { + sourceInited = true; + this.sourceMethodName = sourceMethodName; + } + + /** + * Gets the ID of the thread originating the message. + * + * @return the ID of the thread originating the message + */ + public int getThreadID() { + return threadID; + } + + /** + * Sets the ID of the thread originating the message. + * + * @param threadID + * the ID of the thread originating the message + */ + public void setThreadID(int threadID) { + this.threadID = threadID; + } + + /** + * Gets the <code>Throwable</code> object associated with this log record. + * + * @return the <code>Throwable</code> object associated with this log + * record + */ + public Throwable getThrown() { + return thrown; + } + + /** + * Sets the <code>Throwable</code> object associated with this log record. + * + * @param thrown + * the <code>Throwable</code> object associated with this log + * record + */ + public void setThrown(Throwable thrown) { + this.thrown = thrown; + } + + /* + * Customized serialization. + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeByte(MAJOR); + out.writeByte(MINOR); + if (null == parameters) { + out.writeInt(-1); + } else { + out.writeInt(parameters.length); + for (Object element : parameters) { + out.writeObject(null == element ? null : element.toString()); + } + } + } + + /* + * Customized deserialization. + */ + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + byte major = in.readByte(); + byte minor = in.readByte(); + //only check MAJOR version + if (major != MAJOR) { + // logging.5=Different version - {0}.{1} + throw new IOException(Messages.getString("logging.5", major, minor)); //$NON-NLS-1$ + } + + int length = in.readInt(); + if (length >= 0) { + parameters = new Object[length]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = in.readObject(); + } + } + if (null != resourceBundleName) { + try { + resourceBundle = Logger.loadResourceBundle(resourceBundleName); + } catch (MissingResourceException e) { + // Cannot find the specified resource bundle + resourceBundle = null; + } + } + } +} diff --git a/logging/src/main/java/java/util/logging/Logger.java b/logging/src/main/java/java/util/logging/Logger.java new file mode 100644 index 0000000..fbe32ed --- /dev/null +++ b/logging/src/main/java/java/util/logging/Logger.java @@ -0,0 +1,1425 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.StringTokenizer; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * Loggers are used to log records to certain outputs, including file, console, + * etc. They use various handlers to actually do the output-dependent + * operations. + * <p> + * Client applications can get named loggers by calling the methods + * <code>getLogger</code>. They can also get anonymous loggers by calling the + * methods <code>getAnonymousLogger</code>. Named loggers are organized in a + * namespace hierarchy managed by a log manager. The naming convention is + * usually the same as java package's naming convention, i.e., using + * dot-separated strings. Anonymous loggers do not belong to any namespace. + * </p> + * <p> + * Loggers "inherit" log level setting from their parent if its own level is set + * to <code>null</code>. This is also true for the resource bundle. The + * logger's resource bundle is used to localize the log messages if no resource + * bundle name is given when a log method is called. If + * <code>getUseParentHandlers</code> is <code>true</code>, loggers also + * inherit their parent's handlers. Here "inherit" only means the "behaviors" + * are inherited. The internal fields value will not change, for example, + * <code>getLevel()</code> still returns <code>null</code>. + * </p> + * <p> + * When loading a given resource bundle, the logger first tries to use the + * context classloader. If that fails, it tries the system classloader. And if + * that still fails, it searches up the class stack and uses each class's + * classloader to try to locate the resource bundle. + * </p> + * <p> + * Some log methods accept log requests that do not specify the source class and + * source method. In these cases, the logging framework will automatically infer + * the calling class and method, but not guaranteed to be accurate. + * </p> + * <p> + * Once a <code>LogRecord</code> object has been passed into the logging + * framework, it is owned by the logging framework and the client applications + * should not use it any longer. + * </p> + * <p> + * All methods of this class are thread-safe. + * </p> + * + * @see LogManager + */ +public class Logger { + + /** + * The global logger is provided as convenience for casual use. + */ + public final static Logger global = new Logger("global", null); //$NON-NLS-1$ + + // the name of this logger + private volatile String name; + + // the parent logger of this logger + private Logger parent; + + // the logging level of this logger + private volatile Level levelObjVal; + + // the logging level as int of this logger + private volatile int levelIntVal; + + // the filter + private Filter filter; + + // the name of the resource bundle used to localize logging messages + private String resBundleName; + + // the loaded resource bundle according to the specified name + private ResourceBundle resBundle; + + // the handlers attached to this logger + private List<Handler> handlers; + + /* + * flag indicating whether to notify parent's handlers on receiving a log + * request + */ + private boolean notifyParentHandlers; + + // flag indicating whether this logger is named or anonymous + private boolean isNamed; + + private List<Logger> childs; + + private LogManager manager; + + private volatile boolean handlerInited; + + + /* + * ------------------------------------------------------------------- + * Constructors + * ------------------------------------------------------------------- + */ + + /** + * Constructs a <code>Logger</code> object with the supplied name and + * resource bundle name. + * + * @param name + * the name of this logger, may be null for anonymous loggers + * @param resourceBundleName + * the name of the resource bundle used to localize logging + * messages, may be null + * @throws MissingResourceException + * If the specified resource bundle can not be loaded. + */ + protected Logger(String name, String resourceBundleName) { + // try to load the specified resource bundle first + if (null == resourceBundleName) { + this.resBundleName = null; + this.resBundle = null; + } else { + this.resBundle = loadResourceBundle(resourceBundleName); + this.resBundleName = resourceBundleName; + } + this.name = name; + this.parent = null; + this.filter = null; + this.childs = new ArrayList<Logger>(); + this.notifyParentHandlers = true; + // any logger is not anonymous by default + this.isNamed = true; + + //-- 'null' means that level will be inherited from parent (see getLevel) + //-- Level.INFO is default level if we don't set it. It will be + //-- changed to parent level or to configLevel after adding to the + //-- family tree. As of this, actually, setting to Level.INFO is + //-- not needed here. + this.levelObjVal = null; + this.levelIntVal = Level.INFO.intValue(); + } + + //-- should be called under the lm lock + private void setLevelImpl(Level newLevel) { + // update levels for the whole hierarchy + int oldVal = levelIntVal; + levelObjVal = newLevel; + if (null == newLevel) { + levelIntVal = null != parent + ? parent.levelIntVal + : Level.INFO.intValue(); + } else { + levelIntVal = newLevel.intValue(); + } + if (oldVal != levelIntVal) { + forceChildsToInherit(); + } + } + + //-- should be called under the lm lock + private void forceChildsToInherit() { + for (Logger child : childs) { + if (null == child.levelObjVal) { // should inherit + child.setLevelImpl(null); + } + } + } + + /* + * ------------------------------------------------------------------- + * Methods + * ------------------------------------------------------------------- + */ + + /** + * Load the specified resource bundle, use privileged code. + * + * @param resourceBundleName + * the name of the resource bundle to load, cannot be null + * @return the loaded resource bundle. + * @throws MissingResourceException + * If the specified resource bundle can not be loaded. + */ + static ResourceBundle loadResourceBundle(String resourceBundleName) { + // try context class loader to load the resource + ClassLoader cl = AccessController.doPrivileged( + new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + if (null != cl) { + try { + return ResourceBundle.getBundle(resourceBundleName, Locale + .getDefault(), cl); + } catch (MissingResourceException e) { + // Failed to load using context classloader, ignore + } + } + // try system class loader to load the resource + cl = AccessController.doPrivileged( + new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return ClassLoader.getSystemClassLoader(); + } + }); + if (null != cl) { + try { + return ResourceBundle.getBundle(resourceBundleName, Locale + .getDefault(), cl); + } catch (MissingResourceException e) { + // Failed to load using system classloader, ignore + } + } + // try all class loaders up the class stack + final Class<?>[] classes = AccessController + .doPrivileged(new PrivilegedAction<Class<?>[]>() { + public Class<?>[] run() { + return (new PrivateSecurityManager()) + .privateGetClassContext(); + } + }); + // the first class, which is PrivateSecurityManager, is skipped + for (int i = 1; i < classes.length; i++) { + final int index = i; + try { + cl = AccessController.doPrivileged( + new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return classes[index].getClassLoader(); + } + }); + if (null == cl) { + continue; + } + return ResourceBundle.getBundle(resourceBundleName, Locale + .getDefault(), cl); + } catch (MissingResourceException e) { + // Failed to load using the current class's classloader, ignore + } + } + // logging.8=Failed to load the specified resource bundle "{0}". + throw new MissingResourceException(Messages.getString("logging.8", //$NON-NLS-1$ + resourceBundleName), resourceBundleName, null); + } + + /** + * Gets an anonymous logger to use internally in a thread. Anonymous loggers + * are not registered in the log manager's namespace. No security checks + * will be performed when updating an anonymous logger's control settings + * so that they can be used in applets. + * <p> + * Anonymous loggers' parent is set to be the root logger. This enables + * them to inherit default logging level and handlers from the root logger. + * </p> + * + * @return a new instance of anonymous logger + */ + public static Logger getAnonymousLogger() { + return getAnonymousLogger(null); + } + + /** + * Gets an anonymous logger to use internally in a thread. Anonymous loggers + * are not registered in the log manager's namespace. No security checks + * will be performed when updating an anonymous logger's control settings + * so that they can be used in applets. + * <p> + * Anonymous loggers' parent is set to be the root logger. This enables + * them to inherit default logging level and handlers from the root logger. + * </p> + * + * @param resourceBundleName + * the name of the resource bundle used to localize log messages + * @return a new instance of anonymous logger + * @throws MissingResourceException + * If the specified resource bundle can not be loaded. + */ + public static Logger getAnonymousLogger(String resourceBundleName) { + final Logger l = new Logger(null, resourceBundleName); + l.isNamed = false; + l.internalSetParent(LogManager.getLogManager().getLogger("")); //$NON-NLS-1$ + return l; + } + + /* + * Check whether the same resource bundle has been specified. + * Synchronize to ensure the consistency between resource bundle + * and its name. + */ + private static void updateResourceBundle(Logger l, String resourceBundleName) { + synchronized (l) { + if (null == l.getResourceBundleName()) { + if(null == resourceBundleName){ + return; + } + /* + * load the resource bundle if none is specified + * before + */ + l.resBundle = loadResourceBundle(resourceBundleName); + l.resBundleName = resourceBundleName; + } else if (!l.getResourceBundleName().equals(resourceBundleName)) { + /* + * throw exception if the specified resource bundles + * are inconsistent with each other, i.e., different + * names + */ + // logging.9=The specified resource bundle name "{0}" is + // inconsistent with the existing one "{1}". + throw new IllegalArgumentException(Messages.getString( + "logging.9", //$NON-NLS-1$ + resourceBundleName, l.getResourceBundleName())); + } + } + } + + /* + * Gets a named logger associated with the supplied resource bundle. This + * method accepts null resource bundle name. The method body is synchronized + * on the instance of the LogManager to insure the consistency of the whole + * operation. + */ + private static Logger getLoggerWithRes(String name, + String resourceBundleName, boolean hasResourceName) { + LogManager man = LogManager.getLogManager(); + Logger l = null; + synchronized (man) { + // Try to find an existing logger with the specified name + l = man.getLogger(name); + // If no existing logger with the same name, create a new one + if (null == l) { + l = new Logger(name, resourceBundleName); + man.addLogger(l); + return l; + } + } + if (hasResourceName) { + updateResourceBundle(l, resourceBundleName); + } + return l; + } + + /** + * Gets a named logger. The returned logger may already exist, or may be + * newly created. If the latter, its level will be set to the configured + * level according to the <code>LogManager</code>'s properties if any. + * + * @param name + * the name of the logger to get, cannot be null + * @return a named logger + * @throws MissingResourceException + * If the specified resource bundle can not be loaded. + */ + public static Logger getLogger(String name) { + return getLoggerWithRes(name, null, false); + } + + /** + * Gets a named logger associated with the supplied resource bundle. The + * resource bundle will be used to localize logging messages. + * + * @param name + * the name of the logger to get, cannot be null + * @param resourceBundleName + * the name of the resource bundle, may be null + * @return a named logger + */ + public static Logger getLogger(String name, String resourceBundleName) { + return getLoggerWithRes(name, resourceBundleName, true); + } + + /** + * Adds a handler to this logger. The handler will be fed with log records + * received by this logger. + * + * @param handler + * the handler object to add, cannot be null + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission. + */ + public void addHandler(Handler handler) { + if (null == handler) { + // logging.A=The 'handler' parameter is null. + throw new NullPointerException(Messages.getString("logging.A")); //$NON-NLS-1$ + } + // Anonymous loggers can always add handlers + if (this.isNamed) { + LogManager.getLogManager().checkAccess(); + } + initHandler(); + synchronized(this){ + this.handlers.add(handler); + } + } + + /* + * Be cautious to avoid deadlock when using this method, it gets lock on manager + * at first, and then gets lock on this Logger, so any methods should not hold + * lock on this Logger when invoking this method. + */ + private void initHandler() { + if(!handlerInited){ + synchronized (this) { + if (!handlerInited) { + // BEGIN android-added + /* + * Force LogManager to be initialized, since its + * class init code performs necessary one-time setup. + */ + LogManager.getLogManager(); + // END android-added + + if (handlers == null) { + handlers = new ArrayList<Handler>(); + } + if (manager == null) { + return; + } + + String handlerStr = manager + .getProperty("".equals(name) ? "handlers" : name + ".handlers"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (null == handlerStr) { + return; + } + StringTokenizer st = new StringTokenizer(handlerStr, " "); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String handlerName = st.nextToken(); + + // BEGIN android-changed: deal with non-existing handler + try { + Handler handler = (Handler) LogManager + .getInstanceByClass(handlerName); + handlers.add(handler); + String level = manager.getProperty(handlerName + + ".level"); //$NON-NLS-1$ + if (null != level) { + handler.setLevel(Level.parse(level)); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + // END android-changed + + } + handlerInited = true; + } + } + } + } + + /** + * Gets all the handlers associated with this logger. + * + * @return an array of all the handlers associated with this logger + */ + public Handler[] getHandlers() { + initHandler(); + synchronized(this){ + return handlers.toArray(new Handler[handlers.size()]); + } + } + + /** + * Removes a handler for this logger. If the specified handler does not + * exist, this method has no effect. + * + * @param handler + * the handler to be removed, cannot be null + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission. + */ + public void removeHandler(Handler handler) { + // Anonymous loggers can always remove handlers + if (this.isNamed) { + LogManager.getLogManager().checkAccess(); + } + if (null == handler) { + return; + } + initHandler(); + synchronized(this){ + this.handlers.remove(handler); + } + } + + /** + * Gets the filter used by this logger. + * + * @return the filter used by this logger + */ + public Filter getFilter() { + return this.filter; + } + + /** + * Sets the filter used by this logger. + * + * @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) { + // Anonymous loggers can always set the filter + if (this.isNamed) { + LogManager.getLogManager().checkAccess(); + } + filter = newFilter; + } + + /** + * Gets the logging level of this logger. + * + * @return the logging level of this logger + */ + public Level getLevel() { + return levelObjVal; + } + + /** + * Sets the logging level for this logger. A <code>null</code> level + * indicates this logger will inherit its parent's level. + * + * @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) { + // Anonymous loggers can always set the level + if (this.isNamed) { + LogManager.getLogManager().checkAccess(); + } + synchronized (LogManager.getLogManager()) { + setLevelImpl(newLevel); + } + } + + /** + * Gets the flag which indicates whether to use parent's handlers to publish + * incoming log records, potentially recursively up the namespace. + * + * @return <code>true</code> if set to use parent's handlers, otherwise + * <code>false</code> + */ + public boolean getUseParentHandlers() { + return this.notifyParentHandlers; + } + + /** + * Sets the flag which indicates whether to use parent's handlers to publish + * incoming log records, potentially recursively up the namespace. + * + * @param notifyParentHandlers + * the flag whether to use parent's handlers + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission. + */ + public void setUseParentHandlers(boolean notifyParentHandlers) { + // Anonymous loggers can always set the useParentHandlers flag + if (this.isNamed) { + LogManager.getLogManager().checkAccess(); + } + this.notifyParentHandlers = notifyParentHandlers; + } + + /** + * Gets the parent of this logger in the namespace. + * + * @return the parent of this logger in the namespace + */ + public Logger getParent() { + return parent; + } + + /** + * Sets the parent of this logger in the namespace. This method should + * usually be used by the <code>LogManager</code> object only. This + * method does not check security. + * + * @param newParent + * the parent logger to set + */ + void internalSetParent(Logger newParent) { + //All hierarchy related modifications should get LogManager lock at first + synchronized(LogManager.getLogManager()){ + parent = newParent; + // -- update level after setting a parent. + // -- if level == null we should inherit the parent's level + if (null == levelObjVal) { + setLevelImpl(levelObjVal); + } + newParent.addChild(this); + } + } + + /** + * Sets the parent of this logger in the namespace. This method should + * usually be used by the <code>LogManager</code> object only. + * + * @param parent + * the parent logger to set + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission. + */ + public void setParent(Logger parent) { + if (null == parent) { + // logging.B=The 'parent' parameter is null. + throw new NullPointerException(Messages.getString("logging.B")); //$NON-NLS-1$ + } + // even anonymous loggers are checked + LogManager.getLogManager().checkAccess(); + internalSetParent(parent); + } + + final void addChild(Logger logger) { + childs.add(logger); + } + + final void removeChild(Logger child) { + childs.remove(child); + } + + + /** + * Gets the name of this logger. + * + * @return the name of this logger + */ + public String getName() { + return this.name; + } + + /** + * Gets the loaded resource bundle used by this logger to localize logging + * messages. If it's null, the parent's resource bundle will be inherited. + * + * @return the loaded resource bundle used by this logger + */ + public ResourceBundle getResourceBundle() { + return this.resBundle; + } + + /** + * Gets the name of the loaded resource bundle used by this logger to + * localize logging messages. If it's null, the parent's resource bundle + * name will be inherited. + * + * @return the name of the loaded resource bundle used by this logger + */ + public String getResourceBundleName() { + return this.resBundleName; + } + + /** + * This method is for compatibility. Tests written to the reference + * implementation API imply that the isLoggable() method is not called + * directly. This behavior is important because subclass may override + * isLoggable() method, so that affect the result of log methods. + */ + private boolean internalIsLoggable(Level l) { + int effectiveLevel = levelIntVal; + if (effectiveLevel == Level.OFF.intValue()) { + // always return false if the effective level is off + return false; + } + return l.intValue() >= effectiveLevel; + } + + /** + * Determines whether this logger will actually log messages of the + * specified level. The effective level used to do the determination may be + * inherited from its parent. The default level is <code>Level.INFO</code>. + * + * @param l + * the level to check + * @return <code>true</code> if this logger will actually log this level, + * otherwise <code>false</code> + */ + public boolean isLoggable(Level l) { + return internalIsLoggable(l); + } + + /* + * Sets the resource bundle and its name for a supplied LogRecord object. + * This method first tries to use this logger's resource bundle if any, + * otherwise try to inherit from this logger's parent, recursively up the + * namespace. Synchronize to ensure the consistency between resource bundle + * and its name. + */ + private void setResourceBundle(LogRecord record) { + if (null != this.resBundleName) { + record.setResourceBundle(this.resBundle); + record.setResourceBundleName(this.resBundleName); + } else { + Logger anyParent = this.parent; + // no need to synchronize here, because if resBundleName + // is not null, there is no chance to modify it + while (null != anyParent) { + if (null != anyParent.resBundleName) { + record.setResourceBundle(anyParent.resBundle); + record.setResourceBundleName(anyParent.resBundleName); + return; + } + anyParent = anyParent.parent; + } + } + } + + /** + * Logs a message indicating entering a method. A log record with log level + * <code>Level.FINER</code>, log message "ENTRY", and the specified + * source class name and source method name is submitted for logging. + * + * @param sourceClass + * the calling class name + * @param sourceMethod + * the method name + */ + public void entering(String sourceClass, String sourceMethod) { + if (internalIsLoggable(Level.FINER)) { + LogRecord record = new LogRecord(Level.FINER, "ENTRY"); //$NON-NLS-1$ + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message indicating entering a method. A log record with log level + * <code>Level.FINER</code>, log message "ENTRY", and the specified + * source class name and source method name and one parameter is submitted + * for logging. + * + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param param + * the parameter for the method call + */ + public void entering(String sourceClass, String sourceMethod, Object param) { + if (internalIsLoggable(Level.FINER)) { + LogRecord record = new LogRecord(Level.FINER, "ENTRY" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$ + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(new Object[] { param }); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message indicating entering a method. A log record with log level + * <code>Level.FINER</code>, log message "ENTRY", and the specified + * source class name and source method name and parameters is submitted for + * logging. + * + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param params + * an array of parameters for the method call + */ + public void entering(String sourceClass, String sourceMethod, + Object[] params) { + if (internalIsLoggable(Level.FINER)) { + String msg = "ENTRY"; //$NON-NLS-1$ + if (null != params) { + StringBuilder msgBuffer = new StringBuilder("ENTRY"); //$NON-NLS-1$ + for (int i = 0; i < params.length; i++) { + msgBuffer.append(" {" + i + "}"); //$NON-NLS-1$ //$NON-NLS-2$ + } + msg = msgBuffer.toString(); + } + LogRecord record = new LogRecord(Level.FINER, msg); + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(params); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message indicating existing a method. A log record with log level + * <code>Level.FINER</code>, log message "RETURN", and the specified + * source class name and source method name is submitted for logging. + * + * @param sourceClass + * the calling class name + * @param sourceMethod + * the method name + */ + public void exiting(String sourceClass, String sourceMethod) { + if (internalIsLoggable(Level.FINER)) { + LogRecord record = new LogRecord(Level.FINER, "RETURN"); //$NON-NLS-1$ + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message indicating exiting a method. A log record with log level + * <code>Level.FINER</code>, log message "RETURN", and the specified + * source class name and source method name and return value is submitted + * for logging. + * + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param result + * the return value of the method call + */ + public void exiting(String sourceClass, String sourceMethod, Object result) { + if (internalIsLoggable(Level.FINER)) { + LogRecord record = new LogRecord(Level.FINER, "RETURN" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$ + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(new Object[] { result }); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message indicating throwing an exception. A log record with log + * level <code>Level.FINER</code>, log message "THROW", and the specified + * source class name and source method name and <code>Throwable</code> + * object is submitted for logging. + * + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param thrown + * the <code>Throwable</code> object + */ + public void throwing(String sourceClass, String sourceMethod, + Throwable thrown) { + if (internalIsLoggable(Level.FINER)) { + LogRecord record = new LogRecord(Level.FINER, "THROW"); //$NON-NLS-1$ + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setThrown(thrown); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.SEVERE</code>. + * + * @param msg + * the message to log + */ + public void severe(String msg) { + if (internalIsLoggable(Level.SEVERE)) { + LogRecord record = new LogRecord(Level.SEVERE, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.WARNING</code>. + * + * @param msg + * the message to log + */ + public void warning(String msg) { + if (internalIsLoggable(Level.WARNING)) { + LogRecord record = new LogRecord(Level.WARNING, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.INFO</code>. + * + * @param msg + * the message to log + */ + public void info(String msg) { + if (internalIsLoggable(Level.INFO)) { + LogRecord record = new LogRecord(Level.INFO, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.CONFIG</code>. + * + * @param msg + * the message to log + */ + public void config(String msg) { + if (internalIsLoggable(Level.CONFIG)) { + LogRecord record = new LogRecord(Level.CONFIG, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.FINE</code>. + * + * @param msg + * the message to log + */ + public void fine(String msg) { + if (internalIsLoggable(Level.FINE)) { + LogRecord record = new LogRecord(Level.FINE, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.FINER</code>. + * + * @param msg + * the message to log + */ + public void finer(String msg) { + if (internalIsLoggable(Level.FINER)) { + LogRecord record = new LogRecord(Level.FINER, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of level <code>Level.FINEST</code>. + * + * @param msg + * the message to log + */ + public void finest(String msg) { + if (internalIsLoggable(Level.FINEST)) { + LogRecord record = new LogRecord(Level.FINEST, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the specified level. + * + * @param logLevel + * the level of the given message + * @param msg + * the message to log + */ + public void log(Level logLevel, String msg) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the specified level with the supplied parameter. + * + * @param logLevel + * the level of the given message + * @param msg + * the message to log + * @param param + * the parameter associated with the event that need to be logged + */ + public void log(Level logLevel, String msg, Object param) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setParameters(new Object[] { param }); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the specified level with the supplied parameter array. + * + * @param logLevel + * the level of the given message + * @param msg + * the message to log + * @param params + * the parameter array associated with the event that need to be + * logged + */ + public void log(Level logLevel, String msg, Object[] params) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setParameters(params); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the specified level with the supplied + * <code>Throwable</code> object. + * + * @param logLevel + * the level of the given message + * @param msg + * the message to log + * @param thrown + * the <code>Throwable</code> object associated with the event + * that need to be logged + */ + public void log(Level logLevel, String msg, Throwable thrown) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setThrown(thrown); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a given log record. Only those with a logging level no lower than + * this logger's level will be submitted to this logger's handlers for + * logging. If <code>getUseParentHandlers()</code> is <code>true</code>, + * the log record will also be submitted to the parent logger's handlers, + * potentially recursively up the namespace. + * <p> + * Since all other log methods call this method to actually perform the + * logging action, subclasses of this class can override this method to + * catch all logging activities. + * </p> + * + * @param record + * the log record to be logged + */ + public void log(LogRecord record) { + if (internalIsLoggable(record.getLevel())) { + // apply the filter if any + Filter f = filter; + if (null != f && !f.isLoggable(record)) { + return; + } + initHandler(); + /* + * call the handlers of this logger, throw any exception that + * occurs + */ + Handler[] allHandlers = getHandlers(); + for (Handler element : allHandlers) { + element.publish(record); + } + // call the parent's handlers if set useParentHandlers + Logger temp = this; + Logger theParent = temp.parent; + while (theParent != null && temp.getUseParentHandlers()) { + Handler[] ha = theParent.getHandlers(); + for (Handler element : ha) { + element.publish(record); + } + temp = theParent; + theParent = temp.parent; + } + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param msg + * the message to be logged + */ + public void logp(Level logLevel, String sourceClass, String sourceMethod, + String msg) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name and parameter. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param msg + * the message to be logged + * @param param + * the parameter associated with the event that need to be logged + */ + public void logp(Level logLevel, String sourceClass, String sourceMethod, + String msg, Object param) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(new Object[] { param }); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name and parameter array. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param msg + * the message to be logged + * @param params + * the parameter array associated with the event that need to be + * logged + */ + public void logp(Level logLevel, String sourceClass, String sourceMethod, + String msg, Object[] params) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(params); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name and <code>Throwable</code> object. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param msg + * the message to be logged + * @param thrown + * the <code>Throwable</code> object + */ + public void logp(Level logLevel, String sourceClass, String sourceMethod, + String msg, Throwable thrown) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setThrown(thrown); + setResourceBundle(record); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name, using the given resource bundle to localize the + * message. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param bundleName + * the name of the resource bundle, used to localize the message + * @param msg + * the message to be logged + */ + public void logrb(Level logLevel, String sourceClass, String sourceMethod, + String bundleName, String msg) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + if (null != bundleName) { + try { + record.setResourceBundle(loadResourceBundle(bundleName)); + } catch (MissingResourceException e) { + // ignore + } + record.setResourceBundleName(bundleName); + } + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name and parameter, using the given resource bundle to + * localize the message. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param bundleName + * the name of the resource bundle, used to localize the message + * @param msg + * the message to be logged + * @param param + * the parameter associated with the event that need to be logged + */ + public void logrb(Level logLevel, String sourceClass, String sourceMethod, + String bundleName, String msg, Object param) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + if (null != bundleName) { + try { + record.setResourceBundle(loadResourceBundle(bundleName)); + } catch (MissingResourceException e) { + // ignore + } + record.setResourceBundleName(bundleName); + } + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(new Object[] { param }); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name and parameter array, using the given resource + * bundle to localize the message. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param bundleName + * the name of the resource bundle, used to localize the message + * @param msg + * the message to be logged + * @param params + * the parameter array associated with the event that need to be + * logged + */ + public void logrb(Level logLevel, String sourceClass, String sourceMethod, + String bundleName, String msg, Object[] params) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + if (null != bundleName) { + try { + record.setResourceBundle(loadResourceBundle(bundleName)); + } catch (MissingResourceException e) { + // ignore + } + record.setResourceBundleName(bundleName); + } + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setParameters(params); + log(record); + } + } + + /** + * Logs a message of the given level with the specified source class name + * and source method name and <code>Throwable</code> object, using the + * given resource bundle to localize the message. + * + * @param logLevel + * the level of the given message + * @param sourceClass + * the source class name + * @param sourceMethod + * the source method name + * @param bundleName + * the name of the resource bundle, used to localize the message + * @param msg + * the message to be logged + * @param thrown + * the <code>Throwable</code> object + */ + public void logrb(Level logLevel, String sourceClass, String sourceMethod, + String bundleName, String msg, Throwable thrown) { + if (internalIsLoggable(logLevel)) { + LogRecord record = new LogRecord(logLevel, msg); + if (null != bundleName) { + try { + record.setResourceBundle(loadResourceBundle(bundleName)); + } catch (MissingResourceException e) { + // ignore + } + record.setResourceBundleName(bundleName); + } + record.setLoggerName(this.name); + record.setSourceClassName(sourceClass); + record.setSourceMethodName(sourceMethod); + record.setThrown(thrown); + log(record); + } + } + + /* + * This security manager is used to access the class context. + */ + static class PrivateSecurityManager extends SecurityManager { + public Class<?>[] privateGetClassContext() { + return super.getClassContext(); + } + } + + void setManager(LogManager manager) { + if(this.manager != manager){ + this.manager = manager; + handlerInited = false; + } + //init level here, but let handlers be for lazy loading + String configedLevel = manager.getProperty(name+ ".level"); //$NON-NLS-1$ + if (null != configedLevel) { + try { + setLevel(Level.parse(configedLevel)); + } catch (IllegalArgumentException e) { + //ignore + } + } + } + + synchronized void reset() { + levelObjVal = null; + levelIntVal = Level.INFO.intValue(); + if(handlers != null){ + for (Handler element : handlers) { + // close all handlers, when unknown exceptions happen, + // ignore them and go on + try { + element.close(); + } catch (Exception e) { + // Ignored. + } + } + handlers.clear(); + } + handlerInited = false; + } +} + diff --git a/logging/src/main/java/java/util/logging/LoggingMXBean.java b/logging/src/main/java/java/util/logging/LoggingMXBean.java new file mode 100644 index 0000000..71ea65d --- /dev/null +++ b/logging/src/main/java/java/util/logging/LoggingMXBean.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import java.util.List; + +/** + * <p> + * The management interface for the logging sub-system. + * </p> + * + * <p> + * ObjectName = + * {@link LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging} + * </p> + * + * @since 1.5 + */ +public interface LoggingMXBean { + /** + * <p> + * Gets the String value of the logging level of a logger. An empty String + * is returned when the logger's level is defined by its parent. + * </p> + * + * @param loggerName The name of the logger lookup. + * @return A String if the logger was found, otherwise <code>null</code>. + * @see Level#getName() + */ + String getLoggerLevel(String loggerName); + + /** + * <p> + * Gets a list of all currently registered logger's names. This is performed + * using the {@link LogManager#getLoggerNames()}. + * </p> + * + * @return A List of String instances. + */ + List<String> getLoggerNames(); + + /** + * <p> + * Gets the name of the parent logger of a logger. If the logger doesn't + * exist then <code>null</code> is returned. If the logger is the root + * logger, then an empty String is returned. + * </p> + * + * @param loggerName The name of the logger to lookup. + * @return A String if the logger was found, otherwise <code>null</code>. + */ + String getParentLoggerName(String loggerName); + + /** + * <p> + * Sets the log level of a logger. + * </p> + * + * @param loggerName The name of the logger to set the level on, which must + * not be <code>null</code>. + * @param levelName The level to set on the logger, which may be + * <code>null</code>. + * @throws IllegalArgumentException if <code>loggerName</code> is not a + * registered logger or if <code>levelName</code> is not null and + * an invalid value. + * @throws SecurityException if a security manager exists and the caller + * doesn't have LoggingPermission("control"). + * @see Level#parse(String) + */ + void setLoggerLevel(String loggerName, String levelName); +} diff --git a/logging/src/main/java/java/util/logging/LoggingPermission.java b/logging/src/main/java/java/util/logging/LoggingPermission.java new file mode 100644 index 0000000..6962127 --- /dev/null +++ b/logging/src/main/java/java/util/logging/LoggingPermission.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import java.io.Serializable; +import java.security.BasicPermission; +import java.security.Guard; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * The permission required to control the logging when run with a + * <code>SecurityManager</code>. + * + */ +public final class LoggingPermission extends BasicPermission implements Guard, + Serializable { + + //for serialization compatibility with J2SE 1.4.2 + private static final long serialVersionUID =63564341580231582L; + + + /* + * ------------------------------------------------------------------- + * Constructors + * ------------------------------------------------------------------- + */ + + /** + * Constructs a <code>LoggingPermission</code> object required to control + * the logging. + * + * @param name + * Currently must be "control". + * @param actions + * Currently must be either <code>null</code> or the empty + * string. + */ + public LoggingPermission(String name, String actions) { + super(name, actions); + if (!"control".equals(name)) { //$NON-NLS-1$ + // logging.6=Name must be "control". + throw new IllegalArgumentException(Messages.getString("logging.6")); //$NON-NLS-1$ + } + if (null != actions && !"".equals(actions)) { //$NON-NLS-1$ + // logging.7=Actions must be either null or the empty string. + throw new IllegalArgumentException(Messages.getString("logging.7")); //$NON-NLS-1$ + } + } + +} + diff --git a/logging/src/main/java/java/util/logging/MemoryHandler.java b/logging/src/main/java/java/util/logging/MemoryHandler.java new file mode 100644 index 0000000..ca96dc5 --- /dev/null +++ b/logging/src/main/java/java/util/logging/MemoryHandler.java @@ -0,0 +1,284 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; + +import org.apache.harmony.logging.internal.nls.Messages; + + +/** + * A <code>Handler</code> put the description of log events into a cycled memory + * buffer. + * <p> + * Mostly this <code>MemoryHandler</code> just puts the given <code>LogRecord</code> + * into the internal buffer and doesn't perform any formatting or any other process. + * When the buffer is full, the earliest buffered records will be discarded. + * </p> + * <p> + * Every <code>MemoryHandler</code> has a target handler, and push action can be + * triggered so that all buffered records will be output to the target handler + * and normally the latter will publish the records. After the push action, the + * buffer will be cleared. + * </p> + * <p> + * The push action can be triggered in three ways: + * <ul> + * <li>The push method is called explicitly</li> + * <li>When a new <code>LogRecord</code> is put into the internal buffer, and it has a level which is not less than the specified push level.</li> + * <li>A subclass extends this <code>MemoryHandler</code> and call push method implicitly according to some criteria.</li> + * </ul> + * </p> + * <p> + * <code>MemoryHandler</code> will read following <code>LogManager</code> + * properties for initialization, if given properties are not defined or has + * invalid values, default value will be used. + * <ul> + * <li>java.util.logging.MemoryHandler.level specifies the level for this + * <code>Handler</code>, defaults to <code>Level.ALL</code>.</li> + * <li>java.util.logging.MemoryHandler.filter specifies the <code>Filter</code> + * class name, defaults to no <code>Filter</code>.</li> + * <li>java.util.logging.MemoryHandler.size specifies the buffer size in number + * of <code>LogRecord</code>, defaults to 1000.</li> + * <li>java.util.logging.MemoryHandler.push specifies the push level, defaults + * to level.SEVERE.</li> + * <li>java.util.logging.MemoryHandler.target specifies the class of the target + * <code>Handler</code>, no default value, which means this property must be + * specified either by property setting or by constructor.</li> + * </ul> + * </p> + * + */ +public class MemoryHandler extends Handler { + + //default maximum buffered number of LogRecord + private static final int DEFAULT_SIZE = 1000; + //target handler + private Handler target; + + //buffer size + private int size = DEFAULT_SIZE; + + //push level + private Level push = Level.SEVERE; + + //LogManager instance for convenience + private final LogManager manager = LogManager.getLogManager(); + + //buffer + private LogRecord[] buffer; + + //current position in buffer + private int cursor; + + /** + * Default constructor, construct and init a <code>MemoryHandler</code> using + * <code>LogManager</code> properties or default values + */ + public MemoryHandler() { + super(); + String className = this.getClass().getName(); + //init target + final String targetName = manager.getProperty(className+".target"); //$NON-NLS-1$ + try { + Class<?> targetClass = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>(){ + public Class<?> run() throws Exception{ + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if(loader == null){ + loader = ClassLoader.getSystemClassLoader(); + } + return loader.loadClass(targetName); + } + }); + target = (Handler) targetClass.newInstance(); + } catch (Exception e) { + // logging.10=Cannot load target handler:{0} + throw new RuntimeException(Messages.getString("logging.10", //$NON-NLS-1$ + targetName)); + } + //init size + String sizeString = manager.getProperty(className+".size"); //$NON-NLS-1$ + if (null != sizeString) { + try { + size = Integer.parseInt(sizeString); + if(size <= 0){ + size = DEFAULT_SIZE; + } + } catch (Exception e) { + printInvalidPropMessage(className+".size", sizeString, e); //$NON-NLS-1$ + } + } + //init push level + String pushName = manager.getProperty(className+".push"); //$NON-NLS-1$ + if (null != pushName) { + try { + push = Level.parse(pushName); + } catch (Exception e) { + printInvalidPropMessage(className+".push", pushName, e); //$NON-NLS-1$ + } + } + //init other properties which are common for all Handler + initProperties("ALL", null, "java.util.logging.SimpleFormatter", null); //$NON-NLS-1$//$NON-NLS-2$ + buffer = new LogRecord[size]; + } + + /** + * Construct and init a <code>MemoryHandler</code> using given target, size + * and push level, other properties using <code>LogManager</code> properties + * or default values + * + * @param target + * the given <code>Handler</code> to output + * @param size the maximum number of buffered <code>LogRecord</code> + * @param pushLevel + * the push level + * @throws IllegalArgumentException + * if size<=0 + */ + public MemoryHandler(Handler target, int size, Level pushLevel) { + if (size <= 0) { + // logging.11=Size must be positive. + throw new IllegalArgumentException(Messages.getString("logging.11")); //$NON-NLS-1$ + } + target.getLevel(); + pushLevel.intValue(); + this.target = target; + this.size = size; + this.push = pushLevel; + initProperties("ALL", null, "java.util.logging.SimpleFormatter", null); //$NON-NLS-1$//$NON-NLS-2$ + buffer = new LogRecord[size]; + } + + /** + * Close this handler and target handler, free all associated resources + * + * @throws SecurityException + * if security manager exists and it determines that caller + * does not have the required permissions to control this handler + */ + @Override + public void close() { + manager.checkAccess(); + target.close(); + setLevel(Level.OFF); + } + + /** + * Call target handler to flush any buffered output. + * + * Note that this doesn't cause this <code>MemoryHandler</code> to push. + * + */ + @Override + public void flush() { + target.flush(); + } + + /** + * Put a given <code>LogRecord</code> into internal buffer. + * + * If given record is not loggable, just return. Otherwise it is stored in + * the buffer. Furthermore if the record's level is not less than the push + * level, the push action is triggered to output all the buffered records + * to the target handler, and the target handler will publish them. + * + * @param record the log record. + */ + @Override + public synchronized void publish(LogRecord record) { + if (!isLoggable(record)) { + return; + } + if (cursor >= size) { + cursor = 0; + } + buffer[cursor++] = record; + if (record.getLevel().intValue() >= push.intValue()) { + push(); + } + return; + } + + /** + * Return the push level. + * + * @return the push level + */ + public Level getPushLevel() { + return push; + } + + /** + * <p>Check if given <code>LogRecord</code> would be put into this + * <code>MemoryHandler</code>'s internal buffer. + * </p> + * <p> + * The given <code>LogRecord</code> is loggable if and only if it has + * appropriate level and it pass any associated filter's check. + * </p> + * <p> + * Note that the push level is not used for this check. + * </p> + * @param record + * the given <code>LogRecord</code> + * @return if the given <code>LogRecord</code> should be logged + */ + @Override + public boolean isLoggable(LogRecord record) { + return super.isLoggable(record); + } + + /** + * Triggers a push action to output all buffered records to the target handler, + * and the target handler will publish them. Then the buffer is cleared. + */ + public void push() { + for (int i = cursor; i < size; i++) { + if(null != buffer[i]) { + target.publish(buffer[i]); + } + buffer[i] = null; + } + for (int i = 0; i < cursor; i++) { + if(null != buffer[i]) { + target.publish(buffer[i]); + } + buffer[i] = null; + } + cursor = 0; + } + + /** + * Set the push level. The push level is used to check the push action + * triggering. When a new <code>LogRecord</code> is put into the internal + * buffer and its level is not less than the push level, the push action + * will be triggered. Note that set new push level won't trigger push action. + * + * @param newLevel + * the new level to set + * @throws SecurityException + * if security manager exists and it determines that caller + * does not have the required permissions to control this handler + */ + public void setPushLevel(Level newLevel) { + manager.checkAccess(); + newLevel.intValue(); + this.push = newLevel; + } +} diff --git a/logging/src/main/java/java/util/logging/SimpleFormatter.java b/logging/src/main/java/java/util/logging/SimpleFormatter.java new file mode 100644 index 0000000..cfccda0 --- /dev/null +++ b/logging/src/main/java/java/util/logging/SimpleFormatter.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.MessageFormat; +import java.util.Date; + +/** + * <code>SimpleFormatter</code> can be used to print a summary of the + * information contained in a <code>LogRecord</code> object in a human + * readable format. + * + */ +public class SimpleFormatter extends Formatter { + /** + * Constructs a <code>SimpleFormatter</code> object. + */ + public SimpleFormatter() { + super(); + } + + @Override + public String format(LogRecord r) { + StringBuilder sb = new StringBuilder(); + sb.append(MessageFormat.format("{0, date} {0, time} ", //$NON-NLS-1$ + new Object[] { new Date(r.getMillis()) })); + sb.append(r.getSourceClassName()).append(" "); //$NON-NLS-1$ + sb.append(r.getSourceMethodName()).append(LogManager.getSystemLineSeparator()); //$NON-NLS-1$ + sb.append(r.getLevel().getName()).append(": "); //$NON-NLS-1$ + sb.append(formatMessage(r)).append(LogManager.getSystemLineSeparator()); + if (null != r.getThrown()) { + sb.append("Throwable occurred: "); //$NON-NLS-1$ + Throwable t = r.getThrown(); + PrintWriter pw = null; + try { + StringWriter sw = new StringWriter(); + pw = new PrintWriter(sw); + t.printStackTrace(pw); + sb.append(sw.toString()); + } finally { + if(pw != null){ + try { + pw.close(); + } catch (Exception e) { + // ignore + } + } + } + } + return sb.toString(); + } +} + diff --git a/logging/src/main/java/java/util/logging/SocketHandler.java b/logging/src/main/java/java/util/logging/SocketHandler.java new file mode 100644 index 0000000..3d9ab29 --- /dev/null +++ b/logging/src/main/java/java/util/logging/SocketHandler.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import java.net.Socket; +import java.io.BufferedOutputStream; +import java.io.IOException; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * A handler that writes log messages to a socket connection. + * <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.ALL</code> if this property is not found or has an + * invalid value; + * <li>java.util.logging.SocketHandler.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.SocketHandler.formatter specifies the name of the + * formatter class to be associated with this handler, defaults to + * <code>java.util.logging.XMLFormatter</code> if this property is not found + * or has an invalid value; + * <li>java.util.logging.SocketHandler.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. + * <li>java.util.logging.SocketHandler.host specifies the name of the host that + * this handler should connect to. There's no default value for this property. + * <li>java.util.logging.SocketHandler.encoding specifies the port number that + * this handler should connect to. There's no default value for this property. + * </ul> + * </p> + * <p> + * This handler buffers the outgoing messages, but flushes each time a log + * record has been published. + * </p> + * <p> + * This class is not thread-safe. + * </p> + * + */ +public class SocketHandler extends StreamHandler { + // default level + private static final String DEFAULT_LEVEL = "ALL"; //$NON-NLS-1$ + + // default formatter + private static final String DEFAULT_FORMATTER = "java.util.logging.XMLFormatter"; //$NON-NLS-1$ + + // the socket connection + private Socket socket; + + /** + * Constructs a <code>SocketHandler</code> object using the properties + * read by the log manager, including the host name and port number. + * + * @throws IOException + * If failed to connect to the specified host and port. + * @throws IllegalArgumentException + * If the host name or port number is illegal. + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission to control this handler. + */ + public SocketHandler() throws IOException { + super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); + initSocket(LogManager.getLogManager().getProperty( + "java.util.logging.SocketHandler.host"), LogManager //$NON-NLS-1$ + .getLogManager().getProperty( + "java.util.logging.SocketHandler.port")); //$NON-NLS-1$ + } + + /** + * Constructs a <code>SocketHandler</code> object using the specified host + * name and port number together with other properties read by the log + * manager. + * + * @param host + * the host name + * @param port + * the port number + * @throws IOException + * If failed to connect to the specified host and port. + * @throws IllegalArgumentException + * If the host name or port number is illegal. + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission to control this handler. + */ + public SocketHandler(String host, int port) throws IOException { + super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); + initSocket(host, String.valueOf(port)); + } + + // Initialize the socket connection and prepare the output stream + private void initSocket(String host, String port) throws IOException { + // check the validity of the host name + if (null == host || "".equals(host)) { //$NON-NLS-1$ + // logging.C=Illegal host argument. + throw new IllegalArgumentException(Messages.getString("logging.C")); //$NON-NLS-1$ + } + // check the validity of the port number + int p = 0; + try { + p = Integer.parseInt(port); + } catch (NumberFormatException e) { + // logging.D=Illegal port argument. + throw new IllegalArgumentException(Messages.getString("logging.D")); //$NON-NLS-1$ + } + if (p <= 0) { + // logging.D=Illegal port argument. + throw new IllegalArgumentException(Messages.getString("logging.D")); //$NON-NLS-1$ + } + // establish the network connection + try { + this.socket = new Socket(host, p); + } catch (IOException e) { + // logging.E=Failed to establish the network connection. + getErrorManager().error(Messages.getString("logging.E"), e, //$NON-NLS-1$ + ErrorManager.OPEN_FAILURE); + throw e; + } + // BEGIN android-modified + super.internalSetOutputStream(new BufferedOutputStream(this.socket + .getOutputStream(), 8192)); + // END android-modified + } + + /** + * Closes this handler. The network connection to the host is also closed. + * + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission to control this handler. + */ + @Override + public void close() { + try { + super.close(); + if (null != this.socket) { + this.socket.close(); + this.socket = null; + } + } catch (Exception e) { + // logging.F=Exception occurred when closing the socket handler. + getErrorManager().error(Messages.getString("logging.F"), e, //$NON-NLS-1$ + ErrorManager.CLOSE_FAILURE); + } + } + + /** + * Logs a record if necessary. A flush operation will be done afterwards. + * + * @param record + * the log record to be logged + */ + @Override + public void publish(LogRecord record) { + super.publish(record); + super.flush(); + } + +} diff --git a/logging/src/main/java/java/util/logging/StreamHandler.java b/logging/src/main/java/java/util/logging/StreamHandler.java new file mode 100644 index 0000000..fb48c2a --- /dev/null +++ b/logging/src/main/java/java/util/logging/StreamHandler.java @@ -0,0 +1,350 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +import org.apache.harmony.logging.internal.nls.Messages; + +/** + * A <code>StreamHandler</code> object writes log messages to an output + * stream, that is, objects of the class <code>java.io.OutputStream</code>. + * <p> + * A <code>StreamHandler</code> object reads the following properties from the + * log manager to initialize itself: + * <ul> + * <li>java.util.logging.StreamHandler.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.StreamHandler.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.StreamHandler.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.StreamHandler.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 StreamHandler extends Handler { + // the output stream this handler writes to + private OutputStream os; + + // the writer that writes to the output stream + private Writer writer; + + // the flag indicating whether the writer has been initialized + private boolean writerNotInitialized; + + /** + * Constructs a <code>StreamHandler</code> object. The new stream handler + * does not have an associated output stream. + */ + public StreamHandler() { + initProperties("INFO", null, "java.util.logging.SimpleFormatter", //$NON-NLS-1$//$NON-NLS-2$ + null); + this.os = null; + this.writer = null; + this.writerNotInitialized = true; + } + + /** + * Constructs a <code>StreamHandler</code> object with the supplied output + * stream. Default properties are read. + * + * @param os + * the output stream this handler writes to + */ + StreamHandler(OutputStream os) { + this(); + this.os = os; + } + + /** + * Constructs a <code>StreamHandler</code> object. Specified default + * values will be used if the corresponding properties are found in log + * manager's properties. + */ + StreamHandler(String defaultLevel, String defaultFilter, + String defaultFormatter, String defaultEncoding) { + initProperties(defaultLevel, defaultFilter, defaultFormatter, + defaultEncoding); + this.os = null; + this.writer = null; + this.writerNotInitialized = true; + } + + /** + * Constructs a <code>StreamHandler</code> object with the supplied output + * stream and formatter. + * + * @param os + * the output stream this handler writes to + * @param formatter + * the formatter this handler uses to format the output + */ + public StreamHandler(OutputStream os, Formatter formatter) { + this(); + if (os == null) { + // logging.2=The OutputStream parameter is null + throw new NullPointerException(Messages.getString("logging.2")); //$NON-NLS-1$ + } + if (formatter == null) { + // logging.3=The Formatter parameter is null. + throw new NullPointerException(Messages.getString("logging.3")); //$NON-NLS-1$ + } + this.os = os; + internalSetFormatter(formatter); + } + + // initialize the writer + private void initializeWritter() { + this.writerNotInitialized = false; + if (null == getEncoding()) { + this.writer = new OutputStreamWriter(this.os); + } else { + try { + this.writer = new OutputStreamWriter(this.os, getEncoding()); + } catch (UnsupportedEncodingException e) { + /* + * Should not happen because it's checked in + * super.initProperties(). + */ + } + } + write(getFormatter().getHead(this)); + } + + // Write a string to the output stream. + private void write(String s) { + try { + this.writer.write(s); + } catch (Exception e) { + // logging.14=Exception occurred when writing to the output stream. + getErrorManager().error(Messages.getString("logging.14"), e, //$NON-NLS-1$ + ErrorManager.WRITE_FAILURE); + } + } + + /** + * Sets the output stream this handler writes to. Note it does nothing else. + * + * @param newOs + * the new output stream + */ + void internalSetOutputStream(OutputStream newOs) { + this.os = newOs; + } + + + /** + * Sets the output stream this handler writes to. If there's an existing + * output stream, the tail string of the associated formatter will be + * written to it. Then it will be flushed and closed. + * + * @param os + * the new output stream + * @throws SecurityException + * If a security manager determines that the caller does not + * have the required permission. + */ + protected void setOutputStream(OutputStream os) { + if (null == os) { + throw new NullPointerException(); + } + LogManager.getLogManager().checkAccess(); + close(true); + this.writer = null; + this.os = os; + this.writerNotInitialized = true; + } + + /** + * 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. + */ + @Override + public void setEncoding(String encoding) throws SecurityException, + UnsupportedEncodingException { + //flush first before set new encoding + this.flush(); + super.setEncoding(encoding); + // renew writer only if the writer exists + if (null != this.writer) { + if (null == getEncoding()) { + this.writer = new OutputStreamWriter(this.os); + } else { + try { + this.writer = new OutputStreamWriter(this.os, getEncoding()); + } catch (UnsupportedEncodingException e) { + /* + * Should not happen because it's checked in + * super.initProperties(). + */ + throw new AssertionError(e); + } + } + } + } + + /** + * Closes this handler, but the underlying output stream is only closed when + * <code>closeStream</code> is <code>true</code>. Security is not checked. + * + * @param closeStream + * whether to close the underlying output stream + */ + void close(boolean closeStream) { + if (null != this.os) { + if (this.writerNotInitialized) { + initializeWritter(); + } + write(getFormatter().getTail(this)); + try { + this.writer.flush(); + if (closeStream) { + this.writer.close(); + this.writer = null; + this.os = null; + } + } catch (Exception e) { + // logging.15=Exception occurred when closing the output stream. + getErrorManager().error(Messages.getString("logging.15"), e, //$NON-NLS-1$ + ErrorManager.CLOSE_FAILURE); + } + } + } + + /** + * Closes this handler. The tail string of the formatter associated with + * this handler will be written out. A flush operation a subsequent close + * operation will then be performed upon the outputstream. 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. + */ + @Override + public void close() { + LogManager.getLogManager().checkAccess(); + close(true); + } + + /** + * Flushes any buffered output. + */ + @Override + public void flush() { + if (null != this.os) { + try { + if (null != this.writer) { + this.writer.flush(); + } else { + this.os.flush(); + } + } catch (Exception e) { + // logging.16=Exception occurred while flushing the output stream. + getErrorManager().error(Messages.getString("logging.16"), //$NON-NLS-1$ + e, ErrorManager.FLUSH_FAILURE); + } + } + } + + /** + * Accepts an actual logging request. The log record will be formatted and + * written to the output stream if the following three conditions are met: + * <ul> + * <li>the supplied log record has at least the required logging level; + * <li>the supplied log record passes the filter associated with this + * handler if any; + * <li>the output stream associated with this handler is not + * <code>null</code>. + * </ul> + * If it is the first time a log record need to be written out, the head + * string of the formatter associated with this handler will be written out + * first. + * + * @param record + * the log record to be logged + */ + @Override + public synchronized void publish(LogRecord record) { + try { + if (this.isLoggable(record)) { + if (this.writerNotInitialized) { + initializeWritter(); + } + String msg = null; + try { + msg = getFormatter().format(record); + } catch (Exception e) { + // logging.17=Exception occurred while formatting the log record. + getErrorManager().error(Messages.getString("logging.17"), //$NON-NLS-1$ + e, ErrorManager.FORMAT_FAILURE); + } + write(msg); + } + } catch (Exception e) { + // logging.18=Exception occurred while logging the record. + getErrorManager().error(Messages.getString("logging.18"), e, //$NON-NLS-1$ + ErrorManager.GENERIC_FAILURE); + } + } + + /** + * Determines whether the supplied log record need to be logged. The logging + * levels will be checked as well as the filter. The output stream of this + * handler is also checked. If it's null, this method returns false. + * + * @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> + */ + @Override + public boolean isLoggable(LogRecord record) { + if (null == record) { + return false; + } + if (null != this.os && super.isLoggable(record)) { + return true; + } + return false; + } + +} diff --git a/logging/src/main/java/java/util/logging/XMLFormatter.java b/logging/src/main/java/java/util/logging/XMLFormatter.java new file mode 100644 index 0000000..f3ff280 --- /dev/null +++ b/logging/src/main/java/java/util/logging/XMLFormatter.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package java.util.logging; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.Date; +import java.util.ResourceBundle; + +/** + * Format a given <code>LogRecord</code> into string represents XML. The DTD specified in + * Appendix A to Java Logging APIs specification is used. + * + * <code>XMLFormatter</code> uses given <code>Handler</code>'s encoding if has, otherwise + * uses default platform encoding instead. However, the UTF-8 is recommended encoding. + * + */ +public class XMLFormatter extends Formatter { + + private static final String lineSeperator = LogManager + .getSystemLineSeparator(); + + private static final String indent = " "; //$NON-NLS-1$ + + /** + * Default constructor + */ + public XMLFormatter() { + super(); + } + + /** + * Format a <code>LogRecord</code> into string which represents XML + * + * @param r the given LogRecord instance to be formatted + * @return string which represents XML + */ + @Override + public String format(LogRecord r) { + //call a method of LogRecord to ensure not null + long time = r.getMillis(); + //format to date + String date = MessageFormat.format("{0, date} {0, time}", //$NON-NLS-1$ + new Object[] { new Date(time) }); + + StringBuilder sb = new StringBuilder(); + sb.append(("<record>")).append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(("<date>")).append(date).append(("</date>")) //$NON-NLS-1$ //$NON-NLS-2$ + .append(lineSeperator); + sb.append(indent).append(("<millis>")).append(time).append( //$NON-NLS-1$ + ("</millis>")).append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(("<sequence>")).append(r.getSequenceNumber()) //$NON-NLS-1$ + .append(("</sequence>")).append(lineSeperator); //$NON-NLS-1$ + if (null != r.getLoggerName()) { + sb.append(indent).append(("<logger>")).append(r.getLoggerName()) //$NON-NLS-1$ + .append(("</logger>")).append(lineSeperator); //$NON-NLS-1$ + } + sb.append(indent).append(("<level>")).append(r.getLevel().getName()) //$NON-NLS-1$ + .append(("</level>")).append(lineSeperator); //$NON-NLS-1$ + if (null != r.getSourceClassName()) { + sb.append(indent).append(("<class>")) //$NON-NLS-1$ + .append(r.getSourceClassName()).append(("</class>")) //$NON-NLS-1$ + .append(lineSeperator); + } + if (null != r.getSourceMethodName()) { + sb.append(indent).append(("<method>")).append( //$NON-NLS-1$ + r.getSourceMethodName()).append(("</method>")).append( //$NON-NLS-1$ + lineSeperator); + } + sb.append(indent).append(("<thread>")).append(r.getThreadID()).append( //$NON-NLS-1$ + ("</thread>")).append(lineSeperator); //$NON-NLS-1$ + formatMessages(r, sb); + Object[] params; + if ((params = r.getParameters()) != null) { + for (Object element : params) { + sb.append(indent).append(("<param>")).append(element).append( //$NON-NLS-1$ + ("</param>")).append(lineSeperator); //$NON-NLS-1$ + } + } + formatThrowable(r, sb); + sb.append(("</record>")).append(lineSeperator); //$NON-NLS-1$ + return sb.toString(); + } + + private void formatMessages(LogRecord r, StringBuilder sb) { + //get localized message if has, but don't call Formatter.formatMessage to parse pattern string + ResourceBundle rb = r.getResourceBundle(); + String pattern = r.getMessage(); + if (null != rb && null != pattern) { + String message; + try { + message = rb.getString(pattern); + } catch (Exception e) { + message = null; + } + + if (message == null) { + message = pattern; + sb.append(indent).append(("<message>")).append(message).append( //$NON-NLS-1$ + ("</message>")).append(lineSeperator); //$NON-NLS-1$ + } else { + sb.append(indent).append(("<message>")).append(message).append( //$NON-NLS-1$ + ("</message>")).append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(("<key>")).append(pattern).append( //$NON-NLS-1$ + ("</key>")).append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(("<catalog>")).append( //$NON-NLS-1$ + r.getResourceBundleName()).append(("</catalog>")) //$NON-NLS-1$ + .append(lineSeperator); + } + } else if(null != pattern){ + sb.append(indent).append(("<message>")).append(pattern).append( //$NON-NLS-1$ + ("</message>")).append(lineSeperator); //$NON-NLS-1$ + } else{ + sb.append(indent).append(("<message/>")); //$NON-NLS-1$ + } + } + + private void formatThrowable(LogRecord r, StringBuilder sb) { + Throwable t; + if ((t = r.getThrown()) != null) { + sb.append(indent).append("<exception>").append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(indent).append("<message>").append( //$NON-NLS-1$ + t.toString()).append("</message>").append(lineSeperator); //$NON-NLS-1$ + //format throwable's stack trace + StackTraceElement[] elements = t.getStackTrace(); + for (StackTraceElement e : elements) { + sb.append(indent).append(indent).append("<frame>").append( //$NON-NLS-1$ + lineSeperator); + sb.append(indent).append(indent).append(indent).append( + "<class>").append(e.getClassName()).append("</class>") //$NON-NLS-1$//$NON-NLS-2$ + .append(lineSeperator); + sb.append(indent).append(indent).append(indent).append( + "<method>").append(e.getMethodName()).append( //$NON-NLS-1$ + "</method>").append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(indent).append(indent) + .append("<line>").append(e.getLineNumber()).append( //$NON-NLS-1$ + "</line>").append(lineSeperator); //$NON-NLS-1$ + sb.append(indent).append(indent).append("</frame>").append( //$NON-NLS-1$ + lineSeperator); + } + sb.append(indent).append("</exception>").append(lineSeperator); //$NON-NLS-1$ + } + } + + /** + * Return the header string for XML, use given handler's encoding if has, + * other wise use default platform encoding + * + * @param h the given handler + * @return the header string for XML + */ + @Override + public String getHead(Handler h) { + String encoding = null; + if(null != h) { + encoding = h.getEncoding(); + } + if (null == encoding) { + encoding = getSystemProperty("file.encoding"); //$NON-NLS-1$ + } + StringBuilder sb = new StringBuilder(); + sb.append("<?xml version=\"1.0\" encoding=\"").append(encoding).append( //$NON-NLS-1$ + "\" standalone=\"no\"?>").append(lineSeperator); //$NON-NLS-1$ + sb.append("<!DOCTYPE log SYSTEM \"logger.dtd\">").append(lineSeperator); //$NON-NLS-1$ + sb.append(("<log>")); //$NON-NLS-1$ + return sb.toString(); + } + + /** + * Return the tail string for XML + * + * @param h the given handler + * @return the tail string for XML + */ + @Override + @SuppressWarnings("unused") + public String getTail(Handler h) { + return "</log>"; //$NON-NLS-1$ + } + + //use privilege code to get system property + private static String getSystemProperty(final String key) { + return AccessController.doPrivileged( + new PrivilegedAction<String>() { + public String run() { + return System.getProperty(key); + } + }); + } + +} + + diff --git a/logging/src/main/java/java/util/logging/logging.properties b/logging/src/main/java/java/util/logging/logging.properties new file mode 100644 index 0000000..f99fe3f --- /dev/null +++ b/logging/src/main/java/java/util/logging/logging.properties @@ -0,0 +1,65 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +#------------------------------------------------------------------------------ +# Default logging property file. +# This file is used by java.util.logging package as default settings, users can +# specify another file instead with java.util.logging.config.file system +# property, this property can be set via the Preference API, or as VM arguments +# passed to "java" command, or as property definition passed to JNI_CreateJavaVM. +# You can refer to JavaDoc of java.util.logging package for more information +# about this file. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Global settings +#------------------------------------------------------------------------------ + +# Specify default level for global logger, the event whose level is below won't +# be logged. You can specify level for every logger, otherwise the level of parent +# logger will be used. You can also set the level for every handler, as below for +# java.util.logging.ConsoleHandler. +.level=INFO + +# Specify handler classes list, these classes will be instantiated during the +# logging framework initialization. The list should be white space separated. +# For example, use the line below to add SocketHandler. Note that the handler +# classes must be in the classpath. +# +# handlers=java.util.logging.ConsoleHandler java.util.logging.SocketHandler +# +handlers=java.util.logging.ConsoleHandler + +# Specify a class names list, these classes' default constructor will be executed +# during logging package initialization, which may contain some code to set the +# logging configuration. The list should be white space separated, and the +# classes must be in the classpath. +# +# config= + + +#------------------------------------------------------------------------------ +# Handler settings +#------------------------------------------------------------------------------ + +# The properties below are samples for handler settings. +#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter +#java.util.logging.ConsoleHandler.level=INFO +#java.util.logging.FileHandler.limit=100000 +#java.util.logging.FileHandler.count=1 +#java.util.logging.FileHandler.formatter=java.util.logging.XMLFormatter +#java.util.logging.FileHandler.pattern=%h/java%u.log + diff --git a/logging/src/main/java/java/util/logging/package.html b/logging/src/main/java/java/util/logging/package.html new file mode 100644 index 0000000..4cc90c9 --- /dev/null +++ b/logging/src/main/java/java/util/logging/package.html @@ -0,0 +1,9 @@ +<html> + <body> + <p> + This package allows to add logging to any application. It + supports different levels of importance of a message that needs to be + logged. Later the output can be filtered by this level. + </p> + </body> +</html> diff --git a/logging/src/main/java/org/apache/harmony/logging/internal/nls/Messages.java b/logging/src/main/java/org/apache/harmony/logging/internal/nls/Messages.java new file mode 100644 index 0000000..e052773 --- /dev/null +++ b/logging/src/main/java/org/apache/harmony/logging/internal/nls/Messages.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * THE FILE HAS BEEN AUTOGENERATED BY MSGTOOL TOOL. + * All changes made to this file manually will be overwritten + * if this tool runs again. Better make changes in the template file. + */ + +package org.apache.harmony.logging.internal.nls; + + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.harmony.kernel.vm.VM; +import org.apache.harmony.luni.util.MsgHelp; + +/** + * This class retrieves strings from a resource bundle and returns them, + * formatting them with MessageFormat when required. + * <p> + * It is used by the system classes to provide national language support, by + * looking up messages in the <code> + * org.apache.harmony.logging.internal.nls.messages + * </code> + * resource bundle. Note that if this file is not available, or an invalid key + * is looked up, or resource bundle support is not available, the key itself + * will be returned as the associated message. This means that the <em>KEY</em> + * should a reasonable human-readable (english) string. + * + */ +public class Messages { + + private static final String sResource = + "org.apache.harmony.logging.internal.nls.messages"; //$NON-NLS-1$ + + /** + * Retrieves a message which has no arguments. + * + * @param msg + * String the key to look up. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg) { + return MsgHelp.getString(sResource, msg); + } + + /** + * Retrieves a message which takes 1 argument. + * + * @param msg + * String the key to look up. + * @param arg + * Object the object to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, Object arg) { + return getString(msg, new Object[] { arg }); + } + + /** + * Retrieves a message which takes 1 integer argument. + * + * @param msg + * String the key to look up. + * @param arg + * int the integer to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, int arg) { + return getString(msg, new Object[] { Integer.toString(arg) }); + } + + /** + * Retrieves a message which takes 1 character argument. + * + * @param msg + * String the key to look up. + * @param arg + * char the character to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, char arg) { + return getString(msg, new Object[] { String.valueOf(arg) }); + } + + /** + * Retrieves a message which takes 2 arguments. + * + * @param msg + * String the key to look up. + * @param arg1 + * Object an object to insert in the formatted output. + * @param arg2 + * Object another object to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, Object arg1, Object arg2) { + return getString(msg, new Object[] { arg1, arg2 }); + } + + /** + * Retrieves a message which takes several arguments. + * + * @param msg + * String the key to look up. + * @param args + * Object[] the objects to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, Object[] args) { + return MsgHelp.getString(sResource, msg, args); + } +} diff --git a/logging/src/main/java/org/apache/harmony/logging/internal/nls/messages.properties b/logging/src/main/java/org/apache/harmony/logging/internal/nls/messages.properties new file mode 100644 index 0000000..da3945e --- /dev/null +++ b/logging/src/main/java/org/apache/harmony/logging/internal/nls/messages.properties @@ -0,0 +1,52 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# messages for EN locale +logging.0=This method is not currently implemented. +logging.1=Invalid level name: {0}. +logging.10=Cannot load target handler:{0} +logging.11=Size must be positive. +logging.12=Invalid property value for +logging.13=The encoding "{0}" is not supported. +logging.14=Exception occurred when writing to the output stream. +logging.15=Exception occurred when closing the output stream. +logging.16=Exception occurred while flushing the output stream. +logging.17=Exception occurred while formatting the log record. +logging.18=Exception occurred while logging the record. +logging.19=Pattern cannot be empty +logging.1A=Error happened when open log file. +logging.1B=The limit and count property must be larger than 0 and 1, respectively +logging.1C=The 'name' parameter is null. +logging.1D=Cannot parse this name: {0} +logging.1E=Error message - {0} +logging.1F=Exception - {0} +logging.2=The OutputStream parameter is null +logging.20=Loading class "{0}" failed +logging.21=There Can Be Only One logging MX bean. +logging.22=Exception occurred while getting the logging MX bean. +logging.3=The Formatter parameter is null. +logging.4=The 'level' parameter is null. +logging.5=Different version - {0}.{1} +logging.6=Name must be "control". +logging.7=Actions must be either null or the empty string. +logging.8=Failed to load the specified resource bundle "{0}". +logging.9=The specified resource bundle name "{0}" is inconsistent with the existing one "{1}". +logging.A=The 'handler' parameter is null. +logging.B=The 'parent' parameter is null. +logging.C=Illegal host argument. +logging.D=Illegal port argument. +logging.E=Failed to establish the network connection. +logging.F=Exception occured when closing the socket handler. diff --git a/logging/src/test/java/java/util/logging/LoggerExtension.java b/logging/src/test/java/java/util/logging/LoggerExtension.java new file mode 100644 index 0000000..c31984b --- /dev/null +++ b/logging/src/test/java/java/util/logging/LoggerExtension.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.util.logging; + +import java.util.ResourceBundle; + +/** + * Example of a type injected into logging to access package private members. + */ +public class LoggerExtension { + + public static ResourceBundle loadResourceBundle(String resourceBundleName) { + return Logger.loadResourceBundle(resourceBundleName); + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/AllTests.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/AllTests.java new file mode 100644 index 0000000..ee4a932 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/AllTests.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + */ +public class AllTests { + + public static Test suite() { + TestSuite suite = new TestSuite( + "Suite for org.apache.harmony.logging.tests.java.util.logging"); + // $JUnit-BEGIN$ + suite.addTestSuite(ConsoleHandlerTest.class); + suite.addTestSuite(ErrorManagerTest.class); + suite.addTestSuite(FileHandlerTest.class); + suite.addTestSuite(FilterTest.class); + suite.addTestSuite(FormatterTest.class); + suite.addTestSuite(HandlerTest.class); + suite.addTestSuite(LevelTest.class); + suite.addTestSuite(LoggerTest.class); + suite.addTestSuite(LoggingPermissionTest.class); + suite.addTestSuite(LogManagerTest.class); + suite.addTestSuite(LogRecordTest.class); + suite.addTestSuite(MemoryHandlerTest.class); + suite.addTestSuite(SimpleFormatterTest.class); + suite.addTestSuite(SocketHandlerTest.class); + suite.addTestSuite(StreamHandlerTest.class); + suite.addTestSuite(XMLFormatterTest.class); + // $JUnit-END$ + return suite; + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/ConsoleHandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/ConsoleHandlerTest.java new file mode 100644 index 0000000..bb9717d --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/ConsoleHandlerTest.java @@ -0,0 +1,583 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.security.Permission; +import java.util.Properties; +import java.util.logging.ConsoleHandler; +import java.util.logging.Filter; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.LoggingPermission; +import java.util.logging.SimpleFormatter; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; + +import tests.util.CallVerificationStack; + +/** + * Test class java.util.logging.ConsoleHandler + */ +public class ConsoleHandlerTest extends TestCase { + + private final static String INVALID_LEVEL = "impossible_level"; + + private final PrintStream err = System.err; + + private OutputStream errSubstituteStream = null; + + private static String className = ConsoleHandlerTest.class.getName(); + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + errSubstituteStream = new MockOutputStream(); + System.setErr(new PrintStream(errSubstituteStream)); + LogManager.getLogManager().reset(); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + super.tearDown(); + LogManager.getLogManager().reset(); + CallVerificationStack.getInstance().clear(); + System.setErr(err); + } + + /* + * Test the constructor with no relevant log manager properties are set. + */ + public void testConstructor_NoProperties() { + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.level")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.filter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.formatter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.encoding")); + + ConsoleHandler h = new ConsoleHandler(); + assertSame(h.getLevel(), Level.INFO); + assertTrue(h.getFormatter() instanceof SimpleFormatter); + assertNull(h.getFilter()); + assertSame(h.getEncoding(), null); + } + + /* + * Test the constructor with insufficient privilege. + */ + public void testConstructor_InsufficientPrivilege() { + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.level")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.filter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.formatter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.encoding")); + + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + // set a normal value + try { + ConsoleHandler h = new ConsoleHandler(); + assertSame(h.getLevel(), Level.INFO); + assertTrue(h.getFormatter() instanceof SimpleFormatter); + assertNull(h.getFilter()); + assertSame(h.getEncoding(), null); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test the constructor with valid relevant log manager properties are set. + */ + public void testConstructor_ValidProperties() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.level", "FINE"); + p.put("java.util.logging.ConsoleHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.ConsoleHandler.encoding", "iso-8859-1"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.level"), "FINE"); + assertEquals(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.encoding"), "iso-8859-1"); + ConsoleHandler h = new ConsoleHandler(); + assertSame(h.getLevel(), Level.parse("FINE")); + assertTrue(h.getFormatter() instanceof MockFormatter); + assertTrue(h.getFilter() instanceof MockFilter); + assertEquals(h.getEncoding(), "iso-8859-1"); + } + + /* + * Test the constructor with invalid relevant log manager properties are + * set. + */ + public void testConstructor_InvalidProperties() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.level", INVALID_LEVEL); + p.put("java.util.logging.ConsoleHandler.filter", className); + p.put("java.util.logging.ConsoleHandler.formatter", className); + p.put("java.util.logging.ConsoleHandler.encoding", "XXXX"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.level"), INVALID_LEVEL); + assertEquals(LogManager.getLogManager().getProperty( + "java.util.logging.ConsoleHandler.encoding"), "XXXX"); + ConsoleHandler h = new ConsoleHandler(); + assertSame(h.getLevel(), Level.INFO); + assertTrue(h.getFormatter() instanceof SimpleFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + h.publish(new LogRecord(Level.SEVERE, "test")); + assertNull(h.getEncoding()); + } + + /* + * Test close() when having sufficient privilege, and a record has been + * written to the output stream. + */ + public void testClose_SufficientPrivilege_NormalClose() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + h.publish(new LogRecord(Level.SEVERE, + "testClose_SufficientPrivilege_NormalClose msg")); + h.close(); + assertEquals("flush", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + assertNull(CallVerificationStack.getInstance().pop()); + h.close(); + } + + /* + * Test close() when having sufficient privilege, and an output stream that + * always throws exceptions. + */ + public void testClose_SufficientPrivilege_Exception() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + + h.publish(new LogRecord(Level.SEVERE, + "testClose_SufficientPrivilege_Exception msg")); + h.flush(); + h.close(); + } + + /* + * Test close() when having sufficient privilege, and no record has been + * written to the output stream. + */ + public void testClose_SufficientPrivilege_DirectClose() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + + h.close(); + assertEquals("flush", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + assertNull(CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test close() when having insufficient privilege. + */ + public void testClose_InsufficientPrivilege() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + h.close(); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test publish(), use no filter, having output stream, normal log record. + */ + public void testPublish_NoFilter() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_NoFilter"); + h.setLevel(Level.INFO); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter", + this.errSubstituteStream.toString()); + + h.setLevel(Level.WARNING); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter", + this.errSubstituteStream.toString()); + + h.setLevel(Level.CONFIG); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter" + + "testPublish_NoFilter", this.errSubstituteStream.toString()); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter" + + "testPublish_NoFilter", this.errSubstituteStream.toString()); + } + + /* + * Test publish(), after system err is reset. + */ + public void testPublish_AfterResetSystemErr() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + h.setFilter(new MockFilter()); + + System.setErr(new PrintStream(new ByteArrayOutputStream())); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_WithFilter"); + h.setLevel(Level.INFO); + h.publish(r); + assertNull(CallVerificationStack.getInstance().pop()); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertEquals("", this.errSubstituteStream.toString()); + } + + /* + * Test publish(), use a filter, having output stream, normal log record. + */ + public void testPublish_WithFilter() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + h.setFilter(new MockFilter()); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_WithFilter"); + h.setLevel(Level.INFO); + h.publish(r); + assertNull(CallVerificationStack.getInstance().pop()); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertEquals("", this.errSubstituteStream.toString()); + + h.setLevel(Level.WARNING); + h.publish(r); + assertNull(CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + assertEquals("", this.errSubstituteStream.toString()); + + h.setLevel(Level.CONFIG); + h.publish(r); + assertNull(CallVerificationStack.getInstance().pop()); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertEquals("", this.errSubstituteStream.toString()); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + h.publish(r); + assertNull(CallVerificationStack.getInstance().pop()); + assertEquals("", this.errSubstituteStream.toString()); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test publish(), null log record, having output stream, spec said + * rather than throw exception, handler should call errormanager to handle + * exception case, so NullPointerException shouldn't be thrown. + */ + public void testPublish_Null() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + h.publish(null); + } + + /* + * Test publish(), a log record with empty msg, having output stream + */ + public void testPublish_EmptyMsg() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + LogRecord r = new LogRecord(Level.INFO, ""); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head", this.errSubstituteStream.toString()); + } + + /* + * Test publish(), a log record with null msg, having output stream + */ + public void testPublish_NullMsg() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + LogRecord r = new LogRecord(Level.INFO, null); + h.publish(r); + h.flush(); + // assertEquals("MockFormatter_Head", + // this.errSubstituteStream.toString()); + } + + public void testPublish_AfterClose() throws Exception { + PrintStream backup = System.err; + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + System.setErr(new PrintStream(bos)); + Properties p = new Properties(); + p.put("java.util.logging.ConsoleHandler.level", "FINE"); + p.put("java.util.logging.ConsoleHandler.formatter", className + + "$MockFormatter"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + ConsoleHandler h = new ConsoleHandler(); + assertSame(h.getLevel(), Level.FINE); + LogRecord r1 = new LogRecord(Level.INFO, "testPublish_Record1"); + LogRecord r2 = new LogRecord(Level.INFO, "testPublish_Record2"); + assertTrue(h.isLoggable(r1)); + h.publish(r1); + assertTrue(bos.toString().indexOf("testPublish_Record1") >= 0); + h.close(); + // assertFalse(h.isLoggable(r)); + assertTrue(h.isLoggable(r2)); + h.publish(r2); + assertTrue(bos.toString().indexOf("testPublish_Record2") >= 0); + h.flush(); + // assertEquals("MockFormatter_Head", + // this.errSubstituteStream.toString()); + } catch (IOException e) { + e.printStackTrace(); + } finally { + System.setErr(backup); + } + } + + /* + * Test setOutputStream() under normal condition. + */ + public void testSetOutputStream_Normal() { + MockStreamHandler h = new MockStreamHandler(); + h.setFormatter(new MockFormatter()); + + LogRecord r = new LogRecord(Level.INFO, "testSetOutputStream_Normal"); + h.publish(r); + assertNull(CallVerificationStack.getInstance().pop()); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal", + this.errSubstituteStream.toString()); + + ByteArrayOutputStream aos2 = new ByteArrayOutputStream(); + h.setOutputStream(aos2); + + // assertEquals("close", DelegationParameterStack.getInstance() + // .getCurrentSourceMethod()); + // assertNull(DelegationParameterStack.getInstance().pop()); + // assertEquals("flush", DelegationParameterStack.getInstance() + // .getCurrentSourceMethod()); + // assertNull(DelegationParameterStack.getInstance().pop()); + // assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal" + // + "MockFormatter_Tail", this.errSubstituteStream.toString()); + // r = new LogRecord(Level.INFO, "testSetOutputStream_Normal2"); + // h.publish(r); + // assertSame(r, DelegationParameterStack.getInstance().pop()); + // assertTrue(DelegationParameterStack.getInstance().empty()); + // assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal2", + // aos2 + // .toString()); + // assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal" + // + "MockFormatter_Tail", this.errSubstituteStream.toString()); + } + + /* + * A mock filter, always return false. + */ + public static class MockFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + CallVerificationStack.getInstance().push(record); + // System.out.println("filter called..."); + return false; + } + } + + /* + * A mock formatter. + */ + public static class MockFormatter extends Formatter { + public String format(LogRecord r) { + // System.out.println("formatter called..."); + return super.formatMessage(r); + } + + /* + * (non-Javadoc) + * + * @see java.util.logging.Formatter#getHead(java.util.logging.Handler) + */ + public String getHead(Handler h) { + return "MockFormatter_Head"; + } + + /* + * (non-Javadoc) + * + * @see java.util.logging.Formatter#getTail(java.util.logging.Handler) + */ + public String getTail(Handler h) { + return "MockFormatter_Tail"; + } + } + + /* + * A mock output stream. + */ + public static class MockOutputStream extends ByteArrayOutputStream { + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#close() + */ + public void close() throws IOException { + CallVerificationStack.getInstance().push(null); + super.close(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#flush() + */ + public void flush() throws IOException { + CallVerificationStack.getInstance().push(null); + super.flush(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#write(int) + */ + public void write(int oneByte) { + // TODO Auto-generated method stub + super.write(oneByte); + } + } + + /* + * Used to grant all permissions except logging control. + */ + public static class MockSecurityManager extends SecurityManager { + + public MockSecurityManager() { + } + + public void checkPermission(Permission perm) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + + public void checkPermission(Permission perm, Object context) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + } + + /* + * A mock stream handler, expose setOutputStream. + */ + public static class MockStreamHandler extends ConsoleHandler { + public MockStreamHandler() { + super(); + } + + public void setOutputStream(OutputStream out) { + super.setOutputStream(out); + } + + public boolean isLoggable(LogRecord r) { + CallVerificationStack.getInstance().push(r); + return super.isLoggable(r); + } + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/ErrorManagerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/ErrorManagerTest.java new file mode 100644 index 0000000..dec61fb --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/ErrorManagerTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.logging.ErrorManager; + +import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream; + +import junit.framework.TestCase; + +public class ErrorManagerTest extends TestCase { + + + private final PrintStream err = System.err; + + private OutputStream errSubstituteStream = null; + + public void setUp() throws Exception{ + super.setUp(); + errSubstituteStream = new NullOutputStream(); + System.setErr(new PrintStream(errSubstituteStream)); + } + + public void tearDown() throws Exception{ + System.setErr(err); + super.tearDown(); + } + + public void test_errorStringStringint() { + ErrorManager em = new ErrorManager(); + em.error(null, new NullPointerException(), ErrorManager.GENERIC_FAILURE); + em.error("An error message.", null, ErrorManager.GENERIC_FAILURE); + em.error(null, null, ErrorManager.GENERIC_FAILURE); + } + + public void test_constants() { + assertEquals(3, ErrorManager.CLOSE_FAILURE); + assertEquals(2, ErrorManager.FLUSH_FAILURE); + assertEquals(5, ErrorManager.FORMAT_FAILURE); + assertEquals(0, ErrorManager.GENERIC_FAILURE); + assertEquals(4, ErrorManager.OPEN_FAILURE); + assertEquals(1, ErrorManager.WRITE_FAILURE); + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java new file mode 100644 index 0000000..745c560 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java @@ -0,0 +1,866 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FilePermission; +import java.io.FileReader; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Reader; +import java.io.StringWriter; +import java.security.Permission; +import java.util.Properties; +import java.util.logging.FileHandler; +import java.util.logging.Filter; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.LoggingPermission; +import java.util.logging.XMLFormatter; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream; +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; + +/** + */ +public class FileHandlerTest extends TestCase { + + static LogManager manager = LogManager.getLogManager(); + + final static Properties props = new Properties(); + + final static String className = FileHandlerTest.class.getName(); + + final static StringWriter writer = new StringWriter(); + + final static SecurityManager securityManager = new MockLogSecurityManager(); + + final static String HOMEPATH = System.getProperty("user.home"); + + final static String TEMPPATH = System.getProperty("java.io.tmpdir"); + + final static String SEP = File.separator; + + private final PrintStream err = System.err; + + private OutputStream errSubstituteStream = null; + + FileHandler handler; + + LogRecord r; + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + manager.reset(); + initProps(); + File file = new File(TEMPPATH + SEP + "log"); + file.mkdir(); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new FileHandler(); + r = new LogRecord(Level.CONFIG, "msg"); + errSubstituteStream = new NullOutputStream(); + System.setErr(new PrintStream(errSubstituteStream)); + } + + /** + * + */ + private void initProps() { + props.clear(); + props.put("java.util.logging.FileHandler.level", "FINE"); + props.put("java.util.logging.FileHandler.filter", className + + "$MockFilter"); + props.put("java.util.logging.FileHandler.formatter", className + + "$MockFormatter"); + props.put("java.util.logging.FileHandler.encoding", "iso-8859-1"); + // limit to only two message + props.put("java.util.logging.FileHandler.limit", "1000"); + // rotation count is 2 + props.put("java.util.logging.FileHandler.count", "2"); + // using append mode + props.put("java.util.logging.FileHandler.append", "true"); + props + .put("java.util.logging.FileHandler.pattern", + "%t/log/java%u.test"); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + if (null != handler) { + handler.close(); + } + reset(TEMPPATH + SEP + "log", ""); + System.setErr(err); + super.tearDown(); + } + + public void testLock() throws Exception { + FileOutputStream output = new FileOutputStream(TEMPPATH + SEP + "log" + + SEP + "java1.test.0"); + FileHandler h = new FileHandler(); + h.publish(r); + h.close(); + assertFileContent(TEMPPATH + SEP + "log", "java1.test.0", h + .getFormatter()); + output.close(); + } + + /* + * test for constructor void FileHandler() + */ + public void testFileHandler() throws Exception { + assertEquals("character encoding is non equal to actual value", + "iso-8859-1", handler.getEncoding()); + assertNotNull("Filter is null", handler.getFilter()); + assertNotNull("Formatter is null", handler.getFormatter()); + assertEquals("is non equal to actual value", Level.FINE, handler + .getLevel()); + assertNotNull("ErrorManager is null", handler.getErrorManager()); + handler.publish(r); + handler.close(); + // output 3 times, and all records left + // append mode is true + for (int i = 0; i < 3; i++) { + handler = new FileHandler(); + handler.publish(r); + handler.close(); + } + assertFileContent(TEMPPATH + SEP + "log", "java0.test.0", + new LogRecord[] { r, null, r, null, r, null, r }, + new MockFormatter()); + } + + /* + * test for constructor void FileHandler(String) + */ + public void testFileHandler_1params() throws Exception { + + handler = new FileHandler("%t/log/string"); + assertEquals("character encoding is non equal to actual value", + "iso-8859-1", handler.getEncoding()); + assertNotNull("Filter is null", handler.getFilter()); + assertNotNull("Formatter is null", handler.getFormatter()); + assertEquals("is non equal to actual value", Level.FINE, handler + .getLevel()); + assertNotNull("ErrorManager is null", handler.getErrorManager()); + handler.publish(r); + handler.close(); + + // output 3 times, and all records left + // append mode is true + for (int i = 0; i < 3; i++) { + handler = new FileHandler("%t/log/string"); + handler.publish(r); + handler.close(); + } + assertFileContent(TEMPPATH + SEP + "log", "/string", new LogRecord[] { + r, null, r, null, r, null, r }, new MockFormatter()); + + // test if unique ids not specified, it will append at the end + // no generation number is used + FileHandler h = new FileHandler("%t/log/string"); + FileHandler h2 = new FileHandler("%t/log/string"); + FileHandler h3 = new FileHandler("%t/log/string"); + FileHandler h4 = new FileHandler("%t/log/string"); + h.publish(r); + h2.publish(r); + h3.publish(r); + h4.publish(r); + h.close(); + h2.close(); + h3.close(); + h4.close(); + assertFileContent(TEMPPATH + SEP + "log", "string", h.getFormatter()); + assertFileContent(TEMPPATH + SEP + "log", "string.1", h.getFormatter()); + assertFileContent(TEMPPATH + SEP + "log", "string.2", h.getFormatter()); + assertFileContent(TEMPPATH + SEP + "log", "string.3", h.getFormatter()); + + // default is append mode + FileHandler h6 = new FileHandler("%t/log/string%u.log"); + h6.publish(r); + h6.close(); + FileHandler h7 = new FileHandler("%t/log/string%u.log"); + h7.publish(r); + h7.close(); + try { + assertFileContent(TEMPPATH + SEP + "log", "string0.log", h + .getFormatter()); + fail("should assertion failed"); + } catch (Error e) { + } + File file = new File(TEMPPATH + SEP + "log"); + assertTrue("length list of file is incorrect", file.list().length <= 2); + + // test unique ids + FileHandler h8 = new FileHandler("%t/log/%ustring%u.log"); + h8.publish(r); + FileHandler h9 = new FileHandler("%t/log/%ustring%u.log"); + h9.publish(r); + h9.close(); + h8.close(); + assertFileContent(TEMPPATH + SEP + "log", "0string0.log", h + .getFormatter()); + assertFileContent(TEMPPATH + SEP + "log", "1string1.log", h + .getFormatter()); + file = new File(TEMPPATH + SEP + "log"); + assertTrue("length list of file is incorrect", file.list().length <= 2); + } + + /* + * test for constructor void FileHandler(String pattern, boolean append) + */ + public void testFileHandler_2params() throws Exception { + boolean append = false; + do { + append = !append; + handler = new FileHandler("%t/log/string", append); + assertEquals("character encoding is non equal to actual value", + "iso-8859-1", handler.getEncoding()); + assertNotNull("Filter is null", handler.getFilter()); + assertNotNull("Formatter is null", handler.getFormatter()); + assertEquals("is non equal to actual value", Level.FINE, handler + .getLevel()); + assertNotNull("ErrorManager is null", handler.getErrorManager()); + handler.publish(r); + handler.close(); + // output 3 times, and all records left + // append mode is true + for (int i = 0; i < 3; i++) { + handler = new FileHandler("%t/log/string", append); + handler.publish(r); + handler.close(); + } + if (append) { + assertFileContent(TEMPPATH + SEP + "log", "/string", + new LogRecord[] { r, null, r, null, r, null, r }, + new MockFormatter()); + } else { + assertFileContent(TEMPPATH + SEP + "log", "/string", + new LogRecord[] { r }, new MockFormatter()); + } + } while (append); + } + + /* + * test for constructor void FileHandler(String pattern, int limit, int + * count) + */ + public void testFileHandler_3params() throws Exception { + int limit = 120; + int count = 1; + handler = new FileHandler("%t/log/string", limit, count); + assertEquals("character encoding is non equal to actual value", + "iso-8859-1", handler.getEncoding()); + assertNotNull("Filter is null", handler.getFilter()); + assertNotNull("Formatter is null", handler.getFormatter()); + assertEquals("is non equal to actual value", Level.FINE, handler + .getLevel()); + assertNotNull("ErrorManager is null", handler.getErrorManager()); + handler.publish(r); + handler.close(); + // output 3 times, and all records left + // append mode is true + for (int i = 0; i < 3; i++) { + handler = new FileHandler("%t/log/string", limit, count); + handler.publish(r); + handler.close(); + } + assertFileContent(TEMPPATH + SEP + "log", "/string", new LogRecord[] { + r, null, r, null, r, null, r }, new MockFormatter()); + } + + /* + * test for constructor public FileHandler(String pattern, int limit, int + * count, boolean append) + */ + public void testFileHandler_4params() throws Exception { + int limit = 120; + int count = 1; + boolean append = false; + do { + append = !append; + handler = new FileHandler("%t/log/string", limit, count, append); + assertEquals("character encoding is non equal to actual value", + "iso-8859-1", handler.getEncoding()); + assertNotNull("Filter is null", handler.getFilter()); + assertNotNull("Formatter is null", handler.getFormatter()); + assertEquals("is non equal to actual value", Level.FINE, handler + .getLevel()); + assertNotNull("ErrorManager is null", handler.getErrorManager()); + handler.publish(r); + handler.close(); + // output 3 times, and all records left + // append mode is true + for (int i = 0; i < 3; i++) { + handler = new FileHandler("%t/log/string", limit, count, append); + handler.publish(r); + handler.close(); + } + if (append) { + assertFileContent(TEMPPATH + SEP + "log", "/string", + new LogRecord[] { r, null, r, null, r, null, r }, + new MockFormatter()); + } else { + assertFileContent(TEMPPATH + SEP + "log", "/string", + new LogRecord[] { r }, new MockFormatter()); + } + } while (append); + } + + public void testDefaultValue() throws Exception { + handler.publish(r); + handler.close(); + props.clear(); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new FileHandler(); + assertNull(handler.getEncoding()); + assertNull(handler.getFilter()); + assertTrue(handler.getFormatter() instanceof XMLFormatter); + assertEquals(handler.getLevel(), Level.ALL); + assertNotNull(handler.getErrorManager()); + handler.publish(r); + handler.close(); + // output 3 times, and only one record left + // default append mode is false + for (int i = 0; i < 3; i++) { + handler = new FileHandler(); + handler.publish(r); + handler.close(); + } + assertFileContent(HOMEPATH, "java0.log", new XMLFormatter()); + } + + private void assertFileContent(String homepath, String filename, + Formatter formatter) throws Exception { + assertFileContent(homepath, filename, new LogRecord[] { r }, formatter); + } + + private void assertFileContent(String homepath, String filename, + LogRecord[] lr, Formatter formatter) throws Exception { + handler.close(); + String msg = ""; + // if formatter is null, the file content should be empty + // else the message should be formatted given records + if (null != formatter) { + StringBuffer sb = new StringBuffer(); + sb.append(formatter.getHead(handler)); + for (int i = 0; i < lr.length; i++) { + if (null == lr[i] && i < lr.length - 1) { + // if one record is null and is not the last record, means + // here is + // output completion point, should output tail, then output + // head + // (ready for next output) + sb.append(formatter.getTail(handler)); + sb.append(formatter.getHead(handler)); + } else { + sb.append(formatter.format(lr[i])); + } + } + sb.append(formatter.getTail(handler)); + msg = sb.toString(); + } + char[] chars = new char[msg.length()]; + Reader reader = null; + try { + reader = new BufferedReader(new FileReader(homepath + SEP + + filename)); + reader.read(chars); + assertEquals(msg, new String(chars)); + // assert has reached the end of the file + assertEquals(-1, reader.read()); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (Exception e) { + // don't care + } + reset(homepath, filename); + } + } + + /** + * Does a cleanup of given file + * + * @param homepath + * @param filename + */ + private void reset(String homepath, String filename) { + File file = null; + try { + file = new File(homepath + SEP + filename); + if (file.isFile()) { + file.delete(); + } else if (file.isDirectory()) { + File[] files = file.listFiles(); + for (int i = 0; i < files.length; i++) { + files[i].delete(); + } + file.delete(); + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + file = new File(homepath + SEP + filename + ".lck"); + file.delete(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void testLimitAndCount() throws Exception { + handler.close(); + // very small limit value, count=2 + // output, rename current output file to the second generation file + // close it and open a new file as rotation output + handler = new FileHandler("%t/testLimitCount%g", 1, 2, false); + handler.publish(r); + handler.close(); + assertFileContent(TEMPPATH, "testLimitCount1", handler.getFormatter()); + + // very small limit value, count=1 + // output once, rotate(equals to nothing output) + handler = new FileHandler("%t/testLimitCount%g", 1, 1, false); + handler.publish(r); + handler.close(); + assertFileContent(TEMPPATH, "testLimitCount0", new LogRecord[0], + handler.getFormatter()); + + // normal case, limit is 60(>2*msg length <3*msg length), append is + // false + handler = new FileHandler("%t/testLimitCount%u", 60, 3, false); + LogRecord[] rs = new LogRecord[10]; + // batch output twice to test the append mode + for (int i = 0; i < 5; i++) { + rs[i] = new LogRecord(Level.SEVERE, "msg" + i); + handler.publish(rs[i]); + } + handler.close(); + handler = new FileHandler("%t/testLimitCount%u", 60, 3, false); + for (int i = 5; i < 10; i++) { + rs[i] = new LogRecord(Level.SEVERE, "msg" + i); + handler.publish(rs[i]); + } + + assertFileContent(TEMPPATH, "testLimitCount0.1", new LogRecord[] { + rs[5], rs[6], rs[7] }, handler.getFormatter()); + assertFileContent(TEMPPATH, "testLimitCount0.0", new LogRecord[] { + rs[8], rs[9] }, handler.getFormatter()); + + // normal case, limit is 60(>2*msg length <3*msg length), append is true + handler = new FileHandler("%t/testLimitCount%u", 60, 3, false); + // batch output twice to test the append mode + for (int i = 0; i < 5; i++) { + rs[i] = new LogRecord(Level.SEVERE, "msg" + i); + handler.publish(rs[i]); + } + handler.close(); + handler = new FileHandler("%t/testLimitCount%u", 60, 3, true); + for (int i = 5; i < 10; i++) { + rs[i] = new LogRecord(Level.SEVERE, "msg" + i); + handler.publish(rs[i]); + } + handler.close(); + assertFileContent(TEMPPATH, "testLimitCount0.2", new LogRecord[] { + rs[3], rs[4], null, rs[5] }, handler.getFormatter()); + assertFileContent(TEMPPATH, "testLimitCount0.1", new LogRecord[] { + rs[6], rs[7], rs[8] }, handler.getFormatter()); + assertFileContent(TEMPPATH, "testLimitCount0.0", + new LogRecord[] { rs[9] }, handler.getFormatter()); + + FileHandler h1 = null; + FileHandler h2 = null; + try { + File logDir = new File("log"); + reset("log", ""); + logDir.mkdir(); + h1 = new FileHandler("log/a", 0, 1); + assertNotNull(h1); + h2 = new FileHandler("log/a", 0, 1, false); + assertNotNull(h2); + } finally { + try { + h1.close(); + } catch (Exception e) { + } + try { + h2.close(); + } catch (Exception e) { + } + reset("log", ""); + } + } + + public void testSecurity() throws IOException { + SecurityManager currentManager = System.getSecurityManager(); + + try { + System.setSecurityManager(new MockLogSecurityManager()); + try { + handler.close(); + fail("should throw security exception"); + } catch (SecurityException e) { + } + + handler.publish(new LogRecord(Level.SEVERE, "msg")); + try { + handler = new FileHandler(); + fail("should throw security exception"); + } catch (SecurityException e) { + } + + try { + handler = new FileHandler("pattern1"); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler = new FileHandler("pattern2", true); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler = new FileHandler("pattern3", 1000, 1); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler = new FileHandler("pattern4", 1000, 1, true); + fail("should throw security exception"); + } catch (SecurityException e) { + } + } finally { + System.setSecurityManager(currentManager); + } + + } + + public void testFileSecurity() throws IOException { + SecurityManager currentManager = System.getSecurityManager(); + + try { + System.setSecurityManager(new MockFileSecurityManager()); + handler.publish(new LogRecord(Level.SEVERE, "msg")); + try { + handler.close(); + fail("should throw security exception"); + } catch (SecurityException e) { + } + + try { + handler = new FileHandler(); + fail("should throw security exception"); + } catch (SecurityException e) { + } + + try { + handler = new FileHandler("pattern1"); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler = new FileHandler("pattern2", true); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler = new FileHandler("pattern3", 1000, 1); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler = new FileHandler("pattern4", 1000, 1, true); + fail("should throw security exception"); + } catch (SecurityException e) { + } + } finally { + System.setSecurityManager(currentManager); + } + } + + public void testInvalidProperty() throws Exception { + props.put("java.util.logging.FileHandler.level", "null"); + props.put("java.util.logging.FileHandler.filter", className + + "$MockFilte"); + props.put("java.util.logging.FileHandler.formatter", className + + "$MockFormatte"); + props.put("java.util.logging.FileHandler.encoding", "ut"); + // limit to only two message + props.put("java.util.logging.FileHandler.limit", "-1"); + // rotation count is 2 + props.put("java.util.logging.FileHandler.count", "-1"); + // using append mode + props.put("java.util.logging.FileHandler.append", "bad"); + + handler.close(); + + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new FileHandler(); + assertEquals(Level.ALL, handler.getLevel()); + assertNull(handler.getFilter()); + assertTrue(handler.getFormatter() instanceof XMLFormatter); + assertNull(handler.getEncoding()); + handler.close(); + + props.put("java.util.logging.FileHandler.pattern", ""); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + try { + handler = new FileHandler(); + fail("shouldn't open file with empty name"); + } catch (NullPointerException e) { + } + } + + public void testInvalidParams() throws IOException { + + // %t and %p parsing can add file separator automatically + FileHandler h1 = new FileHandler("%taaa"); + h1.close(); + File file = new File(TEMPPATH + SEP + "aaa"); + assertTrue(file.exists()); + reset(TEMPPATH, "aaa"); + + // always parse special pattern + try { + h1 = new FileHandler("%t/%h"); + } catch (Exception e) { + fail("Unexpected exception " + e.toString()); + } + h1 = new FileHandler("%t%g"); + h1.close(); + file = new File(TEMPPATH + SEP + "0"); + assertTrue(file.exists()); + reset(TEMPPATH, "0"); + h1 = new FileHandler("%t%u%g"); + h1.close(); + file = new File(TEMPPATH + SEP + "00"); + assertTrue(file.exists()); + reset(TEMPPATH, "00"); + + // this is normal case + h1 = new FileHandler("%t/%u%g%%g"); + h1.close(); + file = new File(TEMPPATH + SEP + "00%g"); + assertTrue(file.exists()); + reset(TEMPPATH, "00%g"); + + // multi separator has no effect + h1 = new FileHandler("//%t//multi%g"); + h1.close(); + file = new File(TEMPPATH + SEP + "multi0"); + assertTrue(file.exists()); + reset(TEMPPATH, "multi0"); + + // bad directory, IOException + try { + h1 = new FileHandler("%t/baddir/multi%g"); + fail("should throw IO exception"); + } catch (IOException e) { + } + file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0"); + assertFalse(file.exists()); + + try { + new FileHandler(null); + fail("should throw null exception"); + } catch (NullPointerException e) { + } + try { + handler.publish(null); + } catch (NullPointerException e) { + fail("should not throw NPE"); + } + try { + new FileHandler(null, false); + fail("should throw null exception"); + } catch (NullPointerException e) { + } + try { + // regression test for Harmony-1299 + new FileHandler(""); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + try { + new FileHandler("%t/java%u", 0, 0); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + new FileHandler("%t/java%u", -1, 1); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } + + /* + * test for method public void publish(LogRecord record) + */ + public void testPublish() throws Exception { + LogRecord[] r = new LogRecord[] { new LogRecord(Level.CONFIG, "msg__"), + new LogRecord(Level.WARNING, "message"), + new LogRecord(Level.INFO, "message for"), + new LogRecord(Level.FINE, "message for test") }; + for (int i = 0; i < r.length; i++) { + handler = new FileHandler("%t/log/stringPublish"); + handler.publish(r[i]); + handler.close(); + assertFileContent(TEMPPATH + SEP + "log", "stringPublish", + new LogRecord[] { r[i] }, handler.getFormatter()); + } + } + + /* + * test for method public void close() + */ + public void testClose() throws Exception { + FileHandler h = new FileHandler("%t/log/stringPublish"); + h.publish(r); + h.close(); + assertFileContent(TEMPPATH + SEP + "log", "stringPublish", h + .getFormatter()); + } + + // set output stream still works, just like super StreamHandler + public void testSetOutputStream() throws Exception { + MockFileHandler handler = new MockFileHandler("%h/setoutput.log"); + handler.setFormatter(new MockFormatter()); + handler.publish(r); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + handler.publicSetOutputStream(out); + handler.publish(r); + handler.close(); + String msg = new String(out.toByteArray()); + Formatter f = handler.getFormatter(); + assertEquals(msg, f.getHead(handler) + f.format(r) + f.getTail(handler)); + assertFileContent(HOMEPATH, "setoutput.log", handler.getFormatter()); + } + + public void testEmptyPattern_3params() throws SecurityException, + IOException { + // regression HARMONY-2421 + try { + new FileHandler(new String(), 1, 1); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + public void testEmptyPattern_2params() throws SecurityException, + IOException { + // regression HARMONY-2421 + try { + new FileHandler(new String(), true); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + public void testEmptyPattern_4params() throws SecurityException, + IOException { + // regression HARMONY-2421 + try { + new FileHandler(new String(), 1, 1, true); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + /* + * mock classes + */ + public static class MockFilter implements Filter { + public boolean isLoggable(LogRecord record) { + return !record.getMessage().equals("false"); + } + } + + public static class MockFormatter extends Formatter { + public String format(LogRecord r) { + if (null == r) { + return ""; + } + return r.getMessage() + " by MockFormatter\n"; + } + + public String getTail(Handler h) { + return "tail\n"; + } + + public String getHead(Handler h) { + return "head\n"; + } + } + + public static class MockLogSecurityManager extends SecurityManager { + public void checkPermission(Permission perm) { + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + return; + } + } + + public static class MockFileSecurityManager extends SecurityManager { + public void checkPermission(Permission perm) { + if (perm instanceof FilePermission) { + throw new SecurityException(); + } + } + } + + public static class MockFileHandler extends FileHandler { + public MockFileHandler() throws IOException { + super(); + } + + public MockFileHandler(String pattern) throws IOException { + super(pattern); + } + + public void publicSetOutputStream(OutputStream stream) { + super.setOutputStream(stream); + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FilterTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FilterTest.java new file mode 100644 index 0000000..710d757 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FilterTest.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.util.logging.Filter; +import java.util.logging.LogRecord; + +import junit.framework.TestCase; + +/** + * This testcase verifies the signature of the interface Filter. + * + */ +public class FilterTest extends TestCase { + public void testFilter() { + MockFilter f = new MockFilter(); + f.isLoggable(null); + } + + /* + * This inner class implements the interface Filter to verify the signature. + */ + private class MockFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + return false; + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FormatterTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FormatterTest.java new file mode 100644 index 0000000..0012035 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FormatterTest.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.logging.FileHandler; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import junit.framework.TestCase; + +public class FormatterTest extends TestCase { + Formatter f; + + LogRecord r; + + FileHandler h; + + static String MSG = "msg, pls. ignore it"; + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + f = new MockFormatter(); + r = new LogRecord(Level.FINE, MSG); + h = new FileHandler(); + } + + /* + * test for constructor protected Formatter() + */ + public void testFormatter() { + Formatter formatter; + formatter = new MockFormatter(); + assertEquals("head string is not empty", "", formatter.getHead(null)); + assertEquals("tail string is not empty", "", formatter.getTail(null)); + } + + public void testFormat() { + assertEquals("format", f.format(r)); + } + + /* + * test for method public String getHead(Handler h) + */ + public void testGetHead() { + assertEquals("head string is not empty", "", f.getHead(null)); + assertEquals("head string is not empty", "", f.getHead(h)); + h.publish(r); + assertEquals("head string is not empty", "", f.getHead(h)); + } + + /* + * test for method public String getTail(Handler h) + */ + public void testGetTail() { + assertEquals("tail string is not empty", "", f.getTail(null)); + assertEquals("tail string is not empty", "", f.getTail(h)); + h.publish(r); + assertEquals("tail string is not empty", "", f.getTail(h)); + } + + public void testFormatMessage() { + assertEquals(MSG, f.formatMessage(r)); + + String pattern = "test formatter {0, number}"; + r.setMessage(pattern); + assertEquals(pattern, f.formatMessage(r)); + + Object[] oa = new Object[0]; + r.setParameters(oa); + assertEquals(pattern, f.formatMessage(r)); + + oa = new Object[] { new Integer(100), new Float(1.1) }; + r.setParameters(oa); + assertEquals(MessageFormat.format(pattern, oa), f.formatMessage(r)); + + r.setMessage(MSG); + assertEquals(MSG, f.formatMessage(r)); + + pattern = "wrong pattern {0, asdfasfd}"; + r.setMessage(pattern); + assertEquals(pattern, f.formatMessage(r)); + + pattern = "pattern without 0 {1, number}"; + r.setMessage(pattern); + assertEquals(MessageFormat.format(pattern, oa), f.formatMessage(r)); + + pattern = null; + r.setMessage(pattern); + assertNull(f.formatMessage(r)); + } + + public void testLocalizedFormatMessage() { + // normal case + r.setMessage("msg"); + ResourceBundle rb = ResourceBundle + .getBundle("bundles/java/util/logging/res"); + r.setResourceBundle(rb); + assertEquals(rb.getString("msg"), f.formatMessage(r)); + + // local message is a pattern + r.setMessage("pattern"); + Object[] oa = new Object[] { new Integer(3) }; + r.setParameters(oa); + assertEquals(MessageFormat.format(rb.getString("pattern"), oa), f + .formatMessage(r)); + + // key is a pattern, but local message is not + r.setMessage("pattern{0,number}"); + oa = new Object[] { new Integer(3) }; + r.setParameters(oa); + assertEquals(rb.getString("pattern{0,number}"), f.formatMessage(r)); + + // another bundle + rb = ResourceBundle.getBundle("bundles/java/util/logging/res", + Locale.US); + r.setMessage("msg"); + r.setResourceBundle(rb); + assertEquals(rb.getString("msg"), f.formatMessage(r)); + + // cannot find local message in bundle + r.setMessage("msg without locale"); + assertEquals("msg without locale", f.formatMessage(r)); + + // set bundle name but not bundle + r.setResourceBundle(null); + r.setResourceBundleName("bundles/java/util/logging/res"); + r.setMessage("msg"); + assertEquals("msg", f.formatMessage(r)); + } + + public static class MockFormatter extends Formatter { + + public String format(LogRecord arg0) { + return "format"; + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/HandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/HandlerTest.java new file mode 100644 index 0000000..9edfb83 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/HandlerTest.java @@ -0,0 +1,595 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.security.Permission; +import java.util.Properties; +import java.util.logging.ErrorManager; +import java.util.logging.Filter; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.LoggingPermission; +import java.util.logging.SimpleFormatter; + +import junit.framework.TestCase; +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; +import tests.util.CallVerificationStack; + +/** + * Test suite for the class java.util.logging.Handler. + * + */ +public class HandlerTest extends TestCase { + private static String className = HandlerTest.class.getName(); + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + super.tearDown(); + CallVerificationStack.getInstance().clear(); + } + + /** + * Constructor for HandlerTest. + * + * @param arg0 + */ + public HandlerTest(String arg0) { + super(arg0); + } + + /* + * Test the constructor. + */ + public void testConstructor() { + MockHandler h = new MockHandler(); + assertSame(h.getLevel(), Level.ALL); + assertNull(h.getFormatter()); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + assertTrue(h.getErrorManager() instanceof ErrorManager); + } + + /* + * Test the constructor, with properties set + */ + public void testConstructor_Properties() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.MockHandler.level", "FINE"); + p + .put("java.util.logging.MockHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.Handler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.MockHandler.encoding", "utf-8"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals(LogManager.getLogManager().getProperty( + "java.util.logging.MockHandler.level"), "FINE"); + assertEquals(LogManager.getLogManager().getProperty( + "java.util.logging.MockHandler.encoding"), "utf-8"); + MockHandler h = new MockHandler(); + assertSame(h.getLevel(), Level.ALL); + assertNull(h.getFormatter()); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + assertTrue(h.getErrorManager() instanceof ErrorManager); + LogManager.getLogManager().reset(); + } + + /* + * Abstract method, no test needed. + */ + public void testClose() { + MockHandler h = new MockHandler(); + h.close(); + } + + /* + * Abstract method, no test needed. + */ + public void testFlush() { + MockHandler h = new MockHandler(); + h.flush(); + } + + /* + * Abstract method, no test needed. + */ + public void testPublish() { + MockHandler h = new MockHandler(); + h.publish(null); + } + + /* + * Test getEncoding & setEncoding methods with supported encoding. + */ + public void testGetSetEncoding_Normal() throws Exception { + MockHandler h = new MockHandler(); + h.setEncoding("iso-8859-1"); + assertEquals("iso-8859-1", h.getEncoding()); + } + + /* + * Test getEncoding & setEncoding methods with null. + */ + public void testGetSetEncoding_Null() throws Exception { + MockHandler h = new MockHandler(); + h.setEncoding(null); + assertNull(h.getEncoding()); + } + + /* + * Test getEncoding & setEncoding methods with unsupported encoding. + */ + public void testGetSetEncoding_Unsupported() { + MockHandler h = new MockHandler(); + try { + h.setEncoding("impossible"); + fail("Should throw UnsupportedEncodingException!"); + } catch (UnsupportedEncodingException e) { + } + assertNull(h.getEncoding()); + } + + /* + * Test setEncoding with insufficient privilege. + */ + public void testSetEncoding_InsufficientPrivilege() throws Exception { + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + // set a normal value + try { + h.setEncoding("iso-8859-1"); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + assertNull(h.getEncoding()); + System.setSecurityManager(new MockSecurityManager()); + // set an invalid value + try { + + h.setEncoding("impossible"); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + assertNull(h.getEncoding()); + } + + /* + * Test getErrorManager & setErrorManager methods with non-null value. + */ + public void testGetSetErrorManager_Normal() throws Exception { + MockHandler h = new MockHandler(); + ErrorManager man = new ErrorManager(); + h.setErrorManager(man); + assertSame(man, h.getErrorManager()); + } + + /* + * Test getErrorManager & setErrorManager methods with null. + */ + public void testGetSetErrorManager_Null() throws Exception { + MockHandler h = new MockHandler(); + // test set null + try { + h.setErrorManager(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + + // test reset null + try { + h.setErrorManager(new ErrorManager()); + h.setErrorManager(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test getErrorManager with insufficient privilege. + */ + public void testGetErrorManager_InsufficientPrivilege() throws Exception { + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + h.getErrorManager(); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setErrorManager with insufficient privilege. + */ + public void testSetErrorManager_InsufficientPrivilege() throws Exception { + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + // set null + try { + + h.setErrorManager(null); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + // set a normal value + System.setSecurityManager(new MockSecurityManager()); + try { + + h.setErrorManager(new ErrorManager()); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getFilter & setFilter methods with non-null value. + */ + public void testGetSetFilter_Normal() throws Exception { + MockHandler h = new MockHandler(); + Filter f = new MockFilter(); + h.setFilter(f); + assertSame(f, h.getFilter()); + } + + /* + * Test getFilter & setFilter methods with null. + */ + public void testGetSetFilter_Null() throws Exception { + MockHandler h = new MockHandler(); + // test set null + h.setFilter(null); + + // test reset null + h.setFilter(new MockFilter()); + h.setFilter(null); + } + + /* + * Test setFilter with insufficient privilege. + */ + public void testSetFilter_InsufficientPrivilege() throws Exception { + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + // set null + try { + + h.setFilter(null); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + // set a normal value + System.setSecurityManager(new MockSecurityManager()); + try { + + h.setFilter(new MockFilter()); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getFormatter & setFormatter methods with non-null value. + */ + public void testGetSetFormatter_Normal() throws Exception { + MockHandler h = new MockHandler(); + Formatter f = new SimpleFormatter(); + h.setFormatter(f); + assertSame(f, h.getFormatter()); + } + + /* + * Test getFormatter & setFormatter methods with null. + */ + public void testGetSetFormatter_Null() throws Exception { + MockHandler h = new MockHandler(); + // test set null + try { + h.setFormatter(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + + // test reset null + try { + h.setFormatter(new SimpleFormatter()); + h.setFormatter(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test setFormatter with insufficient privilege. + */ + public void testSetFormatter_InsufficientPrivilege() throws Exception { + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + // set null + try { + + h.setFormatter(null); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + // set a normal value + System.setSecurityManager(new MockSecurityManager()); + try { + + h.setFormatter(new SimpleFormatter()); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getLevel & setLevel methods with non-null value. + */ + public void testGetSetLevel_Normal() throws Exception { + MockHandler h = new MockHandler(); + Level f = Level.CONFIG; + h.setLevel(f); + assertSame(f, h.getLevel()); + } + + /* + * Test getLevel & setLevel methods with null. + */ + public void testGetSetLevel_Null() throws Exception { + MockHandler h = new MockHandler(); + // test set null + try { + h.setLevel(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + + // test reset null + try { + h.setLevel(Level.CONFIG); + h.setLevel(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test setLevel with insufficient privilege. + */ + public void testSetLevel_InsufficientPrivilege() throws Exception { + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + // set null + try { + + h.setLevel(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } finally { + System.setSecurityManager(oldMan); + } + // set a normal value + System.setSecurityManager(new MockSecurityManager()); + try { + + h.setLevel(Level.CONFIG); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Use no filter + */ + public void testIsLoggable_NoFilter() { + MockHandler h = new MockHandler(); + LogRecord r = new LogRecord(Level.CONFIG, null); + assertTrue(h.isLoggable(r)); + + h.setLevel(Level.CONFIG); + assertTrue(h.isLoggable(r)); + + h.setLevel(Level.SEVERE); + assertFalse(h.isLoggable(r)); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + assertFalse(h.isLoggable(r)); + } + + /* + * Use a filter + */ + public void testIsLoggable_WithFilter() { + MockHandler h = new MockHandler(); + LogRecord r = new LogRecord(Level.CONFIG, null); + h.setFilter(new MockFilter()); + assertFalse(h.isLoggable(r)); + + h.setLevel(Level.CONFIG); + assertFalse(h.isLoggable(r)); + assertSame(r, CallVerificationStack.getInstance().pop()); + + h.setLevel(Level.SEVERE); + assertFalse(h.isLoggable(r)); + assertSame(r, CallVerificationStack.getInstance().pop()); + } + + /** + * @tests java.util.logging.Handler#isLoggable(LogRecord) + */ + public void testIsLoggable_Null() { + MockHandler h = new MockHandler(); + try { + h.isLoggable(null); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + // expected + } + } + + /* + * Test whether the error manager is actually called with expected + * parameters. + */ + public void testReportError() { + MockHandler h = new MockHandler(); + h.setErrorManager(new MockErrorManager()); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + Exception ex = new Exception("test exception"); + // with non-null parameters + h.reportError("test msg", ex, -1); + assertEquals(-1, CallVerificationStack.getInstance().popInt()); + assertSame(ex, CallVerificationStack.getInstance().pop()); + assertEquals("test msg", CallVerificationStack.getInstance().pop()); + // with null parameters + h.reportError(null, null, 0); + assertEquals(0, CallVerificationStack.getInstance().popInt()); + assertSame(null, CallVerificationStack.getInstance().pop()); + assertNull(CallVerificationStack.getInstance().pop()); + } catch (SecurityException e) { + fail("Should not throw SecurityException!"); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Used to enable the testing of Handler because Handler is an abstract + * class. + */ + public static class MockHandler extends Handler { + + public void close() { + } + + public void flush() { + } + + public void publish(LogRecord record) { + } + + public void reportError(String msg, Exception ex, int code) { + super.reportError(msg, ex, code); + } + } + + /* + * Used to grant all permissions except logging control. + */ + public static class MockSecurityManager extends SecurityManager { + + public MockSecurityManager() { + } + + public void checkPermission(Permission perm) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + + public void checkPermission(Permission perm, Object context) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + } + + /* + * A mock filter, always return false. + */ + public static class MockFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + CallVerificationStack.getInstance().push(record); + return false; + } + } + + /* + * A mock error manager, used to validate the expected method is called with + * the expected parameters. + */ + public static class MockErrorManager extends ErrorManager { + + public void error(String msg, Exception ex, int errorCode) { + CallVerificationStack.getInstance().push(msg); + CallVerificationStack.getInstance().push(ex); + CallVerificationStack.getInstance().push(errorCode); + } + } + + public static class NullOutputStream extends OutputStream{ + @Override + public void write(int arg0) throws IOException { + } + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LevelTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LevelTest.java new file mode 100644 index 0000000..7f1fc5a --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LevelTest.java @@ -0,0 +1,440 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.Serializable; +import java.util.ResourceBundle; +import java.util.logging.Level; + +import junit.framework.TestCase; + +import org.apache.harmony.testframework.serialization.SerializationTest; +import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert; + +/* + * This class implements Serializable, so that the non-static inner class + * MockLevel can be Serializable. + */ +public class LevelTest extends TestCase implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Test the constructor without resource bundle parameter using normal + * values. As byproducts, getName & intValue are also tested. + */ + public void testConstructorNoResBundle_Normal() { + MockLevel l = new MockLevel("level1", 1); + assertEquals("level1", l.getName()); + assertEquals(1, l.intValue()); + assertNull(l.getResourceBundleName()); + } + + /** + * Test the constructor without resource bundle parameter using null name. + * As byproducts, getName & intValue are also tested. + */ + public void testConstructorNoResBundle_NullName() { + try { + new MockLevel(null, -2); + fail("No expected NullPointerException"); + } catch (NullPointerException ignore) { + // expected + } + } + + /* + * Test the constructor without resource bundle parameter using empty name. + * As byproducts, getName & intValue are also tested. + */ + public void testConstructorNoResBundle_EmptyName() { + MockLevel l = new MockLevel("", -3); + assertEquals("", l.getName()); + assertEquals(-3, l.intValue()); + assertNull(l.getResourceBundleName()); + } + + /* + * Test the constructor having resource bundle parameter using normal + * values. As byproducts, getName & intValue are also tested. + */ + public void testConstructorHavingResBundle_Normal() { + MockLevel l = new MockLevel("level1", 1, "resourceBundle"); + assertEquals("level1", l.getName()); + assertEquals(1, l.intValue()); + assertEquals("resourceBundle", l.getResourceBundleName()); + } + + /* + * Test the constructor having resource bundle parameter using null names. + * As byproducts, getName & intValue are also tested. + */ + public void testConstructorHavingResBundle_NullName() { + try { + new MockLevel(null, -123, "qwe"); + fail("No expected NullPointerException"); + } catch (NullPointerException ignore) { + // expected + } + } + + /* + * Test the constructor having resource bundle parameter using empty + names. + * As byproducts, getName & intValue are also tested. + */ + public void testConstructorHavingResBundle_EmptyName() { + MockLevel l = new MockLevel("", -1000, ""); + assertEquals("", l.getName()); + assertEquals(-1000, l.intValue()); + assertEquals("", l.getResourceBundleName()); + } + + /* + * Test method parse, with the pre-defined string consts. + */ + public void testParse_PredefinedConstStrings() { + assertSame(Level.SEVERE, Level.parse("SEVERE")); + assertSame(Level.WARNING, Level.parse("WARNING")); + assertSame(Level.INFO, Level.parse("INFO")); + assertSame(Level.CONFIG, Level.parse("CONFIG")); + assertSame(Level.FINE, Level.parse("FINE")); + assertSame(Level.FINER, Level.parse("FINER")); + assertSame(Level.FINEST, Level.parse("FINEST")); + assertSame(Level.OFF, Level.parse("OFF")); + assertSame(Level.ALL, Level.parse("ALL")); + } + + /* + * Test method parse, with an undefined string. + */ + public void testParse_IllegalConstString() { + try { + Level.parse("SEVERe"); + fail("Should throw IllegalArgumentException if undefined string."); + } catch (IllegalArgumentException e) { + // expected + } + } + + /* + * Test method parse, with a null string. + */ + public void testParse_NullString() { + try { + Level.parse(null); + fail("Should throw NullPointerException."); + } catch (NullPointerException e) { + // expected + } + } + + /* + * Test method parse, with pre-defined valid number strings. + */ + public void testParse_PredefinedNumber() { + assertSame(Level.SEVERE, Level.parse("SEVERE")); + assertSame(Level.WARNING, Level.parse("WARNING")); + assertSame(Level.INFO, Level.parse("INFO")); + assertSame(Level.CONFIG, Level.parse("CONFIG")); + assertSame(Level.FINE, Level.parse("FINE")); + assertSame(Level.FINER, Level.parse("FINER")); + assertSame(Level.FINEST, Level.parse("FINEST")); + assertSame(Level.OFF, Level.parse("OFF")); + assertSame(Level.ALL, Level.parse("ALL")); + assertSame(Level.SEVERE, Level.parse("1000")); + assertSame(Level.WARNING, Level.parse("900")); + assertSame(Level.INFO, Level.parse("800")); + assertSame(Level.CONFIG, Level.parse("700")); + assertSame(Level.FINE, Level.parse("500")); + assertSame(Level.FINER, Level.parse("400")); + assertSame(Level.FINEST, Level.parse("300")); + assertSame(Level.OFF, Level.parse(String.valueOf(Integer.MAX_VALUE))); + assertSame(Level.ALL, Level.parse(String.valueOf(Integer.MIN_VALUE))); + } + + /* + * Test method parse, with an undefined valid number strings. + */ + public void testParse_UndefinedNumber() { + Level l = Level.parse("0"); + assertEquals(0, l.intValue()); + assertEquals("0", l.getName()); + assertNull(l.getResourceBundleName()); + } + + /* + * Test method parse, with an undefined valid number strings with spaces. + */ + public void testParse_UndefinedNumberWithSpaces() { + try { + Level.parse(" 0"); + } catch (IllegalArgumentException e) { + // expected + } + } + + public void testParse_NegativeNumber() { + Level l = Level.parse("-4"); + assertEquals(-4, l.intValue()); + assertEquals("-4", l.getName()); + assertNull(l.getResourceBundleName()); + } + + /* + * Test method parse, expecting the same objects will be returned given the + * same name, even for non-predefined levels. + */ + public void testParse_SameObject() { + Level l = Level.parse("-100"); + assertSame(l, Level.parse("-100")); + } + + /* + * Test method hashCode, with normal fields. + */ + public void testHashCode_Normal() { + assertEquals(100, Level.parse("100").hashCode()); + assertEquals(-1, Level.parse("-1").hashCode()); + assertEquals(0, Level.parse("0").hashCode()); + assertEquals(Integer.MIN_VALUE, Level.parse("ALL").hashCode()); + } + + /* + * Test equals when two objects are equal. + */ + public void testEquals_Equal() { + MockLevel l1 = new MockLevel("level1", 1); + MockLevel l2 = new MockLevel("level2", 1); + assertEquals(l1, l2); + assertEquals(l2, l1); + } + + /* + * Test equals when two objects are not equal. + */ + public void testEquals_NotEqual() { + MockLevel l1 = new MockLevel("level1", 1); + MockLevel l2 = new MockLevel("level1", 2); + assertFalse(l1.equals(l2)); + assertFalse(l2.equals(l1)); + } + + /* + * Test equals when the other object is null. + */ + public void testEquals_Null() { + assertFalse(Level.ALL.equals(null)); + } + + /* + * Test equals when the other object is not an instance of Level. + */ + public void testEquals_NotLevel() { + assertFalse(Level.ALL.equals(new Object())); + } + + /* + * Test equals when the other object is itself. + */ + public void testEquals_Itself() { + assertTrue(Level.ALL.equals(Level.ALL)); + } + + /* + * Test toString of a normal Level. + */ + public void testToString_Normal() { + assertEquals("ALL", Level.ALL.toString()); + + MockLevel l = new MockLevel("name", 2); + assertEquals("name", l.toString()); + + MockLevel emptyLevel = new MockLevel("", 3); + assertEquals("", emptyLevel.toString()); + } + + // comparator for Level objects: + // is used because Level.equals() method only takes into account + // 'level' value but ignores 'name' and 'resourceBundleName' values + private static final SerializableAssert LEVEL_COMPARATOR = new SerializableAssert() { + public void assertDeserialized(Serializable initial, + Serializable deserialized) { + + Level init = (Level) initial; + Level dser = (Level) deserialized; + + assertEquals("Class", init.getClass(), dser.getClass()); + assertEquals("Name", init.getName(), dser.getName()); + assertEquals("Value", init.intValue(), dser.intValue()); + assertEquals("ResourceBundleName", init.getResourceBundleName(), + dser.getResourceBundleName()); + } + }; + + /** + * @tests serialization/deserialization compatibility. + * + * Test serialization of pre-defined const levels. It is expected that the + * deserialized cost level should be the same instance as the existing one. + */ + public void testSerialization_ConstLevel() throws Exception { + + SerializationTest.verifySelf(Level.ALL, + SerializationTest.SAME_COMPARATOR); + } + + /** + * @tests serialization/deserialization compatibility. + * + * Test serialization of normal instance of Level. It is expected that the + * deserialized level object should be equal to the original one. + */ + public void testSerialization_InstanceLevel() throws Exception { + + // tests that objects are the same + Level[] objectsToTest = new Level[] { Level.parse("550")}; + + SerializationTest.verifySelf(objectsToTest, + SerializationTest.SAME_COMPARATOR); + + // tests that objects are the equals + objectsToTest = new Level[] { + new MockLevel("123", 123, "bundle"), + new MockLevel("123", 123, null) }; + + SerializationTest.verifySelf(objectsToTest, LEVEL_COMPARATOR); + } + + /** + * @tests serialization/deserialization compatibility with RI. + */ + public void testSerializationCompatibility() throws Exception { + + SerializationTest.verifyGolden(this, + new MockLevel("123", 123, "bundle"), LEVEL_COMPARATOR); + } + + public void testGetLocalName() { + ResourceBundle rb = ResourceBundle.getBundle("bundles/java/util/logging/res"); + Level l = new MockLevel("level1", 120, + "bundles/java/util/logging/res"); + assertEquals(rb.getString("level1"), l.getLocalizedName()); + + // regression test for HARMONY-2415 + rb = ResourceBundle.getBundle( + "org.apache.harmony.logging.tests.java.util.logging.LevelTestResource"); + l = new MockLevel("Level_error", 120, + "org.apache.harmony.logging.tests.java.util.logging.LevelTestResource"); + assertEquals(rb.getString("Level_error"), l.getLocalizedName()); + + l = new MockLevel("bad name", 120, "res"); + assertEquals("bad name", l.getLocalizedName()); + + l = new MockLevel("level1", 11120, "bad name"); + assertEquals("level1", l.getLocalizedName()); + + l = new MockLevel("level1", 1120); + assertEquals("level1", l.getLocalizedName()); + } + + /* + * test for method public String getResourceBundleName() + */ + public void testGetResourceBundleName() { + String bundleName = "bundles/java/util/logging/res"; + Level l = new MockLevel("level1", 120); + assertNull("level's localization resource bundle name is not null", l + .getResourceBundleName()); + l = new MockLevel("level1", 120, bundleName); + assertEquals("bundleName is non equal to actual value", bundleName, l + .getResourceBundleName()); + l = new MockLevel("level1", 120, bundleName + "+abcdef"); + assertEquals("bundleName is non equal to actual value", bundleName + + "+abcdef", l.getResourceBundleName()); + } + + /* + * test for method public final int intValue() + */ + public void testIntValue() { + int value1 = 120; + Level l = new MockLevel("level1", value1); + assertEquals( + "integer value for this level is non equal to actual value", + value1, l.intValue()); + } + + /* + * Test defining new levels in subclasses of Level + */ + public void testSubclassNewLevel() { + MyLevel.DUPLICATENAME.getName();// just to load MyLevel class + + // test duplicated name and num + assertEquals("INFO", MyLevel.parse("800").getName()); + assertEquals(800, MyLevel.parse("INFO").intValue()); + // test duplicated name + assertEquals("FINE", MyLevel.parse("499").getName()); + assertEquals("FINE", MyLevel.parse("500").getName()); + assertEquals(500, MyLevel.parse("FINE").intValue()); + // test duplicated number + assertEquals("FINEST", MyLevel.parse("300").getName()); + assertEquals(300, MyLevel.parse("FINEST").intValue()); + assertEquals(300, MyLevel.parse("MYLEVEL1").intValue()); + // test a normal new level, without duplicated elements + assertEquals("MYLEVEL2", MyLevel.parse("299").getName()); + assertEquals(299, MyLevel.parse("MYLEVEL2").intValue()); + } + + /* + * This subclass is to test whether subclasses of Level can add new defined + * levels. + */ + static class MyLevel extends Level implements Serializable { + private static final long serialVersionUID = 1L; + + public MyLevel(String name, int value) { + super(name, value); + } + + public static final Level DUPLICATENAMENUM = new MyLevel("INFO", 800); + + public static final Level DUPLICATENAME = new MyLevel("FINE", 499); + + public static final Level DUPLICATENUM = new MyLevel("MYLEVEL1", 300); + + public static final Level NORMAL = new MyLevel("MYLEVEL2", 299); + } + + /* + * This Mock is used to expose the protected constructors. + */ + public class MockLevel extends Level implements Serializable { + + private static final long serialVersionUID = 1L; + + public MockLevel(String name, int value) { + super(name, value); + } + + public MockLevel(String name, int value, String resourceBundleName) { + super(name, value, resourceBundleName); + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LevelTestResource.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LevelTestResource.java new file mode 100644 index 0000000..5e06b70 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LevelTestResource.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.util.ListResourceBundle; + +public class LevelTestResource extends ListResourceBundle { + public Object[][] getContents() { + return contents; + } + + @SuppressWarnings("nls") + static final Object[][] contents = { { "Level_error", "Name" }, + { "Localized", "Localized message" }, }; +}
\ No newline at end of file diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java new file mode 100644 index 0000000..61406ff --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java @@ -0,0 +1,1197 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +//import android.access.IPropertyChangeEvent; +//import android.access.; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.security.Permission; +import java.util.Enumeration; +import java.util.Properties; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.logging.LoggingPermission; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream; +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; + +/** + * + * add/get logger(dot) + * + */ +public class LogManagerTest extends TestCase { + + private static final String FOO = "LogManagerTestFoo"; + + LogManager mockManager; + + LogManager manager = LogManager.getLogManager(); + + // MockPropertyChangeListener listener; + + Properties props; + + private static String className = LogManagerTest.class.getName(); + + static Handler handler = null; + + static final String CONFIG_CLASS = "java.util.logging.config.class"; + + static final String CONFIG_FILE = "java.util.logging.config.file"; + + static final String MANAGER_CLASS = "java.util.logging.config.manager"; + + static final SecurityManager securityManager = System.getSecurityManager(); + + static final String clearPath = System.getProperty("clearpath"); + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + mockManager = new MockLogManager(); + // listener = new MockPropertyChangeListener(); + handler = new MockHandler(); + props = initProps(); + } + + static Properties initProps() throws Exception { + Properties props = new Properties(); + props.put("handlers", className + "$MockHandler " + className + "$MockHandler"); + props.put("java.util.logging.FileHandler.pattern", "%h/java%u.log"); + props.put("java.util.logging.FileHandler.limit", "50000"); + props.put("java.util.logging.FileHandler.count", "5"); + props.put("java.util.logging.FileHandler.formatter", "java.util.logging.XMLFormatter"); + props.put(".level", "FINE"); + props.put("java.util.logging.ConsoleHandler.level", "OFF"); + props + .put("java.util.logging.ConsoleHandler.formatter", + "java.util.logging.SimpleFormatter"); + props.put("LogManagerTestFoo.handlers", "java.util.logging.ConsoleHandler"); + props.put("LogManagerTestFoo.level", "WARNING"); + return props; + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + } + + public void testAddGetLogger() { + Logger log = new MockLogger(FOO, null); + Logger foo = mockManager.getLogger(FOO); + assertNull(foo); + assertTrue(mockManager.addLogger(log)); + foo = mockManager.getLogger(FOO); + assertSame(foo, log); + assertNull(foo.getParent()); + + try { + mockManager.addLogger(null); + fail("add null should throw NullPointerException"); + } catch (NullPointerException e) { + } + + try { + mockManager.getLogger(null); + fail("get null should throw NullPointerException"); + } catch (NullPointerException e) { + } + + assertNull(mockManager.getLogger("bad name")); + + Enumeration<String> enumar = mockManager.getLoggerNames(); + int i = 0; + while (enumar.hasMoreElements()) { + String name = (String)enumar.nextElement(); + i++; + assertEquals(FOO, name); + } + assertEquals(i, 1); + } + + public void testAddGetLogger_duplicateName() { + // add logger with duplicate name has no effect + Logger foo = new MockLogger(FOO, null); + Logger foo2 = new MockLogger(FOO, null); + assertTrue(mockManager.addLogger(foo)); + assertSame(foo, mockManager.getLogger(FOO)); + assertFalse(mockManager.addLogger(foo2)); + assertSame(foo, mockManager.getLogger(FOO)); + Enumeration<String> enumar = mockManager.getLoggerNames(); + int i = 0; + while (enumar.hasMoreElements()) { + enumar.nextElement(); + i++; + } + assertEquals(1, i); + } + + public void testAddGetLogger_Hierachy() { + Logger foo = new MockLogger("testAddGetLogger_Hierachy.foo", null); + Logger child = new MockLogger("testAddGetLogger_Hierachy.foo.child", null); + Logger fakeChild = new MockLogger("testAddGetLogger_Hierachy.foo2.child", null); + Logger grandson = new MockLogger("testAddGetLogger_Hierachy.foo.child.grandson", null); + Logger otherChild = new MockLogger("testAddGetLogger_Hierachy.foo.child", null); + assertNull(foo.getParent()); + assertNull(child.getParent()); + assertNull(grandson.getParent()); + assertNull(otherChild.getParent()); + + // whenever a logger is added to a LogManager, hierarchy will be updated + // accordingly + assertTrue(mockManager.addLogger(child)); + assertNull(child.getParent()); + + assertTrue(mockManager.addLogger(fakeChild)); + assertNull(fakeChild.getParent()); + + assertTrue(mockManager.addLogger(grandson)); + assertSame(child, grandson.getParent()); + + assertTrue(mockManager.addLogger(foo)); + assertSame(foo, child.getParent()); + assertNull(foo.getParent()); + assertNull(fakeChild.getParent()); + + // but for non-mock LogManager, foo's parent should be root + assertTrue(manager.addLogger(foo)); + assertSame(manager.getLogger(""), manager.getLogger("testAddGetLogger_Hierachy.foo") + .getParent()); + + // if we add one logger to two LogManager, parent will changed + assertTrue(manager.addLogger(otherChild)); + assertTrue(manager.addLogger(grandson)); + assertSame(foo, otherChild.getParent()); + assertSame(otherChild, grandson.getParent()); + } + + public void testAddLoggerReverseOrder() { + Logger root = new MockLogger("testAddLoggerReverseOrder", null); + Logger foo = new MockLogger("testAddLoggerReverseOrder.foo", null); + Logger fooChild = new MockLogger("testAddLoggerReverseOrder.foo.child", null); + Logger fooGrandChild = new MockLogger("testAddLoggerReverseOrder.foo.child.grand", null); + Logger fooGrandChild2 = new MockLogger("testAddLoggerReverseOrder.foo.child.grand2", null); + + Logger realRoot = manager.getLogger(""); + + manager.addLogger(fooGrandChild); + assertEquals(realRoot, fooGrandChild.getParent()); + + manager.addLogger(root); + assertSame(root, fooGrandChild.getParent()); + assertSame(realRoot, root.getParent()); + + manager.addLogger(foo); + assertSame(root, foo.getParent()); + assertSame(foo, fooGrandChild.getParent()); + + manager.addLogger(fooGrandChild2); + assertSame(foo, fooGrandChild2.getParent()); + assertSame(foo, fooGrandChild.getParent()); + + manager.addLogger(fooChild); + assertSame(fooChild, fooGrandChild2.getParent()); + assertSame(fooChild, fooGrandChild.getParent()); + assertSame(foo, fooChild.getParent()); + assertSame(root, foo.getParent()); + assertSame(realRoot, root.getParent()); + } + + public void testAddSimiliarLogger() { + Logger root = new MockLogger("testAddSimiliarLogger", null); + Logger foo = new MockLogger("testAddSimiliarLogger.foo", null); + Logger similiarFoo = new MockLogger("testAddSimiliarLogger.fop", null); + Logger fooo = new MockLogger("testAddSimiliarLogger.fooo", null); + Logger fooChild = new MockLogger("testAddSimiliarLogger.foo.child", null); + Logger similiarFooChild = new MockLogger("testAddSimiliarLogger.fop.child", null); + Logger foooChild = new MockLogger("testAddSimiliarLogger.fooo.child", null); + + manager.addLogger(root); + manager.addLogger(fooChild); + manager.addLogger(similiarFooChild); + manager.addLogger(foooChild); + assertSame(root, fooChild.getParent()); + assertSame(root, similiarFooChild.getParent()); + assertSame(root, foooChild.getParent()); + + manager.addLogger(foo); + assertSame(foo, fooChild.getParent()); + assertSame(root, similiarFooChild.getParent()); + assertSame(root, foooChild.getParent()); + + manager.addLogger(similiarFoo); + assertSame(foo, fooChild.getParent()); + assertSame(similiarFoo, similiarFooChild.getParent()); + assertSame(root, foooChild.getParent()); + + manager.addLogger(fooo); + assertSame(fooo, foooChild.getParent()); + } + + public void testAddGetLogger_nameWithSpace() { + Logger foo = new MockLogger(FOO, null); + Logger fooBeforeSpace = new MockLogger(FOO + " ", null); + Logger fooAfterSpace = new MockLogger(" " + FOO, null); + Logger fooWithBothSpace = new MockLogger(" " + FOO + " ", null); + assertTrue(mockManager.addLogger(foo)); + assertTrue(mockManager.addLogger(fooBeforeSpace)); + assertTrue(mockManager.addLogger(fooAfterSpace)); + assertTrue(mockManager.addLogger(fooWithBothSpace)); + + assertSame(foo, mockManager.getLogger(FOO)); + assertSame(fooBeforeSpace, mockManager.getLogger(FOO + " ")); + assertSame(fooAfterSpace, mockManager.getLogger(" " + FOO)); + assertSame(fooWithBothSpace, mockManager.getLogger(" " + FOO + " ")); + } + + public void testAddGetLogger_addRoot() throws IOException { + Logger foo = new MockLogger(FOO, null); + Logger fooChild = new MockLogger(FOO + ".child", null); + Logger other = new MockLogger("other", null); + Logger root = new MockLogger("", null); + assertNull(foo.getParent()); + assertNull(root.getParent()); + assertNull(other.getParent()); + + // add root to mock logmanager and it works as "root" logger + assertTrue(mockManager.addLogger(foo)); + assertTrue(mockManager.addLogger(other)); + assertTrue(mockManager.addLogger(fooChild)); + assertNull(foo.getParent()); + assertNull(other.getParent()); + assertSame(foo, fooChild.getParent()); + + assertTrue(mockManager.addLogger(root)); + assertSame(root, foo.getParent()); + assertSame(root, other.getParent()); + assertNull(root.getParent()); + + // try to add root logger to non-mock LogManager, no effect + assertFalse(manager.addLogger(root)); + assertNotSame(root, manager.getLogger("")); + } + + /** + * @tests java.util.logging.LogManager#addLogger(Logger) + */ + public void test_addLoggerLLogger_Security() throws Exception { + // regression test for Harmony-1286 + SecurityManager originalSecurityManager = System.getSecurityManager(); + System.setSecurityManager(new SecurityManager()); + try { + LogManager manager = LogManager.getLogManager(); + manager.addLogger(new MockLogger("mock", null)); + manager.addLogger(new MockLogger("mock.child", null)); + } finally { + System.setSecurityManager(originalSecurityManager); + } + } + + public void testDefaultLoggerProperties() throws Exception { + // mock LogManager has no default logger + assertNull(mockManager.getLogger("")); + assertNull(mockManager.getLogger("global")); + + // non-mock LogManager has two default logger + Logger global = manager.getLogger("global"); + Logger root = manager.getLogger(""); + + assertSame(global, Logger.global); + assertSame(root, global.getParent()); + + // root properties + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertNull(root.getFilter()); + assertEquals(2, root.getHandlers().length); + assertEquals(Level.FINE, root.getLevel()); + assertEquals("", root.getName()); + assertSame(root.getParent(), null); + assertNull(root.getResourceBundle()); + assertNull(root.getResourceBundleName()); + assertTrue(root.getUseParentHandlers()); + + } + + /* + * test for method public Logger getLogger(String name) + * test covers following usecases: + * case 1: test default and valid value + * case 2: test throw NullPointerException + * case 3: test bad name + * case 4: check correct tested value + */ + public void testGetLogger() throws Exception { + + // case 1: test default and valid value + Logger log = new MockLogger(FOO, null); + Logger foo = mockManager.getLogger(FOO); + assertNull("Logger should be null", foo); + assertTrue("logger was't registered successfully", mockManager.addLogger(log)); + foo = mockManager.getLogger(FOO); + assertSame("two loggers not refer to the same object", foo, log); + assertNull("logger foo should not haven parent", foo.getParent()); + + // case 2: test throw NullPointerException + try { + mockManager.getLogger(null); + fail("get null should throw NullPointerException"); + } catch (NullPointerException e) { + } + + // case 3: test bad name + assertNull("LogManager should not have logger with unforeseen name", mockManager + .getLogger("bad name")); + + // case 4: check correct tested value + Enumeration<String> enumar = mockManager.getLoggerNames(); + int i = 0; + while (enumar.hasMoreElements()) { + String name = (String)enumar.nextElement(); + i++; + assertEquals("name logger should be equal to foreseen name", FOO, name); + } + assertEquals("LogManager should contain one element", 1, i); + } + + /* + * test for method public Logger getLogger(String name) + */ + public void testGetLogger_duplicateName() throws Exception { + // test duplicate name + // add logger with duplicate name has no effect + mockManager.reset(); + Logger foo2 = new MockLogger(FOO, null); + Logger foo3 = new MockLogger(FOO, null); + mockManager.addLogger(foo2); + assertSame(foo2, mockManager.getLogger(FOO)); + mockManager.addLogger(foo3); + assertSame(foo2, mockManager.getLogger(FOO)); + + Enumeration<String> enumar2 = mockManager.getLoggerNames(); + int i = 0; + while (enumar2.hasMoreElements()) { + enumar2.nextElement(); + i++; + } + assertEquals(1, i); + } + + /* + * test for method public Logger getLogger(String name) + */ + public void testGetLogger_hierachy() throws Exception { + // test hierachy + Logger foo = new MockLogger("testGetLogger_hierachy.foo", null); + // but for non-mock LogManager, foo's parent should be root + assertTrue(manager.addLogger(foo)); + assertSame(manager.getLogger(""), manager.getLogger("testGetLogger_hierachy.foo") + .getParent()); + } + + /* + * test for method public Logger getLogger(String name) + */ + public void testGetLogger_nameSpace() throws Exception { + // test name with space + Logger foo = new MockLogger(FOO, null); + Logger fooBeforeSpace = new MockLogger(FOO + " ", null); + Logger fooAfterSpace = new MockLogger(" " + FOO, null); + Logger fooWithBothSpace = new MockLogger(" " + FOO + " ", null); + assertTrue(mockManager.addLogger(foo)); + assertTrue(mockManager.addLogger(fooBeforeSpace)); + assertTrue(mockManager.addLogger(fooAfterSpace)); + assertTrue(mockManager.addLogger(fooWithBothSpace)); + + assertSame(foo, mockManager.getLogger(FOO)); + assertSame(fooBeforeSpace, mockManager.getLogger(FOO + " ")); + assertSame(fooAfterSpace, mockManager.getLogger(" " + FOO)); + assertSame(fooWithBothSpace, mockManager.getLogger(" " + FOO + " ")); + } + + /* + * test for method public void checkAccess() throws SecurityException + */ + public void testCheckAccess() { + try { + manager.checkAccess(); + } catch (SecurityException e) { + fail("securityException should not be thrown"); + } + System.setSecurityManager(new MockSecurityManagerLogPermission()); + mockManager.addLogger(new MockLogger("abc", null)); + mockManager.getLogger(""); + mockManager.getLoggerNames(); + mockManager.getProperty(".level"); + LogManager.getLogManager(); + try { + manager.checkAccess(); + fail("should throw securityException"); + } catch (SecurityException e) { + } + + System.setSecurityManager(securityManager); + } + + public void testLoggingPermission() throws IOException { + System.setSecurityManager(new MockSecurityManagerLogPermission()); + mockManager.addLogger(new MockLogger("abc", null)); + mockManager.getLogger(""); + mockManager.getLoggerNames(); + mockManager.getProperty(".level"); + LogManager.getLogManager(); + try { + manager.checkAccess(); + fail("should throw securityException"); + } catch (SecurityException e) { + } + try { + mockManager.readConfiguration(); + fail("should throw SecurityException"); + } catch (SecurityException e) { + } + try { + mockManager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + fail("should throw SecurityException"); + } catch (SecurityException e) { + } + try { + mockManager.readConfiguration(null); + fail("should throw SecurityException"); + } catch (SecurityException e) { + } + // try { + // mockManager + // .addPropertyChangeListener(new MockPropertyChangeListener()); + // fail("should throw SecurityException"); + // } catch (SecurityException e) { + // } + // try { + // mockManager.addPropertyChangeListener(null); + // fail("should throw NPE"); + // } catch (NullPointerException e) { + // } + // try { + // mockManager.removePropertyChangeListener(null); + // fail("should throw SecurityException"); + // } catch (SecurityException e) { + // } + try { + mockManager.reset(); + fail("should throw SecurityException"); + } catch (SecurityException e) { + } + System.setSecurityManager(securityManager); + } + + public void testMockGetProperty() throws Exception { + // mock manager doesn't read configuration until you call + // readConfiguration() + Logger root = new MockLogger("", null); + assertTrue(mockManager.addLogger(root)); + root = mockManager.getLogger(""); + checkPropertyNull(mockManager); + assertEquals(0, root.getHandlers().length); + assertNull(root.getLevel()); + mockManager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(Level.FINE, root.getLevel()); + checkProperty(mockManager); + mockManager.reset(); + checkPropertyNull(mockManager); + assertEquals(Level.INFO, root.getLevel()); + assertEquals(0, mockManager.getLogger("").getHandlers().length); + } + + public void testGetProperty() throws SecurityException, IOException { + // //FIXME: move it to exec + // manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + // Logger root = manager.getLogger(""); + //// checkProperty(manager); + // assertEquals(Level.FINE, root.getLevel()); + // assertEquals(2, root.getHandlers().length); + + // but non-mock manager DO read it from the very beginning + Logger root = manager.getLogger(""); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + checkProperty(manager); + assertEquals(2, root.getHandlers().length); + assertEquals(Level.FINE, root.getLevel()); + + manager.reset(); + checkPropertyNull(manager); + assertEquals(0, root.getHandlers().length); + assertEquals(Level.INFO, root.getLevel()); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + } + + public void testReadConfiguration_null() throws SecurityException, IOException { + try { + manager.readConfiguration(null); + fail("should throw null pointer exception"); + } catch (NullPointerException e) { + } + + } + + private static void checkPropertyNull(LogManager m) { + // assertNull(m.getProperty(".level")); + assertNull(m.getProperty("java.util.logging.FileHandler.limit")); + assertNull(m.getProperty("java.util.logging.ConsoleHandler.formatter")); + // assertNull(m.getProperty("handlers")); + assertNull(m.getProperty("java.util.logging.FileHandler.count")); + assertNull(m.getProperty("com.xyz.foo.level")); + assertNull(m.getProperty("java.util.logging.FileHandler.formatter")); + assertNull(m.getProperty("java.util.logging.ConsoleHandler.level")); + assertNull(m.getProperty("java.util.logging.FileHandler.pattern")); + } + + private static void checkProperty(LogManager m) { + // assertEquals(m.getProperty(".level"), "INFO"); + assertEquals(m.getProperty("java.util.logging.FileHandler.limit"), "50000"); + assertEquals(m.getProperty("java.util.logging.ConsoleHandler.formatter"), + "java.util.logging.SimpleFormatter"); + // assertEquals(m.getProperty("handlers"), + // "java.util.logging.ConsoleHandler"); + assertEquals(m.getProperty("java.util.logging.FileHandler.count"), "5"); + assertEquals(m.getProperty("LogManagerTestFoo.level"), "WARNING"); + assertEquals(m.getProperty("java.util.logging.FileHandler.formatter"), + "java.util.logging.XMLFormatter"); + assertEquals(m.getProperty("java.util.logging.ConsoleHandler.level"), "OFF"); + assertEquals(m.getProperty("java.util.logging.FileHandler.pattern"), "%h/java%u.log"); + } + + // public void testReadConfiguration() throws SecurityException, IOException { + // FIXME: move the support_exec + // Logger foo = new MockLogger("foo", null); + // assertNull(foo.getLevel()); + // assertTrue(mockManager.addLogger(foo)); + // + // Logger fo = new MockLogger("foo2", null); + // fo.setLevel(Level.ALL); + // assertTrue(mockManager.addLogger(fo)); + // + // Handler h = new ConsoleHandler(); + // Level l = h.getLevel(); + // assertNotSame(Level.OFF, h.getLevel()); + // + // // read configuration + // mockManager.readConfiguration(); + // // level DO has effect + // assertEquals(Level.WARNING, foo.getLevel()); + // // for non specified logger, level is reset to null + // assertNull(fo.getLevel()); + // + // // read properties don't affect handler + // assertNotSame(Level.OFF, h.getLevel()); + // assertSame(l, h.getLevel()); + // + // } + + /* + * Class under test for void readConfiguration(InputStream) + */ + public void testReadConfigurationInputStream() throws IOException { + // mock LogManager + InputStream stream = EnvironmentHelper.PropertiesToInputStream(props); + + Logger foo = new MockLogger(FOO, null); + assertNull(foo.getLevel()); + assertTrue(mockManager.addLogger(foo)); + + Logger fo = new MockLogger("LogManagerTestFoo2", null); + fo.setLevel(Level.ALL); + assertTrue(mockManager.addLogger(fo)); + + Handler h = new ConsoleHandler(); + Level l = h.getLevel(); + assertNotSame(Level.OFF, h.getLevel()); + + // read configuration from stream + mockManager.readConfiguration(stream); + stream.close(); + + // level DO has effect + assertEquals(Level.WARNING, foo.getLevel()); + + // for non specified logger, level is reset to null + assertNull(fo.getLevel()); + + // read properties don't affect handler + assertNotSame(Level.OFF, h.getLevel()); + assertSame(l, h.getLevel()); + } + + public void testReadConfigurationInputStream_null() throws SecurityException, IOException { + try { + mockManager.readConfiguration(null); + fail("should throw null pointer exception"); + } catch (NullPointerException e) { + } + + } + + public void testReadConfigurationInputStream_root() throws IOException { + InputStream stream = EnvironmentHelper.PropertiesToInputStream(props); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + + Logger logger = new MockLogger("testReadConfigurationInputStream_root.foo", null); + Logger root = manager.getLogger(""); + Logger logger2 = Logger.getLogger("testReadConfigurationInputStream_root.foo2"); + + manager.addLogger(logger); + assertNull(logger.getLevel()); + assertEquals(0, logger.getHandlers().length); + assertSame(root, logger.getParent()); + + assertNull(logger2.getLevel()); + assertEquals(0, logger2.getHandlers().length); + assertSame(root, logger2.getParent()); + // if (!hasConfigClass) { + assertEquals(Level.FINE, root.getLevel()); + assertEquals(2, root.getHandlers().length); + // } + + // after read stream + manager.readConfiguration(stream); + assertEquals(Level.FINE, root.getLevel()); + assertEquals(2, root.getHandlers().length); + assertNull(logger.getLevel()); + assertEquals(0, logger.getHandlers().length); + stream.close(); + } + + // public void testAddRemovePropertyChangeListener() throws Exception { + // MockPropertyChangeListener listener1 = new MockPropertyChangeListener(); + // MockPropertyChangeListener listener2 = new MockPropertyChangeListener(); + // // add same listener1 two times + // mockManager.addPropertyChangeListener(listener1); + // mockManager.addPropertyChangeListener(listener1); + // mockManager.addPropertyChangeListener(listener2); + // + // assertNull(listener1.getEvent()); + // assertNull(listener2.getEvent()); + // mockManager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + // // if (!hasConfigClass) { + // assertNotNull(listener1.getEvent()); + // assertNotNull(listener2.getEvent()); + // // } + // + // listener1.reset(); + // listener2.reset(); + // + // // remove listener1, no effect + // mockManager.removePropertyChangeListener(listener1); + // mockManager.readConfiguration(EnvironmentHelper + // .PropertiesToInputStream(props)); + // assertNotNull(listener1.getEvent()); + // assertNotNull(listener2.getEvent()); + // listener1.reset(); + // listener2.reset(); + // + // // remove listener1 again and it works + // mockManager.removePropertyChangeListener(listener1); + // mockManager.readConfiguration(EnvironmentHelper + // .PropertiesToInputStream(props)); + // assertNull(listener1.getEvent()); + // assertNotNull(listener2.getEvent()); + // listener2.reset(); + // + // // reset don't produce event + // mockManager.reset(); + // assertNull(listener2.getEvent()); + // + // mockManager.removePropertyChangeListener(listener2); + // mockManager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + // assertNull(listener1.getEvent()); + // assertNull(listener2.getEvent()); + // } + // + // public void testAddRemovePropertyChangeListener_null() { + // // seems nothing happened + // try{ + // mockManager.addPropertyChangeListener(null); + // fail("Should throw NPE"); + // }catch(NullPointerException e){ + // } + // mockManager.removePropertyChangeListener(null); + // } + + public void testReset() throws SecurityException, IOException { + // mock LogManager + mockManager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertNotNull(mockManager.getProperty("handlers")); + Logger foo = new MockLogger(FOO, null); + assertNull(foo.getLevel()); + assertEquals(0, foo.getHandlers().length); + foo.setLevel(Level.ALL); + foo.addHandler(new ConsoleHandler()); + assertTrue(mockManager.addLogger(foo)); + assertEquals(Level.WARNING, foo.getLevel()); + assertEquals(2, foo.getHandlers().length); + + // reset + mockManager.reset(); + + // properties is cleared + assertNull(mockManager.getProperty("handlers")); + + // level is null + assertNull(foo.getLevel()); + // handlers are all closed + assertEquals(0, foo.getHandlers().length); + + // for root logger + manager.reset(); + assertNull(manager.getProperty("handlers")); + Logger root = manager.getLogger(""); + // level reset to info + assertEquals(Level.INFO, root.getLevel()); + // also close root's handler + assertEquals(0, root.getHandlers().length); + } + + public void testGlobalPropertyConfig() throws Exception { + PrintStream err = System.err; + try { + System.setErr(new PrintStream(new NullOutputStream())); + // before add config property, root has two handler + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(2, manager.getLogger("").getHandlers().length); + + // one valid config class + props.setProperty("config", className + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(3, manager.getLogger("").getHandlers().length); + + // two config class take effect orderly + props.setProperty("config", className + "$MockValidConfig " + className + + "$MockValidConfig2"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(2, manager.getLogger("").getHandlers().length); + + props.setProperty("config", className + "$MockValidConfig2 " + className + + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(3, manager.getLogger("").getHandlers().length); + + // invalid config class which throw exception, just print exception + // and + // message + props.setProperty("config", className + "$MockInvalidConfigException"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + + // invalid config class without default constructor, just print + // exception and message + props.setProperty("config", className + "$MockInvalidConfigNoDefaultConstructor"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + + // bad config class name, just print exception and message + props.setProperty("config", "badname"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + + // invalid separator, nothing happened + props.setProperty("config", className + "$MockValidConfig2;" + className + + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(2, manager.getLogger("").getHandlers().length); + props.setProperty("config", className + "$MockValidConfig2;" + className + + "$MockValidConfig " + className + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(3, manager.getLogger("").getHandlers().length); + + // duplicate config class, take effect twice + props.setProperty("config", className + "$MockValidConfig " + className + + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(4, manager.getLogger("").getHandlers().length); + + // invalid config classes mixed with valid config classes, valid + // config + // classes take effect + props.setProperty("config", "badname " + className + "$MockValidConfig " + className + + "$MockInvalidConfigNoDefaultConstructor " + className + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(4, manager.getLogger("").getHandlers().length); + + // global property take effect before logger specified property + props.setProperty("config", className + "$MockValidConfig"); + manager.readConfiguration(EnvironmentHelper.PropertiesToInputStream(props)); + assertEquals(Level.FINE, manager.getLogger("").getLevel()); + } finally { + System.setErr(err); + } + + } + + public void testValidConfigClass() throws Exception { + String oldProperty = System.getProperty("java.util.logging.config.class"); + try { + // System.setProperty("java.util.logging.config.class", "org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$ConfigClass"); + System.setProperty("java.util.logging.config.class", this.getClass().getName() + + "$ConfigClass"); + assertNull(manager.getLogger("testConfigClass.foo")); + + manager.readConfiguration(); + assertNull(manager.getLogger("testConfigClass.foo")); + Logger l = Logger.getLogger("testConfigClass.foo.child"); + assertSame(Level.FINEST, manager.getLogger("").getLevel()); + assertEquals(0, manager.getLogger("").getHandlers().length); + assertEquals("testConfigClass.foo", l.getParent().getName()); + } finally { + if (oldProperty != null) { + System.setProperty("java.util.logging.config.class", oldProperty); + } + } + } + + // regression for HARMONY-3075 + //??? logging: MX is based on Management package: not supported. + // public void testGetLoggingMXBean() throws Exception{ + // assertNotNull(LogManager.getLoggingMXBean()); + // } + + /* + * ---------------------------------------------------- + * mock classes + * ---------------------------------------------------- + */ + public static class ConfigClass { + public ConfigClass() throws Exception { + LogManager man = LogManager.getLogManager(); + Properties props = LogManagerTest.initProps(); + props.put("testConfigClass.foo.level", "OFF"); + props.put("testConfigClass.foo.handlers", "java.util.logging.ConsoleHandler"); + props.put(".level", "FINEST"); + props.remove("handlers"); + InputStream in = EnvironmentHelper.PropertiesToInputStream(props); + man.readConfiguration(in); + } + } + + public static class MockInvalidInitClass { + public MockInvalidInitClass() { + throw new RuntimeException(); + } + } + + public static class TestInvalidConfigFile { + public static void main(String[] args) { + LogManager manager = LogManager.getLogManager(); + Logger root = manager.getLogger(""); + checkPropertyNull(manager); + assertEquals(0, root.getHandlers().length); + assertEquals(Level.INFO, root.getLevel()); + + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + checkProperty(manager); + assertNull(root.getHandlers()[0].getLevel()); + assertEquals(1, root.getHandlers().length); + assertEquals(Level.INFO, root.getLevel()); + + manager.reset(); + checkProperty(manager); + assertEquals(0, root.getHandlers().length); + assertEquals(Level.INFO, root.getLevel()); + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static class TestValidConfigFile { + public static void main(String[] args) { + LogManager manager = LogManager.getLogManager(); + Logger root = manager.getLogger(""); + checkPropertyNull(manager); + assertEquals(2, root.getHandlers().length); + assertEquals(root.getHandlers()[0].getLevel(), Level.OFF); + assertEquals(Level.ALL, root.getLevel()); + + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + checkPropertyNull(manager); + assertEquals(root.getHandlers()[0].getLevel(), Level.OFF); + assertEquals(2, root.getHandlers().length); + assertEquals(Level.ALL, root.getLevel()); + + manager.reset(); + checkPropertyNull(manager); + assertEquals(0, root.getHandlers().length); + assertEquals(Level.INFO, root.getLevel()); + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static class TestMockLogManager { + public static void main(String[] args) { + LogManager manager = LogManager.getLogManager(); + assertTrue(manager instanceof MockLogManager); + } + } + + public static class TestValidConfigClass { + public static void main(String[] args) { + LogManager manager = LogManager.getLogManager(); + Logger root = manager.getLogger(""); + checkPropertyNull(manager); + assertEquals(1, root.getHandlers().length); + assertEquals(Level.OFF, root.getLevel()); + + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + checkPropertyNull(manager); + assertEquals(1, root.getHandlers().length); + assertEquals(Level.OFF, root.getLevel()); + + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + checkPropertyNull(manager); + assertEquals(1, root.getHandlers().length); + assertEquals(Level.OFF, root.getLevel()); + + manager.reset(); + checkPropertyNull(manager); + assertEquals(0, root.getHandlers().length); + assertEquals(Level.INFO, root.getLevel()); + try { + manager.readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static class MockLogger extends Logger { + public MockLogger(String name, String rbName) { + super(name, rbName); + } + } + + public static class MockLogManager extends LogManager { + } + + public static class MockHandler extends Handler { + static int number = 0; + + public MockHandler() { + addNumber(); + // System.out.println(this + ":start:" + number); + } + + private synchronized void addNumber() { + number++; + } + + public void close() { + minusNumber(); + // System.out.println(this + ":close:" + number); + } + + private synchronized void minusNumber() { + number--; + } + + public void flush() { + // System.out.println(this + ":flush"); + } + + public void publish(LogRecord record) { + } + + } + + public static class MockValidInitClass { + public MockValidInitClass() { + Properties p = new Properties(); + p.put("handlers", className + "$MockHandler"); + p.put(".level", "OFF"); + InputStream in = null; + try { + in = EnvironmentHelper.PropertiesToInputStream(p); + LogManager manager = LogManager.getLogManager(); + manager.readConfiguration(in); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + in.close(); + } catch (Exception e) { + } + } + } + } + + public static class MockValidConfig { + public MockValidConfig() { + handler = new MockHandler(); + LogManager manager = LogManager.getLogManager(); + Logger root = null; + if (null != manager) { + root = manager.getLogger(""); + } else { + System.out.println("null manager"); + } + if (null != root) { + root.addHandler(handler); + root.setLevel(Level.OFF); + } + } + } + + public static class MockValidConfig2 { + + static Logger root = null; + + public MockValidConfig2() { + root = LogManager.getLogManager().getLogger(""); + root.removeHandler(handler); + } + } + + public static class MockInvalidConfigException { + public MockInvalidConfigException() { + throw new RuntimeException("invalid config class - throw exception"); + } + } + + public static class MockInvalidConfigNoDefaultConstructor { + public MockInvalidConfigNoDefaultConstructor(int i) { + throw new RuntimeException("invalid config class - no default constructor"); + } + } + + // public static class MockPropertyChangeListener implements + // IPropertyChangeListener { + // + // IPropertyChangeEvent event = null; + // + // public void propertyChange(IPropertyChangeEvent event) { + // this.event = event; + // } + // + // public IPropertyChangeEvent getEvent() { + // return event; + // } + // + // public void reset() { + // event = null; + // } + // + // } + + public static class MockSecurityManagerLogPermission extends SecurityManager { + + public void checkPermission(Permission permission, Object context) { + if (permission instanceof LoggingPermission) { + throw new SecurityException(); + } + } + + public void checkPermission(Permission permission) { + if (permission instanceof LoggingPermission) { + StackTraceElement[] stack = (new Throwable()).getStackTrace(); + for (int i = 0; i < stack.length; i++) { + if (stack[i].getClassName().equals("java.util.logging.Logger")) { + return; + } + } + throw new SecurityException("Found LogManager checkAccess()"); + } + } + } + + public static class MockSecurityManagerOtherPermission extends SecurityManager { + + public void checkPermission(Permission permission, Object context) { + if (permission instanceof LoggingPermission) { + return; + } + if (permission.getName().equals("setSecurityManager")) { + return; + } + // throw new SecurityException(); + super.checkPermission(permission, context); + } + + public void checkPermission(Permission permission) { + if (permission instanceof LoggingPermission) { + return; + } + if (permission.getName().equals("setSecurityManager")) { + return; + } + super.checkPermission(permission); + } + } + + /* + * Test config class loading + * java -Djava.util.logging.config.class=badConfigClassName ClassLoadingTest + */ + public static class ClassLoadingTest { + public static void main(String[] args) { + Thread.currentThread().setContextClassLoader(new MockErrorClassLoader()); + try { + LogManager.getLogManager(); + fail("Should throw mock error"); + } catch (MockError e) { + } + } + + static class MockErrorClassLoader extends ClassLoader { + public Class<?> loadClass(String name) { + throw new MockError(); + } + } + + static class MockError extends Error { + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java new file mode 100644 index 0000000..5656f6d --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java @@ -0,0 +1,448 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.Serializable; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import junit.framework.TestCase; + +import org.apache.harmony.testframework.serialization.SerializationTest; +import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert; + +public class LogRecordTest extends TestCase { + + static final String MSG = "test msg, pls. ignore itb"; + + private LogRecord lr; + + private static String className = LogRecordTest.class.getName(); + + protected void setUp() throws Exception { + super.setUp(); + lr = new LogRecord(Level.CONFIG, MSG); + + } + + public void testLogRecordWithNullPointers() { + try { + new LogRecord(null, null); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + } + try { + new LogRecord(null, MSG); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + } + LogRecord r = new LogRecord(Level.WARNING, null); + assertSame(r.getLevel(), Level.WARNING); + assertNull(r.getMessage()); + } + + public void testGetSetLoggerName() { + assertNull(lr.getLoggerName()); + lr.setLoggerName(null); + assertNull(lr.getLoggerName()); + lr.setLoggerName("test logger name"); + assertEquals("test logger name", lr.getLoggerName()); + } + + public void testGetSetResourceBundle() { + assertNull(lr.getResourceBundleName()); + assertNull(lr.getResourceBundle()); + + lr.setResourceBundle(null); + assertNull(lr.getResourceBundle()); + + lr.setResourceBundleName("bundles/java/util/logging/res"); + assertNull(lr.getResourceBundle()); + + lr.setResourceBundleName(null); + ResourceBundle rb = ResourceBundle + .getBundle("bundles/java/util/logging/res"); + lr.setResourceBundle(rb); + assertEquals(rb, lr.getResourceBundle()); + assertNull(lr.getResourceBundleName()); + } + + public void testGetSetResourceBundleName() { + assertNull(lr.getResourceBundleName()); + lr.setResourceBundleName(null); + assertNull(lr.getResourceBundleName()); + lr.setResourceBundleName("test"); + assertEquals("test", lr.getResourceBundleName()); + } + + public void testGetSetLevel() { + try { + lr.setLevel(null); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + } + assertSame(lr.getLevel(), Level.CONFIG); + } + + public void testGetSetSequenceNumber() { + long l = lr.getSequenceNumber(); + lr.setSequenceNumber(-111); + assertEquals(lr.getSequenceNumber(), -111L); + lr.setSequenceNumber(0); + assertEquals(lr.getSequenceNumber(), 0L); + lr = new LogRecord(Level.ALL, null); + assertEquals(lr.getSequenceNumber(), l + 1); + } + + public void testGetSetSourceClassName() { + lr.setSourceClassName(null); + assertNull(lr.getSourceClassName()); + lr.setSourceClassName("bad class name"); + assertEquals("bad class name", lr.getSourceClassName()); + lr.setSourceClassName(this.getClass().getName()); + assertEquals(this.getClass().getName(), lr.getSourceClassName()); + } + + public void testGetSetSourceMethodName() { + lr.setSourceMethodName(null); + assertNull(lr.getSourceMethodName()); + lr.setSourceMethodName("bad class name"); + assertEquals("bad class name", lr.getSourceMethodName()); + lr.setSourceMethodName(this.getClass().getName()); + assertEquals(this.getClass().getName(), lr.getSourceMethodName()); + } + + public void testGetSourceDefaultValue() { + assertNull(lr.getSourceMethodName()); + assertNull(lr.getSourceClassName()); + + // find class and method who called logger + Logger logger = Logger.global; + MockHandler handler = new MockHandler(); + logger.addHandler(handler); + logger.log(Level.SEVERE, MSG); + assertEquals(this.getClass().getName(), handler.getSourceClassName()); + assertEquals("testGetSourceDefaultValue", handler.getSourceMethodName()); + + // only set source method to null + lr = new LogRecord(Level.SEVERE, MSG); + lr.setSourceMethodName(null); + logger.log(lr); + assertNull(handler.getSourceClassName()); + assertNull(handler.getSourceMethodName()); + + // only set source class to null + lr = new LogRecord(Level.SEVERE, MSG); + lr.setSourceClassName(null); + logger.log(lr); + assertNull(handler.getSourceClassName()); + assertNull(handler.getSourceMethodName()); + + // set both + lr = new LogRecord(Level.SEVERE, MSG); + lr.setSourceClassName("className"); + lr.setSourceMethodName(null); + logger.log(lr); + assertEquals("className", handler.getSourceClassName()); + assertNull(handler.getSourceMethodName()); + + // test if LogRecord is constructed in another class, and is published + // by Logger + logger.log(RecordFactory.getDefaultRecord()); + assertEquals(this.getClass().getName(), handler.getSourceClassName()); + assertEquals("testGetSourceDefaultValue", handler.getSourceMethodName()); + + lr = RecordFactory.getDefaultRecord(); + // assertNull(lr.getSourceClassName()); + // assertNull(lr.getSourceMethodName()); + RecordFactory.log(logger, lr); + assertEquals(RecordFactory.class.getName(), handler + .getSourceClassName()); + assertEquals("log", handler.getSourceMethodName()); + + // only try once to get the default value + lr = RecordFactory.getDefaultRecord(); + assertNull(lr.getSourceClassName()); + assertNull(lr.getSourceMethodName()); + RecordFactory.log(logger, lr); + assertNull(handler.getSourceClassName()); + assertNull(handler.getSourceMethodName()); + + // it cannot find correct default value when logger is subclass + MockLogger ml = new MockLogger("foo", null); + ml.addHandler(handler); + ml.info(MSG); + assertEquals(className + "$MockLogger", handler.getSourceClassName()); + assertEquals("info", handler.getSourceMethodName()); + + // it can find nothing when only call Subclass + ml = new MockLogger("foo", null); + ml.addHandler(handler); + ml.log(Level.SEVERE, MSG); + assertNull(handler.getSourceClassName()); + assertNull(handler.getSourceMethodName()); + + // test if don't call logger, what is the default value + lr = new LogRecord(Level.SEVERE, MSG); + handler.publish(lr); + assertNull(handler.getSourceClassName()); + assertNull(handler.getSourceMethodName()); + logger.removeHandler(handler); + } + + public void testGetSetMessage() { + assertEquals(MSG, lr.getMessage()); + lr.setMessage(null); + assertNull(lr.getMessage()); + lr.setMessage(""); + assertEquals("", lr.getMessage()); + } + + public void testGetSetParameters() { + assertNull(lr.getParameters()); + lr.setParameters(null); + assertNull(lr.getParameters()); + Object[] oa = new Object[0]; + lr.setParameters(oa); + assertEquals(oa, lr.getParameters()); + oa = new Object[] { new Object(), new Object() }; + lr.setParameters(oa); + assertSame(oa, lr.getParameters()); + } + + public void testGetSetMillis() { + long milli = lr.getMillis(); + assertTrue(milli > 0); + lr.setMillis(-1); + assertEquals(-1, lr.getMillis()); + lr.setMillis(0); + assertEquals(0, lr.getMillis()); + } + + public void testGetSetThreadID() { + // TODO how to test the different thread + int id = lr.getThreadID(); + lr = new LogRecord(Level.ALL, "a1"); + assertEquals(id, lr.getThreadID()); + lr.setThreadID(id + 10); + assertEquals(id + 10, lr.getThreadID()); + lr = new LogRecord(Level.ALL, "a1"); + assertEquals(id, lr.getThreadID()); + } + + public void testGetSetThrown() { + assertNull(lr.getThrown()); + lr.setThrown(null); + assertNull(lr.getThrown()); + Throwable e = new Exception(); + lr.setThrown(e); + assertEquals(e, lr.getThrown()); + } + + // comparator for LogRecord objects + private static final SerializableAssert LOGRECORD_COMPARATOR = new SerializableAssert() { + public void assertDeserialized(Serializable initial, + Serializable deserialized) { + + LogRecord init = (LogRecord) initial; + LogRecord dser = (LogRecord) deserialized; + + assertEquals("Class", init.getClass(), dser.getClass()); + assertEquals("Level", init.getLevel(), dser.getLevel()); + assertEquals("LoggerName", init.getLoggerName(), dser + .getLoggerName()); + assertEquals("Message", init.getMessage(), dser.getMessage()); + assertEquals("Millis", init.getMillis(), dser.getMillis()); + + // compare parameters + Object[] paramInit = init.getParameters(); + Object[] paramDser = dser.getParameters(); + assertEquals("Parameters length", paramInit.length, + paramDser.length); + for (int i = 0; i < paramInit.length; i++) { + assertEquals("Param: " + i, paramInit[i].toString(), + paramDser[i]); + } + + // don't check ResourceBundle object + // verify only bundle's name + assertEquals("ResourceBundleName", init.getResourceBundleName(), + dser.getResourceBundleName()); + assertEquals("SequenceNumber", init.getSequenceNumber(), dser + .getSequenceNumber()); + assertEquals("SourceClassName", init.getSourceClassName(), dser + .getSourceClassName()); + assertEquals("SourceMethodName", init.getSourceMethodName(), dser + .getSourceMethodName()); + assertEquals("ThreadID", init.getThreadID(), dser.getThreadID()); + + SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(init + .getThrown(), dser.getThrown()); + } + }; + + /** + * @tests serialization/deserialization compatibility. + */ + public void testSerializationSelf() throws Exception { + LogRecord r = new LogRecord(Level.ALL, "msg"); + r.setLoggerName("LoggerName"); + r.setMillis(123456789); + r.setResourceBundleName("ResourceBundleName"); + r.setSequenceNumber(987654321); + r.setSourceClassName("SourceClassName"); + r.setSourceMethodName("SourceMethodName"); + r + .setParameters(new Object[] { "test string", + new Exception("ex-msg") }); + r.setThreadID(3232); + r.setThrown(new Exception("ExceptionMessage")); + + SerializationTest.verifySelf(r, LOGRECORD_COMPARATOR); + } + + /** + * @tests resolution of resource bundle for serialization/deserialization. + */ + public void testSerializationResourceBundle() throws Exception { + + // test case: valid resource bundle name + lr.setResourceBundleName("bundles/java/util/logging/res2"); + lr.setResourceBundle(ResourceBundle.getBundle( + "bundles/java/util/logging/res", Locale.US)); + + LogRecord result = (LogRecord) SerializationTest.copySerializable(lr); + assertNotNull(result.getResourceBundle()); + + // test case: invalid resource bundle name, it is not resolved during + // deserialization LogRecord object so check for returned null value + lr.setResourceBundleName("bad bundle name"); + lr.setResourceBundle(ResourceBundle.getBundle( + "bundles/java/util/logging/res", Locale.US)); + + result = (LogRecord) SerializationTest.copySerializable(lr); + assertNull(result.getResourceBundle()); + } + + /** + * @tests serialization/deserialization compatibility with RI. + */ + public void testSerializationCompatibility() throws Exception { + LogRecord r = new LogRecord(Level.ALL, "msg"); + r.setLoggerName("LoggerName"); + r.setMillis(123456789); + r.setResourceBundleName("ResourceBundleName"); + r.setSequenceNumber(987654321); + r.setSourceClassName("SourceClassName"); + r.setSourceMethodName("SourceMethodName"); + r + .setParameters(new Object[] { "test string", + new Exception("ex-msg") }); + r.setThreadID(3232); + r.setThrown(new Exception("ExceptionMessage")); + + SerializationTest.verifyGolden(this, r, LOGRECORD_COMPARATOR); + } + + public static class MockHandler extends Handler { + private String className; + + private String methodName; + + public void close() { + } + + public void flush() { + } + + public void publish(LogRecord record) { + className = record.getSourceClassName(); + methodName = record.getSourceMethodName(); + } + + public String getSourceMethodName() { + return methodName; + } + + public String getSourceClassName() { + return className; + } + } + + // mock class, try to test when the sourceclass and sourcemethod of + // LogRecord is initiated + public static class RecordFactory { + + public static LogRecord getDefaultRecord() { + return new LogRecord(Level.SEVERE, MSG); + } + + public static void log(Logger logger, LogRecord lr) { + logger.log(lr); + } + } + + public static class MockLogger extends Logger { + + /** + * @param name + * @param resourceBundleName + */ + public MockLogger(String name, String resourceBundleName) { + super(name, resourceBundleName); + } + + public void log(Level l, String s) { + this.log(new LogRecord(l, s)); + } + + public void info(String s) { + super.info(s); + } + + public void log(LogRecord record) { + if (isLoggable(record.getLevel())) { + // call the handlers of this logger + // TODO: What if an exception occurred in handler? + Handler[] ha = this.getHandlers(); + for (int i = 0; i < ha.length; i++) { + ha[i].publish(record); + } + // call the parent's handlers if set useParentHandlers + if (getUseParentHandlers()) { + Logger anyParent = this.getParent(); + while (null != anyParent) { + ha = anyParent.getHandlers(); + for (int i = 0; i < ha.length; i++) { + ha[i].publish(record); + } + if (anyParent.getUseParentHandlers()) { + anyParent = anyParent.getParent(); + } else { + break; + } + } + } + } + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerExtension.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerExtension.java new file mode 100644 index 0000000..1828d94 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerExtension.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.util.ResourceBundle; +import java.util.logging.Logger; + +/** + * Example of a type injected into logging to access package private members. + */ +public class LoggerExtension { + + public static ResourceBundle loadResourceBundle(String resourceBundleName) { +// return Logger.loadResourceBundle(resourceBundleName); + return Logger.getAnonymousLogger(resourceBundleName).getResourceBundle(); + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java new file mode 100644 index 0000000..ca9dc1c --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java @@ -0,0 +1,3638 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.File; +import java.io.FileInputStream; +import java.security.Permission; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.logging.Filter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.logging.LoggingPermission; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; + +import tests.util.CallVerificationStack; + +/** + * Test suite for the class java.util.logging.Logger. + * + */ +public class LoggerTest extends TestCase { + + private final static String VALID_RESOURCE_BUNDLE = "bundles/java/util/logging/res"; + + private final static String VALID_RESOURCE_BUNDLE2 = "bundles/java/util/logging/res2"; + + private final static String VALID_RESOURCE_BUNDLE3 = "bundles/java/util/logging/res3"; + + private final static String INVALID_RESOURCE_BUNDLE = "impossible_not_existing"; + + private final static String LOGGING_CONFIG_FILE= "src/test/resources/config/java/util/logging/logging.config"; + + private final static String VALID_KEY = "LOGGERTEST"; + + private final static String VALID_VALUE = "Test_ZH_CN"; + + private final static String VALID_VALUE2 = "Test_NoLocale2"; + + private Logger sharedLogger = null; + + private Locale oldLocale = null; + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + oldLocale = Locale.getDefault(); + Locale.setDefault(new Locale("zh", "CN")); + sharedLogger = new MockLogger("SharedLogger", VALID_RESOURCE_BUNDLE); + sharedLogger.addHandler(new MockHandler()); + } + + /* + * Reset the log manager. + */ + protected void tearDown() throws Exception { + CallVerificationStack.getInstance().clear(); + Locale.setDefault(oldLocale); + super.tearDown(); + } + + /** + * Constructor for LoggerTest. + * + * @param arg0 + */ + public LoggerTest(String arg0) { + super(arg0); + } + + /* + * Test the global logger + */ + public void testGlobalLogger() { + assertNull(Logger.global.getFilter()); + assertEquals(0, Logger.global.getHandlers().length); + assertNull(Logger.global.getLevel()); + assertEquals("global", Logger.global.getName()); + assertNull(Logger.global.getParent().getParent()); + assertNull(Logger.global.getResourceBundle()); + assertNull(Logger.global.getResourceBundleName()); + assertTrue(Logger.global.getUseParentHandlers()); + assertSame(Logger.global, Logger.getLogger("global")); + assertSame(Logger.global, LogManager.getLogManager() + .getLogger("global")); + } + + /* + * Test constructor under normal conditions. + * + * TODO: using a series of class loaders to load resource bundles + */ + public void testConstructor_Normal() { + MockLogger mlog = new MockLogger("myname", VALID_RESOURCE_BUNDLE); + assertNull(mlog.getFilter()); + assertEquals(0, mlog.getHandlers().length); + assertNull(mlog.getLevel()); + assertEquals("myname", mlog.getName()); + assertNull(mlog.getParent()); + ResourceBundle rb = mlog.getResourceBundle(); + assertEquals(VALID_VALUE, rb.getString(VALID_KEY)); + assertEquals(mlog.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + assertTrue(mlog.getUseParentHandlers()); + } + + /* + * Test constructor with null parameters. + */ + public void testConstructor_Null() { + MockLogger mlog = new MockLogger(null, null); + assertNull(mlog.getFilter()); + assertEquals(0, mlog.getHandlers().length); + assertNull(mlog.getLevel()); + assertNull(mlog.getName()); + assertNull(mlog.getParent()); + assertNull(mlog.getResourceBundle()); + assertNull(mlog.getResourceBundleName()); + assertTrue(mlog.getUseParentHandlers()); + } + + /* + * Test constructor with invalid name. + */ + public void testConstructor_InvalidName() { + MockLogger mlog = new MockLogger("...#$%%^&&()-_+=!@~./,[]{};:'\\\"?|", + null); + assertEquals("...#$%%^&&()-_+=!@~./,[]{};:'\\\"?|", mlog.getName()); + } + + /* + * Test constructor with empty name. + */ + public void testConstructor_EmptyName() { + MockLogger mlog = new MockLogger("", null); + assertEquals("", mlog.getName()); + } + + /* + * Test constructor with invalid resource bundle name. + */ + public void testConstructor_InvalidResourceBundle() { + try { + new MockLogger(null, INVALID_RESOURCE_BUNDLE); + fail("Should throw MissingResourceException!"); + } catch (MissingResourceException e) { + } + // try empty string + try { + new MockLogger(null, ""); + fail("Should throw MissingResourceException!"); + } catch (MissingResourceException e) { + } + } + + /* + * Test getAnonymousLogger() + */ + public void testGetAnonymousLogger() { + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + Logger alog = Logger.getAnonymousLogger(); + assertNotSame(alog, Logger.getAnonymousLogger()); + assertNull(alog.getFilter()); + assertEquals(0, alog.getHandlers().length); + assertNull(alog.getLevel()); + assertNull(alog.getName()); + assertNull(alog.getParent().getParent()); + assertNull(alog.getResourceBundle()); + assertNull(alog.getResourceBundleName()); + assertTrue(alog.getUseParentHandlers()); + // fail("Should throw SecurityException!"); + // } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getAnonymousLogger(String resourceBundleName) with valid resource + * bundle. + */ + public void testGetAnonymousLogger_ValidResourceBundle() { + Logger alog = Logger.getAnonymousLogger(VALID_RESOURCE_BUNDLE); + assertNotSame(alog, Logger.getAnonymousLogger(VALID_RESOURCE_BUNDLE)); + assertNull(alog.getFilter()); + assertEquals(0, alog.getHandlers().length); + assertNull(alog.getLevel()); + assertNull(alog.getName()); + assertNull(alog.getParent().getParent()); + assertEquals(VALID_VALUE, alog.getResourceBundle().getString(VALID_KEY)); + assertEquals(alog.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + assertTrue(alog.getUseParentHandlers()); + } + + /* + * Test getAnonymousLogger(String resourceBundleName) with null resource + * bundle. + */ + public void testGetAnonymousLogger_NullResourceBundle() { + Logger alog = Logger.getAnonymousLogger(null); + assertNotSame(alog, Logger.getAnonymousLogger(null)); + assertNull(alog.getFilter()); + assertEquals(0, alog.getHandlers().length); + assertNull(alog.getLevel()); + assertNull(alog.getName()); + assertNull(alog.getParent().getParent()); + assertNull(alog.getResourceBundle()); + assertNull(alog.getResourceBundleName()); + assertTrue(alog.getUseParentHandlers()); + } + + /* + * Test getAnonymousLogger(String resourceBundleName) with invalid resource + * bundle. + */ + public void testGetAnonymousLogger_InvalidResourceBundle() { + try { + Logger.getAnonymousLogger(INVALID_RESOURCE_BUNDLE); + fail("Should throw MissingResourceException!"); + } catch (MissingResourceException e) { + } + // try empty name + try { + Logger.getAnonymousLogger(""); + fail("Should throw MissingResourceException!"); + } catch (MissingResourceException e) { + } + } + + /* + * Test getLogger(String), getting a logger with no parent. + */ + public void testGetLogger_Normal() throws Exception { + // config the level + Properties p = new Properties(); + p.put("testGetLogger_Normal_ANewLogger.level", "ALL"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertNull(LogManager.getLogManager().getLogger( + "testGetLogger_Normal_ANewLogger")); + // create a new logger + Logger log = Logger.getLogger("testGetLogger_Normal_ANewLogger"); + // get an existing logger + assertSame(log, Logger.getLogger("testGetLogger_Normal_ANewLogger")); + // check it has been registered + assertSame(log, LogManager.getLogManager().getLogger( + "testGetLogger_Normal_ANewLogger")); + + assertNull(log.getFilter()); + assertEquals(0, log.getHandlers().length); + // check it's set to the preconfigured level + assertSame(Level.ALL, log.getLevel()); + assertEquals("testGetLogger_Normal_ANewLogger", log.getName()); + assertNull(log.getParent().getParent()); + assertNull(log.getResourceBundle()); + assertNull(log.getResourceBundleName()); + assertTrue(log.getUseParentHandlers()); + } + + /* + * Test getLogger(String), getting a logger with invalid level configured. + */ + public void testGetLogger_InvalidLevel() throws Exception { + // config the level + Properties p = new Properties(); + p + .put("testGetLogger_InvalidLevel_ANewLogger.level", + "impossible_level"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertNull(LogManager.getLogManager().getLogger( + "testGetLogger_InvalidLevel_ANewLogger")); + // create a new logger + Logger log = Logger.getLogger("testGetLogger_InvalidLevel_ANewLogger"); + // get an existing logger + assertSame(log, Logger + .getLogger("testGetLogger_InvalidLevel_ANewLogger")); + // check it has been registered + assertSame(log, LogManager.getLogManager().getLogger( + "testGetLogger_InvalidLevel_ANewLogger")); + assertNull(log.getLevel()); + } + + /* + * Test getLogger(String) with null name. + */ + public void testGetLogger_Null() { + try { + Logger.getLogger(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + Logger logger = Logger.getLogger("", null); + assertNull(logger.getResourceBundleName()); + assertNull(logger.getResourceBundle()); + } + + /* + * Test getLogger(String) with invalid name. + */ + public void testGetLogger_Invalid() { + Logger log = Logger.getLogger("...#$%%^&&()-_+=!@~./,[]{};:'\\\"?|"); + assertEquals("...#$%%^&&()-_+=!@~./,[]{};:'\\\"?|", log.getName()); + } + + /* + * Test getLogger(String) with empty name. + */ + public void testGetLogger_Empty() { + assertNotNull(LogManager.getLogManager().getLogger("")); + Logger log = Logger.getLogger(""); + assertSame(log, LogManager.getLogManager().getLogger("")); + assertNull(log.getFilter()); + assertEquals(0, log.getHandlers().length); + // check it's set to the preconfigured level + assertSame(Level.INFO, log.getLevel()); + assertEquals("", log.getName()); + assertNull(log.getParent()); + assertNull(log.getResourceBundle()); + assertNull(log.getResourceBundleName()); + assertTrue(log.getUseParentHandlers()); + } + + /* + * Test getLogger(String), getting a logger with existing parent. + */ + public void testGetLogger_WithParentNormal() { + assertNull(LogManager.getLogManager().getLogger( + "testGetLogger_WithParent_ParentLogger")); + // create the parent logger + Logger pLog = Logger.getLogger("testGetLogger_WithParent_ParentLogger", + VALID_RESOURCE_BUNDLE); + pLog.setLevel(Level.CONFIG); + pLog.addHandler(new MockHandler()); + pLog.setFilter(new MockFilter()); + pLog.setUseParentHandlers(false); + + assertNull(LogManager.getLogManager().getLogger( + "testGetLogger_WithParent_ParentLogger.child")); + // create the child logger + Logger log = Logger + .getLogger("testGetLogger_WithParent_ParentLogger.child"); + assertNull(log.getFilter()); + assertEquals(0, log.getHandlers().length); + assertNull(log.getLevel()); + assertEquals("testGetLogger_WithParent_ParentLogger.child", log + .getName()); + assertSame(log.getParent(), pLog); + assertNull(log.getResourceBundle()); + assertNull(log.getResourceBundleName()); + assertTrue(log.getUseParentHandlers()); + } + + // /* + // * Test getLogger(String), getting a logger with existing parent, using + // * abnormal names (containing '.'). + // */ + // public void testGetLogger_WithParentAbnormal() { + // Logger log = Logger.getLogger("."); + // assertSame(log.getParent(), Logger.getLogger("")); + // Logger log2 = Logger.getLogger(".."); + // assertSame(log2.getParent(), Logger.getLogger("")); + // //TODO: a lot more can be tested + // } + + /* + * Test getLogger(String, String), getting a logger with no parent. + */ + public void testGetLoggerWithRes_Normal() throws Exception { + // config the level + Properties p = new Properties(); + p.put("testGetLoggerWithRes_Normal_ANewLogger.level", "ALL"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertNull(LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_Normal_ANewLogger")); + // create a new logger + Logger log = Logger.getLogger("testGetLoggerWithRes_Normal_ANewLogger", + VALID_RESOURCE_BUNDLE); + // get an existing logger + assertSame(log, Logger + .getLogger("testGetLoggerWithRes_Normal_ANewLogger")); + // check it has been registered + assertSame(log, LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_Normal_ANewLogger")); + + assertNull(log.getFilter()); + assertEquals(0, log.getHandlers().length); + // check it's set to the preconfigured level + assertSame(Level.ALL, log.getLevel()); + assertEquals("testGetLoggerWithRes_Normal_ANewLogger", log.getName()); + assertNull(log.getParent().getParent()); + assertEquals(VALID_VALUE, log.getResourceBundle().getString(VALID_KEY)); + assertEquals(log.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + assertTrue(log.getUseParentHandlers()); + } + + /* + * Test getLogger(String, String) with null parameters. + */ + public void testGetLoggerWithRes_Null() { + Logger.getLogger("testGetLoggerWithRes_Null_ANewLogger", null); + try { + Logger.getLogger(null, VALID_RESOURCE_BUNDLE); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test getLogger(String, String) with invalid resource bundle. + */ + public void testGetLoggerWithRes_InvalidRes() { + try { + Logger.getLogger("", INVALID_RESOURCE_BUNDLE); + fail("Should throw MissingResourceException!"); + } catch (MissingResourceException e) { + } + assertNull(Logger.getLogger("").getResourceBundle()); + assertNull(Logger.getLogger("").getResourceBundleName()); + // try empty string + try { + Logger.getLogger("", ""); + fail("Should throw MissingResourceException!"); + } catch (MissingResourceException e) { + } + } + + /* + * Test getLogger(String, String) with valid resource bundle, to get an + * existing logger with no associated resource bundle. + */ + public void testGetLoggerWithRes_ExistingLoggerWithNoRes() { + assertNull(LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_ExistingLoggerWithNoRes_ANewLogger")); + // create a new logger + Logger log1 = Logger + .getLogger("testGetLoggerWithRes_ExistingLoggerWithNoRes_ANewLogger"); + // get an existing logger + Logger log2 = Logger.getLogger( + "testGetLoggerWithRes_ExistingLoggerWithNoRes_ANewLogger", + VALID_RESOURCE_BUNDLE); + assertSame(log1, log2); + assertEquals(VALID_VALUE, log1.getResourceBundle().getString(VALID_KEY)); + assertEquals(log1.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + } + + /* + * Test getLogger(String, String) with valid resource bundle, to get an + * existing logger with the same associated resource bundle. + */ + public void testGetLoggerWithRes_ExistingLoggerWithSameRes() { + assertNull(LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_ExistingLoggerWithSameRes_ANewLogger")); + // create a new logger + Logger log1 = Logger.getLogger( + "testGetLoggerWithRes_ExistingLoggerWithSameRes_ANewLogger", + VALID_RESOURCE_BUNDLE); + // get an existing logger + Logger log2 = Logger.getLogger( + "testGetLoggerWithRes_ExistingLoggerWithSameRes_ANewLogger", + VALID_RESOURCE_BUNDLE); + assertSame(log1, log2); + assertEquals(VALID_VALUE, log1.getResourceBundle().getString(VALID_KEY)); + assertEquals(log1.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + } + + /* + * Test getLogger(String, String) with valid resource bundle, to get an + * existing logger with different associated resource bundle. + */ + public void testGetLoggerWithRes_ExistingLoggerWithDiffRes() { + assertNull(LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_ExistingLoggerWithDiffRes_ANewLogger")); + // create a new logger + Logger log1 = Logger.getLogger( + "testGetLoggerWithRes_ExistingLoggerWithDiffRes_ANewLogger", + VALID_RESOURCE_BUNDLE); + assertNotNull(log1); + // get an existing logger + try { + Logger.getLogger("testGetLoggerWithRes_ExistingLoggerWithDiffRes_ANewLogger", + VALID_RESOURCE_BUNDLE2); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + Logger.getLogger("testGetLoggerWithRes_ExistingLoggerWithDiffRes_ANewLogger", null); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + } + + /* + * Test getLogger(String, String) with invalid name. + */ + public void testGetLoggerWithRes_InvalidName() { + Logger log = Logger.getLogger( + "...#$%%^&&()-_+=!@~./,[]{};:'\\\"?|WithRes", + VALID_RESOURCE_BUNDLE); + assertEquals("...#$%%^&&()-_+=!@~./,[]{};:'\\\"?|WithRes", log + .getName()); + } + + /* + * Test getLogger(String, String) with empty name. + */ + public void testGetLoggerWithRes_Empty() { + Logger log = Logger.getLogger("", VALID_RESOURCE_BUNDLE); + assertSame(log, LogManager.getLogManager().getLogger("")); + assertNull(log.getFilter()); + assertEquals(0, log.getHandlers().length); + // check it's set to the preconfigured level + assertSame(Level.INFO, log.getLevel()); + assertEquals("", log.getName()); + assertNull(log.getParent()); + assertEquals(VALID_VALUE, log.getResourceBundle().getString(VALID_KEY)); + assertEquals(log.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + assertTrue(log.getUseParentHandlers()); + } + + /* + * Test getLogger(String, String), getting a logger with existing parent. + */ + public void testGetLoggerWithRes_WithParentNormal() { + assertNull(LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_WithParent_ParentLogger")); + // create the parent logger + Logger pLog = Logger + .getLogger("testGetLoggerWithRes_WithParent_ParentLogger"); + pLog.setLevel(Level.CONFIG); + pLog.addHandler(new MockHandler()); + pLog.setFilter(new MockFilter()); + pLog.setUseParentHandlers(false); + + assertNull(LogManager.getLogManager().getLogger( + "testGetLoggerWithRes_WithParent_ParentLogger.child")); + // create the child logger + Logger log = Logger.getLogger( + "testGetLoggerWithRes_WithParent_ParentLogger.child", + VALID_RESOURCE_BUNDLE); + assertNull(log.getFilter()); + assertEquals(0, log.getHandlers().length); + assertNull(log.getLevel()); + assertEquals("testGetLoggerWithRes_WithParent_ParentLogger.child", log + .getName()); + assertSame(log.getParent(), pLog); + assertEquals(VALID_VALUE, log.getResourceBundle().getString(VALID_KEY)); + assertEquals(log.getResourceBundleName(), VALID_RESOURCE_BUNDLE); + assertTrue(log.getUseParentHandlers()); + } + + /* + * Test addHandler(Handler) for a named logger with sufficient privilege. + */ + public void testAddHandler_NamedLoggerSufficientPrivilege() { + Logger log = Logger + .getLogger("testAddHandler_NamedLoggerSufficientPrivilege"); + MockHandler h = new MockHandler(); + assertEquals(log.getHandlers().length, 0); + log.addHandler(h); + assertEquals(log.getHandlers().length, 1); + assertSame(log.getHandlers()[0], h); + } + + /* + * Test addHandler(Handler) for a named logger with sufficient privilege, + * add duplicate handlers. + */ + public void testAddHandler_NamedLoggerSufficientPrivilegeDuplicate() { + Logger log = Logger + .getLogger("testAddHandler_NamedLoggerSufficientPrivilegeDuplicate"); + MockHandler h = new MockHandler(); + assertEquals(log.getHandlers().length, 0); + log.addHandler(h); + log.addHandler(h); + assertEquals(log.getHandlers().length, 2); + assertSame(log.getHandlers()[0], h); + assertSame(log.getHandlers()[1], h); + } + + /* + * Test addHandler(Handler) with a null handler. + */ + public void testAddHandler_Null() { + Logger log = Logger.getLogger("testAddHandler_Null"); + try { + log.addHandler(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + assertEquals(log.getHandlers().length, 0); + } + + /* + * Test addHandler(Handler) for a named logger with insufficient privilege. + */ + public void testAddHandler_NamedLoggerInsufficientPrivilege() { + Logger log = Logger + .getLogger("testAddHandler_NamedLoggerInsufficientPrivilege"); + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + log.addHandler(h); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test addHandler(Handler) for a named logger with insufficient privilege, + * using a null handler. + */ + public void testAddHandler_NamedLoggerInsufficientPrivilegeNull() { + Logger log = Logger + .getLogger("testAddHandler_NamedLoggerInsufficientPrivilege"); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + log.addHandler(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test addHandler(Handler) for an anonymous logger with sufficient + * privilege. + */ + public void testAddHandler_AnonyLoggerSufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + MockHandler h = new MockHandler(); + assertEquals(log.getHandlers().length, 0); + log.addHandler(h); + assertEquals(log.getHandlers().length, 1); + assertSame(log.getHandlers()[0], h); + } + + /* + * Test addHandler(Handler) for an anonymous logger with insufficient + * privilege. + */ + public void testAddHandler_AnonyLoggerInsufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + assertEquals(log.getHandlers().length, 0); + log.addHandler(h); + assertEquals(log.getHandlers().length, 1); + assertSame(log.getHandlers()[0], h); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test addHandler(Handler) for a null-named mock logger with insufficient + * privilege. + */ + public void testAddHandler_NullNamedMockLoggerInsufficientPrivilege() { + MockLogger mlog = new MockLogger(null, null); + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + mlog.addHandler(h); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test removeHandler(Handler) for a named logger with sufficient privilege, + * remove an existing handler. + */ + public void testRemoveHandler_NamedLoggerSufficientPrivilege() { + Logger log = Logger + .getLogger("testRemoveHandler_NamedLoggerSufficientPrivilege"); + MockHandler h = new MockHandler(); + log.addHandler(h); + assertEquals(log.getHandlers().length, 1); + log.removeHandler(h); + assertEquals(log.getHandlers().length, 0); + } + + /* + * Test removeHandler(Handler) for a named logger with sufficient privilege, + * remove a non-existing handler. + */ + public void testRemoveHandler_NamedLoggerSufficientPrivilegeNotExisting() { + Logger log = Logger + .getLogger("testRemoveHandler_NamedLoggerSufficientPrivilegeNotExisting"); + MockHandler h = new MockHandler(); + assertEquals(log.getHandlers().length, 0); + log.removeHandler(h); + assertEquals(log.getHandlers().length, 0); + } + + /* + * Test removeHandler(Handler) with a null handler. + */ + public void testRemoveHandler_Null() { + Logger log = Logger.getLogger("testRemoveHandler_Null"); + log.removeHandler(null); + assertEquals(log.getHandlers().length, 0); + } + + /* + * Test removeHandler(Handler) for a named logger with insufficient + * privilege. + */ + public void testRemoveHandler_NamedLoggerInsufficientPrivilege() { + Logger log = Logger + .getLogger("testRemoveHandler_NamedLoggerInsufficientPrivilege"); + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + log.removeHandler(h); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test removeHandler(Handler) for a named logger with insufficient + * privilege, using a null handler. + */ + public void testRemoveHandler_NamedLoggerInsufficientPrivilegeNull() { + Logger log = Logger + .getLogger("testRemoveHandler_NamedLoggerInsufficientPrivilege"); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + log.removeHandler(null); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test removeHandler(Handler) for an anonymous logger with sufficient + * privilege. + */ + public void testRemoveHandler_AnonyLoggerSufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + MockHandler h = new MockHandler(); + log.addHandler(h); + assertEquals(log.getHandlers().length, 1); + log.removeHandler(h); + assertEquals(log.getHandlers().length, 0); + } + + /* + * Test removeHandler(Handler) for an anonymous logger with insufficient + * privilege. + */ + public void testRemoveHandler_AnonyLoggerInsufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.addHandler(h); + assertEquals(log.getHandlers().length, 1); + log.removeHandler(h); + assertEquals(log.getHandlers().length, 0); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test removeHandler(Handler) for a null-named mock logger with + * insufficient privilege. + */ + public void testRemoveHandler_NullNamedMockLoggerInsufficientPrivilege() { + MockLogger mlog = new MockLogger(null, null); + MockHandler h = new MockHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + mlog.removeHandler(h); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getHandlers() when there's no handler. + */ + public void testGetHandlers_None() { + Logger log = Logger.getLogger("testGetHandlers_None"); + assertEquals(log.getHandlers().length, 0); + } + + /* + * Test getHandlers() when there are several handlers. + */ + public void testGetHandlers_Several() { + Logger log = Logger.getLogger("testGetHandlers_None"); + assertEquals(log.getHandlers().length, 0); + MockHandler h1 = new MockHandler(); + MockHandler h2 = new MockHandler(); + MockHandler h3 = new MockHandler(); + log.addHandler(h1); + log.addHandler(h2); + log.addHandler(h3); + assertEquals(log.getHandlers().length, 3); + assertSame(log.getHandlers()[0], h1); + assertSame(log.getHandlers()[1], h2); + assertSame(log.getHandlers()[2], h3); + // remove one + log.removeHandler(h2); + assertEquals(log.getHandlers().length, 2); + assertSame(log.getHandlers()[0], h1); + assertSame(log.getHandlers()[1], h3); + } + + /* + * Test getFilter & setFilter with normal value for a named logger, having + * sufficient privilege. + */ + public void testGetSetFilter_NamedLoggerSufficientPrivilege() { + Logger log = Logger + .getLogger("testGetSetFilter_NamedLoggerSufficientPrivilege"); + Filter f = new MockFilter(); + + assertNull(log.getFilter()); + log.setFilter(f); + assertSame(f, log.getFilter()); + } + + /* + * Test getFilter & setFilter with null value, having sufficient privilege. + */ + public void testGetSetFilter_Null() { + Logger log = Logger.getLogger("testGetSetFilter_Null"); + + assertNull(log.getFilter()); + log.setFilter(null); + assertNull(log.getFilter()); + log.setFilter(new MockFilter()); + log.setFilter(null); + assertNull(log.getFilter()); + } + + /* + * Test setFilter with normal value for a named logger, having insufficient + * privilege. + */ + public void testGetSetFilter_NamedLoggerInsufficientPrivilege() { + Logger log = Logger + .getLogger("testGetSetFilter_NamedLoggerInsufficientPrivilege"); + Filter f = new MockFilter(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.setFilter(f); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setFilter for an anonymous logger with sufficient privilege. + */ + public void testSetFilter_AnonyLoggerSufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + Filter f = new MockFilter(); + assertNull(log.getFilter()); + log.setFilter(f); + assertSame(f, log.getFilter()); + } + + /* + * Test setFilter for an anonymous logger with insufficient privilege. + */ + public void testSetFilter_AnonyLoggerInsufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + Filter f = new MockFilter(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + assertNull(log.getFilter()); + log.setFilter(f); + assertSame(f, log.getFilter()); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setFilter for a null-named mock logger with insufficient privilege. + */ + public void testSetFilter_NullNamedMockLoggerInsufficientPrivilege() { + MockLogger mlog = new MockLogger(null, null); + Filter f = new MockFilter(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + mlog.setFilter(f); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getLevel & setLevel with normal value for a named logger, having + * sufficient privilege. + */ + public void testGetSetLevel_NamedLoggerSufficientPrivilege() { + Logger log = Logger + .getLogger("testGetSetLevel_NamedLoggerSufficientPrivilege"); + + assertNull(log.getLevel()); + log.setLevel(Level.CONFIG); + assertSame(Level.CONFIG, log.getLevel()); + } + + /* + * Test getLevel & setLevel with null value, having sufficient privilege. + */ + public void testGetSetLevel_Null() { + Logger log = Logger.getLogger("testGetSetLevel_Null"); + + assertNull(log.getLevel()); + log.setLevel(null); + assertNull(log.getLevel()); + log.setLevel(Level.CONFIG); + log.setLevel(null); + assertNull(log.getLevel()); + } + + /* + * Test setLevel with normal value for a named logger, having insufficient + * privilege. + */ + public void testGetSetLevel_NamedLoggerInsufficientPrivilege() { + Logger log = Logger + .getLogger("testGetSetLevel_NamedLoggerInsufficientPrivilege"); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.setLevel(Level.CONFIG); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setLevel for an anonymous logger with sufficient privilege. + */ + public void testSetLevel_AnonyLoggerSufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + assertNull(log.getLevel()); + log.setLevel(Level.CONFIG); + assertSame(Level.CONFIG, log.getLevel()); + } + + /* + * Test setLevel for an anonymous logger with insufficient privilege. + */ + public void testSetLevel_AnonyLoggerInsufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + assertNull(log.getLevel()); + log.setLevel(Level.CONFIG); + assertSame(Level.CONFIG, log.getLevel()); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setLevel for a null-named mock logger with insufficient privilege. + */ + public void testSetLevel_NullNamedMockLoggerInsufficientPrivilege() { + MockLogger mlog = new MockLogger(null, null); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + mlog.setLevel(Level.CONFIG); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getUseParentHandlers & setUseParentHandlers with normal value for a + * named logger, having sufficient privilege. + */ + public void testGetSetUseParentHandlers_NamedLoggerSufficientPrivilege() { + Logger log = Logger + .getLogger("testGetSetUseParentHandlers_NamedLoggerSufficientPrivilege"); + + assertTrue(log.getUseParentHandlers()); + log.setUseParentHandlers(false); + assertFalse(log.getUseParentHandlers()); + } + + /* + * Test setUseParentHandlers with normal value for a named logger, having + * insufficient privilege. + */ + public void testGetSetUseParentHandlers_NamedLoggerInsufficientPrivilege() { + Logger log = Logger + .getLogger("testGetSetUseParentHandlers_NamedLoggerInsufficientPrivilege"); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.setUseParentHandlers(true); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setUseParentHandlers for an anonymous logger with sufficient + * privilege. + */ + public void testSetUseParentHandlers_AnonyLoggerSufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + assertTrue(log.getUseParentHandlers()); + log.setUseParentHandlers(false); + assertFalse(log.getUseParentHandlers()); + } + + /* + * Test setUseParentHandlers for an anonymous logger with insufficient + * privilege. + */ + public void testSetUseParentHandlers_AnonyLoggerInsufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + assertTrue(log.getUseParentHandlers()); + log.setUseParentHandlers(false); + assertFalse(log.getUseParentHandlers()); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setUseParentHandlers for a null-named mock logger with insufficient + * privilege. + */ + public void testSetUseParentHandlers_NullNamedMockLoggerInsufficientPrivilege() { + MockLogger mlog = new MockLogger(null, null); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + mlog.setUseParentHandlers(true); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getParent() for root logger. + */ + public void testGetParent_Root() { + assertNull(Logger.getLogger("").getParent()); + } + + /* + * Test getParent() for normal named loggers. + */ + public void testGetParent_NormalNamed() { + Logger log = Logger.getLogger("testGetParent_NormalNamed"); + assertSame(log.getParent(), Logger.getLogger("")); + Logger child = Logger.getLogger("testGetParent_NormalNamed.child"); + assertSame(child.getParent(), log); + Logger child2 = Logger.getLogger("testGetParent_NormalNamed.a.b.c"); + assertSame(child2.getParent(), log); + } + + /* + * Test getParent() for anonymous loggers. + */ + public void testGetParent_Anonymous() { + assertSame(Logger.getAnonymousLogger().getParent(), Logger + .getLogger("")); + } + + /* + * Test setParent(Logger) for the mock logger since it is advised not to + * call this method on named loggers. Test normal conditions. + */ + public void testSetParent_Normal() { + Logger log = new MockLogger(null, null); + Logger parent = new MockLogger(null, null); + assertNull(log.getParent()); + log.setParent(parent); + assertSame(log.getParent(), parent); + } + + /* + * Test setParent(Logger) with null. + */ + public void testSetParent_Null() { + try { + (new MockLogger(null, null)).setParent(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test setParent(Logger), having insufficient privilege. + */ + public void testSetParent_InsufficientPrivilege() { + MockLogger log = new MockLogger(null, null); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.setParent(log); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setParent(Logger) with null, having insufficient privilege. + */ + public void testSetParent_InsufficientPrivilegeNull() { + MockLogger log = new MockLogger(null, null); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.setParent(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test setParent(Logger) for an anonymous logger with insufficient + * privilege. + */ + public void testSetParent_AnonyLoggerInsufficientPrivilege() { + Logger log = Logger.getAnonymousLogger(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + log.setParent(log); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test getName() for normal names. + */ + public void testGetName_Normal() { + Logger log = Logger.getLogger("testGetName_Normal"); + assertEquals("testGetName_Normal", log.getName()); + + Logger mlog = new MockLogger("testGetName_Normal", null); + assertEquals("testGetName_Normal", mlog.getName()); + } + + /* + * Test getName() for empty name. + */ + public void testGetName_Empty() { + Logger log = Logger.getLogger(""); + assertEquals("", log.getName()); + + Logger mlog = new MockLogger("", null); + assertEquals("", mlog.getName()); + } + + /* + * Test getName() for null name. + */ + public void testGetName_Null() { + Logger log = Logger.getAnonymousLogger(); + assertNull(log.getName()); + + Logger mlog = new MockLogger(null, null); + assertNull(mlog.getName()); + } + + /* + * Test getResourceBundle() when it it not null. + */ + public void testGetResourceBundle_Normal() { + Logger log = Logger.getLogger("testGetResourceBundle_Normal", + VALID_RESOURCE_BUNDLE); + assertEquals(VALID_VALUE, log.getResourceBundle().getString(VALID_KEY)); + + Logger mlog = new MockLogger(null, VALID_RESOURCE_BUNDLE); + assertEquals(VALID_VALUE, mlog.getResourceBundle().getString(VALID_KEY)); + } + + /* + * Test getResourceBundle() when it it null. + */ + public void testGetResourceBundle_Null() { + Logger log = Logger.getLogger("testGetResourceBundle_Null", null); + assertNull(log.getResourceBundle()); + + Logger mlog = new MockLogger(null, null); + assertNull(mlog.getResourceBundle()); + } + + /* + * Test getResourceBundleName() when it it not null. + */ + public void testGetResourceBundleName_Normal() { + Logger log = Logger.getLogger("testGetResourceBundleName_Normal", + VALID_RESOURCE_BUNDLE); + assertEquals(VALID_RESOURCE_BUNDLE, log.getResourceBundleName()); + + Logger mlog = new MockLogger(null, null); + assertNull(mlog.getResourceBundleName()); + } + + /* + * Test getResourceBundleName() when it it null. + */ + public void testGetResourceBundleName_Null() { + Logger log = Logger.getLogger("testGetResourceBundleName_Null", null); + assertNull(log.getResourceBundleName()); + + Logger mlog = new MockLogger(null, null); + assertNull(mlog.getResourceBundleName()); + } + + /* + * Test isLoggable(Level). + */ + public void testIsLoggable() { + MockLogger mlog = new MockLogger(null, null); + assertNull(mlog.getLevel()); + assertNull(mlog.getParent()); + + assertTrue(mlog.isLoggable(Level.SEVERE)); + assertTrue(mlog.isLoggable(Level.WARNING)); + assertTrue(mlog.isLoggable(Level.INFO)); + assertFalse(mlog.isLoggable(Level.CONFIG)); + assertFalse(mlog.isLoggable(Level.FINE)); + assertFalse(mlog.isLoggable(Level.ALL)); + assertTrue(mlog.isLoggable(Level.OFF)); + + mlog.setLevel(Level.CONFIG); + assertTrue(mlog.isLoggable(Level.SEVERE)); + assertTrue(mlog.isLoggable(Level.CONFIG)); + assertFalse(mlog.isLoggable(Level.ALL)); + assertTrue(mlog.isLoggable(Level.OFF)); + + mlog.setLevel(Level.ALL); + assertTrue(mlog.isLoggable(Level.ALL)); + assertTrue(mlog.isLoggable(Level.SEVERE)); + assertTrue(mlog.isLoggable(Level.OFF)); + + mlog.setLevel(Level.OFF); + assertFalse(mlog.isLoggable(Level.ALL)); + assertFalse(mlog.isLoggable(Level.SEVERE)); + assertFalse(mlog.isLoggable(Level.OFF)); + } + + /* + * Test throwing(String, String, Throwable) with normal values. + */ + public void testThrowing_Normal() { + Throwable t = new Throwable(); + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.throwing("sourceClass", "sourceMethod", t); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "THROW"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters(), null); + assertSame(r.getThrown(), t); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.throwing("sourceClass", "sourceMethod", t); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test throwing(String, String, Throwable) with null values. + */ + public void testThrowing_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.throwing(null, null, null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertEquals(r.getMessage(), "THROW"); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters(), null); + assertSame(r.getThrown(), null); + } + + /* + * Test entering(String, String) with normal values. + */ + public void testEntering_StringString_Normal() { + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.entering("sourceClass", "sourceMethod"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "ENTRY"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters(), null); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.entering("sourceClass", "sourceMethod"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test entering(String, String) with null values. + */ + public void testEntering_StringString_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.entering(null, null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertEquals(r.getMessage(), "ENTRY"); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters(), null); + assertSame(r.getThrown(), null); + } + + /* + * Test entering(String, String, Object) with normal values. + */ + public void testEntering_StringStringObject_Normal() { + Object param = new Object(); + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.entering("sourceClass", "sourceMethod", param); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "ENTRY {0}"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters()[0], param); + assertEquals(1, r.getParameters().length); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.entering("sourceClass", "sourceMethod", param); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test entering(String, String, Object) with null values. + */ + public void testEntering_StringStringObject_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.entering(null, null, (Object) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertEquals(r.getMessage(), "ENTRY {0}"); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertEquals(r.getParameters().length, 1); + assertNull(r.getParameters()[0]); + assertSame(r.getThrown(), null); + } + + /* + * Test entering(String, String, Object[]) with normal values. + */ + public void testEntering_StringStringObjects_Normal() { + Object[] params = new Object[2]; + params[0] = new Object(); + params[1] = new Object(); + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.entering("sourceClass", "sourceMethod", params); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "ENTRY {0} {1}"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters()[0], params[0]); + assertSame(r.getParameters()[1], params[1]); + assertEquals(2, r.getParameters().length); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.entering("sourceClass", "sourceMethod", params); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test entering(String, String, Object[]) with null class name and method + * name and empty parameter array. + */ + public void testEntering_StringStringObjects_NullEmpty() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.entering(null, null, new Object[0]); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertEquals(r.getMessage(), "ENTRY"); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertEquals(0, r.getParameters().length); + assertSame(r.getThrown(), null); + } + + /* + * Test entering(String, String, Object[]) with null values with appropriate + * logging level set. + */ + public void testEntering_StringStringObjects_Null() { + sharedLogger.setLevel(Level.FINER); + sharedLogger.entering(null, null, (Object[]) null); + // regression test for Harmony-1265 + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(sharedLogger.getName(), r.getLoggerName()); + assertEquals("ENTRY", r.getMessage()); + assertSame(sharedLogger.getResourceBundleName(), r + .getResourceBundleName()); + assertSame(sharedLogger.getResourceBundle(), r.getResourceBundle()); + assertNull(r.getSourceClassName()); + assertNull(r.getSourceMethodName()); + assertSame(Level.FINER, r.getLevel()); + assertNull(r.getParameters()); + assertNull(r.getThrown()); + } + + /* + * Test entering(String, String, Object[]) with null values with + * inappropriate logging level set. + */ + public void testEntering_StringStringObjects_NullDisabled() { + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.entering(null, null, (Object[]) null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test exiting(String, String) with normal values. + */ + public void testExiting_StringString_Normal() { + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.exiting("sourceClass", "sourceMethod"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "RETURN"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.FINER); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.exiting("sourceClass", "sourceMethod"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test exiting(String, String) with null values. + */ + public void testExiting_StringString_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.exiting(null, null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertEquals(r.getMessage(), "RETURN"); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters(), null); + assertSame(r.getThrown(), null); + } + + /* + * Test exiting(String, String, Object) with normal values. + */ + public void testExiting_StringStringObject_Normal() { + Object param = new Object(); + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.exiting("sourceClass", "sourceMethod", param); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "RETURN {0}"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.FINER); + assertSame(r.getParameters()[0], param); + assertEquals(1, r.getParameters().length); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.exiting("sourceClass", "sourceMethod", param); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test exiting(String, String, Object) with null values. + */ + public void testExiting_StringStringObject_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.exiting(null, null, (Object) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertEquals(r.getMessage(), "RETURN {0}"); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertEquals(r.getParameters().length, 1); + assertNull(r.getParameters()[0]); + assertSame(r.getThrown(), null); + } + + /* + * Test config(String) with normal values. + */ + public void testConfig_Normal() { + this.sharedLogger.setLevel(Level.CONFIG); + this.sharedLogger.config("config msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "config msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.CONFIG); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.config("config again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test config(String) with null values. + */ + public void testConfig_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.CONFIG); + child.config(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.CONFIG); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.config(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test fine(String) with normal values. + */ + public void testFine_Normal() { + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.fine("fine msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertEquals(r.getMessage(), "fine msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.CONFIG); + this.sharedLogger.fine("fine again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test fine(String) with null values. + */ + public void testFine_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINE); + child.fine(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.CONFIG); + this.sharedLogger.fine(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test finer(String) with normal values. + */ + public void testFiner_Normal() { + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.finer("finer msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "finer msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.finer("finer again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test finer(String) with null values. + */ + public void testFiner_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINER); + child.finer(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINER); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINE); + this.sharedLogger.finer(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test finest(String) with normal values. + */ + public void testFinest_Normal() { + this.sharedLogger.setLevel(Level.FINEST); + this.sharedLogger.finest("finest msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "finest msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINEST); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.finest("finest again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test finest(String) with null values. + */ + public void testFinest_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.FINEST); + child.finest(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINEST); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.FINER); + this.sharedLogger.finest(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test info(String) with normal values. + */ + public void testInfo_Normal() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.info("info msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "info msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.WARNING); + this.sharedLogger.info("info again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test info(String) with null values. + */ + public void testInfo_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.info(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.WARNING); + this.sharedLogger.info(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test warning(String) with normal values. + */ + public void testWarning_Normal() { + this.sharedLogger.setLevel(Level.WARNING); + this.sharedLogger.warning("warning msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "warning msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.WARNING); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.SEVERE); + this.sharedLogger.warning("warning again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test warning(String) with null values. + */ + public void testWarning_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.WARNING); + child.warning(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.WARNING); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.SEVERE); + this.sharedLogger.warning(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test severe(String) with normal values. + */ + public void testSevere_Normal() { + this.sharedLogger.setLevel(Level.SEVERE); + this.sharedLogger.severe("severe msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "severe msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.SEVERE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.severe("severe again"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test severe(String) with null values. + */ + public void testSevere_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.SEVERE); + child.severe(null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.SEVERE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.severe(null); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test log(Level, String) with normal values. + */ + public void testLog_LevelString_Normal() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.log(Level.INFO, "log(Level, String) msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "log(Level, String) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.log(Level.CONFIG, "log(Level, String) msg"); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.log(Level.OFF, "log(Level, String) msg"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test log(Level, String) with null message. + */ + public void testLog_LevelString_NullMsg() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.log(Level.INFO, null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test log(Level, String) with null level. + */ + public void testLog_LevelString_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.log(null, "log(Level, String) msg"); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test log(Level, String, Object) with normal values. + */ + public void testLog_LevelStringObject_Normal() { + Object param = new Object(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.log(Level.INFO, "log(Level, String, Object) msg", + param); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "log(Level, String, Object) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertEquals(1, r.getParameters().length); + assertSame(param, r.getParameters()[0]); + assertSame(r.getThrown(), null); + + this.sharedLogger.log(Level.CONFIG, "log(Level, String, Object) msg", + param); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.log(Level.OFF, "log(Level, String, Object) msg", + param); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test log(Level, String, Object) with null message and object. + */ + public void testLog_LevelStringObject_NullMsgObj() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.log(Level.INFO, null, (Object) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertEquals(1, r.getParameters().length); + assertNull(r.getParameters()[0]); + assertSame(r.getThrown(), null); + } + + /* + * Test log(Level, String, Object) with null level. + */ + public void testLog_LevelStringObject_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.log(null, "log(Level, String, Object) msg", + new Object()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test log(Level, String, Object[]) with normal values. + */ + public void testLog_LevelStringObjects_Normal() { + Object[] params = new Object[2]; + params[0] = new Object(); + params[1] = new Object(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.log(Level.INFO, "log(Level, String, Object[]) msg", + params); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "log(Level, String, Object[]) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertEquals(2, r.getParameters().length); + assertSame(params[0], r.getParameters()[0]); + assertSame(params[1], r.getParameters()[1]); + assertSame(r.getThrown(), null); + + this.sharedLogger.log(Level.CONFIG, "log(Level, String, Object[]) msg", + params); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.log(Level.OFF, "log(Level, String, Object[]) msg", + params); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test log(Level, String, Object[]) with null message and object. + */ + public void testLog_LevelStringObjects_NullMsgObj() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.log(Level.INFO, null, (Object[]) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test log(Level, String, Object[]) with null level. + */ + public void testLog_LevelStringObjects_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.log(null, "log(Level, String, Object[]) msg", + new Object[0]); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test log(Level, String, Throwable) with normal values. + */ + public void testLog_LevelStringThrowable_Normal() { + Throwable t = new Throwable(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.log(Level.INFO, "log(Level, String, Throwable) msg", + t); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "log(Level, String, Throwable) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), t); + + this.sharedLogger.log(Level.CONFIG, + "log(Level, String, Throwable) msg", t); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger + .log(Level.OFF, "log(Level, String, Throwable) msg", t); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test log(Level, String, Throwable) with null message and throwable. + */ + public void testLog_LevelStringThrowable_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.log(Level.INFO, null, (Throwable) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test log(Level, String, Throwable) with null level. + */ + public void testLog_LevelStringThrowable_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.log(null, "log(Level, String, Throwable) msg", + new Throwable()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logp(Level, String, String, String) with normal values. + */ + public void testLogp_LevelStringStringString_Normal() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logp(Level.INFO, "sourceClass", "sourceMethod", + "logp(Level, String, String, String) msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), "logp(Level, String, String, String) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.logp(Level.CONFIG, "sourceClass", "sourceMethod", + "logp(Level, String, String, String) msg"); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logp(Level.OFF, "sourceClass", "sourceMethod", + "logp(Level, String, String, String) msg"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logp(Level, String, String, String) with null message. + */ + public void testLogp_LevelStringStringString_NullMsg() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.logp(Level.INFO, null, null, null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logp(Level, String, String, String) with null level. + */ + public void testLogp_LevelStringStringString_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.logp(null, "sourceClass", "sourceMethod", + "logp(Level, String, String, String) msg"); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logp(Level, String, String, String, Object) with normal values. + */ + public void testLogp_LevelStringStringStringObject_Normal() { + Object param = new Object(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logp(Level.INFO, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object) msg", param); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logp(Level, String, String, String, Object) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertEquals(1, r.getParameters().length); + assertSame(param, r.getParameters()[0]); + assertSame(r.getThrown(), null); + + this.sharedLogger.logp(Level.CONFIG, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object) msg", param); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logp(Level.OFF, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object) msg", param); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logp(Level, String, String, String, Object) with null message and + * object. + */ + public void testLogp_LevelStringStringStringObject_NullMsgObj() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.logp(Level.INFO, null, null, null, (Object) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertEquals(1, r.getParameters().length); + assertNull(r.getParameters()[0]); + assertSame(r.getThrown(), null); + } + + /* + * Test logp(Level, String, String, String, Object) with null level. + */ + public void testLogp_LevelStringStringStringObject_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.logp(null, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object) msg", + new Object()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logp(Level, String, String, String, Object[]) with normal values. + */ + public void testLogp_LevelStringStringStringObjects_Normal() { + Object[] params = new Object[2]; + params[0] = new Object(); + params[1] = new Object(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logp(Level.INFO, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object[]) msg", params); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logp(Level, String, String, String, Object[]) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertEquals(2, r.getParameters().length); + assertSame(params[0], r.getParameters()[0]); + assertSame(params[1], r.getParameters()[1]); + assertSame(r.getThrown(), null); + + this.sharedLogger.logp(Level.CONFIG, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object[]) msg", params); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logp(Level.OFF, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object[]) msg", params); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logp(Level, String, String, String, Object[]) with null message and + * object. + */ + public void testLogp_LevelStringStringStringObjects_NullMsgObj() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.logp(Level.INFO, null, null, null, (Object[]) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logp(Level, String, String, String, Object[]) with null level. + */ + public void testLogp_LevelStringStringStringObjects_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.logp(null, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Object[]) msg", + new Object[0]); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logp(Level, String, String, String, Throwable) with normal values. + */ + public void testLogp_LevelStringStringStringThrowable_Normal() { + Throwable t = new Throwable(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logp(Level.INFO, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Throwable) msg", t); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logp(Level, String, String, String, Throwable) msg"); + assertSame(r.getResourceBundleName(), this.sharedLogger + .getResourceBundleName()); + assertSame(r.getResourceBundle(), this.sharedLogger.getResourceBundle()); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), t); + + this.sharedLogger.logp(Level.CONFIG, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Throwable) msg", t); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logp(Level.OFF, "sourceClass", "sourceMethod", + "logp(Level, String, String, String, Throwable) msg", t); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logp(Level, String, String, String, Throwable) with null message and + * throwable. + */ + public void testLogp_LevelStringTStringStringhrowable_Null() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + + child.setLevel(Level.INFO); + child.logp(Level.INFO, null, null, null, (Throwable) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), child.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), parent.getResourceBundleName()); + assertSame(r.getResourceBundle(), parent.getResourceBundle()); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logp(Level, String, String, String, Throwable) with null level. + */ + public void testLogp_LevelStringStringStringThrowable_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.logp(null, "sourceClass", "sourceMethod", + "log(Level, String, String, String, Throwable) msg", + new Throwable()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logrb(Level, String, String, String, String) with normal values. + */ + public void testLogrb_LevelStringStringString_Normal() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String) msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String) msg"); + assertSame(r.getResourceBundleName(), VALID_RESOURCE_BUNDLE2); + assertEquals(VALID_VALUE2, r.getResourceBundle().getString(VALID_KEY)); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + this.sharedLogger.logrb(Level.CONFIG, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String) msg"); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logrb(Level.OFF, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String) msg"); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logrb(Level, String, String, String, String) with null message. + */ + public void testLogrb_LevelStringStringString_NullMsg() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, null, null, null, null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logrb(Level, String, String, String) with null level. + */ + public void testLogrb_LevelStringStringString_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.logrb(null, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String) msg"); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logrb(Level, String, String, String, String) with invalid resource + * bundle. + */ + public void testLogrb_LevelStringStringString_InvalidRes() { + this.sharedLogger.setLevel(Level.ALL); + this.sharedLogger.logrb(Level.ALL, "sourceClass", "sourceMethod", + INVALID_RESOURCE_BUNDLE, + "logrb(Level, String, String, String, String) msg"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String) msg"); + assertSame(r.getResourceBundleName(), INVALID_RESOURCE_BUNDLE); + assertSame(r.getResourceBundle(), null); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.ALL); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logrb(Level, String, String, String, String, Object) with normal + * values. + */ + public void testLogrb_LevelStringStringStringObject_Normal() { + Object param = new Object(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object) msg", + param); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String, Object) msg"); + assertSame(r.getResourceBundleName(), VALID_RESOURCE_BUNDLE2); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertEquals(1, r.getParameters().length); + assertSame(param, r.getParameters()[0]); + assertSame(r.getThrown(), null); + + this.sharedLogger.logrb(Level.CONFIG, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object) msg", + param); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logrb(Level.OFF, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object) msg", + param); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logrb(Level, String, String, String, String, Object) with null + * message and object. + */ + public void testLogrb_LevelStringStringStringObject_NullMsgObj() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, null, null, null, null, + (Object) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertEquals(1, r.getParameters().length); + assertNull(r.getParameters()[0]); + assertSame(r.getThrown(), null); + } + + /** + * @tests java.util.logging.Logger#logrb(Level, String, String, String, + * String, Object) + */ + public void test_logrbLLevel_LString_LString_LObject_Security() + throws Exception { + // regression test for Harmony-1290 + SecurityManager originalSecurityManager = System.getSecurityManager(); + try { + System.setSecurityManager(new MockSecurityManager()); + Logger.global.logrb(Level.OFF, null, null, "abc", "def"); + } finally { + System.setSecurityManager(originalSecurityManager); + } + } + + /* + * Test logrb(Level, String, String, String, String, Object) with null + * level. + */ + public void testLogrb_LevelStringStringStringObject_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger.logrb(null, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object) msg", + new Object()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logrb(Level, String, String, String, String, Object) with invalid + * resource bundle. + */ + public void testLogrb_LevelStringStringStringObject_InvalidRes() { + Object param = new Object(); + this.sharedLogger.setLevel(Level.ALL); + this.sharedLogger.logrb(Level.ALL, "sourceClass", "sourceMethod", + INVALID_RESOURCE_BUNDLE, + "logrb(Level, String, String, String, String) msg", param); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String) msg"); + assertSame(r.getResourceBundleName(), INVALID_RESOURCE_BUNDLE); + assertSame(r.getResourceBundle(), null); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.ALL); + assertEquals(1, r.getParameters().length); + assertSame(param, r.getParameters()[0]); + assertSame(r.getThrown(), null); + } + + /* + * Test logrb(Level, String, String, String, String, Object[]) with normal + * values. + */ + public void testLogrb_LevelStringStringStringObjects_Normal() { + Object[] params = new Object[2]; + params[0] = new Object(); + params[1] = new Object(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object[]) msg", + params); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String, Object[]) msg"); + assertSame(r.getResourceBundleName(), VALID_RESOURCE_BUNDLE2); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.INFO); + assertEquals(2, r.getParameters().length); + assertSame(params[0], r.getParameters()[0]); + assertSame(params[1], r.getParameters()[1]); + assertSame(r.getThrown(), null); + + this.sharedLogger.logrb(Level.CONFIG, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object[]) msg", + params); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logrb(Level.OFF, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object[]) msg", + params); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logrb(Level, String, String, String, String, Object[]) with null + * message and object. + */ + public void testLogrb_LevelStringStringStringObjects_NullMsgObj() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, null, null, null, null, + (Object[]) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logrb(Level, String, String, String, String, Object[]) with null + * level. + */ + public void testLogrb_LevelStringStringStringObjects_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger + .logrb( + null, + "sourceClass", + "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Object[]) msg", + new Object[0]); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logrb(Level, String, String, String, String, Object[]) with invalid + * resource bundle. + */ + public void testLogrb_LevelStringStringStringObjects_InvalidRes() { + Object[] params = new Object[2]; + params[0] = new Object(); + params[1] = new Object(); + this.sharedLogger.setLevel(Level.ALL); + this.sharedLogger.logrb(Level.ALL, "sourceClass", "sourceMethod", + INVALID_RESOURCE_BUNDLE, + "logrb(Level, String, String, String, String) msg", params); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String) msg"); + assertSame(r.getResourceBundleName(), INVALID_RESOURCE_BUNDLE); + assertSame(r.getResourceBundle(), null); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.ALL); + assertEquals(2, r.getParameters().length); + assertSame(params[0], r.getParameters()[0]); + assertSame(params[1], r.getParameters()[1]); + assertSame(r.getThrown(), null); + } + + /* + * Test logrb(Level, String, String, String, String, Throwable) with normal + * values. + */ + public void testLogrb_LevelStringStringStringThrowable_Normal() { + Throwable t = new Throwable(); + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.parse("1611"), "sourceClass", + "sourceMethod", VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Throwable) msg", + t); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String, Throwable) msg"); + assertSame(r.getResourceBundleName(), VALID_RESOURCE_BUNDLE2); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.parse("1611")); + assertNull(r.getParameters()); + assertSame(r.getThrown(), t); + assertNull(Level.parse("1611").getResourceBundleName()); + + this.sharedLogger.logrb(Level.CONFIG, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Throwable) msg", + t); + assertTrue(CallVerificationStack.getInstance().empty()); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.logrb(Level.OFF, "sourceClass", "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "logrb(Level, String, String, String, String, Throwable) msg", + t); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test logrb(Level, String, String, String, String, Throwable) with null + * message and throwable. + */ + public void testLogrb_LevelStringTStringStringhrowable_NullMsgObj() { + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.logrb(Level.INFO, null, null, null, null, + (Throwable) null); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertNull(r.getMessage()); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test logrb(Level, String, String, String, String, Throwable) with null + * level. + */ + public void testLogrb_LevelStringStringStringThrowable_NullLevel() { + // this.sharedLogger.setLevel(Level.OFF); + try { + this.sharedLogger + .logrb( + null, + "sourceClass", + "sourceMethod", + VALID_RESOURCE_BUNDLE2, + "log(Level, String, String, String, String, Throwable) msg", + new Throwable()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test logrb(Level, String, String, String, String, Throwable) with invalid + * resource bundle. + */ + public void testLogrb_LevelStringStringStringThrowable_InvalidRes() { + Throwable t = new Throwable(); + this.sharedLogger.setLevel(Level.ALL); + this.sharedLogger.logrb(Level.ALL, "sourceClass", "sourceMethod", + INVALID_RESOURCE_BUNDLE, + "logrb(Level, String, String, String, String) msg", t); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), this.sharedLogger.getName()); + assertEquals(r.getMessage(), + "logrb(Level, String, String, String, String) msg"); + assertSame(r.getResourceBundleName(), INVALID_RESOURCE_BUNDLE); + assertSame(r.getResourceBundle(), null); + assertSame(r.getSourceClassName(), "sourceClass"); + assertSame(r.getSourceMethodName(), "sourceMethod"); + assertSame(r.getLevel(), Level.ALL); + assertNull(r.getParameters()); + assertSame(r.getThrown(), t); + } + + /* + * Test log(LogRecord) for a normal log record. Meanwhile the logger has an + * appropriate level, no filter, no parent. + */ + public void testLog_LogRecord_AppropriateLevelNoFilterNoParent() { + LogRecord r = new LogRecord(Level.INFO, + "testLog_LogRecord_AppropriateLevelNoFilterNoParent"); + + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.log(r); + + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), null); + assertEquals(r.getMessage(), + "testLog_LogRecord_AppropriateLevelNoFilterNoParent"); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test log(LogRecord) with null log record. + */ + public void testLog_LogRecord_Null() { + this.sharedLogger.setLevel(Level.INFO); + try { + this.sharedLogger.log(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + } + } + + /* + * Test log(LogRecord) for a normal log record. Meanwhile the logger has an + * inappropriate level, no filter, no parent. + */ + public void testLog_LogRecord_InppropriateLevelNoFilterNoParent() { + LogRecord r = new LogRecord(Level.INFO, + "testLog_LogRecord_InppropriateLevelNoFilterNoParent"); + + this.sharedLogger.setLevel(Level.WARNING); + this.sharedLogger.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + + r.setLevel(Level.OFF); + this.sharedLogger.setLevel(Level.OFF); + this.sharedLogger.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test log(LogRecord) for a normal log record. Meanwhile the logger has an + * appropriate level, a filter that accepts the fed log record, no parent. + */ + public void testLog_LogRecord_AppropriateLevelTrueFilterNoParent() { + LogRecord r = new LogRecord(Level.INFO, + "testLog_LogRecord_AppropriateLevelTrueFilterNoParent"); + + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.setFilter(new MockTrueFilter()); + this.sharedLogger.log(r); + + // pop twice, one pushed by mock handler, one by true mock filter + assertSame(r, CallVerificationStack.getInstance().pop()); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + assertSame(r.getLoggerName(), null); + assertEquals(r.getMessage(), + "testLog_LogRecord_AppropriateLevelTrueFilterNoParent"); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test log(LogRecord) for a normal log record. Meanwhile the logger has an + * appropriate level, a filter that rejects the fed log record, no parent. + */ + public void testLog_LogRecord_AppropriateLevelFalseFilterNoParent() { + LogRecord r = new LogRecord(Level.INFO, + "testLog_LogRecord_AppropriateLevelFalseFilterNoParent"); + + this.sharedLogger.setLevel(Level.INFO); + this.sharedLogger.setFilter(new MockFilter()); + this.sharedLogger.log(r); + + // pop only once, pushed by mock filter + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + assertSame(r.getLoggerName(), null); + assertEquals(r.getMessage(), + "testLog_LogRecord_AppropriateLevelFalseFilterNoParent"); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + } + + /* + * Test that the parent's handler is notified for a new log record when + * getUseParentHandlers() is true. + */ + public void testLog_ParentInformed() { + Logger child = new MockLogger("childLogger", VALID_RESOURCE_BUNDLE); + Logger parent = new MockParentLogger("parentLogger", + VALID_RESOURCE_BUNDLE2); + + child.setParent(parent); + child.setLevel(Level.INFO); + parent.setLevel(Level.INFO); + parent.addHandler(new MockHandler()); + LogRecord r = new LogRecord(Level.INFO, "testLog_ParentInformed"); + child.log(r); + assertTrue(child.getUseParentHandlers()); + // pop only once, pushed by the parent logger's handler, not by the + // parent itself! + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + assertSame(r.getLoggerName(), null); + assertEquals(r.getMessage(), "testLog_ParentInformed"); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.INFO); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + + // set the child logger to disabling level + child.setLevel(Level.SEVERE); + child.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + + // set the parent logger to disabling level + child.setLevel(Level.INFO); + parent.setLevel(Level.SEVERE); + child.log(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + // set the child logger off + child.setLevel(Level.OFF); + child.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + + // set the record off + r.setLevel(Level.OFF); + child.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test that the ancestor's handler is notified for a new log record when + * getUseParentHandlers() is true. + */ + public void testLog_AncestorInformed() { + Logger child = new MockLogger("childLogger", VALID_RESOURCE_BUNDLE); + Logger parent = new MockParentLogger("parentLogger", + VALID_RESOURCE_BUNDLE2); + Logger ancestor = new MockParentLogger("ancestorLogger", + VALID_RESOURCE_BUNDLE3); + + child.setParent(parent); + parent.setParent(ancestor); + child.setLevel(Level.INFO); + parent.setLevel(Level.INFO); + ancestor.setLevel(Level.OFF); + ancestor.addHandler(new MockHandler()); + LogRecord r = new LogRecord(Level.INFO, "testLog_AncestorInformed"); + child.log(r); + assertTrue(child.getUseParentHandlers()); + assertTrue(parent.getUseParentHandlers()); + // pop only once, pushed by the ancestor's logger's handler, not by the + // parent itself! + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + // set parent's level to a disabling one + parent.setLevel(Level.WARNING); + child.log(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + // set child's level to a disabling one + parent.setLevel(Level.INFO); + child.setLevel(Level.WARNING); + child.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + + // set parent's useParentHandlers to false + parent.setLevel(Level.INFO); + child.setLevel(Level.INFO); + parent.setUseParentHandlers(false); + child.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test that the parent's handler is notified for a new log record when + * getUseParentHandlers() is false. + */ + public void testLog_ParentNotInformed() { + Logger child = new MockLogger("childLogger", VALID_RESOURCE_BUNDLE); + Logger parent = new MockParentLogger("parentLogger", + VALID_RESOURCE_BUNDLE2); + + child.setParent(parent); + child.setLevel(Level.INFO); + parent.setLevel(Level.INFO); + parent.addHandler(new MockHandler()); + LogRecord r = new LogRecord(Level.INFO, "testLog_ParentInformed"); + child.setUseParentHandlers(false); + child.log(r); + assertFalse(child.getUseParentHandlers()); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test that a logger with null level and no parent. Defaulted to + * Level.INFO. + */ + public void testLog_NullLevelNoParent() { + LogRecord r = new LogRecord(Level.INFO, "testLog_NullLevelNoParent"); + assertNull(this.sharedLogger.getLevel()); + assertNull(this.sharedLogger.getParent()); + assertTrue(this.sharedLogger.isLoggable(r.getLevel())); + this.sharedLogger.log(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + assertNull(this.sharedLogger.getLevel()); + + r.setLevel(Level.WARNING); + assertTrue(this.sharedLogger.isLoggable(r.getLevel())); + this.sharedLogger.log(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + r.setLevel(Level.CONFIG); + this.sharedLogger.log(r); + assertFalse(this.sharedLogger.isLoggable(r.getLevel())); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test that a logger inherits its parent level when its level is null. + */ + public void testLog_NullLevelHasParent() { + Logger child = new MockLogger("childLogger", VALID_RESOURCE_BUNDLE); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + parent.setLevel(Level.FINER); + + assertNull(child.getLevel()); + + LogRecord r = new LogRecord(Level.FINE, "testLog_NullLevelHasParent"); + child.log(r); + assertTrue(child.isLoggable(r.getLevel())); + // pop only once, pushed by the child logger's handler + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + + assertSame(r.getLoggerName(), null); + assertEquals(r.getMessage(), "testLog_NullLevelHasParent"); + assertSame(r.getResourceBundleName(), null); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + assertNull(child.getLevel()); + + // set the parent logger to disabling level + parent.setLevel(Level.CONFIG); + assertFalse(child.isLoggable(r.getLevel())); + child.log(r); + assertTrue(CallVerificationStack.getInstance().empty()); + assertNull(child.getLevel()); + + // test ancestor + Logger ancestor = new MockLogger("ancestorLogger", + VALID_RESOURCE_BUNDLE3); + parent.setParent(ancestor); + parent.setLevel(null); + parent.setUseParentHandlers(false); + ancestor.setLevel(Level.ALL); + child.log(r); + assertTrue(child.isLoggable(r.getLevel())); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + assertNull(child.getLevel()); + assertNull(parent.getLevel()); + } + + /* + * Test that a logger with null resource bundle and no parent. Defaulted to + * null. + */ + public void testLog_NullResNoParent() { + Logger log = new MockLogger("Logger", null); + log.addHandler(new MockHandler()); + log.setLevel(Level.FINE); + + assertNull(log.getResourceBundle()); + assertNull(log.getResourceBundleName()); + assertNull(log.getParent()); + log.log(Level.INFO, "testLog_NullResNoParent"); + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + assertNull(log.getResourceBundle()); + assertNull(log.getResourceBundleName()); + assertNull(r.getResourceBundle()); + assertNull(r.getResourceBundleName()); + } + + /* + * Test that a logger inherits its parent resource bundle when its resource + * bundle is null. + */ + public void testLog_NullResHasParent() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", VALID_RESOURCE_BUNDLE2); + child.addHandler(new MockHandler()); + child.setParent(parent); + parent.setLevel(Level.FINER); + assertNull(child.getResourceBundle()); + assertNull(child.getResourceBundleName()); + + child.log(Level.FINE, "testLog_NullResHasParent"); + // pop only once, pushed by the child logger's handler + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + + assertSame(r.getLoggerName(), "childLogger"); + assertEquals(r.getMessage(), "testLog_NullResHasParent"); + assertSame(r.getResourceBundleName(), VALID_RESOURCE_BUNDLE2); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + assertNull(child.getResourceBundle()); + assertNull(child.getResourceBundleName()); + } + + /* + * Test that a logger inherits its ancestor's resource bundle when its + * resource bundle and its parent's resource bundle are both null. + */ + public void testLog_NullResHasAncestor() { + Logger child = new MockLogger("childLogger", null); + Logger parent = new MockLogger("parentLogger", null); + Logger ancestor = new MockLogger("ancestorLogger", + VALID_RESOURCE_BUNDLE3); + child.addHandler(new MockHandler()); + child.setParent(parent); + parent.setParent(ancestor); + parent.setLevel(Level.FINER); + assertNull(child.getResourceBundle()); + assertNull(child.getResourceBundleName()); + + child.log(Level.FINE, "testLog_NullResHasAncestor"); + // pop only once, pushed by the child logger's handler + LogRecord r = (LogRecord) CallVerificationStack.getInstance().pop(); + assertTrue(CallVerificationStack.getInstance().empty()); + + assertSame(r.getLoggerName(), "childLogger"); + assertEquals(r.getMessage(), "testLog_NullResHasAncestor"); + assertSame(r.getResourceBundleName(), VALID_RESOURCE_BUNDLE3); + assertSame(r.getSourceClassName(), null); + assertSame(r.getSourceMethodName(), null); + assertSame(r.getLevel(), Level.FINE); + assertNull(r.getParameters()); + assertSame(r.getThrown(), null); + assertNull(child.getResourceBundle()); + assertNull(child.getResourceBundleName()); + } + + /* + * Test when one handler throws an exception. + */ + public void testLog_ExceptionalHandler() { + MockLogger l = new MockLogger("testLog_ExceptionalHandler", null); + l.addHandler(new MockExceptionalHandler()); + l.addHandler(new MockHandler()); + try { + l.severe("testLog_ExceptionalHandler"); + fail("Should throw RuntimeException!"); + } catch (RuntimeException e) { + } + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test whether privileged code is used to load resource bundles. + */ + public void testLoadResourceBundle() { + // + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockNoLoadingClassSecurityManager()); + try { + Logger.getAnonymousLogger(VALID_RESOURCE_BUNDLE); + } finally { + System.setSecurityManager(oldMan); + } + } + + public void testLoadResourceBundleNonExistent() { + try { + // Try a load a non-existent resource bundle. + LoggerExtension.loadResourceBundle("missinglogger.properties"); + fail("Expected an exception."); + } catch (MissingResourceException ex) { + // Expected exception is precisely a MissingResourceException + assertTrue(ex.getClass() == MissingResourceException.class); + } + } + + /** + * @tests java.util.logging.Logger#logrb(Level, String, String, String, + * String, Object) + */ + public void test_init_logger() + throws Exception { + Properties p = new Properties(); + p.put("testGetLogger_Normal_ANewLogger2.level", "ALL"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertNull(LogManager.getLogManager().getLogger( + "testGetLogger_Normal_ANewLogger2")); + SecurityManager originalSecurityManager = System.getSecurityManager(); + try { + System.setSecurityManager(new MockSecurityManagerOtherPermission()); + // should not throw expection + Logger logger = Logger.getLogger("testGetLogger_Normal_ANewLogger2"); + // should throw exception + try{ + logger.setLevel(Level.ALL); + fail("should throw SecurityException"); + } catch (SecurityException e){ + // expected + } + try{ + logger.setParent(Logger.getLogger("root")); + fail("should throw SecurityException"); + } catch (SecurityException e){ + // expected + } + } finally { + System.setSecurityManager(originalSecurityManager); + } + } + + /* + * test initHandler + */ + public void test_initHandler() throws Exception { + File logProps = new File(LOGGING_CONFIG_FILE); + LogManager lm = LogManager.getLogManager(); + lm.readConfiguration(new FileInputStream(logProps)); + + Logger log = Logger.getLogger(""); + // can log properly + Handler[] handlers = log.getHandlers(); + assertEquals(2, handlers.length); + } + + /* + * A mock logger, used to test the protected constructors and fields. + */ + public static class MockLogger extends Logger { + + public MockLogger(String name, String resourceBundleName) { + super(name, resourceBundleName); + } + } + + /* + * A mock logger, used to test inheritance. + */ + public static class MockParentLogger extends Logger { + + public MockParentLogger(String name, String resourceBundleName) { + super(name, resourceBundleName); + } + + public void log(LogRecord record) { + CallVerificationStack.getInstance().push(record); + super.log(record); + } + + } + + /* + * A mock handler, used to validate the expected method is called with the + * expected parameters. + */ + public static class MockHandler extends Handler { + + public void close() { + // System.out.println("close!"); + } + + public void flush() { + // System.out.println("flushed!"); + } + + public void publish(LogRecord record) { + // System.out.println("publish!"); + CallVerificationStack.getInstance().push(record); + } + } + + /* + * A mock handler that throws an exception when publishing a log record. + */ + public static class MockExceptionalHandler extends Handler { + + public void close() { + // System.out.println("close!"); + } + + public void flush() { + // System.out.println("flushed!"); + } + + public void publish(LogRecord record) { + // System.out.println("publish!"); + throw new RuntimeException(); + } + } + + /* + * Used to grant all permissions except logging control. + */ + public static class MockSecurityManager extends SecurityManager { + + public MockSecurityManager() { + } + + public void checkPermission(Permission perm) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + + public void checkPermission(Permission perm, Object context) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + } + + /* + * Used to grant all permissions except getting class loader. + */ + public static class MockNoLoadingClassSecurityManager extends + SecurityManager { + + public MockNoLoadingClassSecurityManager() { + } + + public void checkPermission(Permission perm) { + // grant all permissions except getting class loader + if (perm instanceof RuntimePermission) { + if ("getClassLoader".equals(perm.getName())) { + throw new SecurityException(); + } + } + } + + public void checkPermission(Permission perm, Object context) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + } + + public static class MockSecurityManagerOtherPermission extends + SecurityManager { + + public void checkPermission(Permission permission, Object context) { + if (permission instanceof LoggingPermission) { + if (!permission.getName().equals("control")) { + throw new SecurityException(); + } + return; + } + if (permission.getName().equals("setSecurityManager")) { + return; + } + throw new SecurityException(); + } + + public void checkPermission(Permission permission) { + if (permission instanceof LoggingPermission) { + if (!permission.getName().equals("control")) { + throw new SecurityException(); + } + return; + } + if (permission.getName().equals("setSecurityManager")) { + return; + } + throw new SecurityException(); + } + } + + /* + * A mock filter, always return false. + */ + public static class MockFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + CallVerificationStack.getInstance().push(record); + return false; + } + } + + /* + * A mock filter, always return true. + */ + public static class MockTrueFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + CallVerificationStack.getInstance().push(record); + return true; + } + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggingPermissionTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggingPermissionTest.java new file mode 100644 index 0000000..cd3eee9 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggingPermissionTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.util.logging.LoggingPermission; + +import junit.framework.TestCase; + +import org.apache.harmony.testframework.serialization.SerializationTest; + +public class LoggingPermissionTest extends TestCase { + + /** + * @tests serialization/deserialization compatibility. + */ + public void testSerializationSelf() throws Exception { + SerializationTest.verifySelf(new LoggingPermission("control", "")); + } + + /** + * @tests serialization/deserialization compatibility with RI. + */ + public void testSerializationCompatibility() throws Exception { + + SerializationTest.verifyGolden(this, new LoggingPermission("control", + "")); + } + + public void testLoggingPermission() { + try { + new LoggingPermission(null, null); + fail("should throw IllegalArgumentException"); + } catch (NullPointerException e) { + } + try { + new LoggingPermission("", null); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + new LoggingPermission("bad name", null); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + new LoggingPermission("Control", null); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + new LoggingPermission("control", + "bad action"); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + new LoggingPermission("control", ""); + + new LoggingPermission("control", null); + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/MemoryHandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/MemoryHandlerTest.java new file mode 100644 index 0000000..4a6b52c --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/MemoryHandlerTest.java @@ -0,0 +1,425 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.StringWriter; +import java.security.Permission; +import java.util.Properties; +import java.util.logging.Filter; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.LoggingPermission; +import java.util.logging.MemoryHandler; +import java.util.logging.SimpleFormatter; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream; +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; + +/** + * + */ +public class MemoryHandlerTest extends TestCase { + + final static LogManager manager = LogManager.getLogManager(); + + final static Properties props = new Properties(); + + final static String baseClassName = MemoryHandlerTest.class.getName(); + + final static StringWriter writer = new StringWriter(); + + final static SecurityManager securityManager = new MockSecurityManager(); + + private final PrintStream err = System.err; + + private OutputStream errSubstituteStream = null; + + MemoryHandler handler; + + Handler target = new MockHandler(); + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + manager.reset(); + initProps(); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + errSubstituteStream = new NullOutputStream(); + System.setErr(new PrintStream(errSubstituteStream)); + } + + /** + * + */ + private void initProps() { + props.put("java.util.logging.MemoryHandler.level", "FINE"); + props.put("java.util.logging.MemoryHandler.filter", baseClassName + + "$MockFilter"); + props.put("java.util.logging.MemoryHandler.size", "2"); + props.put("java.util.logging.MemoryHandler.push", "WARNING"); + props.put("java.util.logging.MemoryHandler.target", baseClassName + + "$MockHandler"); + props.put("java.util.logging.MemoryHandler.formatter", baseClassName + + "$MockFormatter"); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + super.tearDown(); + manager.readConfiguration(); + props.clear(); + System.setErr(err); + } + + public void testSecurity() { + SecurityManager currentManager = System.getSecurityManager(); + System.setSecurityManager(securityManager); + try { + try { + handler.close(); + fail("should throw security exception"); + } catch (SecurityException e) { + } + try { + handler.setPushLevel(Level.CONFIG); + fail("should throw security exception"); + } catch (SecurityException e) { + } + handler.flush(); + handler.push(); + handler.getPushLevel(); + handler.isLoggable(new LogRecord(Level.ALL, "message")); + handler.publish(new LogRecord(Level.ALL, "message")); + } finally { + System.setSecurityManager(currentManager); + } + + } + + public void testClose() { + Filter filter = handler.getFilter(); + Formatter formatter = handler.getFormatter(); + writer.getBuffer().setLength(0); + handler.close(); + assertEquals(writer.toString(), "close"); + assertEquals(handler.getFilter(), filter); + assertEquals(handler.getFormatter(), formatter); + assertNull(handler.getEncoding()); + assertNotNull(handler.getErrorManager()); + assertEquals(handler.getLevel(), Level.OFF); + assertEquals(handler.getPushLevel(), Level.WARNING); + assertFalse(handler.isLoggable(new LogRecord(Level.SEVERE, "test"))); + } + + public void testFlush() { + Filter filter = handler.getFilter(); + Formatter formatter = handler.getFormatter(); + writer.getBuffer().setLength(0); + handler.flush(); + assertEquals(writer.toString(), "flush"); + assertEquals(handler.getFilter(), filter); + assertEquals(handler.getFormatter(), formatter); + assertNull(handler.getEncoding()); + assertNotNull(handler.getErrorManager()); + assertEquals(handler.getLevel(), Level.FINE); + assertEquals(handler.getPushLevel(), Level.WARNING); + assertTrue(handler.isLoggable(new LogRecord(Level.SEVERE, "test"))); + } + + public void testIsLoggable() { + try { + handler.isLoggable(null); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + // expected + } + LogRecord record = new LogRecord(Level.FINER, "MSG1"); + assertFalse(handler.isLoggable(record)); + + record = new LogRecord(Level.FINE, "MSG2"); + assertTrue(handler.isLoggable(record)); + + record = new LogRecord(Level.CONFIG, "MSG3"); + assertTrue(handler.isLoggable(record)); + + record = new LogRecord(Level.CONFIG, "false"); + assertFalse(handler.isLoggable(record)); + + handler.setFilter(null); + record = new LogRecord(Level.CONFIG, "false"); + assertTrue(handler.isLoggable(record)); + } + + /* + * Class under test for void MemoryHandler() + */ + public void testMemoryHandler() { + assertNotNull("Filter should not be null", handler.getFilter()); + assertNotNull("Formatter should not be null", handler.getFormatter()); + assertNull("character encoding should be null", handler.getEncoding()); + assertNotNull("ErrorManager should not be null", handler + .getErrorManager()); + assertEquals("Level should be FINE", Level.FINE, handler.getLevel()); + assertEquals("Level should be WARNING", Level.WARNING, handler + .getPushLevel()); + } + + public void testMemoryHandlerInvalidProps() throws IOException { + // null target + try { + props.remove("java.util.logging.MemoryHandler.target"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + fail("should throw RuntimeException: target must be set"); + } catch (RuntimeException e) { + } + + // invalid target + try { + props.put("java.util.logging.MemoryHandler.target", "badname"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + fail("should throw RuntimeException: target must be valid"); + } catch (RuntimeException e) { + } + + // invalid formatter + initProps(); + props.put("java.util.logging.MemoryHandler.formatter", "badname"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + assertTrue(handler.getFormatter() instanceof SimpleFormatter); + + // invalid level + initProps(); + props.put("java.util.logging.MemoryHandler.level", "badname"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + assertEquals(handler.getLevel(), Level.ALL); + + // invalid pushlevel + initProps(); + props.put("java.util.logging.MemoryHandler.push", "badname"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + assertEquals(handler.getPushLevel(), Level.SEVERE); + + // invalid filter + initProps(); + props.put("java.util.logging.MemoryHandler.filter", "badname"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + assertNull(handler.getFilter()); + + // invalid size + initProps(); + props.put("java.util.logging.MemoryHandler.size", "-1"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + initProps(); + props.put("java.util.logging.MemoryHandler.size", "badsize"); + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + + } + + public void testMemoryHandlerDefaultValue() throws SecurityException, + IOException { + props.clear(); + props.put("java.util.logging.MemoryHandler.target", baseClassName + + "$MockHandler"); + + manager.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + handler = new MemoryHandler(); + assertNull(handler.getFilter()); + assertTrue(handler.getFormatter() instanceof SimpleFormatter); + assertNull(handler.getEncoding()); + assertNotNull(handler.getErrorManager()); + assertEquals(handler.getLevel(), Level.ALL); + assertEquals(handler.getPushLevel(), Level.SEVERE); + } + + /* + * Class under test for void MemoryHandler(Handler, int, Level) + */ + public void testMemoryHandlerHandlerintLevel() { + handler = new MemoryHandler(target, 2, Level.FINEST); + assertNotNull("Filter should not be null", handler.getFilter()); + assertNotNull("Formatter should not be null", handler.getFormatter()); + assertNull("character encoding should be null", handler.getEncoding()); + assertNotNull("ErrorManager should not be null", handler + .getErrorManager()); + assertEquals("Level should be FINE", Level.FINE, handler.getLevel()); + assertEquals("Level should be FINEST", Level.FINEST, handler + .getPushLevel()); + + try { + new MemoryHandler(null, 2, Level.FINEST); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + } + try { + new MemoryHandler(target, 2, null); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + } + try { + new MemoryHandler(target, 0, Level.FINEST); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + new MemoryHandler(target, -1, Level.FINEST); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + } + + public void testGetPushLevel() { + try { + handler.setPushLevel(null); + fail("should throw NullPointerException"); + } catch (NullPointerException e) { + } + handler.setPushLevel(Level.parse("123")); + assertEquals(handler.getPushLevel(), Level.parse("123")); + } + + public void testSetPushLevel() { + // change push level don't trigger push action + writer.getBuffer().setLength(0); + LogRecord lr = new LogRecord(Level.CONFIG, "lr"); + assertTrue(handler.isLoggable(lr)); + handler.publish(lr); + assertEquals(writer.toString(), ""); + // assertEquals(writer.toString(), "flush"); + writer.getBuffer().setLength(0); + handler.setPushLevel(Level.FINE); + assertEquals(writer.toString(), ""); + handler.publish(lr); + assertEquals(writer.toString(), lr.getMessage() + lr.getMessage()); + } + + public void testPushPublic() { + writer.getBuffer().setLength(0); + // loggable but don't trig push + handler.publish(new LogRecord(Level.CONFIG, "MSG1")); + assertEquals("", writer.toString()); + // trig push + handler.publish(new LogRecord(Level.SEVERE, "MSG2")); + assertEquals(writer.toString(), "MSG1MSG2"); + writer.getBuffer().setLength(0); + + // regression test for Harmony-1292 + handler.publish(new LogRecord(Level.WARNING, "MSG")); + assertEquals("MSG",writer.toString()); + + writer.getBuffer().setLength(0); + // push nothing + handler.push(); + assertEquals("", writer.toString()); + // loggable but not push + handler.publish(new LogRecord(Level.CONFIG, "MSG3")); + assertEquals("", writer.toString()); + // not loggable + handler.publish(new LogRecord(Level.FINEST, "MSG4")); + assertEquals("", writer.toString()); + // loggable but not push + handler.publish(new LogRecord(Level.CONFIG, "MSG5")); + assertEquals("", writer.toString()); + // not loggable + handler.publish(new LogRecord(Level.FINER, "MSG6")); + assertEquals("", writer.toString()); + // not loggable + handler.publish(new LogRecord(Level.FINER, "false")); + assertEquals("", writer.toString()); + // loggable but not push + handler.publish(new LogRecord(Level.CONFIG, "MSG8")); + assertEquals("", writer.toString()); + // push all + handler.push(); + assertEquals(writer.toString(), "MSG5MSG8"); + writer.getBuffer().setLength(0); + handler.push(); + assertEquals("", writer.toString()); + } + + /* + * mock classes + */ + public static class MockFilter implements Filter { + public boolean isLoggable(LogRecord record) { + return !record.getMessage().equals("false"); + } + } + + public static class MockHandler extends Handler { + public void close() { + writer.write("close"); + } + + public void flush() { + writer.write("flush"); + } + + public void publish(LogRecord record) { + writer.write(record.getMessage()); + } + + } + + public static class MockFormatter extends Formatter { + public String format(LogRecord r) { + return r.getMessage(); + } + } + + public static class MockSecurityManager extends SecurityManager { + public void checkPermission(Permission perm) { + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + return; + } + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/SimpleFormatterTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/SimpleFormatterTest.java new file mode 100644 index 0000000..65111af --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/SimpleFormatterTest.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.util.Calendar; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.SimpleFormatter; + +import junit.framework.TestCase; + +/** + * + */ +public class SimpleFormatterTest extends TestCase { + + SimpleFormatter sf; + + LogRecord lr; + + private static String MSG = "test msg. pls. ignore it\nadaadasfdasfd\nadfafdadfsa"; + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + sf = new SimpleFormatter(); + lr = new LogRecord(Level.FINE, MSG); + } + + /* + * test for constructor protected SimpleFormatter + */ + public void testSimpleFormatter() { + assertEquals("Head for this SimpleFormatter should be empty", "", sf + .getHead(null)); + assertEquals("Tail for this SimpleFormatter should be empty", "", sf + .getTail(null)); + } + + public void testFormatNull() { + try { + sf.format(null); + fail("should throw nullpointer exception"); + } catch (NullPointerException e) { + } + sf.format(new LogRecord(Level.SEVERE, null)); + } + + public void testLocalizedFormat() { + // if bundle set, should use localized message + ResourceBundle rb = ResourceBundle + .getBundle("bundles/java/util/logging/res"); + lr.setResourceBundle(rb); + lr.setMessage("msg"); + String localeMsg = rb.getString("msg"); + String str = sf.format(lr); + assertTrue(str.indexOf(localeMsg) > 0); + + // if bundle not set but bundle name set, should use original message + lr.setResourceBundle(null); + lr.setResourceBundleName("bundles/java/util/logging/res"); + lr.setMessage("msg"); + str = sf.format(lr); + localeMsg = rb.getString("msg"); + assertTrue(str.indexOf(localeMsg) < 0); + } + + public void testFormat() { + String str = sf.format(lr); + Throwable t; + + lr.setMessage(MSG + " {0,number}"); + lr.setLoggerName("logger"); + lr.setResourceBundleName("rb name"); + lr.setSourceClassName("class"); + lr.setSourceMethodName("method"); + lr.setParameters(new Object[] { new Integer(100), new Object() }); + lr.setThreadID(1000); + lr.setThrown(t = new Exception("exception") { + private static final long serialVersionUID = 1L; + + public String getLocalizedMessage() { + return "locale"; + } + }); + lr.setSequenceNumber(12321312); + lr.setMillis(0); + str = sf.format(lr); + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(12321312); + assertTrue(str.indexOf(String.valueOf(cal.get(Calendar.YEAR))) >= 0); + assertTrue(str.indexOf("class") > 0); + assertTrue(str.indexOf("method") > 0); + assertTrue(str.indexOf("100") > 0); + assertTrue(str.indexOf(t.toString()) > 0); + assertTrue(str.indexOf(Level.FINE.getLocalizedName()) > 0); + } + + public void testGetHead() { + assertEquals("", sf.getHead(null)); + } + + public void testGetTail() { + assertEquals("", sf.getTail(null)); + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/SocketHandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/SocketHandlerTest.java new file mode 100644 index 0000000..75915e7 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/SocketHandlerTest.java @@ -0,0 +1,875 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.security.Permission; +import java.util.Properties; +import java.util.logging.Filter; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.LoggingPermission; +import java.util.logging.SocketHandler; +import java.util.logging.XMLFormatter; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream; +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; + +import tests.util.CallVerificationStack; + +/** + * Test class java.util.logging.ConsoleHandler + */ +public class SocketHandlerTest extends TestCase { + + private static final LogManager LOG_MANAGER = LogManager.getLogManager(); + + private final static String INVALID_LEVEL = "impossible_level"; + + private final PrintStream err = System.err; + + private OutputStream errSubstituteStream = null; + + private static String className = SocketHandlerTest.class.getName(); + + private SocketHandler h = null; + + private Properties props; + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + errSubstituteStream = new NullOutputStream(); + System.setErr(new PrintStream(errSubstituteStream)); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + initProps(); + LOG_MANAGER.reset(); + LOG_MANAGER.readConfiguration(EnvironmentHelper + .PropertiesToInputStream(props)); + CallVerificationStack.getInstance().clear(); + if (null != h) { + h.close(); + h = null; + } + System.setErr(err); + super.tearDown(); + } + + + private void initProps() throws Exception { + props = new Properties(); + props.put("handlers", className + "$MockHandler " + className + + "$MockHandler"); + props.put("java.util.logging.FileHandler.pattern", "%h/java%u.log"); + props.put("java.util.logging.FileHandler.limit", "50000"); + props.put("java.util.logging.FileHandler.count", "5"); + props.put("java.util.logging.FileHandler.formatter", + "java.util.logging.XMLFormatter"); + props.put(".level", "FINE"); + props.put("java.util.logging.ConsoleHandler.level", "OFF"); + props.put("java.util.logging.ConsoleHandler.formatter", + "java.util.logging.SimpleFormatter"); + props.put("foo.handlers", "java.util.logging.ConsoleHandler"); + props.put("foo.level", "WARNING"); + props.put("com.xyz.foo.level", "SEVERE"); + } + + /* + * Test the constructor with no relevant log manager properties are set. + */ + public void testConstructor_NoProperties() throws Exception { + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.level")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.filter")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.formatter")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.encoding")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.host")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.port")); + + try { + h = new SocketHandler(); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + h = new SocketHandler(null, 0); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + h = new SocketHandler("", 0); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + h = new SocketHandler("127.0.0.1", -1); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + h = new SocketHandler("127.0.0.1", Integer.MAX_VALUE); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + h = new SocketHandler("127.0.0.1", 66666); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + try { + h = new SocketHandler("127.0.0.1", 0); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + } + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler("127.0.0.1", 6666); + assertSame(h.getLevel(), Level.ALL); + assertTrue(h.getFormatter() instanceof XMLFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + } + + /* + * Test the constructor with no relevant log manager properties are set + * except host and port. + */ + public void testConstructor_NoBasicProperties() throws Exception { + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.level")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.filter")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.formatter")); + assertNull(LOG_MANAGER.getProperty( + "java.util.logging.SocketHandler.encoding")); + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + assertSame(h.getLevel(), Level.ALL); + assertTrue(h.getFormatter() instanceof XMLFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + + try { + h = new SocketHandler("127.0.sdfcdsfsa%%&&^0.1", 6665); + fail("Should throw IOException!"); + } catch (IOException e) { + } + } + + /* + * Test the constructor with insufficient privilege for connection. + */ + public void testConstructor_InsufficientPrivilege() throws Exception { + SecurityManager oldMan = null; + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.level", "FINE"); + p.put("java.util.logging.SocketHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.encoding", "utf-8"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockNoSocketSecurityManager()); + try { + new SocketHandler(); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + System.setSecurityManager(new MockNoSocketSecurityManager()); + try { + new SocketHandler("127.0.0.1", 6666); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test the constructor with valid relevant log manager properties are set. + */ + public void testConstructor_ValidProperties() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.level", "FINE"); + p.put("java.util.logging.SocketHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.encoding", "iso-8859-1"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + assertSame(h.getLevel(), Level.parse("FINE")); + assertTrue(h.getFormatter() instanceof MockFormatter); + assertTrue(h.getFilter() instanceof MockFilter); + assertEquals(h.getEncoding(), "iso-8859-1"); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + + // start the server to be ready to accept log messages + thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler("127.0.0.1", 6666); + assertSame(h.getLevel(), Level.parse("FINE")); + assertTrue(h.getFormatter() instanceof MockFormatter); + assertTrue(h.getFilter() instanceof MockFilter); + assertEquals(h.getEncoding(), "iso-8859-1"); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + } + + /* + * Test the constructor with invalid relevant log manager properties are set + * except host and port. + */ + public void testConstructor_InvalidBasicProperties() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.level", INVALID_LEVEL); + p.put("java.util.logging.SocketHandler.filter", className + ""); + p.put("java.util.logging.SocketHandler.formatter", className + ""); + p.put("java.util.logging.SocketHandler.encoding", "XXXX"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + assertSame(h.getLevel(), Level.ALL); + assertTrue(h.getFormatter() instanceof XMLFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + h.publish(new LogRecord(Level.SEVERE, "test")); + assertNull(h.getEncoding()); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + + // start the server to be ready to accept log messages + thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler("127.0.0.1", 6666); + assertSame(h.getLevel(), Level.ALL); + assertTrue(h.getFormatter() instanceof XMLFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + h.publish(new LogRecord(Level.SEVERE, "test")); + assertNull(h.getEncoding()); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + } + + /* + * Test the constructor with valid relevant log manager properties are set + * except port. + */ + public void testConstructor_InvalidPort() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.level", "FINE"); + p.put("java.util.logging.SocketHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.encoding", "iso-8859-1"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666i"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + try { + h = new SocketHandler(); + fail("Should throw IllegalArgumentException!"); + } catch (IllegalArgumentException e) { + + } + } + + /* + * Test the constructor with valid relevant log manager properties are set, + * but the port is not open. + */ + public void testConstructor_NotOpenPort() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.level", "FINE"); + p.put("java.util.logging.SocketHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.encoding", "iso-8859-1"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6665"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + try { + h = new SocketHandler(); + fail("Should throw IOException!"); + } catch (IOException e) { + + } + + try { + h = new SocketHandler("127.0.0.1", 6665); + fail("Should throw IOException!"); + } catch (IOException e) { + + } + } + + /* + * Test the constructor with valid relevant log manager properties are set + * except port. + */ + public void testConstructor_InvalidHost() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.level", "FINE"); + p.put("java.util.logging.SocketHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.encoding", "iso-8859-1"); + p.put("java.util.logging.SocketHandler.host", " 34345 #$#%$%$"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + try { + h = new SocketHandler(); + fail("Should throw IOException!"); + } catch (IOException e) { + + } + + try { + h = new SocketHandler(" 34345 #$#%$%$", 6666); + fail("Should throw IOException!"); + } catch (IOException e) { + + } + } + + /* + * Test close() when having sufficient privilege, and a record has been + * written to the output stream. + */ + public void testClose_SufficientPrivilege_NormalClose() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + h.publish(new LogRecord(Level.SEVERE, + "testClose_SufficientPrivilege_NormalClose msg")); + h.close(); + assertEquals("MockFormatter_Head" + + "testClose_SufficientPrivilege_NormalClose msg" + + "MockFormatter_Tail", thread.getReadString()); + h.close(); + } + + /* + * Test close() when having sufficient privilege, and no record has been + * written to the output stream. + */ + public void testClose_SufficientPrivilege_DirectClose() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + h.setLevel(Level.INFO); + + h.close(); + assertEquals("MockFormatter_Head" + "MockFormatter_Tail", thread + .getReadString()); + } + + /* + * Test close() when having insufficient privilege. + */ + public void testClose_InsufficientPrivilege() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + h.setLevel(Level.INFO); + + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + h.close(); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + } finally { + System.setSecurityManager(oldMan); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + } + } + + /* + * Test publish(), use no filter, having output stream, normal log record. + */ + public void testPublish_NoFilter() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + + h = new SocketHandler(); + h.setLevel(Level.INFO); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_NoFilter"); + h.setLevel(Level.INFO); + h.publish(r); + + h.setLevel(Level.WARNING); + h.publish(r); + + h.setLevel(Level.CONFIG); + h.publish(r); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + h.publish(r); + h.close(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter" + + "testPublish_NoFilter" + "MockFormatter_Tail", thread + .getReadString()); + } + + /* + * Test publish(), use a filter, having output stream, normal log record. + */ + public void testPublish_WithFilter() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + h = new SocketHandler(); + h.setLevel(Level.INFO); + h.setFilter(new MockFilter()); + + System.setErr(new PrintStream(new ByteArrayOutputStream())); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_WithFilter"); + h.setLevel(Level.INFO); + h.publish(r); + h.close(); + assertEquals("MockFormatter_Head" + "MockFormatter_Tail", thread + .getReadString()); + } + + /* + * Test publish(), null log record, having output stream + */ + public void testPublish_Null() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + h = new SocketHandler(); + h.setLevel(Level.INFO); + try { + h.publish(null); + } finally { + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + } + } + + /* + * Test publish(), a log record with empty msg, having output stream + */ + public void testPublish_EmptyMsg() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + h = new SocketHandler(); + h.setLevel(Level.INFO); + LogRecord r = new LogRecord(Level.INFO, ""); + h.publish(r); + h.close(); + assertEquals("MockFormatter_Head" + "MockFormatter_Tail", thread + .getReadString()); + } + + /* + * Test publish(), a log record with null msg, having output stream + */ + public void testPublish_NullMsg() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + h = new SocketHandler(); + h.setLevel(Level.INFO); + LogRecord r = new LogRecord(Level.INFO, null); + h.publish(r); + h.close(); + assertEquals("MockFormatter_Head" + "MockFormatter_Tail", thread + .getReadString()); + } + + /* + * Test publish(), after close. + */ + public void testPublish_AfterClose() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.SocketHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.SocketHandler.host", "127.0.0.1"); + p.put("java.util.logging.SocketHandler.port", "6666"); + LOG_MANAGER.readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + // start the server to be ready to accept log messages + ServerThread thread = new ServerThread(); + thread.start(); + Thread.sleep(2000); + h = new SocketHandler(); + h.setLevel(Level.FINE); + + assertSame(h.getLevel(), Level.FINE); + LogRecord r = new LogRecord(Level.INFO, "testPublish_NoFormatter"); + assertTrue(h.isLoggable(r)); + h.close(); + // ensure the thread exits and the port becomes available again + thread.getReadString(); + // assertFalse(h.isLoggable(r)); + h.publish(r); + h.flush(); + // assertEquals("MockFormatter_Head", + // this.errSubstituteStream.toString()); + } + + /* + * A mock filter, always return false. + */ + public static class MockFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + CallVerificationStack.getInstance().push(record); + // System.out.println("filter called..."); + return false; + } + } + + /* + * A mock formatter. + */ + public static class MockFormatter extends Formatter { + public String format(LogRecord r) { + // System.out.println("formatter called..."); + return super.formatMessage(r); + } + + /* + * (non-Javadoc) + * + * @see java.util.logging.Formatter#getHead(java.util.logging.Handler) + */ + public String getHead(Handler h) { + return "MockFormatter_Head"; + } + + /* + * (non-Javadoc) + * + * @see java.util.logging.Formatter#getTail(java.util.logging.Handler) + */ + public String getTail(Handler h) { + return "MockFormatter_Tail"; + } + } + + /* + * Used to grant all permissions except logging control. + */ + public static class MockSecurityManager extends SecurityManager { + + public MockSecurityManager() { + } + + public void checkPermission(Permission perm) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + + public void checkPermission(Permission perm, Object context) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + } + + /* + * Used to grant all permissions except logging control. + */ + public static class MockNoSocketSecurityManager extends SecurityManager { + + public MockNoSocketSecurityManager() { + } + + public void checkPermission(Permission perm) { + } + + public void checkPermission(Permission perm, Object context) { + } + + public void checkConnect(String host, int port) { + throw new SecurityException(); + } + } + + /* + * A mock stream handler, expose setOutputStream. + */ + public static class MockSocketHandler extends SocketHandler { + public MockSocketHandler() throws Exception { + super(); + } + + public void setOutputStream(OutputStream out) { + super.setOutputStream(out); + } + + public boolean isLoggable(LogRecord r) { + CallVerificationStack.getInstance().push(r); + return super.isLoggable(r); + } + } + + /* + * A server thread that accepts an incoming connection request and reads any + * incoming data into an byte array. + */ + public static class ServerThread extends Thread { + + private volatile StringBuffer sb = new StringBuffer(); + + private volatile boolean finished = false; + + public boolean finished() { + return this.finished; + } + + public String getReadString() throws Exception { + int i = 0; + while (!this.finished) { + sleep(100); + if (++i > 100) { + // connect to port 6666 to stop the listening. + try { + Socket s = new Socket("127.0.0.1", 6666); + OutputStream os = s.getOutputStream(); + os.write(1); + os.close(); + s.close(); + } catch (Exception e) { + // ignore + } + } + } + return this.sb.toString(); + } + + public void run() { + ServerSocket ss = null; + Socket s = null; + InputStreamReader reader = null; + try { + char[] buffer = new char[32]; + ss = new ServerSocket(6666); + s = ss.accept(); + reader = new InputStreamReader(s.getInputStream()); + while (true) { + int length = reader.read(buffer); + if (-1 == length) { + break; + } + this.sb.append(buffer, 0, length); + } + } catch (Exception e) { + e.printStackTrace(System.err); + } finally { + try { + if (null != reader) { + reader.close(); + s.close(); + ss.close(); + } + } catch (Exception e) { + e.printStackTrace(System.err); + } + this.finished = true; + } + } + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/StreamHandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/StreamHandlerTest.java new file mode 100644 index 0000000..ba9d775 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/StreamHandlerTest.java @@ -0,0 +1,1082 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; +import java.security.Permission; +import java.util.Arrays; +import java.util.Properties; +import java.util.logging.Filter; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.LoggingPermission; +import java.util.logging.SimpleFormatter; +import java.util.logging.StreamHandler; + +import junit.framework.TestCase; + +import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream; +import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper; +import tests.util.CallVerificationStack; + +/** + * Test the class StreamHandler. + */ +public class StreamHandlerTest extends TestCase { + + private final static String INVALID_LEVEL = "impossible_level"; + + private final PrintStream err = System.err; + + private OutputStream errSubstituteStream = null; + + private static String className = StreamHandlerTest.class.getName(); + + private static CharsetEncoder encoder; + + static { + encoder = Charset.forName("iso-8859-1").newEncoder(); + encoder.onMalformedInput(CodingErrorAction.REPLACE); + encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + } + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + errSubstituteStream = new NullOutputStream(); + System.setErr(new PrintStream(errSubstituteStream)); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + LogManager.getLogManager().reset(); + CallVerificationStack.getInstance().clear(); + System.setErr(err); + super.tearDown(); + } + + /* + * Test the constructor with no parameter, and no relevant log manager + * properties are set. + */ + public void testConstructor_NoParameter_NoProperties() { + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.filter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.formatter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + + StreamHandler h = new StreamHandler(); + assertSame(Level.INFO, h.getLevel()); + assertTrue(h.getFormatter() instanceof SimpleFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + } + + /* + * Test the constructor with insufficient privilege. + */ + public void testConstructor_NoParameter_InsufficientPrivilege() { + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.filter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.formatter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + // set a normal value + try { + StreamHandler h = new StreamHandler(); + assertSame(Level.INFO, h.getLevel()); + assertTrue(h.getFormatter() instanceof SimpleFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test the constructor with no parameter, and valid relevant log manager + * properties are set. + */ + public void testConstructor_NoParameter_ValidProperties() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", "FINE"); + p.put("java.util.logging.StreamHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.StreamHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.StreamHandler.encoding", "iso-8859-1"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals("FINE", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertEquals("iso-8859-1", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + StreamHandler h = new StreamHandler(); + assertSame(h.getLevel(), Level.parse("FINE")); + assertTrue(h.getFormatter() instanceof MockFormatter); + assertTrue(h.getFilter() instanceof MockFilter); + assertEquals("iso-8859-1", h.getEncoding()); + } + + /* + * Test the constructor with no parameter, and invalid relevant log manager + * properties are set. + */ + public void testConstructor_NoParameter_InvalidProperties() + throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", INVALID_LEVEL); + p.put("java.util.logging.StreamHandler.filter", className + ""); + p.put("java.util.logging.StreamHandler.formatter", className + ""); + p.put("java.util.logging.StreamHandler.encoding", "XXXX"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals(INVALID_LEVEL, LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertEquals("XXXX", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + StreamHandler h = new StreamHandler(); + assertSame(Level.INFO, h.getLevel()); + assertTrue(h.getFormatter() instanceof SimpleFormatter); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + h.publish(new LogRecord(Level.SEVERE, "test")); + assertTrue(CallVerificationStack.getInstance().empty()); + assertNull(h.getEncoding()); + } + + /* + * Test the constructor with normal parameter values, and no relevant log + * manager properties are set. + */ + public void testConstructor_HasParameters_NoProperties() { + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.filter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.formatter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new MockFormatter2()); + assertSame(Level.INFO, h.getLevel()); + assertTrue(h.getFormatter() instanceof MockFormatter2); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + } + + /* + * Test the constructor with insufficient privilege. + */ + public void testConstructor_HasParameter_InsufficientPrivilege() { + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.filter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.formatter")); + assertNull(LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + // set a normal value + try { + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new MockFormatter2()); + assertSame(Level.INFO, h.getLevel()); + assertTrue(h.getFormatter() instanceof MockFormatter2); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test the constructor with normal parameter values, and valid relevant log + * manager properties are set. + */ + public void testConstructor_HasParameters_ValidProperties() + throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", "FINE"); + p.put("java.util.logging.StreamHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.StreamHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.StreamHandler.encoding", "iso-8859-1"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals("FINE", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertEquals("iso-8859-1", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new MockFormatter2()); + assertSame(h.getLevel(), Level.parse("FINE")); + assertTrue(h.getFormatter() instanceof MockFormatter2); + assertTrue(h.getFilter() instanceof MockFilter); + assertEquals("iso-8859-1", h.getEncoding()); + } + + /* + * Test the constructor with normal parameter, and invalid relevant log + * manager properties are set. + */ + public void testConstructor_HasParameters_InvalidProperties() + throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", INVALID_LEVEL); + p.put("java.util.logging.StreamHandler.filter", className + ""); + p.put("java.util.logging.StreamHandler.formatter", className + ""); + p.put("java.util.logging.StreamHandler.encoding", "XXXX"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals(INVALID_LEVEL, LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertEquals("XXXX", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new MockFormatter2()); + assertSame(Level.INFO, h.getLevel()); + assertTrue(h.getFormatter() instanceof MockFormatter2); + assertNull(h.getFilter()); + assertNull(h.getEncoding()); + } + + /* + * Test the constructor with null formatter, and invalid relevant log manager + * properties are set. + */ + public void testConstructor_HasParameters_ValidPropertiesNullStream() + throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", "FINE"); + p.put("java.util.logging.StreamHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.StreamHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.StreamHandler.encoding", "iso-8859-1"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals("FINE", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertEquals("iso-8859-1", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + try { + new StreamHandler(new ByteArrayOutputStream(), null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + // expected + } + } + + /* + * Test the constructor with null output stream, and invalid relevant log + * manager properties are set. + */ + public void testConstructor_HasParameters_ValidPropertiesNullFormatter() + throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", "FINE"); + p.put("java.util.logging.StreamHandler.filter", className + + "$MockFilter"); + p.put("java.util.logging.StreamHandler.formatter", className + + "$MockFormatter"); + p.put("java.util.logging.StreamHandler.encoding", "iso-8859-1"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + assertEquals("FINE", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.level")); + assertEquals("iso-8859-1", LogManager.getLogManager().getProperty( + "java.util.logging.StreamHandler.encoding")); + try { + new StreamHandler(null, new MockFormatter2()); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + // expected + } + } + + /* + * Test close() when having sufficient privilege, and a record has been + * written to the output stream. + */ + public void testClose_SufficientPrivilege_NormalClose() { + ByteArrayOutputStream aos = new MockOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.publish(new LogRecord(Level.SEVERE, + "testClose_SufficientPrivilege_NormalClose msg")); + h.close(); + assertEquals("close", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + assertNull(CallVerificationStack.getInstance().pop()); + assertEquals("flush", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + CallVerificationStack.getInstance().clear(); + assertTrue(aos.toString().endsWith("MockFormatter_Tail")); + h.close(); + } + + /* + * Test close() when having sufficient privilege, and an output stream that + * always throws exceptions. + */ + public void testClose_SufficientPrivilege_Exception() { + ByteArrayOutputStream aos = new MockExceptionOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.publish(new LogRecord(Level.SEVERE, + "testClose_SufficientPrivilege_Exception msg")); + h.flush(); + h.close(); + } + + /* + * Test close() when having sufficient privilege, and no record has been + * written to the output stream. + */ + public void testClose_SufficientPrivilege_DirectClose() { + ByteArrayOutputStream aos = new MockOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.close(); + assertEquals("close", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + assertNull(CallVerificationStack.getInstance().pop()); + assertEquals("flush", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + CallVerificationStack.getInstance().clear(); + assertEquals("MockFormatter_HeadMockFormatter_Tail", aos.toString() + ); + } + + /* + * Test close() when having insufficient privilege. + */ + public void testClose_InsufficientPrivilege() { + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + try { + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new MockFormatter()); + h.close(); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + // expected + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * Test close() when having no output stream. + */ + public void testClose_NoOutputStream() { + StreamHandler h = new StreamHandler(); + h.close(); + } + + /* + * Test flush(). + */ + public void testFlush_Normal() { + ByteArrayOutputStream aos = new MockOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.flush(); + assertEquals("flush", CallVerificationStack.getInstance() + .getCurrentSourceMethod()); + assertNull(CallVerificationStack.getInstance().pop()); + CallVerificationStack.getInstance().clear(); + } + + /* + * Test flush() when having no output stream. + */ + public void testFlush_NoOutputStream() { + StreamHandler h = new StreamHandler(); + h.flush(); + } + + /* + * Test isLoggable(), use no filter, having output stream + */ + public void testIsLoggable_NoOutputStream() { + StreamHandler h = new StreamHandler(); + LogRecord r = new LogRecord(Level.INFO, null); + assertFalse(h.isLoggable(r)); + + h.setLevel(Level.WARNING); + assertFalse(h.isLoggable(r)); + + h.setLevel(Level.CONFIG); + assertFalse(h.isLoggable(r)); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + assertFalse(h.isLoggable(r)); + } + + /* + * Test isLoggable(), use no filter, having output stream + */ + public void testIsLoggable_NoFilter() { + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new SimpleFormatter()); + LogRecord r = new LogRecord(Level.INFO, null); + assertTrue(h.isLoggable(r)); + + h.setLevel(Level.WARNING); + assertFalse(h.isLoggable(r)); + + h.setLevel(Level.CONFIG); + assertTrue(h.isLoggable(r)); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + assertFalse(h.isLoggable(r)); + } + + /* + * Test isLoggable(), use a filter, having output stream + */ + public void testIsLoggable_WithFilter() { + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new SimpleFormatter()); + LogRecord r = new LogRecord(Level.INFO, null); + h.setFilter(new MockFilter()); + assertFalse(h.isLoggable(r)); + assertSame(r, CallVerificationStack.getInstance().pop()); + + h.setLevel(Level.CONFIG); + assertFalse(h.isLoggable(r)); + assertSame(r, CallVerificationStack.getInstance().pop()); + + h.setLevel(Level.WARNING); + assertFalse(h.isLoggable(r)); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test isLoggable(), null log record, having output stream. Handler should + * call ErrorManager to handle exceptional case + */ + public void testIsLoggable_Null() { + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new SimpleFormatter()); + assertFalse(h.isLoggable(null)); + } + + /* + * Test isLoggable(), null log record, without output stream + */ + public void testIsLoggable_Null_NoOutputStream() { + StreamHandler h = new StreamHandler(); + assertFalse(h.isLoggable(null)); + } + + /* + * Test publish(), use no filter, having output stream, normal log record. + */ + public void testPublish_NoOutputStream() { + StreamHandler h = new StreamHandler(); + LogRecord r = new LogRecord(Level.INFO, "testPublish_NoOutputStream"); + h.publish(r); + + h.setLevel(Level.WARNING); + h.publish(r); + + h.setLevel(Level.CONFIG); + h.publish(r); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + h.publish(r); + } + + /* + * Test publish(), use no filter, having output stream, normal log record. + */ + public void testPublish_NoFilter() { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_NoFilter"); + h.setLevel(Level.INFO); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter", aos + .toString()); + + h.setLevel(Level.WARNING); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter", aos + .toString()); + + h.setLevel(Level.CONFIG); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter" + + "testPublish_NoFilter", aos.toString()); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head" + "testPublish_NoFilter" + + "testPublish_NoFilter", aos.toString()); + } + + /* + * Test publish(), use a filter, having output stream, normal log record. + */ + public void testPublish_WithFilter() { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.setFilter(new MockFilter()); + + LogRecord r = new LogRecord(Level.INFO, "testPublish_WithFilter"); + h.setLevel(Level.INFO); + h.publish(r); + h.flush(); + assertEquals("", aos.toString()); + assertSame(r, CallVerificationStack.getInstance().pop()); + + h.setLevel(Level.WARNING); + h.publish(r); + h.flush(); + assertEquals("", aos.toString()); + assertTrue(CallVerificationStack.getInstance().empty()); + + h.setLevel(Level.CONFIG); + h.publish(r); + h.flush(); + assertEquals("", aos.toString()); + assertSame(r, CallVerificationStack.getInstance().pop()); + + r.setLevel(Level.OFF); + h.setLevel(Level.OFF); + h.publish(r); + h.flush(); + assertEquals("", aos.toString()); + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test publish(), null log record, handler should call ErrorManager to + * handle exceptional case + */ + public void testPublish_Null() { + StreamHandler h = new StreamHandler(new ByteArrayOutputStream(), + new SimpleFormatter()); + h.publish(null); + } + + /* + * Test publish(), null log record, without output stream + */ + public void testPublish_Null_NoOutputStream() { + StreamHandler h = new StreamHandler(); + h.publish(null); + // regression test for Harmony-1279 + MockFilter filter = new MockFilter(); + h.setLevel(Level.FINER); + h.setFilter(filter); + LogRecord record = new LogRecord(Level.FINE, "abc"); + h.publish(record); + // verify that filter.isLoggable is not called, because there's no + // associated output stream. + assertTrue(CallVerificationStack.getInstance().empty()); + } + + /* + * Test publish(), a log record with empty msg, having output stream + */ + public void testPublish_EmptyMsg() { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + LogRecord r = new LogRecord(Level.INFO, ""); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head", aos.toString()); + } + + /* + * Test publish(), a log record with null msg, having output stream + */ + public void testPublish_NullMsg() { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + LogRecord r = new LogRecord(Level.INFO, null); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_Head", aos.toString()); + } + + /* + * Test publish(), after close. + */ + public void testPublish_AfterClose() throws Exception { + Properties p = new Properties(); + p.put("java.util.logging.StreamHandler.level", "FINE"); + LogManager.getLogManager().readConfiguration( + EnvironmentHelper.PropertiesToInputStream(p)); + + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + assertSame(h.getLevel(), Level.FINE); + LogRecord r = new LogRecord(Level.INFO, "testPublish_NoFormatter"); + assertTrue(h.isLoggable(r)); + h.close(); + assertFalse(h.isLoggable(r)); + h.publish(r); + h.flush(); + assertEquals("MockFormatter_HeadMockFormatter_Tail", aos.toString()); + } + + /* + * Test setEncoding() method with supported encoding. + */ + public void testSetEncoding_Normal() throws Exception { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.setEncoding("iso-8859-1"); + assertEquals("iso-8859-1", h.getEncoding()); + LogRecord r = new LogRecord(Level.INFO, "\u6881\u884D\u8F69"); + h.publish(r); + h.flush(); + + byte[] bytes = encoder.encode( + CharBuffer.wrap("MockFormatter_Head" + "\u6881\u884D\u8F69")) + .array(); + assertTrue(Arrays.equals(bytes, aos.toByteArray())); + } + + /* + * Test setEncoding() method with supported encoding, after a log record + * has been written. + */ + public void testSetEncoding_AfterPublish() throws Exception { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + h.setEncoding("iso-8859-1"); + assertEquals("iso-8859-1", h.getEncoding()); + LogRecord r = new LogRecord(Level.INFO, "\u6881\u884D\u8F69"); + h.publish(r); + h.flush(); + assertTrue(Arrays.equals(aos.toByteArray(), encoder.encode( + CharBuffer.wrap("MockFormatter_Head" + "\u6881\u884D\u8F69")) + .array())); + + h.setEncoding("iso8859-1"); + assertEquals("iso8859-1", h.getEncoding()); + r = new LogRecord(Level.INFO, "\u6881\u884D\u8F69"); + h.publish(r); + h.flush(); + assertFalse(Arrays.equals(aos.toByteArray(), encoder.encode( + CharBuffer.wrap("MockFormatter_Head" + "\u6881\u884D\u8F69" + + "testSetEncoding_Normal2")).array())); + byte[] b0 = aos.toByteArray(); + byte[] b1 = encoder.encode( + CharBuffer.wrap("MockFormatter_Head" + "\u6881\u884D\u8F69")) + .array(); + byte[] b2 = encoder.encode(CharBuffer.wrap("\u6881\u884D\u8F69")) + .array(); + byte[] b3 = new byte[b1.length + b2.length]; + System.arraycopy(b1, 0, b3, 0, b1.length); + System.arraycopy(b2, 0, b3, b1.length, b2.length); + assertTrue(Arrays.equals(b0, b3)); + } + + /* + * Test setEncoding() methods with null. + */ + public void testSetEncoding_Null() throws Exception { + StreamHandler h = new StreamHandler(); + h.setEncoding(null); + assertNull(h.getEncoding()); + } + + /* + * Test setEncoding() methods with unsupported encoding. + */ + public void testSetEncoding_Unsupported() { + StreamHandler h = new StreamHandler(); + try { + h.setEncoding("impossible"); + fail("Should throw UnsupportedEncodingException!"); + } catch (UnsupportedEncodingException e) { + // expected + } + assertNull(h.getEncoding()); + } + + /* + * Test setEncoding() with insufficient privilege. + */ + public void testSetEncoding_InsufficientPrivilege() throws Exception { + StreamHandler h = new StreamHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + // set a normal value + try { + h.setEncoding("iso-8859-1"); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + // expected + } finally { + System.setSecurityManager(oldMan); + } + assertNull(h.getEncoding()); + System.setSecurityManager(new MockSecurityManager()); + // set an invalid value + try { + + h.setEncoding("impossible"); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + // expected + } finally { + System.setSecurityManager(oldMan); + } + assertNull(h.getEncoding()); + } + + /* + * Test setEncoding() methods will flush a stream before setting. + */ + public void testSetEncoding_FlushBeforeSetting() throws Exception { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + StreamHandler h = new StreamHandler(aos, new MockFormatter()); + LogRecord r = new LogRecord(Level.INFO, "abcd"); + h.publish(r); + assertFalse(aos.toString().indexOf("abcd") > 0); + h.setEncoding("iso-8859-1"); + assertTrue(aos.toString().indexOf("abcd") > 0); + } + + /* + * Test setOutputStream() with null. + */ + public void testSetOutputStream_null() { + MockStreamHandler h = new MockStreamHandler( + new ByteArrayOutputStream(), new SimpleFormatter()); + try { + h.setOutputStream(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + // expected + } + } + + /* + * Test setOutputStream() under normal condition. + */ + public void testSetOutputStream_Normal() { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + MockStreamHandler h = new MockStreamHandler(aos, new MockFormatter()); + + LogRecord r = new LogRecord(Level.INFO, "testSetOutputStream_Normal"); + h.publish(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + h.flush(); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal", aos + .toString()); + + ByteArrayOutputStream aos2 = new ByteArrayOutputStream(); + h.setOutputStream(aos2); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal" + + "MockFormatter_Tail", aos.toString()); + r = new LogRecord(Level.INFO, "testSetOutputStream_Normal2"); + h.publish(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + h.flush(); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal2", aos2 + .toString()); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal" + + "MockFormatter_Tail", aos.toString()); + } + + /* + * Test setOutputStream() after close. + */ + public void testSetOutputStream_AfterClose() { + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + MockStreamHandler h = new MockStreamHandler(aos, new MockFormatter()); + + LogRecord r = new LogRecord(Level.INFO, "testSetOutputStream_Normal"); + h.publish(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + h.flush(); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal", aos + .toString()); + h.close(); + + ByteArrayOutputStream aos2 = new ByteArrayOutputStream(); + h.setOutputStream(aos2); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal" + + "MockFormatter_Tail", aos.toString()); + r = new LogRecord(Level.INFO, "testSetOutputStream_Normal2"); + h.publish(r); + assertSame(r, CallVerificationStack.getInstance().pop()); + assertTrue(CallVerificationStack.getInstance().empty()); + h.flush(); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal2", aos2 + .toString()); + assertEquals("MockFormatter_Head" + "testSetOutputStream_Normal" + + "MockFormatter_Tail", aos.toString()); + } + + /* + * Test setOutputStream() when having insufficient privilege. + */ + public void testSetOutputStream_InsufficientPrivilege() { + MockStreamHandler h = new MockStreamHandler(); + SecurityManager oldMan = System.getSecurityManager(); + System.setSecurityManager(new MockSecurityManager()); + + try { + h.setOutputStream(new ByteArrayOutputStream()); + fail("Should throw SecurityException!"); + } catch (SecurityException e) { + // expected + } finally { + System.setSecurityManager(oldMan); + } + + h = new MockStreamHandler(); + System.setSecurityManager(new MockSecurityManager()); + try { + h.setOutputStream(null); + fail("Should throw NullPointerException!"); + } catch (NullPointerException e) { + // expected + } finally { + System.setSecurityManager(oldMan); + } + } + + /* + * A mock stream handler, expose setOutputStream. + */ + public static class MockStreamHandler extends StreamHandler { + public MockStreamHandler() { + super(); + } + + public MockStreamHandler(OutputStream out, Formatter formatter) { + super(out, formatter); + } + + public void setOutputStream(OutputStream out) { + super.setOutputStream(out); + } + + public boolean isLoggable(LogRecord r) { + CallVerificationStack.getInstance().push(r); + return super.isLoggable(r); + } + } + + /* + * A mock filter, always return false. + */ + public static class MockFilter implements Filter { + + public boolean isLoggable(LogRecord record) { + CallVerificationStack.getInstance().push(record); + return false; + } + } + + /* + * A mock formatter. + */ + public static class MockFormatter extends java.util.logging.Formatter { + public String format(LogRecord r) { + // System.out.println("formatter called..."); + return super.formatMessage(r); + } + + /* + * (non-Javadoc) + * + * @see java.util.logging.Formatter#getHead(java.util.logging.Handler) + */ + public String getHead(Handler h) { + return "MockFormatter_Head"; + } + + /* + * (non-Javadoc) + * + * @see java.util.logging.Formatter#getTail(java.util.logging.Handler) + */ + public String getTail(Handler h) { + return "MockFormatter_Tail"; + } + } + + /* + * Another mock formatter. + */ + public static class MockFormatter2 extends java.util.logging.Formatter { + public String format(LogRecord r) { + // System.out.println("formatter2 called..."); + return r.getMessage(); + } + } + + /* + * A mock output stream. + */ + public static class MockOutputStream extends ByteArrayOutputStream { + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#close() + */ + public void close() throws IOException { + CallVerificationStack.getInstance().push(null); + super.close(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#flush() + */ + public void flush() throws IOException { + CallVerificationStack.getInstance().push(null); + super.flush(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#write(int) + */ + public void write(int oneByte) { + // TODO Auto-generated method stub + super.write(oneByte); + } + } + + /* + * A mock output stream that always throw exception. + */ + public static class MockExceptionOutputStream extends ByteArrayOutputStream { + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#close() + */ + public void close() throws IOException { + throw new IOException(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#flush() + */ + public void flush() throws IOException { + throw new IOException(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#write(byte[], int, int) + */ + public synchronized void write(byte[] buffer, int offset, int count) { + throw new NullPointerException(); + } + + /* + * (non-Javadoc) + * + * @see java.io.OutputStream#write(int) + */ + public synchronized void write(int oneByte) { + throw new NullPointerException(); + } + } + + /* + * Used to grant all permissions except logging control. + */ + public static class MockSecurityManager extends SecurityManager { + + public MockSecurityManager() { + } + + public void checkPermission(Permission perm) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + + public void checkPermission(Permission perm, Object context) { + // grant all permissions except logging control + if (perm instanceof LoggingPermission) { + throw new SecurityException(); + } + } + } + +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/XMLFormatterTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/XMLFormatterTest.java new file mode 100644 index 0000000..54582d1 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/XMLFormatterTest.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging; + +import java.io.UnsupportedEncodingException; +import java.util.ResourceBundle; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.XMLFormatter; + +import junit.framework.TestCase; + +public class XMLFormatterTest extends TestCase { + + XMLFormatter formatter = null; + + MockHandler handler = null; + + LogRecord lr = null; + + protected void setUp() throws Exception { + super.setUp(); + formatter = new XMLFormatter(); + handler = new MockHandler(); + lr = new LogRecord(Level.SEVERE, "pattern"); + } + + /* + * test for constructor public XMLFormatter() + */ + public void testXMLFormatter() { + String result = formatter.getHead(handler); + int headPos = result + .indexOf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); + int dtdPos = result.indexOf("<!DOCTYPE log SYSTEM \"logger.dtd\">"); + int rootPos = result.indexOf("<log>"); + assertTrue("head string position should be more or equal zero", + headPos >= 0); + assertTrue("dtd string position should be more head string position", + dtdPos > headPos); + assertTrue("root string position should be more dtd string position", + rootPos > dtdPos); + + assertTrue("Tail string position should be more zero", formatter + .getTail(handler).indexOf("/log>") > 0); + } + + public void testLocalFormat() { + // if set resource bundle, output will use localized message, + // but put the original message into the key element + // further more, if message pattern has no effect + ResourceBundle rb = ResourceBundle + .getBundle("bundles/java/util/logging/res"); + lr.setResourceBundle(rb); + lr.setMessage("pattern"); + String result = formatter.format(lr); + assertTrue(result.indexOf("<message>" + rb.getString("pattern") + + "</message>") > 0); + assertTrue(result.indexOf("<key>pattern</key>") > 0); + + lr.setMessage("msg"); + result = formatter.format(lr); + assertTrue(result.indexOf("<message>" + rb.getString("msg") + + "</message>") > 0); + assertTrue(result.indexOf("<key>msg</key>") > 0); + + lr.setMessage("pattern {0, number}"); + result = formatter.format(lr); + assertTrue(result.indexOf("<message>pattern {0, number}</message>") > 0); + assertTrue(result.indexOf("<key>") < 0); + + // if message has no relevant localized message, use the original + lr.setMessage("bad key"); + result = formatter.format(lr); + assertTrue(result.indexOf("<message>bad key</message>") > 0); + assertTrue(result.indexOf("<key>") < 0); + } + + public void testFullFormat() { + lr.setSourceClassName("source class"); + lr.setSourceMethodName("source method"); + lr.setLoggerName("logger name"); + lr.setMillis(0); + lr.setThrown(new Throwable("message")); + lr.setParameters(new Object[] { "100", "200" }); + lr.setSequenceNumber(1); + ResourceBundle rb = ResourceBundle + .getBundle("bundles/java/util/logging/res"); + lr.setResourceBundle(rb); + lr.setResourceBundleName("rbname"); + String output = formatter.format(lr); + // System.out.println(output); + assertTrue(output.indexOf("<record>") >= 0); + assertTrue(output.indexOf("<date>") >= 0); + assertTrue(output.indexOf("<millis>0</millis>") >= 0); + assertTrue(output.indexOf("<sequence>") >= 0); + assertTrue(output.indexOf("<level>SEVERE</level>") >= 0); + assertTrue(output.indexOf("<thread>") >= 0); + assertTrue(output.indexOf("<message>" + rb.getString("pattern") + + "</message>") >= 0); + assertTrue(output.indexOf("<logger>logger name</logger>") > 0); + assertTrue(output.indexOf("<class>source class</class>") > 0); + assertTrue(output.indexOf("<method>source method</method>") > 0); + assertTrue(output.indexOf("<catalog>rbname</catalog>") > 0); + assertTrue(output.indexOf("<param>100</param>") > 0); + assertTrue(output.indexOf("<param>200</param>") > 0); + assertTrue(output.indexOf("<exception>") > 0); + assertTrue(output.indexOf("<key>pattern</key>") > 0); + } + + public void testFormat() { + String output = formatter.format(lr); + // System.out.println(output); + assertTrue(output.indexOf("<record>") >= 0); + assertTrue(output.indexOf("<date>") >= 0); + assertTrue(output.indexOf("<millis>") >= 0); + assertTrue(output.indexOf("<sequence>") >= 0); + assertTrue(output.indexOf("<level>SEVERE</level>") >= 0); + assertTrue(output.indexOf("<thread>") >= 0); + assertTrue(output.indexOf("<message>pattern</message>") >= 0); + assertTrue(output.indexOf("<logger>") < 0); + assertTrue(output.indexOf("<class>") < 0); + assertTrue(output.indexOf("<method>") < 0); + assertTrue(output.indexOf("<catalog>") < 0); + assertTrue(output.indexOf("<param>") < 0); + assertTrue(output.indexOf("<exception>") < 0); + assertTrue(output.indexOf("<key>") < 0); + } + + public void testGetHead() throws SecurityException, + UnsupportedEncodingException { + String result = formatter.getHead(handler); + assertNull(handler.getEncoding()); + // TODO: where do we get the default encoding from? + // assertTrue(result.indexOf(defaultEncoding)>0); + + handler.setEncoding("ISO-8859-1"); + String head = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>"; + String dtd = "<!DOCTYPE log SYSTEM \"logger.dtd\">"; + String rootELement = "<log>"; + result = formatter.getHead(handler); + int headPos = result.indexOf(head); + int dtdPos = result.indexOf(dtd); + int rootPos = result.indexOf(rootELement); + assertTrue(headPos >= 0); + assertTrue(dtdPos > headPos); + assertTrue(rootPos > dtdPos); + + handler.setEncoding(null); + result = formatter.getHead(handler); + assertNull(handler.getEncoding()); + // assertTrue(result.indexOf(defaultEncoding)>0); + + // regression test for Harmony-1280 + // make sure no NPE is thrown + formatter.getHead(null); + + } + + /* + * test for method public String getTail(Handler h) + */ + public void testGetTail() { + assertEquals( + "Tail string with null handler should be equal expected value", + "</log>", formatter.getTail(null).trim()); + assertEquals("Tail string should be equal expected value", "</log>", + formatter.getTail(handler).trim()); + handler.publish(lr); + assertEquals( + "Tail string after publish() should be equal expected value", + "</log>", formatter.getTail(handler).trim()); + } + + public void testInvalidParameter() { + formatter.getTail(null); + try { + formatter.format(null); + fail(); + } catch (NullPointerException e) { + } + + formatter = new XMLFormatter(); + lr = new LogRecord(Level.SEVERE, null); + String output = formatter.format(lr); + assertTrue(output.indexOf("<message") < 0); + } + + public static class MockHandler extends Handler { + public void close() { + } + + public void flush() { + } + + public void publish(LogRecord record) { + } + + } +} diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/util/EnvironmentHelper.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/util/EnvironmentHelper.java new file mode 100644 index 0000000..0dafe68 --- /dev/null +++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/util/EnvironmentHelper.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.logging.tests.java.util.logging.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.Properties; + +/** + * Helper to prepare testing environment, for example, configuration files. + */ +public class EnvironmentHelper { + + /** + * Can't be instantiated. + */ + private EnvironmentHelper() { + } + + public static InputStream PropertiesToInputStream(Properties p) { + ByteArrayOutputStream bos = null; + try { + bos = new ByteArrayOutputStream(); + p.store(bos, ""); + return new ByteArrayInputStream(bos.toByteArray()); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + try { + bos.close(); + } catch (Exception ex) { + } + } + } + +} diff --git a/logging/src/test/java/tests/logging/AllTests.java b/logging/src/test/java/tests/logging/AllTests.java new file mode 100644 index 0000000..2b89b52 --- /dev/null +++ b/logging/src/test/java/tests/logging/AllTests.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.logging; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Test suite that includes all tests for the Logging 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 Logging test suites"); + // $JUnit-BEGIN$ + suite.addTest(org.apache.harmony.logging.tests.java.util.logging.AllTests.suite()); + // $JUnit-END$ + return suite; + } +}
\ No newline at end of file diff --git a/logging/src/test/resources/bundles/java/util/logging/res.properties b/logging/src/test/resources/bundles/java/util/logging/res.properties new file mode 100644 index 0000000..db455b0 --- /dev/null +++ b/logging/src/test/resources/bundles/java/util/logging/res.properties @@ -0,0 +1,12 @@ +level1=en_US_level1 +SEVERE=US_SEVERE +WARNING=US_WARNING +CONFIG=US_CONFIG +FINE=US_FINE +FINER=US_FINER +FINEST=US_FINEST +ALL=US_ALL +OFF=US_OFF +msg=US_MSG +pattern=US_pattern {0, number} +pattern{0,number}=US
\ No newline at end of file diff --git a/logging/src/test/resources/bundles/java/util/logging/res2.properties b/logging/src/test/resources/bundles/java/util/logging/res2.properties new file mode 100644 index 0000000..66f02eb --- /dev/null +++ b/logging/src/test/resources/bundles/java/util/logging/res2.properties @@ -0,0 +1,13 @@ +level1=level1 +SEVERE=SEVERE2 +WARNING=WARNING2 +CONFIG=CONFIG2 +FINE=FINE2 +FINER=FINER2 +FINEST=FINEST2 +ALL=ALL2 +OFF=OFF2 +msg=MSG2 +pattern=pattern {0, number}2 +pattern{0,number}=NOLOCALE2 +LOGGERTEST=Test_NoLocale2
\ No newline at end of file diff --git a/logging/src/test/resources/bundles/java/util/logging/res3.properties b/logging/src/test/resources/bundles/java/util/logging/res3.properties new file mode 100644 index 0000000..f7b4b29 --- /dev/null +++ b/logging/src/test/resources/bundles/java/util/logging/res3.properties @@ -0,0 +1,13 @@ +level1=level13 +SEVERE=SEVERE3 +WARNING=WARNING3 +CONFIG=CONFIG3 +FINE=FINE3 +FINER=FINER3 +FINEST=FINEST3 +ALL=ALL3 +OFF=OFF3 +msg=MSG3 +pattern=pattern {0, number}3 +pattern{0,number}=NOLOCALE3 +LOGGERTEST=Test_NoLocale3
\ No newline at end of file diff --git a/logging/src/test/resources/bundles/java/util/logging/res_en_US.properties b/logging/src/test/resources/bundles/java/util/logging/res_en_US.properties new file mode 100644 index 0000000..db455b0 --- /dev/null +++ b/logging/src/test/resources/bundles/java/util/logging/res_en_US.properties @@ -0,0 +1,12 @@ +level1=en_US_level1 +SEVERE=US_SEVERE +WARNING=US_WARNING +CONFIG=US_CONFIG +FINE=US_FINE +FINER=US_FINER +FINEST=US_FINEST +ALL=US_ALL +OFF=US_OFF +msg=US_MSG +pattern=US_pattern {0, number} +pattern{0,number}=US
\ No newline at end of file diff --git a/logging/src/test/resources/bundles/java/util/logging/res_zh_CN.properties b/logging/src/test/resources/bundles/java/util/logging/res_zh_CN.properties new file mode 100644 index 0000000..e96803d --- /dev/null +++ b/logging/src/test/resources/bundles/java/util/logging/res_zh_CN.properties @@ -0,0 +1,13 @@ +level1=zh_CN_level1 +SEVERE=zh_CN_SEVERE +WARNING=zh_CN_WARNING +CONFIG=ZH_CN_CONFIG +FINE=ZH_CN_FINE +FINER=ZH_CN_FINER +FINEST=ZH_CN_FINEST +ALL=ZH_CN_ALL +OFF=ZH_CN_OFF +msg=ZH_CN_MSG +pattern=ZH_CN_pattern {0, number} +pattern{0,number}=ZH_CN +LOGGERTEST=Test_ZH_CN
\ No newline at end of file diff --git a/logging/src/test/resources/config/java/util/logging/logging.config b/logging/src/test/resources/config/java/util/logging/logging.config new file mode 100644 index 0000000..f4c5146 --- /dev/null +++ b/logging/src/test/resources/config/java/util/logging/logging.config @@ -0,0 +1,3 @@ +handlers=org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler java.util.logging.ConsoleHandler +.level=ALL +org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler.level=OFF
\ No newline at end of file diff --git a/logging/src/test/resources/config/java/util/logging/logging.properties b/logging/src/test/resources/config/java/util/logging/logging.properties new file mode 100644 index 0000000..f4c5146 --- /dev/null +++ b/logging/src/test/resources/config/java/util/logging/logging.properties @@ -0,0 +1,3 @@ +handlers=org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler java.util.logging.ConsoleHandler +.level=ALL +org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler.level=OFF
\ No newline at end of file diff --git a/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LevelTest.golden.ser b/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LevelTest.golden.ser Binary files differnew file mode 100644 index 0000000..721a368 --- /dev/null +++ b/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LevelTest.golden.ser diff --git a/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.golden.ser b/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.golden.ser Binary files differnew file mode 100644 index 0000000..955c6fb --- /dev/null +++ b/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.golden.ser diff --git a/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LoggingPermissionTest.golden.ser b/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LoggingPermissionTest.golden.ser Binary files differnew file mode 100644 index 0000000..f4cdced --- /dev/null +++ b/logging/src/test/resources/serialization/org/apache/harmony/logging/tests/java/util/logging/LoggingPermissionTest.golden.ser |