Java/Development Class/Debug
Содержание
- 1 A bean that can be used to keep track of a counter
- 2 A long integer counter class
- 3 An integer synchronized counter class.
- 4 A simple logging facility.
- 5 Class providing static methods to log diagnostics
- 6 Counts down from a specified value the number of bytes actually read from the wrapped InputStream.
- 7 Debugging utility that reports, in a brute force manner, any internal data of a class instance
- 8 Debug InputStream
- 9 Debug Utilities
- 10 Debug Utility
- 11 Handle obtaining string timestamps
- 12 How to do Benchmark
- 13 Logging class to record errors or unexpected behavior to a file
- 14 Methods for logging events
- 15 Methods for printing Debug messages
- 16 Printing indented text
- 17 Prints messages formatted for a specific line width.
- 18 Scans java source files in cvs tree and validates the license header
- 19 Swing Console
- 20 Trace InputStream
- 21 Trace OutputStream
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 long integer counter class
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.Serializable;
/**
* A long integer counter class.
*
* @version <tt>$Revision: 2800 $</tt>
* @author
*/
public class LongCounter implements Serializable, Cloneable {
/** The serialVersionUID */
private static final long serialVersionUID = 1615297462859270139L;
/** The current count */
private long count;
/**
* Construct a LongCounter with a starting value.
*
* @param count
* Starting value for counter.
*/
public LongCounter(final long count) {
this.count = count;
}
/**
* Construct a LongCounter.
*/
public LongCounter() {
}
/**
* Increment the counter. (Optional operation)
*
* @return The incremented value of the counter.
*/
public long increment() {
return ++count;
}
/**
* Decrement the counter. (Optional operation)
*
* @return The decremented value of the counter.
*/
public long decrement() {
return --count;
}
/**
* Return the current value of the counter.
*
* @return The current value of the counter.
*/
public long getCount() {
return count;
}
/**
* Reset the counter to zero. (Optional operation)
*/
public void reset() {
this.count = 0;
}
/**
* Check if the given object is equal to this.
*
* @param obj
* Object to test equality with.
* @return True if object is equal to this.
*/
public boolean equals(final Object obj) {
if (obj == this)
return true;
if (obj != null && obj.getClass() == getClass()) {
return ((LongCounter) obj).count == count;
}
return false;
}
/**
* Return a string representation of this.
*
* @return A string representation of this.
*/
public String toString() {
return String.valueOf(count);
}
/**
* Return a cloned copy of this object.
*
* @return A cloned copy of this object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
// ///////////////////////////////////////////////////////////////////////
// Wrappers //
// ///////////////////////////////////////////////////////////////////////
/**
* Base wrapper class for other wrappers.
*/
private static class Wrapper extends LongCounter {
/** The serialVersionUID */
private static final long serialVersionUID = 6720507617603163762L;
/** The wrapped counter */
protected final LongCounter counter;
public Wrapper(final LongCounter counter) {
this.counter = counter;
}
public long increment() {
return counter.increment();
}
public long decrement() {
return counter.decrement();
}
public long getCount() {
return counter.getCount();
}
public void reset() {
counter.reset();
}
public boolean equals(final Object obj) {
return counter.equals(obj);
}
public String toString() {
return counter.toString();
}
public Object clone() {
return counter.clone();
}
}
/**
* Return a synchronized counter.
*
* @param counter
* LongCounter to synchronize.
* @return Synchronized counter.
*/
public static LongCounter makeSynchronized(final LongCounter counter) {
return new Wrapper(counter) {
/** The serialVersionUID */
private static final long serialVersionUID = 8903330696503363758L;
public synchronized long increment() {
return this.counter.increment();
}
public synchronized long decrement() {
return this.counter.decrement();
}
public synchronized long getCount() {
return this.counter.getCount();
}
public synchronized void reset() {
this.counter.reset();
}
public synchronized int hashCode() {
return this.counter.hashCode();
}
public synchronized boolean equals(final Object obj) {
return this.counter.equals(obj);
}
public synchronized String toString() {
return this.counter.toString();
}
public synchronized Object clone() {
return this.counter.clone();
}
};
}
/**
* Returns a directional counter.
*
* @param counter
* LongCounter to make directional.
* @param increasing
* True to create an increasing only or false to create a decreasing
* only.
* @return A directional counter.
*/
public static LongCounter makeDirectional(final LongCounter counter, final boolean increasing) {
LongCounter temp;
if (increasing) {
temp = new Wrapper(counter) {
/** The serialVersionUID */
private static final long serialVersionUID = -8902748795144754375L;
public long decrement() {
throw new UnsupportedOperationException();
}
public void reset() {
throw new UnsupportedOperationException();
}
};
} else {
temp = new Wrapper(counter) {
/** The serialVersionUID */
private static final long serialVersionUID = 2584758778978644599L;
public long increment() {
throw new UnsupportedOperationException();
}
};
}
return temp;
}
}
An integer synchronized counter class.
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.util;
import java.io.Serializable;
/**
* An integer counter class.
*
* @version <tt>$Revision: 2800 $</tt>
* @author
*/
public class Counter
implements Serializable, Cloneable
{
/** The serialVersionUID */
private static final long serialVersionUID = 7736259185393081556L;
/** The current count */
private int count;
/**
* Construct a Counter with a starting value.
*
* @param count Starting value for counter.
*/
public Counter(final int count) {
this.count = count;
}
/**
* Construct a Counter.
*/
public Counter() {}
/**
* Increment the counter. (Optional operation)
*
* @return The incremented value of the counter.
*/
public int increment() {
return ++count;
}
/**
* Decrement the counter. (Optional operation)
*
* @return The decremented value of the counter.
*/
public int decrement() {
return --count;
}
/**
* Return the current value of the counter.
*
* @return The current value of the counter.
*/
public int getCount() {
return count;
}
/**
* Reset the counter to zero. (Optional operation)
*/
public void reset() {
this.count = 0;
}
/**
* Check if the given object is equal to this.
*
* @param obj Object to test equality with.
* @return True if object is equal to this.
*/
public boolean equals(final Object obj) {
if (obj == this) return true;
if (obj != null && obj.getClass() == getClass()) {
return ((Counter)obj).count == count;
}
return false;
}
/**
* Return a string representation of this.
*
* @return A string representation of this.
*/
public String toString() {
return String.valueOf(count);
}
/**
* Return a cloned copy of this object.
*
* @return A cloned copy of this object.
*/
public Object clone() {
try {
return super.clone();
}
catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
/////////////////////////////////////////////////////////////////////////
// Wrappers //
/////////////////////////////////////////////////////////////////////////
/**
* Base wrapper class for other wrappers.
*/
private static class Wrapper
extends Counter
{
/** The serialVersionUID */
private static final long serialVersionUID = -1803971437884946242L;
/** The wrapped counter */
protected final Counter counter;
public Wrapper(final Counter counter) {
this.counter = counter;
}
public int increment() {
return counter.increment();
}
public int decrement() {
return counter.decrement();
}
public int getCount() {
return counter.getCount();
}
public void reset() {
counter.reset();
}
public boolean equals(final Object obj) {
return counter.equals(obj);
}
public String toString() {
return counter.toString();
}
public Object clone() {
return counter.clone();
}
}
/**
* Return a synchronized counter.
*
* @param counter Counter to synchronize.
* @return Synchronized counter.
*/
public static Counter makeSynchronized(final Counter counter) {
return new Wrapper(counter) {
/** The serialVersionUID */
private static final long serialVersionUID = -6024309396861726945L;
public synchronized int increment() {
return this.counter.increment();
}
public synchronized int decrement() {
return this.counter.decrement();
}
public synchronized int getCount() {
return this.counter.getCount();
}
public synchronized void reset() {
this.counter.reset();
}
public synchronized int hashCode() {
return this.counter.hashCode();
}
public synchronized boolean equals(final Object obj) {
return this.counter.equals(obj);
}
public synchronized String toString() {
return this.counter.toString();
}
public synchronized Object clone() {
return this.counter.clone();
}
};
}
/**
* Returns a directional counter.
*
* @param counter Counter to make directional.
* @param increasing True to create an increasing only
* or false to create a decreasing only.
* @return A directional counter.
*/
public static Counter makeDirectional(final Counter counter,
final boolean increasing)
{
Counter temp;
if (increasing) {
temp = new Wrapper(counter) {
/** The serialVersionUID */
private static final long serialVersionUID = 2161377898611431781L;
public int decrement() {
throw new UnsupportedOperationException();
}
public void reset() {
throw new UnsupportedOperationException();
}
};
}
else {
temp = new Wrapper(counter) {
/** The serialVersionUID */
private static final long serialVersionUID = -4683457706354663230L;
public int increment() {
throw new UnsupportedOperationException();
}
};
}
return temp;
}
}
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);
}
}
Class providing static methods to log diagnostics
// jTDS JDBC Driver for Microsoft SQL Server and Sybase
// Copyright (C) 2004 The jTDS Project
//
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
import java.sql.*;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Class providing static methods to log diagnostics.
* <p>
* There are three ways to enable logging:
* <ol>
* <li>Pass a valid PrintWriter to DriverManager.setLogWriter().
* <li>Pass a valid PrintWriter to DataSource.setLogWriter().
* <li>For backwards compatibility call Logger.setActive();
* </ol>
*
* @author Mike Hutchinson
* @version $Id: Logger.java,v 1.11 2005/04/20 16:49:31 alin_sinpalean Exp $
*/
public class Logger {
/** PrintWriter stream set by DataSource. */
private static PrintWriter log;
/**
* Set the logging PrintWriter stream.
*
* @param out the PrintWriter stream
*/
public static void setLogWriter(PrintWriter out) {
log = out;
}
/**
* Get the logging PrintWriter Stream.
*
* @return the logging stream as a <code>PrintWriter</code>
*/
public static PrintWriter getLogWriter() {
return log;
}
/**
* Retrieve the active status of the logger.
*
* @return <code>boolean</code> true if logging enabled
*/
public static boolean isActive() {
return(log != null || DriverManager.getLogWriter() != null);
}
/**
* Print a diagnostic message to the output stream provided by
* the DataSource or the DriverManager.
*
* @param message the diagnostic message to print
*/
public static void println(String message) {
if (log != null) {
log.println(message);
} else {
DriverManager.println(message);
}
}
private static final char hex[] =
{"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
/**
* Print a dump of the current input or output network packet.
*
* @param streamId the owner of this packet
* @param in true if this is an input packet
* @param pkt the packet data
*/
public static void logPacket(int streamId, boolean in, byte[] pkt) {
int len = ((pkt[2] & 0xFF) << 8)| (pkt[3] & 0xFF);
StringBuffer line = new StringBuffer(80);
line.append("----- Stream #");
line.append(streamId);
line.append(in ? " read" : " send");
line.append((pkt[1] != 0) ? " last " : " ");
switch (pkt[0]) {
case 1:
line.append("Request packet ");
break;
case 2:
line.append("Login packet ");
break;
case 3:
line.append("RPC packet ");
break;
case 4:
line.append("Reply packet ");
break;
case 6:
line.append("Cancel packet ");
break;
case 14:
line.append("XA control packet ");
break;
case 15:
line.append("TDS5 Request packet ");
break;
case 16:
line.append("MS Login packet ");
break;
case 17:
line.append("NTLM Authentication packet ");
break;
case 18:
line.append("MS Prelogin packet ");
break;
default:
line.append("Invalid packet ");
break;
}
println(line.toString());
println("");
line.setLength(0);
for (int i = 0; i < len; i += 16) {
if (i < 1000) {
line.append(" ");
}
if (i < 100) {
line.append(" ");
}
if (i < 10) {
line.append(" ");
}
line.append(i);
line.append(":").append(" ");
int j = 0;
for (; j < 16 && i + j < len; j++) {
int val = pkt[i+j] & 0xFF;
line.append(hex[val >> 4]);
line.append(hex[val & 0x0F]);
line.append(" ");
}
for (; j < 16 ; j++) {
line.append(" ");
}
line.append("|");
for (j = 0; j < 16 && i + j < len; j++) {
int val = pkt[i + j] & 0xFF;
if (val > 31 && val < 127) {
line.append((char) val);
} else {
line.append(" ");
}
}
line.append("|");
println(line.toString());
line.setLength(0);
}
println("");
}
/**
* Print an Exception stack trace to the log.
*
* @param e the exception to log
*/
public static void logException(Exception e) {
if (log != null) {
e.printStackTrace(log);
} else if (DriverManager.getLogWriter() != null) {
e.printStackTrace(DriverManager.getLogWriter());
}
}
//
// Backward compatbility method
//
/**
* Turn the logging on or off.
*
* @deprecated Use the JDBC standard mechanisms to enable logging.
* @param value true to turn on logging
*/
public static void setActive(boolean value) {
if (value && log == null) {
try {
log = new PrintWriter(new FileOutputStream("log.out"), true);
} catch (IOException e) {
log = null; // Sorry no logging!
}
}
}
}
Counts down from a specified value the number of bytes actually read from the wrapped InputStream.
/* 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.io.IOException;
import java.io.InputStream;
/**
* Counts down from a specified value the number of bytes actually read
* from the wrapped InputStream. <p>
*
* Returns minus one (-1) early from readXXX methods if the count
* down reaches zero (0) before the end of the wrapped InputStream
* is encountered. <p>
*
* This class is especially useful when a fixed number of bytes is to be read
* from an InputStream that is in turn to be used as the source for an
* {@link java.io.InputStreamReader InputStreamReader}.
*
* @author boucherb@users
* @version 1.8.x
* @since 1.8.x
*/
public final class CountdownInputStream extends InputStream {
private long count;
private InputStream input;
public CountdownInputStream(final InputStream is) {
this.input = is;
}
public int read() throws IOException {
if (this.count <= 0) {
return -1;
}
final int b = this.input.read();
if (b >= 0) {
this.count--;
}
return b;
}
public int read(final byte[] buf) throws IOException {
if (this.count <= 0) {
return -1;
}
int len = buf.length;
if (len > this.count) {
len = (int) this.count;
}
final int r = this.input.read(buf, 0, len);
if (r > 0) {
this.count -= r;
}
return r;
}
public int read(final byte[] buf, final int off,
int len) throws IOException {
if (this.count <= 0) {
return -1;
}
if (len > this.count) {
len = (int) this.count;
}
final int r = this.input.read(buf, 0, len);
if (r > 0) {
this.count -= r;
}
return r;
}
public void close() throws IOException {
this.input.close();
}
public long getCount() {
return this.count;
}
public void setCount(long count) {
this.count = count;
}
}
Debugging utility that reports, in a brute force manner, any internal data of a class instance
//----------------------------------------------------------------------------//
// //
// D u m p e r //
// //
// Copyright (C) Herve Bitteur 2000-2009. All rights reserved. //
// This software is released under the GNU General Public License. //
// Please contact users@audiveris.dev.java.net to report bugs & suggestions. //
//----------------------------------------------------------------------------//
//
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;
/**
* Class <code>Dumper</code> is a debugging utility that reports, in a brute
* force manner, any internal data of a class instance.
*
* <p> When used on a class instance, all class internal fields which are
* considered as "relevant" are printed using their toString() method, then we
* walk up the inheritance tree and repeat the same actions, until there is no
* more superclass or until the superclass we have reached is considered as
* non-relevant. </p>
*
* <p> A (super)class is considered "relevant" if the static method
* <code>isClassRelevant(class)</code> returns true. This method can be
* overridden in a subclass of Dumper to adapt to local needs. </p>
*
* <p> A field is considered "relevant" if the following condition if the method
* <code>isFieldRelevant(field)</code> returns true. Similarly, the behavior of
* this predicate can be customized by subclassing the Dumper class. </p>
*
* <p> There are several kinds of print outs available through subclassing. Each
* of them export two public methods: <code>dump()</code> which prints the
* result on default output stream, and <code>dumpOf()</code> which simply
* returns the generated dump string.
*
* <ul> <li> <b>Column</b> a dump with one line per field </li>
*
* <li> <b>Row</b> a dump with all information on one row </li>
*
* <li> <b>Html</b> an Html stream with fields arranged in tables </li>
*
* </ul>
*
* Here are some examples of use:
* <pre>
* // Using the predefined static helper methods
* Dumper.dump(myinstance);
* Dumper.dump(myinstance, "My Title");
* Dumper.dump(myinstance, "My Title", 2);
* System.out.println(Dumper.dumpOf(myinstance));
* System.out.println(Dumper.htmlDumpOf(myinstance));
*
* // Using directly the Dumper subclasses
* new Dumper.Column(myinstance).print();
* System.out.println(new Dumper.Row(myinstance).toString());
* display(new Dumper.Html(myinstance).toString());
* </pre>
*
* @author Hervé Bitteur
* @version $Id: Dumper.java,v 1.15 2009/03/03 19:45:51 hbitteur Exp $
*/
public abstract class Dumper
{
//~ Instance fields --------------------------------------------------------
/**
* The object to be dumped
*/
protected final Object obj;
/**
* The string buffer used as output
*/
protected final StringBuffer sb;
/**
* Can we use HTML directives?
*/
protected final boolean useHtml;
/** Maximum number of collection items printed */
private final int MAX_COLLECTION_INDEX = 9;
/**
* Class (beware, this variable is updated as we walk up the inheritance
* tree)
*/
protected Class cl;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new Dumper.
*
* @param obj the object instance to be dumped.
*/
private Dumper (Object obj,
boolean useHtml)
{
// (re)Allocate the string buffer
sb = new StringBuffer(1024);
// Cache the object & the related class
this.obj = obj;
this.useHtml = useHtml;
cl = obj.getClass();
}
//~ Methods ----------------------------------------------------------------
//-----------------//
// isClassRelevant //
//-----------------//
/**
* Predicate to determine if a given class is worth being printed. This
* method could be overridden to reflect customized policy. Note that when
* walking up the inheritance tree, the browsing is stopped as soon as a
* non-relevant class is encountered.
*
* @param cl the class at stake
*
* @return true if found relevant
*/
public static boolean isClassRelevant (Class cl)
{
// return (cl != null) && !cl.getName()
// .startsWith("java.") &&
// !cl.getName()
// .startsWith("javax.");
return (cl != null) && cl.getName()
.startsWith("omr.");
}
//-----------------//
// isFieldRelevant //
//-----------------//
/**
* Predicate to determine if a given field is worth being printed. This
* method could be overridden to reflect customized policy.
*
* @param field the field at stake
*
* @return true if found relevant
*/
public static boolean isFieldRelevant (Field field)
{
// We don"t print static field since the Dumper is meant for instances
if (Modifier.isStatic(field.getModifiers())) {
return false;
}
// We don"t print non-user visible entities
if (field.getName()
.indexOf("$") != -1) {
return false;
}
return true;
}
//------//
// dump //
//------//
/**
* Helper function that prints the internal data of an object onto the
* standard output.
*
* @param obj the instance to dump
*/
public static void dump (Object obj)
{
dump(obj, null, 0);
}
//------//
// dump //
//------//
/**
* Helper function that prints the internal data of an object onto the
* standard output, with a specified left indentation level.
*
* @param obj the instance to dump
* @param level the indentation level (0 means no indentation)
*/
public static void dump (Object obj,
int level)
{
dump(obj, null, level);
}
//------//
// dump //
//------//
/**
* Helper function that prints the internal data of an object onto the
* standard output, with the ability to print a related title
*
* @param obj the object to dump
* @param title the title to print beforehand
*/
public static void dump (Object obj,
String title)
{
dump(obj, title, 0);
}
//------//
// dump //
//------//
/**
* Helper function that prints the internal data of an object onto the
* standard output, with room for a title and left indentation.
*
* @param obj the object to dump
* @param title the title to print beforehand
* @param level the indentation level (0 for no indent)
*/
public static void dump (Object obj,
String title,
int level)
{
new Column(obj, title, level).print();
}
//--------//
// dumpOf //
//--------//
/**
* Helper function that returns a line which contains the whole set of
* internal data
*
* @param obj the object whose data is to be printed
*
* @return the string of data values
*/
public static String dumpOf (Object obj)
{
return new Row(obj).toString();
}
//------------//
// htmlDumpOf //
//------------//
/**
* Helper function that prints a special kind of information string, using
* HTML tags so that an html editor can easily render this.
*
* @param obj the object to dump
*
* @return the HTML string
*/
public static String htmlDumpOf (Object obj)
{
return new Html(obj).toString();
}
//-------//
// print //
//-------//
/**
* Print the dump string onto the standard output
*/
public void print ()
{
System.out.println(toString());
}
//----------//
// toString //
//----------//
/**
* Return the string buffer content
*
* @return the dump of the object as a string
*/
@Override
public String toString ()
{
// Do the processing
processObject();
// Return the final content of string buffer
return sb.toString();
}
//------------------//
// printClassEpilog //
//------------------//
/**
* To be overridden so as to print the epilog of class data
*/
protected void printClassEpilog ()
{
}
//------------------//
// printClassProlog //
//------------------//
/**
* To be overridden so as to print the prolog of class data
*/
protected void printClassProlog ()
{
}
//----------------------//
// printCollectionValue //
//----------------------//
protected void printCollectionValue (Collection col)
{
sb.append("[");
int i = 0;
for (Object obj : col) {
if (i++ > 0) {
sb.append(useHtml ? ",<br/>" : ",");
}
// Safeguard action when the object is a big collection
if (i > MAX_COLLECTION_INDEX) {
sb.append(" ... " + col.size() + " items");
break;
} else {
sb.append(obj);
}
}
sb.append("]");
}
//------------//
// printField //
//------------//
/**
* Basic printing of field name and value. The method can of course be
* overridden.
*
* @param name the field name
* @param value the field value, which may be null
*/
protected void printField (String name,
Object value)
{
if (value == null) {
sb.append("null");
} else {
if (value instanceof Collection) {
printCollectionValue((Collection) value);
} else if (value instanceof Map) {
printCollectionValue(((Map) value).entrySet());
} else {
sb.append(value.toString());
}
}
}
//--------------//
// processClass //
//--------------//
private void processClass ()
{
// Class Prolog
printClassProlog();
// Process the class Fields
for (Field field : cl.getDeclaredFields()) {
processField(field);
}
// Class Epilog
printClassEpilog();
}
//--------------//
// processField //
//--------------//
private void processField (Field field)
{
// Check that we are really interested in printing this field out
if (isFieldRelevant(field)) {
// Override any access limitation
field.setAccessible(true);
try {
// Retrieve field value in the object instance
Object value = field.get(obj);
// Print the field value as requested
printField(field.getName(), value);
} catch (IllegalAccessException ex) {
// Cannot occur in fact, thanks to setAccessible
}
}
}
//---------------//
// processObject //
//---------------//
private void processObject ()
{
do {
// Process the class at hand
processClass();
// Walk up the inheritance tree
cl = cl.getSuperclass();
} while (isClassRelevant(cl));
}
//~ Inner Classes ----------------------------------------------------------
//--------//
// Column //
//--------//
/**
* Class <code>Column</code> implements a Dumper where all fields are
* presented in one column, each field on a separate line. The column can be
* left indented, according to the specified indentation level.
*/
public static class Column
extends Dumper
{
//~ Static fields/initializers -----------------------------------------
private static final String MEMBER_GAP = " ";
private static final String INDENT_GAP = ". ";
//~ Instance fields ----------------------------------------------------
private final String title;
private final StringBuffer prefix;
//~ Constructors -------------------------------------------------------
public Column (Object obj,
String title,
int level)
{
super(obj, false);
// Cache the title
if (title != null) {
this.title = title;
} else {
this.title = "";
}
// Prepare indent prefix
prefix = new StringBuffer(level * INDENT_GAP.length());
for (int i = level; i > 0; i--) {
prefix.append(INDENT_GAP);
}
}
//~ Methods ------------------------------------------------------------
@Override
protected void printClassProlog ()
{
// We print the class name only for the lowest class in
// heritance hierarchy
if (obj.getClass() == cl) {
sb.append("\n");
sb.append(prefix)
.append(cl.getName());
sb.append(" ")
.append(title)
.append(":");
}
}
@Override
protected void printField (String name,
Object value)
{
sb.append("\n");
sb.append(prefix)
.append(MEMBER_GAP);
sb.append(name)
.append("=");
super.printField(name, value);
}
}
//------//
// Html //
//------//
/**
* Class <code>Html</code> implements a Dumper using HTML tags to present
* fields in a table.
*/
public static class Html
extends Dumper
{
//~ Constructors -------------------------------------------------------
protected Html (Object obj)
{
super(obj, true);
}
//~ Methods ------------------------------------------------------------
@Override
public String toString ()
{
// Style
sb.append("<style> td {")
.append(" font-family: Lucida Console, Verdana, sans-serif;")
.append(" font-size: 9px;")
.append(" font-style: normal;")
.append("} </style>");
// Table begin
sb.append("<table border=0 cellpadding=3>");
// The object
super.processObject();
// Table end
sb.append("</table>");
// Return the final content of string buffer
return sb.toString();
}
@Override
protected void printClassProlog ()
{
// Class name
sb.append("<tr><td colspan=2><font color="BLUE">")
.append(cl.getName())
.append("</font></td></tr>");
}
@Override
protected void printField (String name,
Object value)
{
// One table row per field
sb.append("<tr>");
// First the field name
sb.append("<td align="right"><font color="RED">")
.append(name)
.append("</font></td>");
// Then the field value
sb.append("<td>");
super.printField(name, value);
sb.append("</td>")
.append("</tr>");
}
}
//-----//
// Row //
//-----//
/**
* Class <code>Row</code> implements a Dumper where all fields are presented
* on the same line.
*/
public static class Row
extends Dumper
{
//~ Constructors -------------------------------------------------------
protected Row (Object obj)
{
super(obj, false);
}
//~ Methods ------------------------------------------------------------
@Override
protected void printClassEpilog ()
{
sb.append("}");
}
@Override
protected void printClassProlog ()
{
// Class name
sb.append("{");
// Special annotation for superclass
if (obj.getClass() != cl) {
sb.append("from ");
}
sb.append(cl.getName())
.append(":");
}
@Override
protected void printField (String name,
Object value)
{
sb.append(" ");
sb.append(name)
.append("=");
super.printField(name, value);
}
}
}
Debug InputStream
/*
Copyright (C) 2004 Juho Vähä-Herttua
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 (at your option) 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.
*/
import java.io.*;
public class DebugInputStream extends InputStream {
InputStream is;
ByteArrayOutputStream buffer;
boolean debug;
public DebugInputStream(InputStream in, boolean usedebug) {
is = in;
buffer = new ByteArrayOutputStream();
debug = usedebug;
}
public int read() throws IOException {
int input;
input = is.read();
if (debug) buffer.write(input);
return input;
}
public int read(byte b[], int off, int len) throws IOException {
int readb;
readb = is.read(b, off, len);
if (debug) buffer.write(b, off, readb);
return readb;
}
public int available() throws IOException {
return is.available();
}
public void close() throws IOException {
buffer.close();
is.close();
}
public void mark(int readlimit) {
is.mark(readlimit);
}
public void reset() throws IOException {
is.reset();
}
public boolean markSupported() {
return is.markSupported();
}
public byte[] toByteArray() {
return buffer.toByteArray();
}
public int size() {
return buffer.size();
}
}
Debug Utilities
/*
** Copyright (c) 1998 by Timothy Gerard Endres
** <mailto:time@ice.ru> <http://www.ice.ru>
**
** This program is free software.
**
** You may redistribute it and/or modify it under the terms of the GNU
** General Public License as published by the Free Software Foundation.
** Version 2 of the license should be included with this distribution in
** the file LICENSE, as well as License.html. If the license is not
** included with this distribution, you may find a copy at the FSF web
** site at "www.gnu.org" or "www.fsf.org", or you may write to the
** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE.
**
*/
import java.io.PrintWriter;
public class DebugUtilities {
public static void printClassHierarchy(Class aClass, PrintWriter writer, String prefix) {
String subPrefix = "-->";
for (int i = 0;; ++i) {
writer.println(prefix + " " + subPrefix + " " + aClass.getName());
aClass = aClass.getSuperclass();
if (aClass == Object.class)
break;
subPrefix = "--" + subPrefix;
}
}
public static void printContainerComponents(java.awt.Container cont, PrintWriter writer,
String prefix, boolean recurse) {
java.awt.ruponent[] comps = cont.getComponents();
if (comps.length < 1) {
writer.println(prefix + "Contains no components.");
}
for (int i = 0; i < comps.length; ++i) {
DebugUtilities.printClassHierarchy(comps[i].getClass(), writer, prefix + "[" + i + "]");
if (recurse) {
Class c = java.awt.Container.class;
if (c.isAssignableFrom(comps[i].getClass())) {
DebugUtilities.printContainerComponents((java.awt.Container) comps[i], writer, (prefix
+ "[" + i + "] "), recurse);
}
}
}
}
}
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) {
}
}
}
Handle obtaining string timestamps
/**
* Copyright 2007 University Of Southern California
*
* 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.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Create a common interface to handle obtaining string timestamps.
* The difficult part is to allow for an ISO 8601 date formatting.
*
* @author Jens-S. Vöckler
* @author Yong Zhao
* @version $Revision: 379 $
*
* @see java.util.Date
* @see java.text.SimpleDateFormat
*/
public class Currently {
/**
* This is used to format the time stamp.
*/
private SimpleDateFormat m_formatter = null;
/**
* Default time format, which is compact and has a timezone
*/
public static final String DEFAULT_FORMAT = "yyyy.MM.dd HH:mm:ss zzz";
/**
* Default ctor: Create a new instance with a default formatting
* string for timestamps.
*/
public Currently() {
m_formatter = new SimpleDateFormat(DEFAULT_FORMAT);
}
/**
* Ctor: Create a new instance with a formatting string for time stamps.
* @param formatString complies to {@link java.text.SimpleDateFormat}.
*/
public Currently(String formatString) {
m_formatter = new SimpleDateFormat(formatString);
}
/**
* Ctor: Create a new instance with a formatting string for time stamps.
* @param format is a description of the simple date format to use.
*/
public Currently(SimpleDateFormat format) {
m_formatter = (SimpleDateFormat) format.clone();
}
/**
* Accessor: Obtains the default timestamp format for all queues.
*
* @return the currently active timestamp prefix format.
* @see #setDateFormat( String )
* @see #setDateFormat( SimpleDateFormat )
*/
public SimpleDateFormat getDateFormat() {
return m_formatter;
}
/**
* Accessor: Sets the default timestamp format for all queues.
*
* @param format is the new timestamp prefix format.
* @see #setDateFormat( SimpleDateFormat )
* @see #getDateFormat()
*/
public void setDateFormat(SimpleDateFormat format) {
if (format != null) {
m_formatter = format;
}
}
/**
* Accessor: Sets the default timestamp format for all queues.
*
* @param format is the new timestamp prefix format as a string.
* @see #setDateFormat( String )
* @see #getDateFormat()
*/
public void setDateFormat(String format) {
if (format != null) {
m_formatter = new SimpleDateFormat(format);
}
}
/**
* Obtains the current time as formatted string according to
* the format option.
* @return the current time as formatted string.
* @see #now( Date )
*/
public String now() {
return this.now(new Date());
}
/**
* Obtains the current time as formatted string according to
* the format option.
* @param then is a timestamp expressed as Date.
* @return the current time as formatted string.
* @see #now()
*/
public String now(Date then) {
return this.m_formatter.format(then);
}
/**
* Store the regular expressions necessary to parse ISO timestamps.
*/
private static final String c_expression[] = {
"([12][0-9]{3})-([01][0-9])-([0123][0-9])(T([012][0-9]):([0-6][0-9]):([0-6][0-9])?(\\.[0-9]+)?)?(Z|[-+][01][0-9]:?[0-6][0-9])?",
"([12][0-9]{3})([01][0-9])([0123][0-9])(T?([012][0-9])([0-6][0-9])([0-6][0-9])?(\\.[0-9]+)?)?(Z|[-+][01][0-9]:?[0-6][0-9])?"
};
/**
* Stores compiled patterns at first use, quasi-Singleton.
*/
private static Pattern c_pattern[] = null;
/**
* Parses one of the ISO 8601 that it produces. Note, it will not
* parse the full range of ISO timestamps.
*
* @param stamp is the textual timestamp representation.
* @return a time or <code>null</code>, if unparsable.
*/
public static Date parse(String stamp) {
// initialize the compiled expressions once
if (c_pattern == null) {
c_pattern = new Pattern[c_expression.length];
for (int i = 0; i < c_expression.length; ++i) {
c_pattern[i] = Pattern.rupile(c_expression[i]);
}
}
// match against pattern
for (int i = 0; i < c_expression.length; ++i) {
Matcher m = c_pattern[i].matcher(stamp);
if (m.matches()) {
Calendar c = Calendar.getInstance();
TimeZone z = TimeZone.getDefault();
if (m.group(9) != null && m.group(9).length() > 0) {
boolean utc = (Character.toUpperCase(m.group(9).charAt(0)) == "Z");
if (utc) {
z = TimeZone.getTimeZone("GMT+0");
} else {
z = TimeZone.getTimeZone("GMT" + m.group(9));
}
}
c.setTimeZone(z);
c.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
c.set(Calendar.MONTH,
Integer.parseInt(m.group(2)) + (Calendar.JANUARY - 1));
c.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(3)));
if (m.group(4).length() > 0) {
c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(5)));
c.set(Calendar.MINUTE, Integer.parseInt(m.group(6)));
if (m.group(7) != null && m.group(7).length() > 0) {
c.set(Calendar.SECOND, Integer.parseInt(m.group(7)));
}
if (m.group(8) != null && m.group(8).length() > 1) {
String millis = m.group(8).substring(1);
while (millis.length() < 3) {
millis += "0";
}
millis = millis.substring(0, 3);
c.set(Calendar.MILLISECOND, Integer.parseInt(millis));
}
}
return c.getTime();
}
}
// not found
return null;
}
/**
* Ignores any internal date format, and tries to show a complete
* date/timp stamp of the current time in extended ISO 8601 format.
* UTC time (Zulu time) or a local timezone will be used. A sample for
* UTC output is 2002-04-23T02:49:58Z A sample for local zone
* (CDT) is 2002-04-22T21:49:58-05:00
*
* @param zuluTime returns a UTC formatted stamp, if true. Otherwise
* the time will be formatted according to the local zone.
* @return an ISO 8601 formatted date and time representation for the
* current time in extended format without millisecond resolution
* @see #iso8601( boolean, boolean, boolean, Date )
*/
public static String iso8601(boolean zuluTime) {
return Currently.iso8601(zuluTime, true, false, new Date());
}
/**
* Ignores any internal date format, and tries to show a complete
* date/timp stamp in extended ISO 8601 format. UTC time (Zulu time)
* or a local timezone will be used.<p>
*
* <table border=1>
* <tr><th>zone</th><th>format</th><th>fraction</td><th>example</th></tr>
* <tr><td>local</td><td>basic</td><td>integral</td><td>20020523T140427-0500</td></tr>
* <tr><td>UTC</td><td>basic</td><td>integral</td><td>20020523190427Z</td></tr>
* <tr><td>local</td><td>extd.</td><td>integral</td><td>2002-05-23T14:04:27-05:00</td></tr>
* <tr><td>UTC</td><td>extd.</td><td>integral</td><td>2002-05-23T19:04:27Z</td></tr>
* <tr><td>local</td><td>basic</td><td>millis</td><td>20020523T140427.166-0500</td></tr>
* <tr><td>UTC</td><td>basic</td><td>millis</td><td>20020523190427.166Z</td></tr>
* <tr><td>local</td><td>extd.</td><td>millis</td><td>2002-05-23T14:04:27.166-05:00</td></tr>
* <tr><td>UTC</td><td>extd.</td><td>millis</td><td>2002-05-23T19:04:27.166Z</td></tr>
* </table><p>
*
* @param zuluTime returns a UTC formatted stamp, if true. Otherwise
* the time will be formatted according to the local zone. Local time
* should be prefixed with the "T".
* @param extendedFormat will use the extended ISO 8601 format which
* separates the different timestamp items. If false, the basic
* format will be used. In UTC and basic format, the "T" separator
* will be omitted.
* @param withMillis will put the millisecond extension into the timestamp.
* If false, the time will be without millisecond fraction. The separator
* is taken from {@link java.text.DecimalFormatSymbols#getMinusSign()},
* which usually is a period or a comma.
* @param now is a time stamp as Date.
* @return an ISO 8601 formatted date and time representation for
* the given point in time.
*/
public static String iso8601(boolean zuluTime, boolean extendedFormat,
boolean withMillis, Date now) {
Calendar c =
Calendar.getInstance(zuluTime ?
TimeZone.getTimeZone("UTC") :
TimeZone.getDefault());
c.setTime(now);
// set up formattting options
DecimalFormat nf2 = new DecimalFormat("##00");
DecimalFormat nf3 = new DecimalFormat("###000");
DecimalFormat nf4 = new DecimalFormat("####0000");
DecimalFormatSymbols dfs = nf2.getDecimalFormatSymbols();
// allocate result string buffer
int size = extendedFormat ? (zuluTime ? 25 : 30) : (zuluTime ? 21 : 25);
if (!withMillis) {
size -= 4;
}
StringBuffer result = new StringBuffer(size);
result.append(nf4.format(c.get(Calendar.YEAR)));
if (extendedFormat) {
result.append("-"); // position 5
}
result.append(nf2.format(c.get(Calendar.MONTH) + 1));
if (extendedFormat) {
result.append("-"); // position 8
}
result.append(nf2.format(c.get(Calendar.DAY_OF_MONTH)));
// generating UTC in basic format may leave out the "T" separator
if (extendedFormat || !zuluTime) {
result.append("T"); // position 11
}
result.append(nf2.format(c.get(Calendar.HOUR_OF_DAY)));
if (extendedFormat) {
result.append(":"); // position 14
}
result.append(nf2.format(c.get(Calendar.MINUTE)));
if (extendedFormat) {
result.append(":"); // position 17
}
result.append(nf2.format(c.get(Calendar.SECOND)));
if (withMillis) {
// Though there is no explicit spec which allows a complete
// timestamp with milliseconds, it is implied through two
// levels, sigh. 5.3.4.2 allows decimal fractions with
// time-only stamps that have a timezone. The intro of 5.4.2
// allows 5.3.1.3.
result.append(dfs.getDecimalSeparator()); // position 20
result.append(nf3.format(c.get(Calendar.MILLISECOND)));
}
if (zuluTime) {
// this is easy
result.append("Z");
} else {
// time zone calculations
int zone_offset = c.get(Calendar.ZONE_OFFSET) / 1000;
int save_offset = c.get(Calendar.DST_OFFSET) / 1000;
int diff = (zone_offset + save_offset) / 60;
result.append(diff < 0 ? dfs.getMinusSign() : "+"); // position 24
if (diff < 0) {
diff = Math.abs(diff);
}
result.append(nf2.format(diff / 60));
if (extendedFormat) {
result.append(":");
}
result.append(nf2.format(diff % 60));
}
return result.toString();
}
}
How to do Benchmark
/*
* Copyright (c) 1996, 1997 by Doug Bell <dbell@shvn.ru>. 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 THE AUTHOR 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 THE AUTHOR 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.awt.Button;
import java.awt.Checkbox;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Label;
import java.awt.List;
import java.awt.TextArea;
public class BenchmarkApplet extends java.applet.Applet
implements BenchmarkRunner, Runnable
{
static final String spaces =
" ";
static final String newline = System.getProperty("line.separator");
private volatile boolean running;
private int estimatatedSeconds;
private ThreadGroup tgroup;
private Thread testTask;
private List testList;
private TextArea out;
private Label timeEstimate;
private Button doit, abort, clear;
private Checkbox console;
private Benchmark[] tests = {
new Benchmark(this),
new MixedBenchmark(this),
new LoopBenchmark(this),
new VariableBenchmark(this),
new MethodBenchmark(this),
new OperatorBenchmark(this),
new CastingBenchmark(this),
new InstantiationBenchmark(this),
new ExceptionBenchmark(this)
};
public void init () {
tgroup = Thread.currentThread().getThreadGroup();
Font font = new Font("Courier", Font.PLAIN, 10);
FontMetrics fm = getFontMetrics(font);
int lines = Math.max(10, size().height / fm.getHeight() - 4);
out = new TextArea(lines, spaces.length() + Benchmark.resolutionName.length());
out.setFont(font);
out.setEditable(false);
add(out);
boolean toobig;
do {
testList = new List(--lines, true);
add(testList, 0);
validate();
if (toobig = testList.size().height - out.size().height > 2)
remove(testList);
} while (toobig);
for (int ii = 0; ii < tests.length; ii++)
testList.addItem(tests[ii].getName());
testList.select(0); // Calibration benchmark
testList.select(1); // Mixed benchmark
timeEstimate = new Label(getTimeEstimate());
add(timeEstimate);
add(doit = new Button("Run Benchmark"));
add(abort = new Button("Stop"));
add(clear = new Button("Clear"));
abort.disable();
clear.disable();
add(console = new Checkbox("Console"));
validate();
}
public void start () {
Benchmark.recalibrate();
}
public synchronized void run () {
try {
running = true;
timingTests();
}
finally {
running = false;
doit.enable();
abort.disable();
}
}
public boolean action (Event evt, Object arg) {
if (evt.target == doit) {
if (!running) {
testTask = new Thread(tgroup, this);
testTask.start();
}
return true;
}
else if (evt.target == abort) {
if (running) {
testTask.stop();
println("*** aborted by user ***");
}
return true;
}
else if (evt.target == clear) {
out.setText("");
clear.disable();
return true;
}
return false;
}
public boolean handleEvent (Event evt) {
if (evt.target == testList) {
if (evt.id == Event.LIST_SELECT || evt.id == Event.LIST_DESELECT)
if (timeEstimate != null)
timeEstimate.setText(getTimeEstimate());
}
return super.handleEvent(evt);
}
private void timingTests () {
int cnt, testSeconds = 0;
long begin = System.currentTimeMillis();
doit.disable();
abort.enable();
Benchmark.gc();
println(newline +
"Benchmark tests: [mem=" + Runtime.getRuntime().freeMemory() +"/" +
Runtime.getRuntime().totalMemory() +"]");
for (cnt = 0; cnt < testList.countItems(); cnt++)
if (testList.isSelected(cnt))
testSeconds += tests[cnt].getTestTime();
println("Estimated time: " + timeString(estimatatedSeconds) + " (tests " +
timeString(testSeconds) + ")");
long total = 0;
for (cnt = 0; cnt < testList.countItems(); cnt++)
if (testList.isSelected(cnt))
total += tests[cnt].runTest();
println("*** done: " +
timeString((int) (System.currentTimeMillis() + 500 - begin) / 1000) +
" (tests " +
timeString((int) ((total + 500) / 1000)) +
") ***");
}
static String timeString (int seconds) {
int sec = seconds % 60;
return (seconds / 60) + ((sec < 10) ? ":0" : ":") + sec;
}
private String getTimeEstimate () {
estimatatedSeconds = 0;
for (int cnt = 0; cnt < testList.countItems(); cnt++)
if (testList.isSelected(cnt))
estimatatedSeconds += tests[cnt].getRunningTime();
return "Estimated running time: " + timeString(estimatatedSeconds);
}
public void report (String msg, long nanos) {
if (msg != null) {
String time = Long.toString(nanos);
int index = msg.length() + time.length();
String space = (index >= spaces.length()) ? " " : spaces.substring(index);
println(msg + space + time + Benchmark.resolutionName);
}
}
public synchronized void println (String s) {
if (console.getState())
System.out.println(s);
out.appendText(s + newline);
clear.enable();
Thread.yield(); // give interface a chance to process events
}
} // class BenchmarkApplet
// EOF
/*
* Copyright (c) 1996, 1997 by Doug Bell <dbell@shvn.ru>. 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 THE AUTHOR 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 THE AUTHOR 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.
*/
class DerivedObject {}
class DerivedObject2 extends DerivedObject {}
class DerivedObject3 extends DerivedObject2 {}
class DerivedObject4 extends DerivedObject3 {}
class DerivedObject5 extends DerivedObject4 {}
interface Inter1 {}
interface Inter2 extends Inter1 {}
interface Inter3 extends Inter2 {}
interface Inter4 extends Inter3 {}
interface Inter5 extends Inter4 {}
interface Inter6 extends Inter5 {}
/*
* This is the base benchmark class. To create a new benchmark, extend this class and
* implement getTestTime(), getRunningTime() and runTest() in the extended class.
*/
class Benchmark implements Runnable {
private static boolean calibrated;
private static long gcMemTarget;
private static String[] resNames = {" ms", " �s", " ns", " ps"};
private static long[] resValues = {1000L, 1000000L, 1000000000L, 1000000000000L};
protected static int resIndex = 2; // ns = nanosecond
protected static String resolutionName = resNames[resIndex];
protected static long resolution = resValues[resIndex];
protected static long timerLoopNanos;
protected static int[] useint = new int[3]; // used to prevent dead variable elimination
private BenchmarkRunner runner;
private Thread timer;
private long sampleMillis = 1000L; // 1 second for each test
private int sampleCount = 3;
private int timerIterations;
private boolean timerPaused;
private long timerStart, reportMillis;
private int[] iterations = new int[sampleCount];
private long[] milliseconds = new long[sampleCount];
protected long timerMillis, totalMillis;
protected volatile boolean go;
public static void gc () {
System.runFinalization();
System.gc();
if (Runtime.getRuntime().freeMemory() < gcMemTarget) {
try {
int[] mem = new int[(int) gcMemTarget/4];
mem = null;
}
catch (OutOfMemoryError e) {
gcMemTarget -= 10000;
recalibrate();
}
System.gc();
}
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
public static void recalibrate () {
calibrated = false;
}
public static void calibrate () {
calibrated = false;
new Benchmark().runTest();
if (timerLoopNanos < 98) {
if (resIndex < resValues.length - 1) {
resIndex++;
resolutionName = resNames[resIndex];
resolution = resValues[resIndex];
calibrate();
}
}
else if (timerLoopNanos > 102000) {
if (resIndex > 0) {
resIndex--;
resolutionName = resNames[resIndex];
resolution = resValues[resIndex];
calibrate();
}
}
if (!calibrated) {
gcMemTarget = 0;
gc();
long sysmem = Math.min(1000000, Runtime.getRuntime().totalMemory() - 10000);
gcMemTarget = Math.min(1000000, Runtime.getRuntime().freeMemory() - 5000);
if (true|| gcMemTarget < 200000 && sysmem > gcMemTarget) {
boolean ok;
gcMemTarget = sysmem;
do {
ok = true;
try {
int[] mem = new int[(int) gcMemTarget/4];
mem = null;
}
catch (OutOfMemoryError e) {
gcMemTarget -= 10000;
ok = false;
}
} while (!ok);
}
gcMemTarget = Math.min(sysmem, gcMemTarget);
calibrated = true;
}
}
static long getNanos (long[] millis, int[] iterations, long overheadNanos) {
long nanos = resolution * 100;
for (int ii = Math.min(millis.length, iterations.length); --ii >= 0; ) {
if (iterations[ii] > 0)
nanos = Math.min(nanos,
(((resolution/1000) * millis[ii]) / iterations[ii]) -
overheadNanos);
iterations[ii] = 0;
millis[ii] = 0;
}
return nanos;
}
Benchmark () {
this(null);
}
Benchmark (BenchmarkRunner runner) {
this.runner = runner;
}
/** Returns the name of the test.
* Default implementation uses the unqualified class name, stripping "Benchmark"
* from the name if it exists.
*/
public String getName () {
String name = getClass().getName();
int index = name.lastIndexOf(".");
name = name.substring(index < 0 ? 0 : index);
if (name.equals("Benchmark"))
name = "Calibrate";
else if (name.endsWith("Benchmark"))
name = name.substring(0, name.length() - "Benchmark".length());
return name;
}
/** Returns approximate running time of justs the timing tests, in seconds.
* Subclass should override this method.
*/
public int getTestTime () {
return (int) (getSampleCount() * getSampleMillis()) / 1000;
}
/** Returns approximate total running time of the benchmark, in seconds.
* Subclass should override this method.
*/
public int getRunningTime () {
return getTestTime();
}
/** Set the number of samples to measure for a test.
*/
final void setSampleCount (int samples) {
if (samples != sampleCount && samples > 0) {
sampleCount = samples;
iterations = new int[samples];
milliseconds = new long[samples];
}
}
/** Get the number of samples to measure for a test.
*/
final int getSampleCount () {
return sampleCount;
}
/** Set the number of milliseconds to run the timer.
*/
final void setSampleMillis (long millis) {
if (millis > 0)
sampleMillis = millis;
}
/** Get the number of milliseconds to run the timer.
*/
final long getSampleMillis () {
return sampleMillis;
}
/** Should be called at the beginning of runTest().
*/
protected void startTest () {
println("");
println("
Logging class to record errors or unexpected behavior to a file
/*BEGIN_COPYRIGHT_BLOCK
*
* Copyright (c) 2001-2008, JavaPLT group at Rice University (drjava@rice.edu)
* 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 names of DrJava, the JavaPLT group, Rice University, 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 THE COPYRIGHT OWNER 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.
*
* This software is Open Source Initiative approved Open Source Software.
* Open Source Initative Approved is a trademark of the Open Source Initiative.
*
* This file is part of DrJava. Download the current version of this project
* from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
*
* END_COPYRIGHT_BLOCK*/
import java.io.*;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
/** Logging class to record errors or unexpected behavior to a file. The file is created in the current directory,
* and is only used if the log is enabled. All logs can be enabled at once with the ENABLE_ALL field.
* @version $Id: Log.java 4691 2008-12-02 23:33:27Z dlsmith $
*/
public class Log {
public static final boolean ENABLE_ALL = false;
/** Whether this particular log is enabled in development mode. */
protected volatile boolean _isEnabled;
/** The filename of this log. */
protected volatile String _name;
/** The file object for this log. */
protected volatile File _file;
/** PrintWriter to print messages to a file. */
protected volatile PrintWriter _writer;
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("d MMM yyyy H:mm:ss z");
static {
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
DATE_FORMAT.setLenient(false);
}
/** Creates a new Log with the given name. If enabled is true, a file is created in the current directory with the
* given name.
* @param name File name for the log
* @param isEnabled Whether to actively use this log
*/
public Log(String name, boolean isEnabled) { this(new File(name), isEnabled); }
public Log(File f, boolean isEnabled) {
_file = f;
_name = f.getName();
_isEnabled = isEnabled;
_init();
}
/** Creates the log file, if enabled. */
protected void _init() {
if (_writer == null) {
if (_isEnabled || ENABLE_ALL) {
try {
FileWriter w = new FileWriter(_file.getAbsolutePath(), true);
_writer = new PrintWriter(w);
log("Log "" + _name + "" opened: " + DATE_FORMAT.format(new Date()));
}
catch (IOException ioe) {
throw new RuntimeException("Could not create log: " + ioe);
}
}
}
}
/** Sets whether this log is enabled. Only has an effect if the code is in development mode.
* @param isEnabled Whether to print messages to the log file
*/
public void setEnabled(boolean isEnabled) { _isEnabled = isEnabled; }
/** Returns whether this log is currently enabled. */
public boolean isEnabled() { return (_isEnabled || ENABLE_ALL); }
/** Prints a message to the log, if enabled.
* @param message Message to print.
*/
public synchronized void log(String message) {
if (isEnabled()) {
if (_writer == null) {
_init();
}
_writer.println(DATE_FORMAT.format(new Date()) + ": " + message);
_writer.flush();
}
}
/** Converts a stack trace (StackTraceElement[]) to string form */
public static String traceToString(StackTraceElement[] trace) {
final StringBuilder traceImage = new StringBuilder();
for (StackTraceElement e: trace) traceImage.append("\n\tat " + e.toString());
return traceImage.toString();
}
/** Prints a message and exception stack trace to the log, if enabled.
* @param s Message to print
* @param trace Stack track to log
*/
public synchronized void log(String s, StackTraceElement[] trace) {
if (isEnabled()) log(s + traceToString(trace));
}
/** Prints a message and exception stack trace to the log, if enabled.
* @param s Message to print
* @param t Throwable to log
*/
public synchronized void log(String s, Throwable t) {
if (isEnabled()) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
log(s + "\n" + sw.toString());
}
}
/** Closes a log file. */
public void close() {
_writer.close();
_writer = null;
}
}
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.<p>
*
* 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.<p>
*
* Logging of exception tracebacks is supported.<p>
*
* 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.<p>
*
* 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);
} //}}}
} //}}}
}
Methods for printing Debug messages
/*
* (c) Copyright 2003 Christian Lorenz ALL RIGHTS RESERVED.
*
* This file is part of the JavaBluetooth Stack.
*
* The JavaBluetooth Stack 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 (at your option) any later version.
*
* The JavaBluetooth Stack 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.
*
* Created on May 22, 2003
* by Christian Lorenz
*
*/
/**
* This class contains methods for printing Debug messages. Which messages are printed may be changed by adjusting the
* DEBUGLEVELMIN and DEBUGLEVELMAX variables. Care should be taken when prining large byte arrays, as this
* will ususally kill the TINI.
* @author Christian Lorenz
*/
public class Debug {
public static boolean debugMessages = true;
public static final int DEBUGLEVELMIN = 1;
public static final int DEBUGLEVELMAX = 10;
public static void println(int level, String label, byte[] packet) {
if ((level >= DEBUGLEVELMIN) && (level <= DEBUGLEVELMAX)) {
for (int i = 0; i < packet.length; i++)
label += " " + Integer.toString((packet[i] & 0xff) + 0x100, 16).substring(1);
System.err.println(label);
}
}
public static void println(int level, String debugMessage) {
if ((level >= DEBUGLEVELMIN) && (level <= DEBUGLEVELMAX)) { System.err.println(debugMessage); }
}
public static String printByteArray(byte[] packetData) {
String output = "";
for (int i = 0; i < packetData.length; i++)
output += " " + Integer.toString((packetData[i] & 0xff) + 0x100, 16).substring(1);
return output;
}
}
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.
*
* <P>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).
*
* <P>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;
}
}
}
Scans java source files in cvs tree and validates the license header
/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.SyncFailedException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* A utility which scans all java source files in the cvs tree and validates the
* license header prior to the package statement for headers that match those
* declared in varia/src/etc/license-info.xml
*
* @author Scott.Stark@jboss.org
* @version $Revision: 81038 $
*/
public class ValidateLicenseHeaders {
/** Used to strip out diffs due to copyright date ranges */
static final String COPYRIGHT_REGEX = "copyright\\s(\\(c\\))*\\s*[\\d]+(\\s*,\\s*[\\d]+|\\s*-\\s*[\\d]+)*";
static final String DEFAULT_HEADER = "/*\n" + " * JBoss, Home of Professional Open Source.\n"
+ " * Copyright 2008, Red Hat Middleware LLC, and individual contributors\n"
+ " * as indicated by the @author tags. See the copyright.txt file in the\n"
+ " * distribution for a full listing of individual contributors.\n" + " *\n"
+ " * This is free software; you can redistribute it and/or modify it\n"
+ " * under the terms of the GNU Lesser General Public License as\n"
+ " * published by the Free Software Foundation; either version 2.1 of\n"
+ " * the License, or (at your option) any later version.\n" + " *\n"
+ " * This software is distributed in the hope that it will be useful,\n"
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ " * Lesser General Public License for more details.\n" + " *\n"
+ " * You should have received a copy of the GNU Lesser General Public\n"
+ " * License along with this software; if not, write to the Free\n"
+ " * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\n"
+ " * 02110-1301 USA, or see the FSF site: http://www.fsf.org.\n" + " */\n";
static Logger log = Logger.getLogger("ValidateCopyrightHeaders");
static boolean addDefaultHeader = false;
static FileFilter dotJavaFilter = new DotJavaFilter();
/**
* The term-headers from the varia/src/etc/license-info.xml
*/
static TreeMap licenseHeaders = new TreeMap();
/**
* Java source files with no license header
*/
static ArrayList noheaders = new ArrayList();
/**
* Java source files with a header that does not match one from licenseHeaders
*/
static ArrayList invalidheaders = new ArrayList();
/** Total java source files seen */
static int totalCount;
/** Total out of date jboss headers seen */
static int jbossCount;
/**
* ValidateLicenseHeaders jboss-src-root
*
* @param args
*/
public static void main(String[] args) throws Exception {
if (args.length == 0 || args[0].startsWith("-h")) {
log.info("Usage: ValidateLicenseHeaders [-addheader] jboss-src-root");
System.exit(1);
}
int rootArg = 0;
if (args.length == 2) {
if (args[0].startsWith("-add"))
addDefaultHeader = true;
else {
log.severe("Uknown argument: " + args[0]);
log.info("Usage: ValidateLicenseHeaders [-addheader] jboss-src-root");
System.exit(1);
}
rootArg = 1;
}
File jbossSrcRoot = new File(args[rootArg]);
if (jbossSrcRoot.exists() == false) {
log.info("Src root does not exist, check " + jbossSrcRoot.getAbsolutePath());
System.exit(1);
}
URL u = Thread.currentThread().getContextClassLoader().getResource(
"META-INF/services/javax.xml.parsers.DocumentBuilderFactory");
System.err.println(u);
// Load the valid copyright statements for the licenses
File licenseInfo = new File(jbossSrcRoot, "varia/src/etc/license-info.xml");
if (licenseInfo.exists() == false) {
log.severe("Failed to find the varia/src/etc/license-info.xml under the src root");
System.exit(1);
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(licenseInfo);
NodeList licenses = doc.getElementsByTagName("license");
for (int i = 0; i < licenses.getLength(); i++) {
Element license = (Element) licenses.item(i);
String key = license.getAttribute("id");
ArrayList headers = new ArrayList();
licenseHeaders.put(key, headers);
NodeList copyrights = license.getElementsByTagName("terms-header");
for (int j = 0; j < copyrights.getLength(); j++) {
Element copyright = (Element) copyrights.item(j);
copyright.normalize();
String id = copyright.getAttribute("id");
// The id will be blank if there is no id attribute
if (id.length() == 0)
continue;
String text = getElementContent(copyright);
if (text == null)
continue;
// Replace all duplicate whitespace and "*" with a single space
text = text.replaceAll("[\\s*]+", " ");
if (text.length() == 1)
continue;
text = text.toLowerCase().trim();
// Replace any copyright date0-date1,date2 with copyright ...
text = text.replaceAll(COPYRIGHT_REGEX, "...");
LicenseHeader lh = new LicenseHeader(id, text);
headers.add(lh);
}
}
log.fine(licenseHeaders.toString());
File[] files = jbossSrcRoot.listFiles(dotJavaFilter);
log.info("Root files count: " + files.length);
processSourceFiles(files, 0);
log.info("Processed " + totalCount);
log.info("Updated jboss headers: " + jbossCount);
// Files with no headers details
log.info("Files with no headers: " + noheaders.size());
FileWriter fw = new FileWriter("NoHeaders.txt");
for (Iterator iter = noheaders.iterator(); iter.hasNext();) {
File f = (File) iter.next();
fw.write(f.getAbsolutePath());
fw.write("\n");
}
fw.close();
// Files with unknown headers details
log.info("Files with invalid headers: " + invalidheaders.size());
fw = new FileWriter("InvalidHeaders.txt");
for (Iterator iter = invalidheaders.iterator(); iter.hasNext();) {
File f = (File) iter.next();
fw.write(f.getAbsolutePath());
fw.write("\n");
}
fw.close();
// License usage summary
log.info("Creating HeadersSummary.txt");
fw = new FileWriter("HeadersSummary.txt");
for (Iterator iter = licenseHeaders.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
fw.write("+++ License type=" + key);
fw.write("\n");
List list = (List) entry.getValue();
Iterator jiter = list.iterator();
while (jiter.hasNext()) {
LicenseHeader lh = (LicenseHeader) jiter.next();
fw.write("\t");
fw.write(lh.id);
fw.write(", count=");
fw.write("" + lh.count);
fw.write("\n");
}
}
fw.close();
}
/**
* Get all non-comment content from the element.
*
* @param element
* @return the concatenated text/cdata content
*/
public static String getElementContent(Element element) {
if (element == null)
return null;
NodeList children = element.getChildNodes();
StringBuffer result = new StringBuffer();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE) {
result.append(child.getNodeValue());
} else if (child.getNodeType() == Node.ruMENT_NODE) {
// Ignore comment nodes
} else {
result.append(child.getFirstChild());
}
}
return result.toString().trim();
}
/**
* Validate the headers of all java source files
*
* @param files
* @param level
* @throws IOException
*/
static void processSourceFiles(File[] files, int level) throws IOException {
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (level == 0)
log.info("processing " + f);
if (f.isDirectory()) {
File[] children = f.listFiles(dotJavaFilter);
processSourceFiles(children, level + 1);
} else {
parseHeader(f);
}
}
}
/**
* Read the first comment upto the package ...; statement
*
* @param javaFile
*/
static void parseHeader(File javaFile) throws IOException {
totalCount++;
RandomAccessFile raf = new RandomAccessFile(javaFile, "rw");
String line = raf.readLine();
StringBuffer tmp = new StringBuffer();
long endOfHeader = 0;
boolean packageOrImport = false;
while (line != null) {
long nextEOH = raf.getFilePointer();
line = line.trim();
// Ignore any single line comments
if (line.startsWith("//")) {
line = raf.readLine();
continue;
}
// If this is a package/import/class/interface statement break
if (line.startsWith("package") || line.startsWith("import") || line.indexOf("class") >= 0
|| line.indexOf("interface") >= 0) {
packageOrImport = true;
break;
}
// Update the current end of header marker
endOfHeader = nextEOH;
if (line.startsWith("/**"))
tmp.append(line.substring(3));
else if (line.startsWith("/*"))
tmp.append(line.substring(2));
else if (line.startsWith("*"))
tmp.append(line.substring(1));
else
tmp.append(line);
tmp.append(" ");
line = raf.readLine();
}
raf.close();
if (tmp.length() == 0 || packageOrImport == false) {
addDefaultHeader(javaFile);
return;
}
String text = tmp.toString();
// Replace all duplicate whitespace with a single space
text = text.replaceAll("[\\s*]+", " ");
text = text.toLowerCase().trim();
// Replace any copyright date0-date1,date2 with copyright ...
text = text.replaceAll(COPYRIGHT_REGEX, "...");
if (tmp.length() == 0) {
addDefaultHeader(javaFile);
return;
}
// Search for a matching header
boolean matches = false;
String matchID = null;
Iterator iter = licenseHeaders.entrySet().iterator();
escape: while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
List list = (List) entry.getValue();
Iterator jiter = list.iterator();
while (jiter.hasNext()) {
LicenseHeader lh = (LicenseHeader) jiter.next();
if (text.startsWith(lh.text)) {
matches = true;
matchID = lh.id;
lh.count++;
lh.usage.add(javaFile);
if (log.isLoggable(Level.FINE))
log.fine(javaFile + " matches copyright key=" + key + ", id=" + lh.id);
break escape;
}
}
}
text = null;
tmp.setLength(0);
if (matches == false)
invalidheaders.add(javaFile);
else if (matchID.startsWith("jboss") && matchID.endsWith("#0") == false) {
// This is a legacy jboss head that needs to be updated to the default
replaceHeader(javaFile, endOfHeader);
jbossCount++;
}
}
/**
* Replace a legacy jboss header with the current default header
*
* @param javaFile -
* the java source file
* @param endOfHeader -
* the offset to the end of the legacy header
* @throws IOException -
* thrown on failure to replace the header
*/
static void replaceHeader(File javaFile, long endOfHeader) throws IOException {
if (log.isLoggable(Level.FINE))
log.fine("Replacing legacy jboss header in: " + javaFile);
RandomAccessFile raf = new RandomAccessFile(javaFile, "rw");
File bakFile = new File(javaFile.getAbsolutePath() + ".bak");
FileOutputStream fos = new FileOutputStream(bakFile);
fos.write(DEFAULT_HEADER.getBytes());
FileChannel fc = raf.getChannel();
long count = raf.length() - endOfHeader;
fc.transferTo(endOfHeader, count, fos.getChannel());
fc.close();
fos.close();
raf.close();
if (javaFile.delete() == false)
log.severe("Failed to delete java file: " + javaFile);
if (bakFile.renameTo(javaFile) == false)
throw new SyncFailedException("Failed to replace: " + javaFile);
}
/**
* Add the default jboss lgpl header
*/
static void addDefaultHeader(File javaFile) throws IOException {
if (addDefaultHeader) {
FileInputStream fis = new FileInputStream(javaFile);
FileChannel fc = fis.getChannel();
int size = (int) fc.size();
ByteBuffer contents = ByteBuffer.allocate(size);
fc.read(contents);
fis.close();
ByteBuffer hdr = ByteBuffer.wrap(DEFAULT_HEADER.getBytes());
FileOutputStream fos = new FileOutputStream(javaFile);
fos.write(hdr.array());
fos.write(contents.array());
fos.close();
}
noheaders.add(javaFile);
}
/**
* A class that encapsulates the license id and valid terms header
*/
static class LicenseHeader {
String id;
String text;
int count;
ArrayList usage = new ArrayList();
LicenseHeader(String id, String text) {
this.id = id;
this.text = text;
}
}
/**
* A filter which accepts files ending in .java (but not _Stub.java), or
* directories other than gen-src and gen-parsers
*/
static class DotJavaFilter implements FileFilter {
public boolean accept(File pathname) {
boolean accept = false;
String name = pathname.getName();
if (pathname.isDirectory()) {
// Ignore the gen-src directories for generated output
accept = name.equals("gen-src") == false && name.equals("gen-parsers") == false;
} else {
accept = name.endsWith("_Stub.java") == false && name.endsWith(".java");
}
return accept;
}
}
}
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;
}
}
Trace InputStream
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don"t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* @(#)TraceInputStream.java 1.8 07/05/04
*/
import java.io.*;
/**
* This class is a FilterInputStream that writes the bytes
* being read from the given input stream into the given output
* stream. This class is typically used to provide a trace of
* the data that is being retrieved from an input stream.
*
* @author John Mani
*/
public class TraceInputStream extends FilterInputStream {
private boolean trace = false;
private boolean quote = false;
private OutputStream traceOut;
/**
* Creates an input stream filter built on top of the specified
* input stream.
*
* @param in the underlying input stream.
* @param out the trace stream
*/
public TraceInputStream(InputStream in, OutputStream traceOut) {
super(in);
this.traceOut = traceOut;
}
/**
* Set trace mode.
* @param trace the trace mode
*/
public void setTrace(boolean trace) {
this.trace = trace;
}
/**
* Set quote mode.
* @param quote the quote mode
*/
public void setQuote(boolean quote) {
this.quote = quote;
}
/**
* Reads the next byte of data from this input stream. Returns
* <code>-1</code> if no data is available. Writes out the read
* byte into the trace stream, if trace mode is <code>true</code>
*/
public int read() throws IOException {
int b = in.read();
if (trace && b != -1) {
if (quote)
writeByte(b);
else
traceOut.write(b);
}
return b;
}
/**
* Reads up to <code>len</code> bytes of data from this input stream
* into an array of bytes. Returns <code>-1</code> if no more data
* is available. Writes out the read bytes into the trace stream, if
* trace mode is <code>true</code>
*/
public int read(byte b[], int off, int len) throws IOException {
int count = in.read(b, off, len);
if (trace && count != -1) {
if (quote) {
for (int i = 0; i < count; i++)
writeByte(b[off + i]);
} else
traceOut.write(b, off, count);
}
return count;
}
/**
* Write a byte in a way that every byte value is printable ASCII.
*/
private final void writeByte(int b) throws IOException {
b &= 0xff;
if (b > 0x7f) {
traceOut.write("M");
traceOut.write("-");
b &= 0x7f;
}
if (b == "\r") {
traceOut.write("\\");
traceOut.write("r");
} else if (b == "\n") {
traceOut.write("\\");
traceOut.write("n");
traceOut.write("\n");
} else if (b == "\t") {
traceOut.write("\\");
traceOut.write("t");
} else if (b < " ") {
traceOut.write("^");
traceOut.write("@" + b);
} else {
traceOut.write(b);
}
}
}
Trace OutputStream
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don"t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* @(#)TraceOutputStream.java 1.6 07/05/04
*/
import java.io.*;
/**
* This class is a subclass of DataOutputStream that copies the
* data being written into the DataOutputStream into another output
* stream. This class is used here to provide a debug trace of the
* stuff thats being written out into the DataOutputStream.
*
* @author John Mani
*/
public class TraceOutputStream extends FilterOutputStream {
private boolean trace = false;
private boolean quote = false;
private OutputStream traceOut;
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param out the underlying output stream.
* @param traceOut the trace stream.
*/
public TraceOutputStream(OutputStream out, OutputStream traceOut) {
super(out);
this.traceOut = traceOut;
}
/**
* Set the trace mode.
*/
public void setTrace(boolean trace) {
this.trace = trace;
}
/**
* Set quote mode.
* @param quote the quote mode
*/
public void setQuote(boolean quote) {
this.quote = quote;
}
/**
* Writes the specified <code>byte</code> to this output stream.
* Writes out the byte into the trace stream if the trace mode
* is <code>true</code>
*/
public void write(int b) throws IOException {
if (trace) {
if (quote)
writeByte(b);
else
traceOut.write(b);
}
out.write(b);
}
/**
* Writes <code>b.length</code> bytes to this output stream.
* Writes out the bytes into the trace stream if the trace
* mode is <code>true</code>
*/
public void write(byte b[], int off, int len) throws IOException {
if (trace) {
if (quote) {
for (int i = 0; i < len; i++)
writeByte(b[off + i]);
} else
traceOut.write(b, off, len);
}
out.write(b, off, len);
}
/**
* Write a byte in a way that every byte value is printable ASCII.
*/
private final void writeByte(int b) throws IOException {
b &= 0xff;
if (b > 0x7f) {
traceOut.write("M");
traceOut.write("-");
b &= 0x7f;
}
if (b == "\r") {
traceOut.write("\\");
traceOut.write("r");
} else if (b == "\n") {
traceOut.write("\\");
traceOut.write("n");
traceOut.write("\n");
} else if (b == "\t") {
traceOut.write("\\");
traceOut.write("t");
} else if (b < " ") {
traceOut.write("^");
traceOut.write("@" + b);
} else {
traceOut.write(b);
}
}
}