Package net.sf.jiga.xtended.kernel

Source Code of net.sf.jiga.xtended.kernel.Console

/*
* 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) {
    }
}
TOP

Related Classes of net.sf.jiga.xtended.kernel.Console

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.