Java Tutorial/Development/Debug — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 15:30, 31 мая 2010
Содержание
- 1 A bean that can be used to keep track of a counter
- 2 A helper class for printing indented text
- 3 A simple logging facility.
- 4 Count Up Down Latch
- 5 Debug Utility
- 6 Methods for logging events
- 7 Printing indented text
- 8 Prints messages formatted for a specific line width.
- 9 Random data for test
- 10 Swing Console
A bean that can be used to keep track of a counter
/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
import java.io.Serializable;
/**
* A bean that can be used to keep track of a counter.
* <p/>
* Since it is an Iterator it can be used by the iterator tag
*
* @author Rickard Öberg (rickard@middleware-company.ru)
* @version $Revision: 1282 $
* @see <related>
*/
public class Counter implements java.util.Iterator, Serializable {
boolean wrap = false;
// Attributes ----------------------------------------------------
long first = 1;
long current = first;
long interval = 1;
long last = -1;
public void setAdd(long addition) {
current += addition;
}
public void setCurrent(long current) {
this.current = current;
}
public long getCurrent() {
return current;
}
public void setFirst(long first) {
this.first = first;
current = first;
}
public long getFirst() {
return first;
}
public void setInterval(long interval) {
this.interval = interval;
}
public long getInterval() {
return interval;
}
public void setLast(long last) {
this.last = last;
}
public long getLast() {
return last;
}
// Public --------------------------------------------------------
public long getNext() {
long next = current;
current += interval;
if (wrap && (current > last)) {
current -= ((1 + last) - first);
}
return next;
}
public long getPrevious() {
current -= interval;
if (wrap && (current < first)) {
current += (last - first + 1);
}
return current;
}
public void setWrap(boolean wrap) {
this.wrap = wrap;
}
public boolean isWrap() {
return wrap;
}
public boolean hasNext() {
return ((last == -1) || wrap) ? true : (current <= last);
}
public Object next() {
return new Long(getNext());
}
public void remove() {
// Do nothing
}
}
///////////////////
/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.webwork.util;
import junit.framework.TestCase;
/**
* User: plightbo
* Date: Jan 7, 2004
* Time: 7:55:35 PM
*/
public class CounterTest extends TestCase {
Counter c = new Counter();
public void testCurrentAfterNext() {
long next = c.getNext();
long current = c.getCurrent();
assertEquals(next + 1, current);
}
public void testCurrentBeforeNext() {
long current = c.getCurrent();
long next = c.getNext();
assertEquals(current, next);
}
public void testWrap() {
c.setWrap(true);
c.setLast(1);
long a = c.getNext();
long b = c.getNext();
assertEquals(1, a);
assertEquals(1, b);
}
}
A helper class for printing indented text
/*
* 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.
*/
import java.io.PrintWriter;
/**
* A helper class for printing indented text
*
* @version $Revision: 1.2 $
*/
public class IndentPrinter {
private int indentLevel;
private String indent;
private PrintWriter out;
public IndentPrinter() {
this(new PrintWriter(System.out), " ");
}
public IndentPrinter(PrintWriter out) {
this(out, " ");
}
public IndentPrinter(PrintWriter out, String indent) {
this.out = out;
this.indent = indent;
}
public void println(Object value) {
out.print(value.toString());
out.println();
}
public void println(String text) {
out.print(text);
out.println();
}
public void print(String text) {
out.print(text);
}
public void printIndent() {
for (int i = 0; i < indentLevel; i++) {
out.print(indent);
}
}
public void println() {
out.println();
}
public void incrementIndent() {
++indentLevel;
}
public void decrementIndent() {
--indentLevel;
}
public int getIndentLevel() {
return indentLevel;
}
public void setIndentLevel(int indentLevel) {
this.indentLevel = indentLevel;
}
public void flush() {
out.flush();
}
}
A simple logging facility.
/*
* JCommon : a free general purpose class library for the Java(tm) platform
*
*
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jcommon/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* --------
* Log.java
* --------
* (C)opyright 2002-2004, by Thomas Morgner and Contributors.
*
* Original Author: Thomas Morgner (taquera@sherito.org);
* Contributor(s): David Gilbert (for Object Refinery Limited);
*
* $Id: Log.java,v 1.5 2006/06/08 17:42:20 taqua Exp $
*
* Changes
* -------
* 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon
* 11-Jun-2003 : Removing LogTarget did not work.
*
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
/**
* A simple logging facility. Create a class implementing the
* {@link org.jfree.util.LogTarget} interface to use this feature.
*
* @author Thomas Morgner
*/
public class Log {
/**
* A simple message class.
*/
public static class SimpleMessage {
/**
* The message.
*/
private String message;
/**
* The parameters.
*/
private Object[] param;
/**
* Creates a new message.
*
* @param message
* the message text.
* @param param1
* parameter 1.
*/
public SimpleMessage(final String message, final Object param1) {
this.message = message;
this.param = new Object[] { param1 };
}
/**
* Creates a new message.
*
* @param message
* the message text.
* @param param1
* parameter 1.
* @param param2
* parameter 2.
*/
public SimpleMessage(final String message, final Object param1, final Object param2) {
this.message = message;
this.param = new Object[] { param1, param2 };
}
/**
* Creates a new message.
*
* @param message
* the message text.
* @param param1
* parameter 1.
* @param param2
* parameter 2.
* @param param3
* parameter 3.
*/
public SimpleMessage(final String message, final Object param1, final Object param2,
final Object param3) {
this.message = message;
this.param = new Object[] { param1, param2, param3 };
}
/**
* Creates a new message.
*
* @param message
* the message text.
* @param param1
* parameter 1.
* @param param2
* parameter 2.
* @param param3
* parameter 3.
* @param param4
* parameter 4.
*/
public SimpleMessage(final String message, final Object param1, final Object param2,
final Object param3, final Object param4) {
this.message = message;
this.param = new Object[] { param1, param2, param3, param4 };
}
/**
* Creates a new message.
*
* @param message
* the message text.
* @param param
* the parameters.
*/
public SimpleMessage(final String message, final Object[] param) {
this.message = message;
this.param = param;
}
/**
* Returns a string representation of the message (useful for debugging).
*
* @return the string.
*/
public String toString() {
final StringBuffer b = new StringBuffer();
b.append(this.message);
if (this.param != null) {
for (int i = 0; i < this.param.length; i++) {
b.append(this.param[i]);
}
}
return b.toString();
}
}
/**
* The logging threshold.
*/
private int debuglevel;
/**
* Storage for the log targets.
*/
private LogTarget[] logTargets;
/** The log contexts. */
private HashMap logContexts;
/**
* the singleton instance of the Log system.
*/
private static Log singleton;
/**
* Creates a new Log instance. The Log is used to manage the log targets.
*/
protected Log() {
this.logContexts = new HashMap();
this.logTargets = new LogTarget[0];
this.debuglevel = 100;
}
/**
* Returns the singleton Log instance. A new instance is created if necessary.
*
* @return the singleton instance.
*/
public static synchronized Log getInstance() {
if (singleton == null) {
singleton = new Log();
}
return singleton;
}
/**
* Redefines or clears the currently used log instance.
*
* @param log
* the new log instance or null, to return to the default
* implementation.
*/
protected static synchronized void defineLog(final Log log) {
singleton = log;
}
/**
* Returns the currently defined debug level. The higher the level, the more
* details are printed.
*
* @return the debug level.
*/
public int getDebuglevel() {
return this.debuglevel;
}
/**
* Defines the debug level for the log system.
*
* @param debuglevel
* the new debug level
* @see #getDebuglevel()
*/
protected void setDebuglevel(final int debuglevel) {
this.debuglevel = debuglevel;
}
/**
* Adds a log target to this facility. Log targets get informed, via the
* LogTarget interface, whenever a message is logged with this class.
*
* @param target
* the target.
*/
public synchronized void addTarget(final LogTarget target) {
if (target == null) {
throw new NullPointerException();
}
final LogTarget[] data = new LogTarget[this.logTargets.length + 1];
System.arraycopy(this.logTargets, 0, data, 0, this.logTargets.length);
data[this.logTargets.length] = target;
this.logTargets = data;
}
/**
* Removes a log target from this facility.
*
* @param target
* the target to remove.
*/
public synchronized void removeTarget(final LogTarget target) {
if (target == null) {
throw new NullPointerException();
}
final ArrayList l = new ArrayList();
l.addAll(Arrays.asList(this.logTargets));
l.remove(target);
final LogTarget[] targets = new LogTarget[l.size()];
this.logTargets = (LogTarget[]) l.toArray(targets);
}
/**
* Returns the registered logtargets.
*
* @return the logtargets.
*/
public LogTarget[] getTargets() {
return (LogTarget[]) this.logTargets.clone();
}
/**
* Replaces all log targets by the given target.
*
* @param target
* the new and only logtarget.
*/
public synchronized void replaceTargets(final LogTarget target) {
if (target == null) {
throw new NullPointerException();
}
this.logTargets = new LogTarget[] { target };
}
/**
* A convenience method for logging a "debug" message.
*
* @param message
* the message.
*/
public static void debug(final Object message) {
log(LogTarget.DEBUG, message);
}
/**
* A convenience method for logging a "debug" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public static void debug(final Object message, final Exception e) {
log(LogTarget.DEBUG, message, e);
}
/**
* A convenience method for logging an "info" message.
*
* @param message
* the message.
*/
public static void info(final Object message) {
log(LogTarget.INFO, message);
}
/**
* A convenience method for logging an "info" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public static void info(final Object message, final Exception e) {
log(LogTarget.INFO, message, e);
}
/**
* A convenience method for logging a "warning" message.
*
* @param message
* the message.
*/
public static void warn(final Object message) {
log(LogTarget.WARN, message);
}
/**
* A convenience method for logging a "warning" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public static void warn(final Object message, final Exception e) {
log(LogTarget.WARN, message, e);
}
/**
* A convenience method for logging an "error" message.
*
* @param message
* the message.
*/
public static void error(final Object message) {
log(LogTarget.ERROR, message);
}
/**
* A convenience method for logging an "error" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public static void error(final Object message, final Exception e) {
log(LogTarget.ERROR, message, e);
}
/**
* Logs a message to the main log stream. All attached log targets will also
* receive this message. If the given log-level is higher than the given
* debug-level in the main config file, no logging will be done.
*
* @param level
* log level of the message.
* @param message
* text to be logged.
*/
protected void doLog(int level, final Object message) {
if (level > 3) {
level = 3;
}
if (level <= this.debuglevel) {
for (int i = 0; i < this.logTargets.length; i++) {
final LogTarget t = this.logTargets[i];
t.log(level, message);
}
}
}
/**
* Logs a message to the main log stream. All attached log targets will also
* receive this message. If the given log-level is higher than the given
* debug-level in the main config file, no logging will be done.
*
* @param level
* log level of the message.
* @param message
* text to be logged.
*/
public static void log(final int level, final Object message) {
getInstance().doLog(level, message);
}
/**
* Logs a message to the main log stream. All attached logTargets will also
* receive this message. If the given log-level is higher than the given
* debug-level in the main config file, no logging will be done. <p/> The
* exception"s stacktrace will be appended to the log-stream
*
* @param level
* log level of the message.
* @param message
* text to be logged.
* @param e
* the exception, which should be logged.
*/
public static void log(final int level, final Object message, final Exception e) {
getInstance().doLog(level, message, e);
}
/**
* Logs a message to the main log stream. All attached logTargets will also
* receive this message. If the given log-level is higher than the given
* debug-level in the main config file, no logging will be done. <p/> The
* exception"s stacktrace will be appended to the log-stream
*
* @param level
* log level of the message.
* @param message
* text to be logged.
* @param e
* the exception, which should be logged.
*/
protected void doLog(int level, final Object message, final Exception e) {
if (level > 3) {
level = 3;
}
if (level <= this.debuglevel) {
for (int i = 0; i < this.logTargets.length; i++) {
final LogTarget t = this.logTargets[i];
t.log(level, message, e);
}
}
}
/**
* Initializes the logging system. Implementors should override this method to
* supply their own log configuration.
*/
public void init() {
// this method is intentionally empty.
}
/**
* Returns true, if the log level allows debug messages to be printed.
*
* @return true, if messages with an log level of DEBUG are allowed.
*/
public static boolean isDebugEnabled() {
return getInstance().getDebuglevel() >= LogTarget.DEBUG;
}
/**
* Returns true, if the log level allows informational messages to be printed.
*
* @return true, if messages with an log level of INFO are allowed.
*/
public static boolean isInfoEnabled() {
return getInstance().getDebuglevel() >= LogTarget.INFO;
}
/**
* Returns true, if the log level allows warning messages to be printed.
*
* @return true, if messages with an log level of WARN are allowed.
*/
public static boolean isWarningEnabled() {
return getInstance().getDebuglevel() >= LogTarget.WARN;
}
/**
* Returns true, if the log level allows error messages to be printed.
*
* @return true, if messages with an log level of ERROR are allowed.
*/
public static boolean isErrorEnabled() {
return getInstance().getDebuglevel() >= LogTarget.ERROR;
}
/**
* Creates a log context.
*
* @param context
* the class (<code>null</code> not permitted).
*
* @return A log context.
*/
public static LogContext createContext(final Class context) {
return createContext(context.getName());
}
/**
* Creates a log context.
*
* @param context
* the label for the context.
*
* @return A log context.
*/
public static LogContext createContext(final String context) {
return getInstance().internalCreateContext(context);
}
/**
* Creates a log context.
*
* @param context
* the name of the logging context (a common prefix).
*
* @return A log context.
*/
protected LogContext internalCreateContext(final String context) {
synchronized (this) {
LogContext ctx = (LogContext) this.logContexts.get(context);
if (ctx == null) {
ctx = new LogContext(context);
this.logContexts.put(context, ctx);
}
return ctx;
}
}
}
/*
* JCommon : a free general purpose class library for the Java(tm) platform
*
*
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jcommon/index.html
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc. in the
* United States and other countries.]
*
* -------------- LogTarget.java -------------- (C)opyright 2002-2004, by Object
* Refinery Limited.
*
* $Id: LogTarget.java,v 1.3 2005/11/14 10:55:59 mungady Exp $
*
* Changes ------- 11-May-2002 : Initial version 06-Dec-2002 : LogTargets now
* use Object-Parameters instead of Strings. 05-Feb-2003 : Removed unnecessary
* methods. 29-Apr-2003 : Distilled from the JFreeReport project and moved into
* JCommon
*
*/
/**
* An interface that defines a log target (a consumer of log messages). Classes
* which implement this interface can be registered with the
* {@link org.jfree.util.Log} class and will then receive logging messages
* generated by the code.
*
* @author Thomas Morgner
*/
interface LogTarget {
/**
* Loglevel ERROR.
*/
public static final int ERROR = 0;
/**
* Loglevel WARN.
*/
public static final int WARN = 1;
/**
* Loglevel INFO.
*/
public static final int INFO = 2;
/**
* Loglevel DEBUG.
*/
public static final int DEBUG = 3;
/** Strings for the log levels. */
public static final String[] LEVELS = { "ERROR: ", "WARN: ", "INFO: ", "DEBUG: " };
/**
* Logs a message at a specified log level.
*
* @param level
* the log level.
* @param message
* the log message.
*/
public void log(int level, Object message);
/**
* Logs a message at a specified log level.
*
* @param level
* the log level.
* @param message
* the log message.
* @param e
* the exception
*/
public void log(int level, Object message, Exception e);
}
/*
* JCommon : a free general purpose class library for the Java(tm) platform
*
*
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jcommon/index.html
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc. in the
* United States and other countries.]
*
* --------------- LogContext.java --------------- (C)opyright 2004, by Thomas
* Morgner and Contributors.
*
* Original Author: Thomas Morgner; Contributor(s): David Gilbert (for Object
* Refinery Limited);
*
* $Id: LogContext.java,v 1.3 2005/10/18 13:24:19 mungady Exp $
*
* Changes ------- 26-Apr-2004 : Initial version (TM);
*
*/
/**
* A log context.
*
* @author Thomas Morgner
*/
class LogContext {
/** The prefix string. */
private String contextPrefix;
/**
* Creates a new log context.
*
* @param contextPrefix
* the prefix.
*/
public LogContext(final String contextPrefix) {
this.contextPrefix = contextPrefix;
}
/**
* Returns true, if the log level allows debug messages to be printed.
*
* @return true, if messages with an log level of DEBUG are allowed.
*/
public boolean isDebugEnabled() {
return Log.isDebugEnabled();
}
/**
* Returns true, if the log level allows informational messages to be printed.
*
* @return true, if messages with an log level of INFO are allowed.
*/
public boolean isInfoEnabled() {
return Log.isInfoEnabled();
}
/**
* Returns true, if the log level allows warning messages to be printed.
*
* @return true, if messages with an log level of WARN are allowed.
*/
public boolean isWarningEnabled() {
return Log.isWarningEnabled();
}
/**
* Returns true, if the log level allows error messages to be printed.
*
* @return true, if messages with an log level of ERROR are allowed.
*/
public boolean isErrorEnabled() {
return Log.isErrorEnabled();
}
/**
* A convenience method for logging a "debug" message.
*
* @param message
* the message.
*/
public void debug(final Object message) {
log(LogTarget.DEBUG, message);
}
/**
* A convenience method for logging a "debug" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public void debug(final Object message, final Exception e) {
log(LogTarget.DEBUG, message, e);
}
/**
* A convenience method for logging an "info" message.
*
* @param message
* the message.
*/
public void info(final Object message) {
log(LogTarget.INFO, message);
}
/**
* A convenience method for logging an "info" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public void info(final Object message, final Exception e) {
log(LogTarget.INFO, message, e);
}
/**
* A convenience method for logging a "warning" message.
*
* @param message
* the message.
*/
public void warn(final Object message) {
log(LogTarget.WARN, message);
}
/**
* A convenience method for logging a "warning" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public void warn(final Object message, final Exception e) {
log(LogTarget.WARN, message, e);
}
/**
* A convenience method for logging an "error" message.
*
* @param message
* the message.
*/
public void error(final Object message) {
log(LogTarget.ERROR, message);
}
/**
* A convenience method for logging an "error" message.
*
* @param message
* the message.
* @param e
* the exception.
*/
public void error(final Object message, final Exception e) {
log(LogTarget.ERROR, message, e);
}
/**
* Logs a message to the main log stream. All attached log targets will also
* receive this message. If the given log-level is higher than the given
* debug-level in the main config file, no logging will be done.
*
* @param level
* log level of the message.
* @param message
* text to be logged.
*/
public void log(final int level, final Object message) {
if (this.contextPrefix != null) {
Log.getInstance().doLog(level, new Log.SimpleMessage(this.contextPrefix, ":", message));
} else {
Log.getInstance().doLog(level, message);
}
}
/**
* Logs a message to the main log stream. All attached logTargets will also
* receive this message. If the given log-level is higher than the given
* debug-level in the main config file, no logging will be done. <p/> The
* exception"s stacktrace will be appended to the log-stream
*
* @param level
* log level of the message.
* @param message
* text to be logged.
* @param e
* the exception, which should be logged.
*/
public void log(final int level, final Object message, final Exception e) {
if (this.contextPrefix != null) {
Log.getInstance().doLog(level, new Log.SimpleMessage(this.contextPrefix, ":", message), e);
} else {
Log.getInstance().doLog(level, message, e);
}
}
/**
* Tests this object for equality with an arbitrary object.
*
* @param o
* the object to test against (<code>null</code> permitted).
*
* @return A boolean.
*/
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof LogContext)) {
return false;
}
final LogContext logContext = (LogContext) o;
if (this.contextPrefix != null) {
if (!this.contextPrefix.equals(logContext.contextPrefix)) {
return false;
}
} else {
if (logContext.contextPrefix != null) {
return false;
}
}
return true;
}
/**
* Returns a hashcode.
*
* @return The hashcode.
*/
public int hashCode() {
return (this.contextPrefix != null ? this.contextPrefix.hashCode() : 0);
}
}
Count Up Down Latch
/* Copyright (c) 2001-2009, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.util.concurrent.CountDownLatch;
public class CountUpDownLatch {
CountDownLatch latch;
int count;
public CountUpDownLatch() {
latch = new CountDownLatch(1);
this.count = count;
}
public void await() throws InterruptedException {
if (count == 0) {
return;
}
latch.await();
}
public void countDown() {
count--;
if (count == 0) {
latch.countDown();
}
}
public long getCount() {
return count;
}
public void countUp() {
if (latch.getCount() == 0) {
latch = new CountDownLatch(1);
}
count++;
}
public void setCount(int count) {
if (count == 0) {
if (latch.getCount() != 0) {
latch.countDown();
}
} else if (latch.getCount() == 0) {
latch = new CountDownLatch(1);
}
this.count = count;
}
}
Debug Utility
/*
* Copyright (c) 1998-2002 Carnegie Mellon University. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS"" AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
* NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public abstract class Debug {
public static final Debug VERBOSE = new Verbose ();
public static final Debug QUIET = new Quiet ();
public static final Debug NONE = new NoDebug ();
public static Debug getDebugLevel (Class cls)
throws NoSuchFieldException {
try {
Field fld = cls.getField ("debug");
if (fld.getType () != Debug.class
|| !Modifier.isStatic (fld.getModifiers ()))
throw new NoSuchFieldException ();
return (Debug) fld.get (null);
} catch (IllegalArgumentException e) {
throw new NoSuchFieldException ();
} catch (IllegalAccessException e) {
throw new NoSuchFieldException ();
} catch (SecurityException e) {
throw new NoSuchFieldException ();
}
}
public static void setDebugLevel (Class cls, Debug level)
throws NoSuchFieldException {
try {
Field fld = cls.getField ("debug");
if (fld.getType () != Debug.class
|| !Modifier.isStatic (fld.getModifiers ()))
throw new NoSuchFieldException ();
fld.set (null, level);
} catch (IllegalArgumentException e) {
throw new NoSuchFieldException ();
} catch (IllegalAccessException e) {
throw new NoSuchFieldException ();
} catch (SecurityException e) {
throw new NoSuchFieldException ();
}
}
public abstract boolean isEnabled ();
public abstract void print (String message);
public abstract void println (String message);
public abstract void print (Object obj);
public abstract void println (Object obj);
public abstract void report (Throwable t);
public abstract void printThreadInfo ();
public abstract void printStackTrace ();
public abstract void assertion (boolean f);
public static class Verbose extends Debug {
protected PrintStream out;
public Verbose () {
this (System.err);
}
public Verbose (PrintStream out) {
this.out = out;
}
public boolean isEnabled () {
return true;
}
public void print (String message) {
out.print (message);
out.flush ();
}
public void println (String message) {
out.println (message);
out.flush ();
}
public void print (Object obj) {
print (obj.toString ());
}
public void println (Object obj) {
println (obj.toString ());
}
public void report (Throwable t) {
t.printStackTrace (out);
out.flush ();
}
public void printThreadInfo () {
ThreadGroup g = Thread.currentThread().getThreadGroup ();
Thread[] t = new Thread[g.activeCount ()];
g.enumerate (t);
out.println ("Active threads in " + g);
for (int i=0; i<t.length; ++i)
out.println (t[i]);
out.flush ();
}
public void printStackTrace () {
try {
throw new Exception ();
} catch (Exception e) {
e.printStackTrace (out);
out.flush ();
}
}
public void assertion (boolean f) {
if (!f)
throw new RuntimeException ("assertion failure");
}
}
public static class Quiet extends Verbose {
public Quiet () {
}
public Quiet (PrintStream out) {
super (out);
}
public boolean isEnabled () {
return false;
}
public void print (String message) {
}
public void println (String message) {
}
public void print (Object message) {
}
public void println (Object message) {
}
public void report (Throwable t) {
t.printStackTrace (out);
out.flush ();
}
public void printThreadInfo () {
}
public void printStackTrace () {
}
public void assertion (boolean f) {
if (!f) {
try {
throw new RuntimeException ("assertion failure");
} catch (RuntimeException e) {
e.printStackTrace (out);
out.flush ();
}
}
}
}
public static class NoDebug extends Debug {
public boolean isEnabled () {
return false;
}
public void print (String message) {
}
public void println (String message) {
}
public void print (Object message) {
}
public void println (Object message) {
}
public void report (Throwable t) {
}
public void printThreadInfo () {
}
public void printStackTrace () {
}
public void assertion (boolean f) {
}
}
}
Methods for logging events
/*
* Log.java - A class for logging events
* :tabSize=8:indentSize=8:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 1999, 2003 Slava Pestov
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//{{{ Imports
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Writer;
import java.text.DateFormat;
import java.util.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import static java.text.DateFormat.MEDIUM;
//}}}
/**
* This class provides methods for logging events. In terms of functionality,
* it is somewhere in between <code>System.out.println()</code> and
* full-blown logging packages such as log4j.
*
* All events are logged to an in-memory buffer and optionally a stream,
* and those with a high urgency (warnings and errors) are also printed
* to standard output.
*
* Logging of exception tracebacks is supported.
*
* This class can also optionally redirect standard output and error to the log.
*
* @author Slava Pestov
* @version $Id: Log.java 12789 2008-06-04 21:23:10Z kpouer $
*/
public class Log
{
//{{{ Constants
/**
* The maximum number of log messages that will be kept in memory.
* @since jEdit 2.6pre5
*/
public static final int MAXLINES = 500;
/**
* Debugging message urgency. Should be used for messages only
* useful when debugging a problem.
* @since jEdit 2.2pre2
*/
public static final int DEBUG = 1;
/**
* Message urgency. Should be used for messages which give more
* detail than notices.
* @since jEdit 2.2pre2
*/
public static final int MESSAGE = 3;
/**
* Notice urgency. Should be used for messages that directly
* affect the user.
* @since jEdit 2.2pre2
*/
public static final int NOTICE = 5;
/**
* Warning urgency. Should be used for messages that warrant
* attention.
* @since jEdit 2.2pre2
*/
public static final int WARNING = 7;
/**
* Error urgency. Should be used for messages that signal a
* failure.
* @since jEdit 2.2pre2
*/
public static final int ERROR = 9;
//}}}
//{{{ init() method
/**
* Initializes the log.
* @param stdio If true, standard output and error will be
* sent to the log
* @param level Messages with this log level or higher will
* be printed to the system console
* @since jEdit 3.2pre4
*/
public static void init(boolean stdio, int level)
{
if(stdio)
{
if(System.out == realOut && System.err == realErr)
{
System.setOut(createPrintStream(NOTICE,null));
System.setErr(createPrintStream(ERROR,null));
}
}
Log.level = level;
// Log some stuff
log(MESSAGE,Log.class,"When reporting bugs, please"
+ " include the following information:");
String[] props = {
"java.version", "java.vm.version", "java.runtime.version",
"java.vendor", "java.rupiler", "os.name", "os.version",
"os.arch", "user.home", "java.home",
"java.class.path",
};
for(int i = 0; i < props.length; i++)
{
log(MESSAGE,Log.class,
props[i] + "=" + System.getProperty(props[i]));
}
} //}}}
//{{{ setLogWriter() method
/**
* Writes all currently logged messages to this stream if there was no
* stream set previously, and sets the stream to write future log
* messages to.
* @param stream The writer
* @since jEdit 3.2pre4
*/
public static void setLogWriter(Writer stream)
{
if(Log.stream == null && stream != null)
{
try
{
if(wrap)
{
for(int i = logLineCount; i < log.length; i++)
{
stream.write(log[i]);
stream.write(lineSep);
}
}
for(int i = 0; i < logLineCount; i++)
{
stream.write(log[i]);
stream.write(lineSep);
}
stream.flush();
}
catch(Exception e)
{
// do nothing, who cares
}
}
Log.stream = stream;
} //}}}
//{{{ flushStream() method
/**
* Flushes the log stream.
* @since jEdit 2.6pre5
*/
public static void flushStream()
{
if(stream != null)
{
try
{
stream.flush();
}
catch(IOException io)
{
io.printStackTrace(realErr);
}
}
} //}}}
//{{{ closeStream() method
/**
* Closes the log stream. Should be done before your program exits.
* @since jEdit 2.6pre5
*/
public static void closeStream()
{
if(stream != null)
{
try
{
stream.close();
stream = null;
}
catch(IOException io)
{
io.printStackTrace(realErr);
}
}
} //}}}
//{{{ getLogListModel() method
/**
* Returns the list model for viewing the log contents.
* @since jEdit 4.2pre1
*/
public static ListModel getLogListModel()
{
return listModel;
} //}}}
//{{{ log() method
/**
* Logs an exception with a message.
*
* If an exception is the cause of a call to {@link #log}, then
* the exception should be explicitly provided so that it can
* be presented to the (debugging) user in a useful manner
* (not just the exception message, but also the exception stack trace)
*
* @since jEdit 4.3pre5
*/
public static void log(int urgency, Object source, Object message,
Throwable exception)
{
// We can do nicer here, but this is a start...
log(urgency,source,message);
log(urgency,source,exception);
} //}}}
//{{{ log() method
/**
* Logs a message. This method is thread-safe.
*
* The following code sends a typical debugging message to the activity
* log:
* <pre>Log.log(Log.DEBUG,this,"counter = " + counter);</pre>
* The corresponding activity log entry might read as follows:
* <pre>[debug] JavaParser: counter = 15</pre>
*
* @param urgency The urgency; can be one of
* <code>Log.DEBUG</code>, <code>Log.MESSAGE</code>,
* <code>Log.NOTICE</code>, <code>Log.WARNING</code>, or
* <code>Log.ERROR</code>.
* @param source The source of the message, either an object or a
* class instance. When writing log messages from macros, set
* this parameter to <code>BeanShell.class</code> to make macro
* errors easier to spot in the activity log.
* @param message The message. This can either be a string or
* an exception
*
* @since jEdit 2.2pre2
*/
public static void log(int urgency, Object source, Object message)
{
String _source;
if(source == null)
{
_source = Thread.currentThread().getName();
if(_source == null)
{
_source = Thread.currentThread().getClass().getName();
}
}
else if(source instanceof Class)
_source = ((Class)source).getName();
else
_source = source.getClass().getName();
int index = _source.lastIndexOf(".");
if(index != -1)
_source = _source.substring(index+1);
if(message instanceof Throwable)
{
_logException(urgency,source,(Throwable)message);
}
else
{
String _message = String.valueOf(message);
// If multiple threads log stuff, we don"t want
// the output to get mixed up
synchronized(LOCK)
{
StringTokenizer st = new StringTokenizer(
_message,"\r\n");
int lineCount = 0;
boolean oldWrap = wrap;
while(st.hasMoreTokens())
{
lineCount++;
_log(urgency,_source,st.nextToken()
.replace("\t"," "));
}
listModel.update(lineCount,oldWrap);
}
}
} //}}}
//{{{ Private members
//{{{ Instance variables
private static final Object LOCK;
private static final String[] log;
private static int logLineCount;
private static boolean wrap;
private static int level;
private static Writer stream;
private static final String lineSep;
private static final PrintStream realOut;
private static final PrintStream realErr;
private static final LogListModel listModel;
private static final DateFormat timeFormat;
private static final int MAX_THROWABLES = 10;
public static final List<Throwable> throwables;
//}}}
//{{{ Class initializer
static
{
LOCK = new Object();
level = WARNING;
realOut = System.out;
realErr = System.err;
log = new String[MAXLINES];
lineSep = System.getProperty("line.separator");
listModel = new LogListModel();
timeFormat = DateFormat.getTimeInstance(MEDIUM);
throwables = Collections.synchronizedList(new ArrayList<Throwable>(MAX_THROWABLES));
} //}}}
//{{{ createPrintStream() method
private static PrintStream createPrintStream(final int urgency,
final Object source)
{
return new LogPrintStream(urgency, source);
} //}}}
//{{{ _logException() method
private static void _logException(final int urgency,
final Object source,
final Throwable message)
{
PrintStream out = createPrintStream(urgency,source);
if (urgency >= level)
{
synchronized (throwables)
{
if (throwables.size() == MAX_THROWABLES)
{
throwables.remove(0);
}
throwables.add(message);
}
}
synchronized(LOCK)
{
message.printStackTrace(out);
}
} //}}}
//{{{ _log() method
private static void _log(int urgency, String source, String message)
{
String fullMessage = timeFormat.format(new Date()) + " ["+Thread.currentThread().getName()+"] [" + urgencyToString(urgency) + "] " + source
+ ": " + message;
try
{
log[logLineCount] = fullMessage;
if(++logLineCount >= log.length)
{
wrap = true;
logLineCount = 0;
}
if(stream != null)
{
stream.write(fullMessage);
stream.write(lineSep);
}
}
catch(Exception e)
{
e.printStackTrace(realErr);
}
if(urgency >= level)
{
if(urgency == ERROR)
realErr.println(fullMessage);
else
realOut.println(fullMessage);
}
} //}}}
//{{{ urgencyToString() method
private static String urgencyToString(int urgency)
{
switch(urgency)
{
case DEBUG:
return "debug";
case MESSAGE:
return "message";
case NOTICE:
return "notice";
case WARNING:
return "warning";
case ERROR:
return "error";
}
throw new IllegalArgumentException("Invalid urgency: " + urgency);
} //}}}
//}}}
//{{{ LogListModel class
static class LogListModel implements ListModel
{
final List<ListDataListener> listeners = new ArrayList<ListDataListener>();
//{{{ fireIntervalAdded() method
private void fireIntervalAdded(int index1, int index2)
{
for(int i = 0; i < listeners.size(); i++)
{
ListDataListener listener = listeners.get(i);
listener.intervalAdded(new ListDataEvent(this,
ListDataEvent.INTERVAL_ADDED,
index1,index2));
}
} //}}}
//{{{ fireIntervalRemoved() method
private void fireIntervalRemoved(int index1, int index2)
{
for(int i = 0; i < listeners.size(); i++)
{
ListDataListener listener = listeners.get(i);
listener.intervalRemoved(new ListDataEvent(this,
ListDataEvent.INTERVAL_REMOVED,
index1,index2));
}
} //}}}
//{{{ addListDataListener() method
public void addListDataListener(ListDataListener listener)
{
listeners.add(listener);
} //}}}
//{{{ removeListDataListener() method
public void removeListDataListener(ListDataListener listener)
{
listeners.remove(listener);
} //}}}
//{{{ getElementAt() method
public Object getElementAt(int index)
{
if(wrap)
{
if(index < MAXLINES - logLineCount)
return log[index + logLineCount];
else
return log[index - MAXLINES + logLineCount];
}
else
return log[index];
} //}}}
//{{{ getSize() method
public int getSize()
{
if(wrap)
return MAXLINES;
else
return logLineCount;
} //}}}
//{{{ update() method
void update(final int lineCount, final boolean oldWrap)
{
if(lineCount == 0 || listeners.isEmpty())
return;
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
if(wrap)
{
if(oldWrap)
fireIntervalRemoved(0,lineCount - 1);
else
{
fireIntervalRemoved(0,
logLineCount);
}
fireIntervalAdded(
MAXLINES - lineCount + 1,
MAXLINES);
}
else
{
fireIntervalAdded(
logLineCount - lineCount + 1,
logLineCount);
}
}
});
} //}}}
} //}}}
//{{{ LogPrintStream class
/**
* A print stream that uses the "Log" class to output the messages,
* and has special treatment for the printf() function. Using this
* stream has one caveat: printing messages that don"t have a line
* break at the end will have one added automatically...
*/
private static class LogPrintStream extends PrintStream {
private final ByteArrayOutputStream buffer;
private final OutputStream orig;
//{{{ LogPrintStream constructor
LogPrintStream(int urgency, Object source)
{
super(new LogOutputStream(urgency, source));
buffer = new ByteArrayOutputStream();
orig = out;
} //}}}
//{{{ printf() method
/**
* This is a hack to allow "printf" to not print weird
* stuff to the output. Since "printf" doesn"t seem to
* print the whole message in one shot, our output
* stream above would break a line of log into several
* lines; so we buffer the result of the printf call and
* print the whole thing in one shot. A similar hack
* would be needed for the "other" printf method, but
* I"ll settle for the common case only.
*/
public PrintStream printf(String format, Object... args)
{
synchronized (orig)
{
buffer.reset();
out = buffer;
super.printf(format, args);
try
{
byte[] data = buffer.toByteArray();
orig.write(data, 0, data.length);
out = orig;
}
catch (IOException ioe)
{
// don"t do anything?
}
finally
{
buffer.reset();
}
}
return this;
} //}}}
} //}}}
//{{{ LogOutputStream class
private static class LogOutputStream extends OutputStream
{
private final int urgency;
private final Object source;
//{{{ LogOutputStream constructor
LogOutputStream(int urgency, Object source)
{
this.urgency = urgency;
this.source = source;
} //}}}
//{{{ write() method
public synchronized void write(int b)
{
byte[] barray = { (byte)b };
write(barray,0,1);
} //}}}
//{{{ write() method
public synchronized void write(byte[] b, int off, int len)
{
String str = new String(b,off,len);
log(urgency,source,str);
} //}}}
} //}}}
}
Printing indented text
/**
* 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.
*/
import java.io.PrintWriter;
/**
* A helper class for printing indented text
*
* @version $Revision: 1.2 $
*/
public class IndentPrinter {
private int indentLevel;
private String indent;
private PrintWriter out;
public IndentPrinter() {
this(new PrintWriter(System.out), " ");
}
public IndentPrinter(PrintWriter out) {
this(out, " ");
}
public IndentPrinter(PrintWriter out, String indent) {
this.out = out;
this.indent = indent;
}
public void println(Object value) {
out.print(value.toString());
out.println();
}
public void println(String text) {
out.print(text);
out.println();
}
public void print(String text) {
out.print(text);
}
public void printIndent() {
for (int i = 0; i < indentLevel; i++) {
out.print(indent);
}
}
public void println() {
out.println();
}
public void incrementIndent() {
++indentLevel;
}
public void decrementIndent() {
--indentLevel;
}
public int getIndentLevel() {
return indentLevel;
}
public void setIndentLevel(int indentLevel) {
this.indentLevel = indentLevel;
}
public void flush() {
out.flush();
}
}
Prints messages formatted for a specific line width.
/*
* $RCSfile: MsgPrinter.java,v $
* $Revision: 1.1 $
* $Date: 2005/02/11 05:02:26 $
* $State: Exp $
*
* Class: MsgPrinter
*
* Description: Prints messages formatted for a specific
* line width.
*
*
*
* COPYRIGHT:
*
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
*
* Copyright (c) 1999/2000 JJ2000 Partners.
*
*
*
*/
import java.io.*;
/**
* This utility class formats messages to the specified line width, by
* inserting line-breaks between words, and printing the resulting
* lines.
* */
public class MsgPrinter {
/** The line width to use */
public int lw;
/** Signals that a newline was found */
private static final int IS_NEWLINE = -2;
/** Signals that the end-of-string was reached */
private static final int IS_EOS = -1;
/**
* Creates a new message printer with the specified line width and
* with the default locale.
*
* @param linewidth The line width for which to format (in
* characters)
*
*
* */
public MsgPrinter(int linewidth) {
lw = linewidth;
}
/**
* Returns the line width that is used for formatting.
*
* @return The line width used for formatting
*
*
* */
public int getLineWidth() {
return lw;
}
/**
* Sets the line width to the specified value. This new value will
* be used in subsequent calls to the print() message.
*
* @param linewidth The new line width to use (in cahracters)
*
*
* */
public void setLineWidth(int linewidth) {
if (linewidth <1) {
throw new IllegalArgumentException();
}
lw = linewidth;
}
/**
* Formats the message to print in the current line width, by
* breaking the message into lines between words. The number of
* spaces to indent the first line is specified by "flind" and the
* number of spaces to indent each of the following lines is
* specified by "ind". Newlines in "msg" are respected. A newline is
* always printed at the end.
*
* @param out Where to print the message.
*
* @param flind The indentation for the first line.
*
* @param ind The indentation for the other lines.
*
* @param msg The message to format and print.
*
*
* */
public void print(PrintWriter out, int flind, int ind,
String msg) {
int start,end,pend,efflw,lind,i;
start = 0;
end = 0;
pend = 0;
efflw = lw-flind;
lind = flind;
while ((end = nextLineEnd(msg,pend)) != IS_EOS) {
if (end == IS_NEWLINE) { // Forced line break
for (i=0; i<lind; i++) {
out.print(" ");
}
out.println(msg.substring(start,pend));
if (nextWord(msg,pend) == msg.length()) {
// Traling newline => print it and done
out.println("");
start = pend;
break;
}
}
else {
if (efflw > end-pend) { // Room left on current line
efflw -= end-pend;
pend = end;
continue;
}
else { // Filled-up current line => print it
for (i=0; i<lind; i++) {
out.print(" ");
}
if (start == pend) { // Word larger than line width
// Print anyways
out.println(msg.substring(start,end));
pend = end;
}
else {
out.println(msg.substring(start,pend));
}
}
}
// Initialize for next line
lind = ind;
efflw = lw-ind;
start = nextWord(msg,pend);
pend = start;
if (start == IS_EOS) {
break; // Did all the string
}
}
if (pend != start) { // Part of a line left => print it
for (i=0; i<lind; i++) {
out.print(" ");
}
out.println(msg.substring(start,pend));
}
}
/**
* Returns the index of the last character of the next word, plus 1, or
* IS_NEWLINE if a newline character is encountered before the next word,
* or IS_EOS if the end of the string is ecnounterd before the next
* word. The method first skips all whitespace characters at or after
* "from", except newlines. If a newline is found IS_NEWLINE is
* returned. Then it skips all non-whitespace characters and returns the
* position of the last non-whitespace character, plus 1. The returned
* index may be greater than the last valid index in the tsring, but it is
* always suitable to be used in the String.substring() method.
*
* Non-whitespace characters are defined as in the
* Character.isWhitespace method (that method is used).
*
* @param str The string to parse
*
* @param from The index of the first position to search from
*
* @return The index of the last character in the next word, plus 1,
* IS_NEWLINE, or IS_EOS if there are no more words.
*
*
* */
private int nextLineEnd(String str, int from) {
final int len = str.length();
char c = "\0";
// First skip all whitespace, except new line
while (from < len && (c = str.charAt(from)) != "\n" &&
Character.isWhitespace(c)) {
from++;
}
if (c == "\n") {
return IS_NEWLINE;
}
if (from >= len) {
return IS_EOS;
}
// Now skip word characters
while (from < len && !Character.isWhitespace(str.charAt(from))) {
from++;
}
return from;
}
/**
* Returns the position of the first character in the next word, starting
* from "from", if a newline is encountered first then the index of the
* newline character plus 1 is returned. If the end of the string is
* encountered then IS_EOS is returned. Words are defined as any
* concatenation of 1 or more characters which are not
* whitespace. Whitespace characters are those for which
* Character.isWhitespace() returns true (that method is used).
*
* Non-whitespace characters are defined as in the
* Character.isWhitespace method (that method is used).
*
* @param str The string to parse
*
* @param from The index where to start parsing
*
* @return The index of the first character of the next word, or the index
* of the newline plus 1, or IS_EOS.
*
*
* */
private int nextWord(String str, int from) {
final int len = str.length();
char c = "\0";
// First skip all whitespace, but new lines
while (from < len && (c = str.charAt(from)) != "\n" &&
Character.isWhitespace(c)) {
from++;
}
if (from >= len) {
return IS_EOS;
}
else if (c == "\n") {
return from+1;
}
else {
return from;
}
}
}
Random data for test
/*
* Copyright 2005 Joe Walker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Random;
/**
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class RandomData
{
/**
* @param isUS US numbers look different to UK ones
* @return A phone number
*/
public static String getPhoneNumber(boolean isUS)
{
String phoneNumber;
if (isUS)
{
// US
phoneNumber = "+1 (" + random.nextInt(9) + random.nextInt(9) + random.nextInt(9) + ") "
+ random.nextInt(9) + random.nextInt(9) + random.nextInt(9) + " - "
+ random.nextInt(9) + random.nextInt(9) + random.nextInt(9) + random.nextInt(9);
}
else
{
// UK
phoneNumber = "+44 (0) 1" + random.nextInt(9) + random.nextInt(9) + random.nextInt(9)
+ " " + random.nextInt(9) + random.nextInt(9) + random.nextInt(9) + random.nextInt(9)
+ random.nextInt(9) + random.nextInt(9);
}
return phoneNumber;
}
public static String getFirstName()
{
return FIRSTNAMES[random.nextInt(FIRSTNAMES.length)];
}
public static String getSurname()
{
return SURNAMES[random.nextInt(SURNAMES.length)];
}
public static String getFullName()
{
return getFirstName() + " " + getSurname();
}
public static String getAddress()
{
String housenum = (random.nextInt(99) + 1) + " ";
String road1 = ROADS1[random.nextInt(ROADS1.length)];
String road2 = ROADS2[random.nextInt(ROADS2.length)];
int townNum = random.nextInt(TOWNS.length);
String town = TOWNS[townNum];
return housenum + road1 + " " + road2 + ", " + town;
}
public static String[] getAddressAndNumber()
{
String[] reply = new String[2];
String housenum = (random.nextInt(99) + 1) + " ";
String road1 = ROADS1[random.nextInt(ROADS1.length)];
String road2 = ROADS2[random.nextInt(ROADS2.length)];
int townNum = random.nextInt(TOWNS.length);
String town = TOWNS[townNum];
reply[0] = housenum + road1 + " " + road2 + ", " + town;
reply[1] = getPhoneNumber(townNum < 5);
return reply;
}
public static float getSalary()
{
return Math.round(10 + 90 * random.nextFloat()) * 1000;
}
private static final Random random = new Random();
private static final String[] FIRSTNAMES =
{
"Fred", "Jim", "Shiela", "Jack", "Betty", "Jacob", "Martha", "Kelly",
"Luke", "Matt", "Gemma", "Joe", "Ben", "Jessie", "Leanne", "Becky",
"William", "Jo"
};
private static final String[] SURNAMES =
{
"Sutcliffe", "MacDonald", "Duckworth", "Smith", "Wisner",
"Nield", "Turton", "Trelfer", "Wilson", "Johnson", "Daniels",
"Jones", "Wilkinson", "Wilton"
};
private static final String[] ROADS1 =
{
"Green", "Red", "Yellow", "Brown", "Blue", "Black", "White",
};
private static final String[] ROADS2 =
{
"Close", "Drive", "Street", "Avenue", "Crescent", "Road", "Place",
};
private static final String[] TOWNS =
{
"San Mateo", "San Francisco", "San Diego", "New York", "Atlanta",
"Sandford", "York", "London", "Coventry", "Exeter", "Knowle",
};
}
Swing Console
/*
* IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
*
* http://izpack.org/
* http://izpack.codehaus.org/
*
* Copyright 2002 Jan Blok
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.Segment;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.util.Vector;
public final class Console
{
public static final int INITIAL_WIDTH = 800;
public static final int INITIAL_HEIGHT = 600;
public static void main(String[] args)
{
Runtime rt = Runtime.getRuntime();
Process p = null;
try
{
/*
* Start a new process in which to execute the commands in cmd, using the environment in
* env and use pwd as the current working directory.
*/
p = rt.exec(args);// , env, pwd);
new Console(p);
System.exit(p.exitValue());
}
catch (IOException e)
{
/*
* Couldn"t even get the command to start. Most likely it couldn"t be found because of a
* typo.
*/
System.out.println("Error starting: " + args[0]);
System.out.println(e);
}
}
private StdOut so;
private StdOut se;
public String getOutputData()
{
if (so != null)
{
return so.getData();
}
else
{
return "";
}
}
public String getErrorData()
{
if (se != null)
{
return se.getData();
}
else
{
return "";
}
}
public Console(Process p)
{
JFrame frame = new JFrame();
frame.setTitle("Console");
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(screenSize.width / 2 - INITIAL_WIDTH / 2, screenSize.height / 2
- INITIAL_HEIGHT / 2);
ConsoleTextArea cta = new ConsoleTextArea();
JScrollPane scroll = new JScrollPane(cta);
scroll.setPreferredSize(new Dimension(INITIAL_WIDTH, INITIAL_HEIGHT));
frame.getContentPane().add(scroll);
frame.pack();
// From here down your shell should be pretty much
// as it is written here!
/*
* Start up StdOut, StdIn and StdErr threads that write the output generated by the process
* p to the screen, and feed the keyboard input into p.
*/
so = new StdOut(p, cta);
se = new StdOut(p, cta);
StdIn si = new StdIn(p, cta);
so.start();
se.start();
si.start();
// Wait for the process p to complete.
try
{
frame.setVisible(true);
p.waitFor();
}
catch (InterruptedException e)
{
/*
* Something bad happened while the command was executing.
*/
System.out.println("Error during execution");
System.out.println(e);
}
/*
* Now signal the StdOut, StdErr and StdIn threads that the process is done, and wait for
* them to complete.
*/
try
{
so.done();
se.done();
si.done();
so.join();
se.join();
si.join();
}
catch (InterruptedException e)
{
// Something bad happend to one of the Std threads.
System.out.println("Error in StdOut, StdErr or StdIn.");
System.out.println(e);
}
frame.setVisible(false);
}
}
class StdIn extends Thread
{
private BufferedReader kb;
private boolean processRunning;
private PrintWriter op;
public StdIn(Process p, ConsoleTextArea cta)
{
setDaemon(true);
InputStreamReader ir = new InputStreamReader(cta.getIn());
kb = new BufferedReader(ir);
BufferedOutputStream os = new BufferedOutputStream(p.getOutputStream());
op = new PrintWriter((new OutputStreamWriter(os)), true);
processRunning = true;
}
public void run()
{
try
{
while (kb.ready() || processRunning)
{
if (kb.ready())
{
op.println(kb.readLine());
}
}
}
catch (IOException e)
{
System.err.println("Problem reading standard input.");
System.err.println(e);
}
}
public void done()
{
processRunning = false;
}
}
class StdOut extends Thread
{
private InputStreamReader output;
private boolean processRunning;
private ConsoleTextArea cta;
private StringBuffer data;
public StdOut(Process p, ConsoleTextArea cta)
{
setDaemon(true);
output = new InputStreamReader(p.getInputStream());
this.cta = cta;
processRunning = true;
data = new StringBuffer();
}
public void run()
{
try
{
/*
* Loop as long as there is output from the process to be displayed or as long as the
* process is still running even if there is presently no output.
*/
while (output.ready() || processRunning)
{
// If there is output get it and display it.
if (output.ready())
{
char[] array = new char[255];
int num = output.read(array);
if (num != -1)
{
String s = new String(array, 0, num);
data.append(s);
SwingUtilities.invokeAndWait(new ConsoleWrite(cta, s));
}
}
}
}
catch (Exception e)
{
System.err.println("Problem writing to standard output.");
System.err.println(e);
}
}
public void done()
{
processRunning = false;
}
public String getData()
{
return data.toString();
}
}
class ConsoleWrite implements Runnable
{
private ConsoleTextArea textArea;
private String str;
public ConsoleWrite(ConsoleTextArea textArea, String str)
{
this.textArea = textArea;
this.str = str;
}
public void run()
{
textArea.write(str);
}
}
class ConsoleWriter extends java.io.OutputStream
{
private ConsoleTextArea textArea;
private StringBuffer buffer;
public ConsoleWriter(ConsoleTextArea textArea)
{
this.textArea = textArea;
buffer = new StringBuffer();
}
public synchronized void write(int ch)
{
buffer.append((char) ch);
if (ch == "\n")
{
flushBuffer();
}
}
public synchronized void write(char[] data, int off, int len)
{
for (int i = off; i < len; i++)
{
buffer.append(data[i]);
if (data[i] == "\n")
{
flushBuffer();
}
}
}
public synchronized void flush()
{
if (buffer.length() > 0)
{
flushBuffer();
}
}
public void close()
{
flush();
}
private void flushBuffer()
{
String str = buffer.toString();
buffer.setLength(0);
SwingUtilities.invokeLater(new ConsoleWrite(textArea, str));
}
}
class ConsoleTextArea extends JTextArea implements KeyListener, DocumentListener
{
/**
*
*/
private static final long serialVersionUID = 3258410625414475827L;
private ConsoleWriter console1;
private PrintStream out;
private PrintStream err;
private PrintWriter inPipe;
private PipedInputStream in;
private Vector<String> history;
private int historyIndex = -1;
private int outputMark = 0;
public void select(int start, int end)
{
requestFocus();
super.select(start, end);
}
public ConsoleTextArea()
{
super();
history = new java.util.Vector<String>();
console1 = new ConsoleWriter(this);
ConsoleWriter console2 = new ConsoleWriter(this);
out = new PrintStream(console1);
err = new PrintStream(console2);
PipedOutputStream outPipe = new PipedOutputStream();
inPipe = new PrintWriter(outPipe);
in = new PipedInputStream();
try
{
outPipe.connect(in);
}
catch (IOException exc)
{
exc.printStackTrace();
}
getDocument().addDocumentListener(this);
addKeyListener(this);
setLineWrap(true);
setFont(new Font("Monospaced", 0, 12));
}
void returnPressed()
{
Document doc = getDocument();
int len = doc.getLength();
Segment segment = new Segment();
try
{
synchronized (doc)
{
doc.getText(outputMark, len - outputMark, segment);
}
}
catch (javax.swing.text.BadLocationException ignored)
{
ignored.printStackTrace();
}
if (segment.count > 0)
{
history.addElement(segment.toString());
}
historyIndex = history.size();
inPipe.write(segment.array, segment.offset, segment.count);
append("\n");
synchronized (doc)
{
outputMark = doc.getLength();
}
inPipe.write("\n");
inPipe.flush();
console1.flush();
}
public void eval(String str)
{
inPipe.write(str);
inPipe.write("\n");
inPipe.flush();
console1.flush();
}
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_LEFT)
{
if (outputMark == getCaretPosition())
{
e.consume();
}
}
else if (code == KeyEvent.VK_HOME)
{
int caretPos = getCaretPosition();
if (caretPos == outputMark)
{
e.consume();
}
else if (caretPos > outputMark)
{
if (!e.isControlDown())
{
if (e.isShiftDown())
{
moveCaretPosition(outputMark);
}
else
{
setCaretPosition(outputMark);
}
e.consume();
}
}
}
else if (code == KeyEvent.VK_ENTER)
{
returnPressed();
e.consume();
}
else if (code == KeyEvent.VK_UP)
{
historyIndex--;
if (historyIndex >= 0)
{
if (historyIndex >= history.size())
{
historyIndex = history.size() - 1;
}
if (historyIndex >= 0)
{
String str = history.elementAt(historyIndex);
int len = getDocument().getLength();
replaceRange(str, outputMark, len);
int caretPos = outputMark + str.length();
select(caretPos, caretPos);
}
else
{
historyIndex++;
}
}
else
{
historyIndex++;
}
e.consume();
}
else if (code == KeyEvent.VK_DOWN)
{
int caretPos = outputMark;
if (history.size() > 0)
{
historyIndex++;
if (historyIndex < 0)
{
historyIndex = 0;
}
int len = getDocument().getLength();
if (historyIndex < history.size())
{
String str = history.elementAt(historyIndex);
replaceRange(str, outputMark, len);
caretPos = outputMark + str.length();
}
else
{
historyIndex = history.size();
replaceRange("", outputMark, len);
}
}
select(caretPos, caretPos);
e.consume();
}
}
public void keyTyped(KeyEvent e)
{
int keyChar = e.getKeyChar();
if (keyChar == 0x8 /* KeyEvent.VK_BACK_SPACE */)
{
if (outputMark == getCaretPosition())
{
e.consume();
}
}
else if (getCaretPosition() < outputMark)
{
setCaretPosition(outputMark);
}
}
public void keyReleased(KeyEvent e)
{
}
public synchronized void write(String str)
{
insert(str, outputMark);
int len = str.length();
outputMark += len;
select(outputMark, outputMark);
}
public synchronized void insertUpdate(DocumentEvent e)
{
int len = e.getLength();
int off = e.getOffset();
if (outputMark > off)
{
outputMark += len;
}
}
public synchronized void removeUpdate(DocumentEvent e)
{
int len = e.getLength();
int off = e.getOffset();
if (outputMark > off)
{
if (outputMark >= off + len)
{
outputMark -= len;
}
else
{
outputMark = off;
}
}
}
public void postUpdateUI()
{
// this attempts to cleanup the damage done by updateComponentTreeUI
requestFocus();
setCaret(getCaret());
synchronized (this)
{
select(outputMark, outputMark);
}
}
public void changedUpdate(DocumentEvent e)
{
}
public InputStream getIn()
{
return in;
}
public PrintStream getOut()
{
return out;
}
public PrintStream getErr()
{
return err;
}
}