view j2se/src/share/classes/com/sun/tools/example/debug/bdi/ChildSession.java @ 1:193df1943809 trunk

[svn] Load openjdk/jdk7/b13 into jdk/trunk.
author xiomara
date Fri, 25 May 2007 00:49:14 +0000
parents a4ed3fb96592
children
line wrap: on
line source

/*
 * Copyright 1998-1999 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.example.debug.bdi;

import com.sun.jdi.*;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.VMStartException;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import java.io.*;
import java.util.Map;
import javax.swing.SwingUtilities;


class ChildSession extends Session {

    private Process process;

    private PrintWriter in;
    private BufferedReader out;
    private BufferedReader err;

    private InputWriter inputWriter;
    private OutputReader outputReader;
    private OutputReader errorReader;

    private InputListener input;
    private OutputListener output;
    private OutputListener error;

    public ChildSession(ExecutionManager runtime,
			String userVMArgs, String cmdLine,
			InputListener input,
			OutputListener output,
			OutputListener error,
			OutputListener diagnostics) {
	this(runtime, getVM(diagnostics, userVMArgs, cmdLine), 
	     input, output, error, diagnostics);
    }
	
    public ChildSession(ExecutionManager runtime,
			LaunchingConnector connector, 
		        Map<String, Connector.Argument> arguments,
			InputListener input,
			OutputListener output,
			OutputListener error,
			OutputListener diagnostics) {
	this(runtime, generalGetVM(diagnostics, connector, arguments), 
	     input, output, error, diagnostics);
    }
	
    private ChildSession(ExecutionManager runtime,
			VirtualMachine vm,
			InputListener input,
			OutputListener output,
			OutputListener error,
			OutputListener diagnostics) {
	super(vm, runtime, diagnostics);
	this.input = input;
	this.output = output;
	this.error = error;
    }
	
    public boolean attach() {

	if (!connectToVMProcess()) {
	    diagnostics.putString("Could not launch VM");
	    return false;
	}

	/*
	 * Create a Thread that will retrieve and display any output.
	 * Needs to be high priority, else debugger may exit before
	 * it can be displayed.
	 */

	//### Rename InputWriter and OutputReader classes
	//### Thread priorities cribbed from ttydebug.  Think about them.

	OutputReader outputReader =
	    new OutputReader("output reader", "output", 
			     out, output, diagnostics);
	outputReader.setPriority(Thread.MAX_PRIORITY-1);
	outputReader.start();

	OutputReader errorReader =
	    new OutputReader("error reader", "error",
			     err, error, diagnostics);
	errorReader.setPriority(Thread.MAX_PRIORITY-1);
	errorReader.start();

	InputWriter inputWriter =
	    new InputWriter("input writer", in, input);
	inputWriter.setPriority(Thread.MAX_PRIORITY-1);
	inputWriter.start();

	if (!super.attach()) {
	    if (process != null) {
		process.destroy();
		process = null;
	    }
	    return false;
	}

	//### debug
	//System.out.println("IO after attach: "+ inputWriter + " " + outputReader + " "+ errorReader);

	return true;
    }

    public void detach() {

	//### debug
	//System.out.println("IO before detach: "+ inputWriter + " " + outputReader + " "+ errorReader);

	super.detach();

	/*
	inputWriter.quit();
	outputReader.quit();
	errorReader.quit();
	*/

        if (process != null) {
            process.destroy();
            process = null;
        }

    }

    /**
     * Launch child java interpreter, return host:port
     */

    static private void dumpStream(OutputListener diagnostics,
				   InputStream stream) throws IOException {
        BufferedReader in = 
            new BufferedReader(new InputStreamReader(stream));
        String line;
        while ((line = in.readLine()) != null) {
            diagnostics.putString(line);
        }
    }

    static private void dumpFailedLaunchInfo(OutputListener diagnostics,
					     Process process) {
        try {
            dumpStream(diagnostics, process.getErrorStream());
            dumpStream(diagnostics, process.getInputStream());
        } catch (IOException e) {
            diagnostics.putString("Unable to display process output: " +
                                  e.getMessage());
        }
    }

    static private VirtualMachine getVM(OutputListener diagnostics,
					String userVMArgs,
					String cmdLine) {
        VirtualMachineManager manager = Bootstrap.virtualMachineManager();
        LaunchingConnector connector = manager.defaultConnector();
        Map<String, Connector.Argument> arguments = connector.defaultArguments();
        arguments.get("options").setValue(userVMArgs);
        arguments.get("main").setValue(cmdLine);
        return generalGetVM(diagnostics, connector, arguments);
    }

    static private VirtualMachine generalGetVM(OutputListener diagnostics,
                                               LaunchingConnector connector, 
                                               Map<String, Connector.Argument> arguments) {
        VirtualMachine vm = null;
        try {
            diagnostics.putString("Starting child.");
            vm = connector.launch(arguments);
        } catch (IOException ioe) {
            diagnostics.putString("Unable to start child: " + ioe.getMessage());
        } catch (IllegalConnectorArgumentsException icae) {
            diagnostics.putString("Unable to start child: " + icae.getMessage());
        } catch (VMStartException vmse) {
            diagnostics.putString("Unable to start child: " + vmse.getMessage() + '\n');
            dumpFailedLaunchInfo(diagnostics, vmse.process());
        }
        return vm;
    }

    private boolean connectToVMProcess() {
        if (vm == null) {
            return false;
        }
        process = vm.process();
        in = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
        //### Note small buffer sizes!
        out = new BufferedReader(new InputStreamReader(process.getInputStream()), 1);
        err = new BufferedReader(new InputStreamReader(process.getErrorStream()), 1);
        return true;
    }

    /**	
     *	Threads to handle application input/output.
     */

    private static class OutputReader extends Thread {

	private String streamName;
	private BufferedReader stream;
	private OutputListener output;
	private OutputListener diagnostics;
	private boolean running = true;
	private char[] buffer = new char[512];

	OutputReader(String threadName,
		     String streamName,
		     BufferedReader stream,
		     OutputListener output,
		     OutputListener diagnostics) {
	    super(threadName);
	    this.streamName = streamName;
	    this.stream = stream;
	    this.output = output;
	    this.diagnostics = diagnostics;
	}

	public void quit() {
	    running = false;
	}

	public void run() {
	    try {
		int count;
		while (running && (count = stream.read(buffer, 0, 512)) != -1) {
		    if (count > 0) {
			// Run in Swing event dispatcher thread.
			final String chars = new String(buffer, 0, count);
			SwingUtilities.invokeLater(new Runnable() {
			    public void run() {
				output.putString(chars);
			    }
			});
		    }
		    //### Should we sleep briefly here?
		}
	    } catch (IOException e) {
		// Run in Swing event dispatcher thread.
		SwingUtilities.invokeLater(new Runnable() {
		    public void run() {
			diagnostics.putString("IO error reading " +
					      streamName +
					      " stream of child java interpreter");
		    }
		});
	    }
	}
    }

    private static class InputWriter extends Thread {

	private PrintWriter stream;
	private InputListener input;
	private boolean running = true;

	InputWriter(String threadName, 
		    PrintWriter stream,
		    InputListener input) {
	    super(threadName);
	    this.stream = stream;
	    this.input = input;
	}

	public void quit() {
	    //### Won't have much effect if blocked on input!
	    running = false;
	}

	public void run() {
	    String line;
	    while (running) {
		line = input.getLine();
		stream.println(line);
		// Should not be needed for println above!
		stream.flush();
	    }
	}
    }
    
}