300 lines · 10.3 KB · Java
RawDownload
/* * Copyright (c) 1998, 1999, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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 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;    }     @Override    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;    }     @Override    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;        }         @Override        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() {                            @Override                            public void run() {                                output.putString(chars);                            }                        });                    }                    //### Should we sleep briefly here?                }            } catch (IOException e) {                // Run in Swing event dispatcher thread.                SwingUtilities.invokeLater(new Runnable() {                    @Override                    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;        }         @Override        public void run() {            String line;            while (running) {                line = input.getLine();                stream.println(line);                // Should not be needed for println above!                stream.flush();            }        }    } }