001: /*
002: * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.tools.attach;
026:
027: import com.sun.tools.attach.VirtualMachine;
028: import com.sun.tools.attach.AgentLoadException;
029: import com.sun.tools.attach.AttachNotSupportedException;
030: import com.sun.tools.attach.spi.AttachProvider;
031: import sun.tools.attach.HotSpotVirtualMachine;
032: import java.io.IOException;
033: import java.io.File;
034: import java.io.InputStream;
035: import java.util.Properties;
036: import java.util.Random;
037:
038: public class WindowsVirtualMachine extends HotSpotVirtualMachine {
039:
040: // the enqueue code stub (copied into each target VM)
041: private static byte[] stub;
042:
043: private volatile long hProcess; // handle to the process
044:
045: WindowsVirtualMachine(AttachProvider provider, String id)
046: throws AttachNotSupportedException, IOException {
047: super (provider, id);
048:
049: int pid;
050: try {
051: pid = Integer.parseInt(id);
052: } catch (NumberFormatException x) {
053: throw new AttachNotSupportedException(
054: "Invalid process identifier");
055: }
056: hProcess = openProcess(pid);
057:
058: // The target VM might be a pre-6.0 VM so we enqueue a "null" command
059: // which minimally tests that the enqueue function exists in the target
060: // VM.
061: try {
062: enqueue(hProcess, stub, null, null);
063: } catch (IOException x) {
064: throw new AttachNotSupportedException(x.getMessage());
065: }
066: }
067:
068: public void detach() throws IOException {
069: synchronized (this ) {
070: if (hProcess != -1) {
071: closeProcess(hProcess);
072: hProcess = -1;
073: }
074: }
075: }
076:
077: InputStream execute(String cmd, Object... args)
078: throws AgentLoadException, IOException {
079: assert args.length <= 3; // includes null
080:
081: // create a pipe using a random name
082: int r = (new Random()).nextInt();
083: String pipename = "\\\\.\\pipe\\javatool" + r;
084: long hPipe = createPipe(pipename);
085:
086: // check if we are detached - in theory it's possible that detach is invoked
087: // after this check but before we enqueue the command.
088: if (hProcess == -1) {
089: closePipe(hPipe);
090: throw new IOException("Detached from target VM");
091: }
092:
093: try {
094: // enqueue the command to the process
095: enqueue(hProcess, stub, cmd, pipename, args);
096:
097: // wait for command to complete - process will connect with the
098: // completion status
099: connectPipe(hPipe);
100:
101: // create an input stream for the pipe
102: PipedInputStream is = new PipedInputStream(hPipe);
103:
104: // read completion status
105: int status = readInt(is);
106: if (status != 0) {
107: // special case the load command so that the right exception is thrown
108: if (cmd.equals("load")) {
109: throw new AgentLoadException(
110: "Failed to load agent library");
111: } else {
112: throw new IOException("Command failed in target VM");
113: }
114: }
115:
116: // return the input stream
117: return is;
118:
119: } catch (IOException ioe) {
120: closePipe(hPipe);
121: throw ioe;
122: }
123: }
124:
125: // An InputStream based on a pipe to the target VM
126: private class PipedInputStream extends InputStream {
127:
128: private long hPipe;
129:
130: public PipedInputStream(long hPipe) {
131: this .hPipe = hPipe;
132: }
133:
134: public synchronized int read() throws IOException {
135: byte b[] = new byte[1];
136: int n = this .read(b, 0, 1);
137: if (n == 1) {
138: return b[0] & 0xff;
139: } else {
140: return -1;
141: }
142: }
143:
144: public synchronized int read(byte[] bs, int off, int len)
145: throws IOException {
146: if ((off < 0) || (off > bs.length) || (len < 0)
147: || ((off + len) > bs.length) || ((off + len) < 0)) {
148: throw new IndexOutOfBoundsException();
149: } else if (len == 0)
150: return 0;
151:
152: return WindowsVirtualMachine.readPipe(hPipe, bs, off, len);
153: }
154:
155: public void close() throws IOException {
156: if (hPipe != -1) {
157: WindowsVirtualMachine.closePipe(hPipe);
158: hPipe = -1;
159: }
160: }
161: }
162:
163: //-- native methods
164:
165: static native void init();
166:
167: static native byte[] generateStub();
168:
169: static native long openProcess(int pid) throws IOException;
170:
171: static native void closeProcess(long hProcess) throws IOException;
172:
173: static native long createPipe(String name) throws IOException;
174:
175: static native void closePipe(long hPipe) throws IOException;
176:
177: static native void connectPipe(long hPipe) throws IOException;
178:
179: static native int readPipe(long hPipe, byte buf[], int off,
180: int buflen) throws IOException;
181:
182: static native void enqueue(long hProcess, byte[] stub, String cmd,
183: String pipename, Object... args) throws IOException;
184:
185: static {
186: System.loadLibrary("attach");
187: init(); // native initialization
188: stub = generateStub(); // generate stub to copy into target process
189: }
190: }
|