/*
* Console.java
*
* Created on 14 mai 2007, 00:56
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package net.sf.jiga.xtended.kernel;
import java.io.BufferedInputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Vector;
import java.util.logging.Logger;
import net.sf.jiga.xtended.ui.Ant;
/**
* This class implements a console to get log data from System.out and can be
* used in any log Component implementing the InputLogListener.
*
* @see InputLogListener
* @author www.b23prodtm.info <b>-Djxa.debugCSL=true</b> to debug this class (rw
* operations, compress, etc..)
*/
public class Console implements Debugger, Appendable, Resource {
/**
* the System default line separator String (e.g. \n)
*/
public final static String newLine = JXAenvUtils._getSysValue("line.separator");
/**
Console.class debug (it will debug the Console.class code)
* @see Ant#JXA_DEBUG_CSL
* @see DebugMap#setDebugLevelEnabled(boolean, net.sf.jiga.xtended.kernel.Level)
*/
public final static Level dbLevel = DebugMap._getInstance().newDebugLevel();
static {
boolean b = JXAenvUtils._getSysBoolean(Ant.JXA_DEBUG_CSL);
DebugMap._getInstance().setDebuggerEnabled(b, Console.class, dbLevel);
}
public boolean isDebugEnabled() {
return DebugMap._getInstance().isDebuggerEnabled(Console.class);
}
public void setDebugEnabled(boolean b) {
DebugMap._getInstance().setDebuggerEnabled(b, Console.class, dbLevel);
}
/**
* @deprecated not used
*/
public Object loadResource() {
return null;
}
/**
* the System.out default PrintStream
*/
public final static PrintStream _stdout = System.out;
/**
* the System.err default PrintStream
*/
public final static PrintStream _stderr = System.err;
public final static int STDOUT = 1;
public final static int STDERR = 2;
/**
* print error event id
*/
protected final static int PRINT_ERROR = 0;
/**
* print wait event id
*/
protected final static int PRINT_WAIT = 1;
/**
* print stop event id
*/
protected final static int PRINT_STOP = 2;
/**
* print resume id
*/
protected final static int PRINT_RESUME = 3;
/**
* the initial buffer size of this console
*
* @default 200
*/
public static int INIT_BUFFER = 200;
/**
* the buffer SpritesCacheManager for this Console instance
*/
private SpritesCacheManager<Long, StringBuilder> buffer_spm = new SpritesCacheManager<Long, StringBuilder>(INIT_BUFFER);
/**
* the console synchronized sorted map buffer (init. to 200 lines)
*/
private SortedMap<Long, StringBuilder> buffer = Collections.synchronizedSortedMap(buffer_spm);
/**
* the maximum amount of bytes to use on disk before to clear contents
*
* @default 4000000
*/
public static long MAXSWAPUSAGE = 4000000;
/**
* the switch to _stdout
*
* @see #setStdoutEnabled(boolean)
* @default true
*/
private int toStdout = STDOUT;
/**
* the switch to _stdout input PrintStream to the console
*
* @see #setLogStdoutEnabled(boolean)
* @default false
*/
private int fromStdout = 0;
/**
* the console output error listeners list
*/
private Vector<ErrorListener> output = new Vector<ErrorListener>();
/**
* the console input listeners list
*/
private Vector<InputLogListener> input = new Vector<InputLogListener>();
/**
* a standard error listener to setLogStdoutEnabled(true)
*/
private final ErrorListener stdOutCallback = new ErrorListener() {
public void printStreamError(IOException e) {
if (isDebugEnabled()) {
e.printStackTrace();
}
try {
setLogStdoutEnabled(false);
} catch (IOException ex) {
if (isDebugEnabled()) {
ex.printStackTrace();
}
}
}
};
/**
* a standard error listener to setLogStdoutEnabled(true)
*/
private final ErrorListener stdErrCallback = new ErrorListener() {
public void printStreamError(IOException e) {
if (isDebugEnabled()) {
e.printStackTrace();
}
try {
setLogStderrEnabled(false);
} catch (IOException ex) {
if (isDebugEnabled()) {
ex.printStackTrace();
}
}
}
};
/**
* the output if setOutput(PrintStream) is called . default is null.
*
* @see #setOutput(PrintWriter)
*/
private PrintWriter out = null;
/**
* the input streams map identified by a "long" ID
*/
private SortedMap<Long, PrintStream> in;
/**
* the back-cache manager
*/
private TreeMap<Long, PrintStream> _in = new TreeMap<Long, PrintStream>();
/**
* the format String
*
* @default "%s" for String output formatting
*/
public String _format = "%s";
/**
* Creates a new instance. the input is initialized with no printstream
*/
public Console() {
buffer_spm.setSwapDiskEnabled(true);
in = Collections.synchronizedSortedMap(_in);
}
/**
* returns the buffer CAUTION this buffer may overflow memory if it's too
* big
*
* @return the current buffer
*/
public StringBuilder getBuffer() {
StringBuilder strBuf = new StringBuilder();
synchronized (buffer) {
for (Iterator<Long> i = buffer.keySet().iterator(); i.hasNext();) {
StringBuilder line = buffer.get(i.next());
strBuf.append((line instanceof StringBuilder) ? line : null);
}
return strBuf;
}
}
/**
* @return a cache map of the whole console contents. keySet() will return
* the whole map keys with a small memory usage.
*/
public SortedMap<Long, StringBuilder> getCachedBuffer() {
return buffer;
}
/**
* sends a new input to the InputLogListeners list
*
* @see #input
* @param message the characters data
*/
public void notifyInput(String message) {
if (isDebugEnabled()) {
System.err.println(getClass().getName() + "-notifyInput lstSize = " + input.size());
}
synchronized (input) {
for (Iterator<InputLogListener> i = input.iterator(); i.hasNext();) {
InputLogListener ill = i.next();
if (ill != null) {
ill.newLogPacket(message);
}
}
}
}
/**
* adds a new InputLogListener to the input list. it will receive data from
* notifyInput() calls. the methods in the listeners should be synchronized
* with the listener buffers updates
*
* @see #notifyInput(String)
* @param l the input listener
*/
public void addInputLogListener(InputLogListener l) {
if (!input.contains(l)) {
sendConsoleEvent(PRINT_WAIT);
input.add(l);
sendConsoleEvent(PRINT_RESUME);
}
}
/**
* removes an InputLogListener from the input list
*
* @param l the InputLogListener to remove from the input list
*/
public void removeInputLogListener(InputLogListener l) {
sendConsoleEvent(PRINT_WAIT);
input.remove(l);
sendConsoleEvent(PRINT_RESUME);
}
/**
* returns the current line in buffer
*
* @return current line characters data
*/
public StringBuilder getCurrentLine() {
StringBuilder line = buffer.isEmpty() ? null : buffer.get(buffer.lastKey());
return (line instanceof StringBuilder) ? line : new StringBuilder();
}
/**
* dis/enables the tracing of this Console to System.out.
*
* @param b dis/enables the System.out tracing of this Console instance
*/
public void setStdoutEnabled(boolean b) {
setStdoutEnabled(b, STDOUT);
}
/**
* dis/enables the tracing of this Console to System.err.
*
* @param b dis/enables the System.out tracing of this Console instance
*/
public void setStderrEnabled(boolean b) {
setStdoutEnabled(b, STDERR);
}
private void setStdoutEnabled(boolean b, int systemStreams) {
try {
if (b) {
setLogStdoutEnabled(false, systemStreams);
}
} catch (IOException ex) {
if (isDebugEnabled()) {
ex.printStackTrace();
}
} finally {
toStdout = b ? systemStreams : toStdout - (toStdout & systemStreams);
}
}
/**
* returns true or false whether the System.out tracing is enabled or not,
* resp.
*
* @return true or false
* @see #setStdoutEnabled(boolean)
*/
public boolean isStdoutEnabled() {
return (toStdout & STDOUT) != 0;
}
/**
* returns true or false whether the System.out is read to this Console
* instance or not, resp.
*
* @return true or false
* @see #setLogStdoutEnabled(boolean)
*/
public boolean isLogStdoutEnabled() {
return (fromStdout & STDOUT) != 0;
}
public boolean isLogStderrEnabled() {
return (fromStdout & STDERR) != 0;
}
public boolean isStderrEnabled() {
return (toStdout & STDERR) != 0;
}
/**
* dis/enables the System.out as an input to this Console instance. an
* IOException is thrown if the method fails to init.
*
* @param b dis/enables the System.out as an input to this Console instance.
* @see #setLogStderrEnabled(boolean)
*/
public void setLogStdoutEnabled(boolean b) throws IOException {
if (isLogStdoutEnabled() && b) {
return;
}
setLogStdoutEnabled(b, STDOUT);
}
private Map<Integer, Vector<Long>> stdoutPS = Collections.synchronizedMap(new HashMap<Integer, Vector<Long>>());
protected AccessControlContext acc = AccessController.getContext();
private void setLogStdoutEnabled(final boolean b, final int systemStreams) throws IOException {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws IOException {
_setLogStdoutEnabled(b, systemStreams);
return null;
}
}, acc);
} catch (PrivilegedActionException ex) {
throw (IOException) ex.getException();
}
}
private void _setLogStdoutEnabled(boolean b, int systemStreams) throws IOException {
int pty = Thread.currentThread().getPriority();
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
fromStdout = b ? fromStdout | systemStreams : fromStdout - (fromStdout & systemStreams);
int _toStdout = toStdout;
toStdout = 0;
if (b) {
Map<Integer, Map<String, Object>> pss = new HashMap<Integer, Map<String, Object>>();
if ((systemStreams & STDOUT) != 0) {
pss.put(STDOUT, newPrintStream(stdOutCallback));
}
if ((systemStreams & STDERR) != 0) {
pss.put(STDERR, newPrintStream(stdErrCallback));
}
for (Integer out : pss.keySet()) {
if (!stdoutPS.containsKey(out)) {
stdoutPS.put(out, new Vector<Long>());
}
Map<String, Object> ps = pss.get(out);
long id = (Long) ps.get("id");
PrintStream printstream = (PrintStream) ps.get("ps");
if (isDebugEnabled()) {
System.out.println("loading the printStream " + id + " as system stream...");
}
sendConsoleEvent(PRINT_RESUME, id);
if (!printstream.checkError()) {
stdoutPS.get(out).add(id);
if ((out & STDOUT) != 0) {
System.setOut(printstream);
}
if ((out & STDERR) != 0) {
System.setErr(printstream);
}
} else {
if (isDebugEnabled()) {
System.err.println("PrintStream " + id + " is in error.");
}
}
}
} else {
boolean error = false;
if ((systemStreams & STDOUT) != 0) {
if (stdoutPS.containsKey(STDOUT)) {
synchronized (stdoutPS) {
for (Long id : stdoutPS.get(STDOUT)) {
sendConsoleEvent(PRINT_STOP, id);
}
}
}
if (!(error = _stdout.checkError() || error)) {
System.setOut(_stdout);
}
}
if ((systemStreams & STDERR) != 0) {
if (stdoutPS.containsKey(STDERR)) {
synchronized (stdoutPS) {
for (Long id : stdoutPS.get(STDERR)) {
sendConsoleEvent(PRINT_STOP, id);
}
}
}
if (!(error = _stderr.checkError() || error)) {
System.setErr(_stderr);
}
}
if (isDebugEnabled() && error) {
System.err.println("System err PrintStream is in error. see (PrintStream).checkError() !");
}
}
toStdout = _toStdout - (systemStreams & _toStdout);
Thread.currentThread().setPriority(pty);
}
/**
* dis/enables the System.err as an input to this Console instance. an
* IOException is thrown if the method fails to init.
*
* @param b dis/enables the System.err as an input to this Console instance
* @see #setLogStdoutEnabled(boolean)
*/
public void setLogStderrEnabled(boolean b) throws IOException {
if (isLogStderrEnabled() && b) {
return;
}
setLogStdoutEnabled(b, STDERR);
}
/**
* sets up an different output PrintStream for this Console instance
* tracing.
*
* @param newOut the new output PrintStream/PrintWriter for this Console
* instance tracing. or null to disable output.
* @return the previous PrintStream
*/
public PrintWriter setOutput(PrintWriter newOut) {
PrintWriter old = out;
flushOuput();
out = newOut;
return old;
}
public void flushOuput() {
if (out != null) {
out.flush();
}
}
/**
* returns a new Thread instance running with the specified InputStream as
* input for this Console instance. the current formatting is used.
*
* @param in an InputStream to add to this console, it should be buffered.
* @return a new Thread instance running with the specified InputStream as
* input for this Console instance
*/
public Thread getNewInput(InputStream in) throws IOException {
return getNewInput(in, _format);
}
/**
* the input monitor
*/
private ThreadGroup inputMonitor = new ThreadGroup("Console input threadgroup");
/**
* the output monitor
*/
private ThreadGroup outputMonitor = new ThreadGroup("Console output threadgroup");
/**
* returns a new Thread running wih the specified InputStream as input to
* this Console instance. The specified format String is used for
* formatting.
*
* @param in an InputStream to add to this console, it should be buffered.
* @return a new Thread instance running with the specified InputStream as
* input to this Console instance.
*/
public Thread getNewInput(InputStream in, String format) throws IOException {
final String _f = format;
final BufferedInputStream _in = new BufferedInputStream(in);
final Map<String, Object> map = newPrintStream(new ErrorListener() {
public void printStreamError(IOException e) {
if (isDebugEnabled()) {
e.printStackTrace();
}
}
});
Thread t = new Thread(inputMonitor, new Runnable() {
public void run() {
try {
sendConsoleEvent(PRINT_RESUME, (Long) map.get("id"));
PrintStream ps = (PrintStream) map.get("ps");
ps.println(JXAenvUtils.log("New Console input has been created.", JXAenvUtils.LVL.APP_NOT));
Formatter f = new Formatter(ps);
byte[] s = new byte[128];
int r;
do {
while (_in.available() <= 0) {
Thread.sleep(250);
}
if ((r = _in.read(s)) != -1) {
byte[] rB = new byte[r];
for (int i = 0; i < r; i++) {
rB[i] = s[i];
}
f.format(_f, new String(rB));
}
} while (r != -1);
if (isDebugEnabled()) {
System.out.println("InputStream " + (Long) map.get("id") + " is terminating.");
}
sendConsoleEvent(PRINT_STOP, (Long) map.get("id"));
} catch (IOException e) {
if (isDebugEnabled()) {
e.printStackTrace();
}
} catch (InterruptedException e) {
if (isDebugEnabled()) {
e.printStackTrace();
}
}
}
}, "T-Console inputStream");
t.setDaemon(true);
/*
* inputMonitor.addThread(t);
*/
t.setPriority(Thread.MAX_PRIORITY);
return t;
}
/**
* adds an ErrorListener to the Console instance output list
*
* @param l the ErrorListener to the Console instance output list
*/
public void addErrorListener(ErrorListener l) {
if (!output.contains(l)) {
output.add(l);
}
}
/**
* removes an ErrorListener from the Console instance output list
*
* @param l the ErrorListener to remove from the Console instance output
* list
* @see #addErrorListener(ErrorListener)
*/
public void removeErrorListener(ErrorListener l) {
output.remove(l);
}
/**
* sends an error notice to the ErrorListener's list
*
* @param event the error event
* @param e the IOException caught
* @see #PRINT_ERROR
*/
private void notifyError(int event, IOException e) {
synchronized (output) {
switch (event) {
case PRINT_ERROR:
for (Iterator<ErrorListener> i = output.iterator(); i.hasNext();) {
ErrorListener l = i.next();
if (l instanceof ErrorListener) {
l.printStreamError(e);
}
}
break;
default:
break;
}
}
}
/**
* returns a new PrintStream to print on loggin' stack. it is simply a
* 32bits packet atream read from the printStream that will be sent to the
* InputListeners. NOTICE: after this method you MUST send a PRINT_RESUME
* event to the console otherwise the returned PrintStream will stay
* inactive.
*
* @return new buffered PrintStream instance ready to be used as an input
* and it associated "long" ID. That is, when you get the map Map<String,
* Object>: <pre>
* long id = (Long)map.get("id");
* PrintStream ps = (PrintStream)map.get("ps");
* // assign the PrintStream ps somewhere
* // and send a PRINT_RESUME to start writing to the console.
* console.sendConsoleEvent(Console.PRINT_RESUME);
* </pre>
* @see #sendConsoleEvent(int)
* @see #PRINT_RESUME
* @see ErrorListener
* @see #input
* @see InputLogListener#newLogPacket(java.lang.String)
* @param l Output listener to the printStream
* @throws java.io.IOException
*/
protected Map<String, Object> newPrintStream(ErrorListener l) throws IOException {
if (l != null) {
addErrorListener(l);
}
PipedOutputStream pipedOutputStream = new PipedOutputStream();
final long id = System.nanoTime();
final PrintStream ps;
in.put(id, ps = new PrintStream(pipedOutputStream, true));
final BufferedInputStream pis = new BufferedInputStream(new PipedInputStream(pipedOutputStream), FileHelper._SMALLBUFFFER_SIZE);
final Map<String, Object> map = Collections.synchronizedMap(new HashMap<String, Object>());
map.put("id", id);
map.put("ps", ps);
Thread t = new Thread(outputMonitor, new Runnable() {
public void run() {
try {
if (isDebugEnabled()) {
System.out.println("a new PrintStream " + id + " is startin'...");
}
byte[] b = new byte[128];
int r;
/** print stream is started and waiting for a signal */
boolean wait = true;
boolean stop = false;
do {
while (wait) {
switch (readConsoleEvent(id)) {
case Console.PRINT_WAIT:
wait = true;
break;
case Console.PRINT_STOP:
stop = true;
wait = false;
case Console.PRINT_RESUME:
wait = false;
break;
default:
Thread.yield();
break;
}
}
if (stop) {
break;
}
/** wait loop available bytes*/
while (pis.available() <= 0) {
Thread.sleep(250);
}
/** read and apped to console buffer (cache)*/
if ((r = pis.read(b)) != -1) {
byte[] rB = new byte[r];
for (int i = 0; i < r; i++) {
rB[i] = b[i];
}
final String s = new String(rB);
inputNotifiers.doLater(new Runnable() {
public void run() {
notifyInput(s);
try {
append(s);
} catch (IOException ex) {
notifyError(PRINT_ERROR, ex);
} finally {
sendConsoleEvent(PRINT_STOP, id);
}
}
});
}
} while (r != -1);
if (isDebugEnabled()) {
System.out.println("PrintStream " + id + " is terminating...");
}
pis.close();
} catch (InterruptedException ex) {
if (isDebugEnabled()) {
ex.printStackTrace();
}
} catch (IOException ex) {
notifyError(PRINT_ERROR, ex);
} finally {
removePrintStream(id);
}
}
}, "T-PrintStream-" + id);
t.setPriority(Thread.MAX_PRIORITY);
t.setDaemon(true);
/*
* outputMonitor.addThread(t);
*/
t.start();
if (isDebugEnabled()) {
System.out.println("The new PrintStream " + id + " is waiting for a startup delivery...");
}
return map;
}
private ThreadWorks inputNotifiers = new ThreadWorks("Console input");
/**
* removes an identified PrintStream input
*
* @param id the "long" id of the PrintStream input
* @return the same PrintStream
* @see #newPrintStream(ErrorListener)
*/
protected PrintStream removePrintStream(long id) {
return (PrintStream) in.remove(id);
}
/**
* the events map that will be used by sendConsoleEvent() and
* readConsoleEvent()
*
* @see #sendConsoleEvent(int)
* @see #readConsoleEvent(long)
*/
SortedMap<Integer, Map<Long, Integer>> events = Collections.synchronizedSortedMap(new TreeMap<Integer, Map<Long, Integer>>());
/**
* reads a sent event in the events map for the given "long" id
*
* @param id the id of the event
* @return the event id or -1
* @see #PRINT_WAIT
* @see #PRINT_RESUME
* @see #PRINT_STOP
*/
private int readConsoleEvent(long id) {
Set<Integer> set = events.keySet();
synchronized (events) {
for (Iterator<Integer> i = set.iterator(); i.hasNext();) {
int key = i.next();
Map<Long, Integer> event = events.get(key);
if (event != null) {
if (event.get(id) != null) {
i.remove();
return event.get(id);
}
}
}
return -1;
}
}
/**
* sends a new event to the console
*
* @param event the event
* @see #PRINT_WAIT
* @see #PRINT_RESUME
* @see #PRINT_STOP
*/
public void sendConsoleEvent(int event) {
Set<Long> set = in.keySet();
synchronized (in) {
for (Iterator<Long> i = set.iterator(); i.hasNext();) {
sendConsoleEvent(event, (Long) i.next());
}
}
}
/**
* sends a new console event to the selected "long" id, usually a
* PrintStream registered input
*
* @see #newPrintStream(ErrorListener)
* @param event the event
* @param id the "long" id
* @return true or false whether the event could be sent to a registered
* PrintStream
* @see #sendConsoleEvent(int)
*/
private void sendConsoleEvent(int event, long id) {
Map<Long, Integer> map = new HashMap();
map.put(id, event);
events.put(events.size(), map);
}
/**
* appends new characters data to the console buffer and notifies the output
*
* @return the buffer with the new appended data
* @see #buffer
* @param charSequence the data to append
* @throws java.io.IOException
*/
public Appendable append(final CharSequence charSequence) throws IOException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<Appendable>() {
public Appendable run() throws IOException {
return _append(charSequence);
}
}, acc);
} catch (PrivilegedActionException ex) {
throw (IOException) ex.getException();
}
}
private Appendable _append(CharSequence charSequence) throws IOException {
charSequence = new Formatter().format(_format, charSequence).toString().subSequence(0, charSequence.length());
if ((toStdout & STDOUT) != 0) {
_stdout.append(charSequence);
}
if ((toStdout & STDERR) != 0) {
_stderr.append(charSequence);
}
if (out != null) {
out.append(charSequence);
}
String[] s = charSequence.toString().split(newLine);
boolean b = buffer_spm.isDebugEnabled();
buffer_spm.setDebugEnabled(false);
for (int i = 0; i < s.length; i++) {
String line = s[i];
if (i < s.length - 1) {
line += newLine;
}
if (!buffer.isEmpty() && getCurrentLine().lastIndexOf(newLine) == -1) {
buffer.put(buffer.lastKey(), getCurrentLine().append(line));
} else {
buffer.put(System.nanoTime(), new StringBuilder(line));
}
}
if (buffer_spm.getSwapUsage() > MAXSWAPUSAGE) {
if (isDebugEnabled()) {
System.out.println(getClass().getName() + " SWAP MEMORY LIMIT is " + MAXSWAPUSAGE + " clearing swap map...");
}
buffer_spm.clearMemorySwap();
}
buffer_spm.setDebugEnabled(b);
return this;
}
/**
* appends new characters data to the console buffer and notifies the output
*
* @return the buffer with the new appended data
* @see #buffer
* @param charSequence the data to append
* @param i the starting index of the characters data to append
* @param i0 the 1+end index
* @throws java.io.IOException
*/
public Appendable append(final CharSequence charSequence, final int i, final int i0) throws IOException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<Appendable>() {
public Appendable run() throws IOException {
return _append(charSequence, i, i0);
}
}, acc);
} catch (PrivilegedActionException ex) {
throw (IOException) ex.getException();
}
}
private Appendable _append(CharSequence charSequence, int i, int i0) throws IOException {
charSequence = new Formatter().format(_format, charSequence).toString().subSequence(i, i0);
if ((toStdout & STDOUT) != 0) {
_stdout.append(charSequence, i, i0);
}
if ((toStdout & STDERR) != 0) {
_stderr.append(charSequence, i, i0);
}
if (out != null) {
out.append(charSequence, i, i0);
}
String[] s = charSequence.toString().split(newLine);
boolean b = buffer_spm.isDebugEnabled();
buffer_spm.setDebugEnabled(false);
for (int j = 0; j < s.length; j++) {
String line = s[j];
if (j < s.length - 1) {
line += newLine;
}
if (!buffer.isEmpty() && getCurrentLine().lastIndexOf(newLine) == -1) {
buffer.put(buffer.lastKey(), getCurrentLine().append(line, i, i0));
} else {
buffer.put(System.nanoTime(), new StringBuilder().append(line, i, i0));
}
}
if (buffer_spm.getSwapUsage() > MAXSWAPUSAGE) {
if (isDebugEnabled()) {
System.out.println(getClass().getName() + " SWAP MEMORY LIMIT is " + MAXSWAPUSAGE + " clearing swap map...");
}
buffer_spm.clearMemorySwap();
}
buffer_spm.setDebugEnabled(b);
return this;
}
/**
* appends new characters data to the console buffer and notifies the output
*
* @return the buffer with the new appended data
* @see #buffer
* @param c the data to append
* @throws java.io.IOException
*/
public Appendable append(final char c) throws IOException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<Appendable>() {
public Appendable run() throws IOException {
return _append(c);
}
}, acc);
} catch (PrivilegedActionException ex) {
throw (IOException) ex.getException();
}
}
private Appendable _append(char c) throws IOException {
c = new Formatter().format(_format, c).toString().charAt(0);
if ((toStdout & STDOUT) != 0) {
_stdout.append(c);
}
if ((toStdout & STDERR) != 0) {
_stderr.append(c);
}
if (out != null) {
out.append(c);
}
boolean b = buffer_spm.isDebugEnabled();
buffer_spm.setDebugEnabled(false);
if (!buffer.isEmpty() && getCurrentLine().lastIndexOf(newLine) == -1) {
buffer.put(buffer.lastKey(), getCurrentLine().append(c));
} else {
buffer.put(System.nanoTime(), new StringBuilder(c));
}
if (buffer_spm.getSwapUsage() > MAXSWAPUSAGE) {
if (isDebugEnabled()) {
System.out.println(getClass().getName() + " SWAP MEMORY LIMIT is " + MAXSWAPUSAGE + " clearing swap map...");
}
buffer_spm.clearMemorySwap();
}
buffer_spm.setDebugEnabled(b);
return this;
}
/**
* clears the contents of buffer. all previous from input unread data in the
* buffer will be lost.
*
* @see SpritesCacheManager#clearMemorySwap()
*/
public void clearContents() {
buffer.clear();
buffer_spm.clearMemorySwap();
}
/**
* overriden to disable the System.out read stream to this console and reset
* the System.out to _stdout when finalization is requested.
*/
public void finalize() {
clearResource();
}
/**
* returns a new PrintStream to print to this Console instance
*
* @return a new PrintStream to print to this Console instance or null
* @param l the ErrorListener that will listen for eventual error with the
* PrintStream Thread.
* @throws IOException if an error occurred while creating the PrintStream
*/
public PrintStream getNewPrintStream(ErrorListener l) {
try {
Map<String, Object> map = newPrintStream(l);
PrintStream ps = (PrintStream) map.get("ps");
long id = (Long) map.get("id");
sendConsoleEvent(PRINT_RESUME, id);
return ps;
} catch (IOException ex) {
if (isDebugEnabled()) {
ex.printStackTrace();
}
return null;
}
}
/**
* frees up resources, stops (a {@link #PRINT_STOP} event is sent) all
* printstreams instanciated to this console. If it was reading the standard
* (System.out) output or err, it is set back to the System printstreams.
*/
public Object clearResource() {
try {
if (isLogStderrEnabled()) {
setLogStderrEnabled(false);
}
if (isLogStdoutEnabled()) {
setLogStdoutEnabled(false);
}
sendConsoleEvent(PRINT_STOP);
clearContents();
} catch (IOException ex) {
if (isDebugEnabled()) {
ex.printStackTrace();
}
} finally {
return null;
}
}
/**
* @deprecated not used
*/
public boolean isResourceLoaded() {
return true;
}
/**
* @deprecated not used
*/
public boolean isInnerResourceModeEnabled() {
return false;
}
/**
* @deprecated not used
*/
public void setInnerResourceModeEnabled(boolean b) {
}
}