alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *			Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version
 * 1.0 (the "License"). You may not use this file except in compliance
 * with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is Terminal Emulator.
 * The Initial Developer of the Original Code is Sun Microsystems, Inc..
 * Portions created by Sun Microsystems, Inc. are Copyright (C) 2001-2004.
 * All Rights Reserved.
 *
 * Contributor(s): Ivan Soleimanipour.
 */

package org.netbeans.lib.terminalemulator;

import java.io.*;
import java.awt.*;
import javax.swing.SwingUtilities;

public class StreamTerm extends Term {

    static class Fmt {
	public static String pad(int what, int width) {
	    return pad("" + what, width);
	}
	public static String pad(byte what, int width) {
	    return pad("" + (char) what, width);
	}
	public static String pad0(String what, int width) {
	    return padwith(what, width, '0');
	}
	public static String pad(String what, int width) {
	    return padwith(what, width, ' ');
	}
	private static String padwith(String what, int width, char with) {
	    boolean left = false;
	    if (width < 0) {
		left = true;
		width = -width;
	    }
	    String sub;
	    if (what.length() > width)
		sub = what.substring(0, width);     // prevent overflow
	    else
		sub = what;
	    int pad = width - sub.length();
	    StringBuffer buf = new StringBuffer(sub);
	    if (left) {
		while(pad-- > 0)
		    buf.append(with);
	    } else {
		while(pad-- > 0)
		    buf.insert(0, with);
	    }
	    return new String(buf);
	}
    }

    private OutputStreamWriter writer;	// writes to child process

    /*
     * Return the OutputStreamWriter used for writing to the child.
     *
     * This can be used to send characters to the child process explicitly
     * as if they were typed at the keyboard.
     */
    public OutputStreamWriter getOutputStreamWriter() {
	return writer;
    } 

    public StreamTerm() {
	super();

	addInputListener(new TermInputListener() {
	    public void sendChars(char c[], int offset, int count) {
		if (writer == null)
		    return;
		try {
		    writer.write(c, offset, count);
		    writer.flush();
		} catch(Exception x) {
		    x.printStackTrace();
		} 
	    }

	    public void sendChar(char c) {
		if (writer == null)
		    return;
		try {
		    writer.write(c);
		    // writer is buffered, need to use flush!
		    // perhaps SHOULD use an unbuffered writer?
		    // Also fix send_chars()
		    writer.flush();
		} catch(Exception x) {
		    x.printStackTrace();
		} 
	    }
	} );
    }

    /*
     * Monitor output from process and forward to terminal
     */
    private class OutputMonitor extends Thread {
	private static final int BUFSZ = 1024;
	private char[] buf = new char[BUFSZ];
	private Term term;
	private InputStreamReader reader;

	OutputMonitor(InputStreamReader reader, Term term) {
	    super("StreamTerm.OutputMonitor");	// NOI18N
	    this.reader = reader;
	    this.term = term;

	    // Fix for bug 4921071
	    // NetBeans has many request processors running at P1 so
	    // a default priority of this thread will swamp all the RPs
	    // if we have a firehose sub-process.
	    setPriority(1);
	} 

	private void db_echo_receipt(char buf[], int offset, int count) {
	    /*
	     * Debugging function
	     */
	    System.out.println("Received:");	// NOI18N
	    final int width = 20;
	    int cx = 0;
	    while (cx < count) {
		// print numbers
		int cx0 = cx;
		System.out.print(Fmt.pad(cx, 4) + ": ");	// NOI18N
		for (int x = 0; x < width && cx < count; cx++, x++) {
		    String hex = Integer.toHexString(buf[offset+cx]);
		    System.out.print(Fmt.pad0(hex, 2) + " ");	// NOI18N
		}
		System.out.println();

		// print charcters
		cx = cx0;
		System.out.print("      ");	// NOI18N
		for (int x = 0; x < width && cx < count; cx++, x++) {
		    char c = (char) buf[offset+cx];
		    if (Character.isISOControl(c))
			c = ' ';
		    System.out.print(Fmt.pad((byte)c, 2) + " ");	// NOI18N
		}
		System.out.println();
	    } 
	}

	final private class Trampoline implements Runnable {
	    public int nread;
	    public void run() {
		term.putChars(buf, 0, nread);
	    }
	}

	public void run() {
	    Trampoline tramp = new Trampoline();

	    try {
		while(true) {
		    int nread = reader.read(buf, 0, BUFSZ);
		    if (nread == -1) {
			// This happens if someone closes the input stream,
			// say the master end of the pty.
			/* When we clean up this gets closed so it's not
			   always an error.
			System.err.println("com.sun.spro.Term.OutputMonitor: " +	// NOI18N
			    "Input stream closed");inp	// NOI18N
			*/
			break;
		    }
		    if (debugInput())
			db_echo_receipt(buf, 0, nread);

		    if (false) {
			term.putChars(buf, 0, nread);
		    } else {
			// InvokeAndWait() is surprisingly fast and
			// eliminates one whole set of MT headaches.
			tramp.nread = nread;
			SwingUtilities.invokeAndWait(tramp);
		    }
		} 
		reader.close();
	    } catch(Exception x) {
		x.printStackTrace();
	    }
	} 
    }

    /**
     * Connect an I/O stream pair or triple to this Term.
     *
     * @param pin Input (and paste operations) to the sub-process.
     *             this stream.
     * @param pout Main output from the sub-process. Stuff received via this
     *             stream will be rendered on the screen.
     * @param perr Error output from process. May be null if the error stream
     *		   is already absorbed into 'pout' as the case might be with
     *             ptys.
     */
    public void connect(OutputStream pin, InputStream pout, InputStream perr) {

	// Now that we have a stream force resize notifications to be sent out.
	updateTtySize();

	if (pin != null)
	    writer = new OutputStreamWriter(pin);

	InputStreamReader out_reader = new InputStreamReader(pout);
	OutputMonitor out_monitor = new OutputMonitor(out_reader, this);
	out_monitor.start();

	if (perr != null) {
	    InputStreamReader err_reader = new InputStreamReader(perr);
	    OutputMonitor err_monitor = new OutputMonitor(err_reader, this);
	    err_monitor.start();
	}
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.