History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/example/debug/tty/VMConnection.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/example/debug/tty/VMConnection.java+376−0
@@ -0,0 +1,376 @@
1/*
2 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.example.debug.tty;
27
28import com.sun.jdi.*;
29import com.sun.jdi.connect.*;
30import com.sun.jdi.request.EventRequestManager;
31import com.sun.jdi.request.ThreadStartRequest;
32import com.sun.jdi.request.ThreadDeathRequest;
33
34import java.util.*;
35import java.util.regex.*;
36import java.io.*;
37
38class VMConnection {
39
40 private VirtualMachine vm;
41 private Process process = null;
42 private int outputCompleteCount = 0;
43
44 private final Connector connector;
45 private final Map<String, com.sun.jdi.connect.Connector.Argument> connectorArgs;
46 private final int traceFlags;
47
48 synchronized void notifyOutputComplete() {
49 outputCompleteCount++;
50 notifyAll();
51 }
52
53 synchronized void waitOutputComplete() {
54 // Wait for stderr and stdout
55 if (process != null) {
56 while (outputCompleteCount < 2) {
57 try {wait();} catch (InterruptedException e) {}
58 }
59 }
60 }
61
62 private Connector findConnector(String name) {
63 for (Connector connector :
64 Bootstrap.virtualMachineManager().allConnectors()) {
65 if (connector.name().equals(name)) {
66 return connector;
67 }
68 }
69 return null;
70 }
71
72 private Map <String, com.sun.jdi.connect.Connector.Argument> parseConnectorArgs(Connector connector, String argString) {
73 Map<String, com.sun.jdi.connect.Connector.Argument> arguments = connector.defaultArguments();
74
75 /*
76 * We are parsing strings of the form:
77 * name1=value1,[name2=value2,...]
78 * However, the value1...valuen substrings may contain
79 * embedded comma(s), so make provision for quoting inside
80 * the value substrings. (Bug ID 4285874)
81 */
82 String regexPattern =
83 "(quote=[^,]+,)|" + // special case for quote=.,
84 "(\\w+=)" + // name=
85 "(((\"[^\"]*\")|" + // ( "l , ue"
86 "('[^']*')|" + // 'l , ue'
87 "([^,'\"]+))+,)"; // v a l u e )+ ,
88 Pattern p = Pattern.compile(regexPattern);
89 Matcher m = p.matcher(argString);
90 while (m.find()) {
91 int startPosition = m.start();
92 int endPosition = m.end();
93 if (startPosition > 0) {
94 /*
95 * It is an error if parsing skips over any part of argString.
96 */
97 throw new IllegalArgumentException
98 (MessageOutput.format("Illegal connector argument",
99 argString));
100 }
101
102 String token = argString.substring(startPosition, endPosition);
103 int index = token.indexOf('=');
104 String name = token.substring(0, index);
105 String value = token.substring(index + 1,
106 token.length() - 1); // Remove comma delimiter
107
108 Connector.Argument argument = arguments.get(name);
109 if (argument == null) {
110 throw new IllegalArgumentException
111 (MessageOutput.format("Argument is not defined for connector:",
112 new Object [] {name, connector.name()}));
113 }
114 argument.setValue(value);
115
116 argString = argString.substring(endPosition); // Remove what was just parsed...
117 m = p.matcher(argString); // and parse again on what is left.
118 }
119 if ((! argString.equals(",")) && (argString.length() > 0)) {
120 /*
121 * It is an error if any part of argString is left over,
122 * unless it was empty to begin with.
123 */
124 throw new IllegalArgumentException
125 (MessageOutput.format("Illegal connector argument", argString));
126 }
127 return arguments;
128 }
129
130 VMConnection(String connectSpec, int traceFlags) {
131 String nameString;
132 String argString;
133 int index = connectSpec.indexOf(':');
134 if (index == -1) {
135 nameString = connectSpec;
136 argString = "";
137 } else {
138 nameString = connectSpec.substring(0, index);
139 argString = connectSpec.substring(index + 1);
140 }
141
142 connector = findConnector(nameString);
143 if (connector == null) {
144 throw new IllegalArgumentException
145 (MessageOutput.format("No connector named:", nameString));
146 }
147
148 connectorArgs = parseConnectorArgs(connector, argString);
149 this.traceFlags = traceFlags;
150 }
151
152 synchronized VirtualMachine open() {
153 if (connector instanceof LaunchingConnector) {
154 vm = launchTarget();
155 } else if (connector instanceof AttachingConnector) {
156 vm = attachTarget();
157 } else if (connector instanceof ListeningConnector) {
158 vm = listenTarget();
159 } else {
160 throw new InternalError
161 (MessageOutput.format("Invalid connect type"));
162 }
163 vm.setDebugTraceMode(traceFlags);
164 if (vm.canBeModified()){
165 setEventRequests(vm);
166 resolveEventRequests();
167 }
168 /*
169 * Now that the vm connection is open, fetch the debugee
170 * classpath and set up a default sourcepath.
171 * (Unless user supplied a sourcepath on the command line)
172 * (Bug ID 4186582)
173 */
174 if (Env.getSourcePath().length() == 0) {
175 if (vm instanceof PathSearchingVirtualMachine) {
176 PathSearchingVirtualMachine psvm =
177 (PathSearchingVirtualMachine) vm;
178 Env.setSourcePath(psvm.classPath());
179 } else {
180 Env.setSourcePath(".");
181 }
182 }
183
184 return vm;
185 }
186
187 boolean setConnectorArg(String name, String value) {
188 /*
189 * Too late if the connection already made
190 */
191 if (vm != null) {
192 return false;
193 }
194
195 Connector.Argument argument = connectorArgs.get(name);
196 if (argument == null) {
197 return false;
198 }
199 argument.setValue(value);
200 return true;
201 }
202
203 String connectorArg(String name) {
204 Connector.Argument argument = connectorArgs.get(name);
205 if (argument == null) {
206 return "";
207 }
208 return argument.value();
209 }
210
211 public synchronized VirtualMachine vm() {
212 if (vm == null) {
213 throw new VMNotConnectedException();
214 } else {
215 return vm;
216 }
217 }
218
219 boolean isOpen() {
220 return (vm != null);
221 }
222
223 boolean isLaunch() {
224 return (connector instanceof LaunchingConnector);
225 }
226
227 public void disposeVM() {
228 try {
229 if (vm != null) {
230 vm.dispose();
231 vm = null;
232 }
233 } finally {
234 if (process != null) {
235 process.destroy();
236 process = null;
237 }
238 waitOutputComplete();
239 }
240 }
241
242 private void setEventRequests(VirtualMachine vm) {
243 EventRequestManager erm = vm.eventRequestManager();
244
245 // Normally, we want all uncaught exceptions. We request them
246 // via the same mechanism as Commands.commandCatchException()
247 // so the user can ignore them later if they are not
248 // interested.
249 // FIXME: this works but generates spurious messages on stdout
250 // during startup:
251 // Set uncaught java.lang.Throwable
252 // Set deferred uncaught java.lang.Throwable
253 Commands evaluator = new Commands();
254 evaluator.commandCatchException
255 (new StringTokenizer("uncaught java.lang.Throwable"));
256
257 ThreadStartRequest tsr = erm.createThreadStartRequest();
258 tsr.enable();
259 ThreadDeathRequest tdr = erm.createThreadDeathRequest();
260 tdr.enable();
261 }
262
263 private void resolveEventRequests() {
264 Env.specList.resolveAll();
265 }
266
267 private void dumpStream(InputStream stream) throws IOException {
268 BufferedReader in =
269 new BufferedReader(new InputStreamReader(stream));
270 int i;
271 try {
272 while ((i = in.read()) != -1) {
273 MessageOutput.printDirect((char)i);// Special case: use
274 // printDirect()
275 }
276 } catch (IOException ex) {
277 String s = ex.getMessage();
278 if (!s.startsWith("Bad file number")) {
279 throw ex;
280 }
281 // else we got a Bad file number IOException which just means
282 // that the debuggee has gone away. We'll just treat it the
283 // same as if we got an EOF.
284 }
285 }
286
287 /**
288 * Create a Thread that will retrieve and display any output.
289 * Needs to be high priority, else debugger may exit before
290 * it can be displayed.
291 */
292 private void displayRemoteOutput(final InputStream stream) {
293 Thread thr = new Thread("output reader") {
294 @Override
295 public void run() {
296 try {
297 dumpStream(stream);
298 } catch (IOException ex) {
299 MessageOutput.fatalError("Failed reading output");
300 } finally {
301 notifyOutputComplete();
302 }
303 }
304 };
305 thr.setPriority(Thread.MAX_PRIORITY-1);
306 thr.start();
307 }
308
309 private void dumpFailedLaunchInfo(Process process) {
310 try {
311 dumpStream(process.getErrorStream());
312 dumpStream(process.getInputStream());
313 } catch (IOException e) {
314 MessageOutput.println("Unable to display process output:",
315 e.getMessage());
316 }
317 }
318
319 /* launch child target vm */
320 private VirtualMachine launchTarget() {
321 LaunchingConnector launcher = (LaunchingConnector)connector;
322 try {
323 VirtualMachine vm = launcher.launch(connectorArgs);
324 process = vm.process();
325 displayRemoteOutput(process.getErrorStream());
326 displayRemoteOutput(process.getInputStream());
327 return vm;
328 } catch (IOException ioe) {
329 ioe.printStackTrace();
330 MessageOutput.fatalError("Unable to launch target VM.");
331 } catch (IllegalConnectorArgumentsException icae) {
332 icae.printStackTrace();
333 MessageOutput.fatalError("Internal debugger error.");
334 } catch (VMStartException vmse) {
335 MessageOutput.println("vmstartexception", vmse.getMessage());
336 MessageOutput.println();
337 dumpFailedLaunchInfo(vmse.process());
338 MessageOutput.fatalError("Target VM failed to initialize.");
339 }
340 return null; // Shuts up the compiler
341 }
342
343 /* attach to running target vm */
344 private VirtualMachine attachTarget() {
345 AttachingConnector attacher = (AttachingConnector)connector;
346 try {
347 return attacher.attach(connectorArgs);
348 } catch (IOException ioe) {
349 ioe.printStackTrace();
350 MessageOutput.fatalError("Unable to attach to target VM.");
351 } catch (IllegalConnectorArgumentsException icae) {
352 icae.printStackTrace();
353 MessageOutput.fatalError("Internal debugger error.");
354 }
355 return null; // Shuts up the compiler
356 }
357
358 /* listen for connection from target vm */
359 private VirtualMachine listenTarget() {
360 ListeningConnector listener = (ListeningConnector)connector;
361 try {
362 String retAddress = listener.startListening(connectorArgs);
363 MessageOutput.println("Listening at address:", retAddress);
364 vm = listener.accept(connectorArgs);
365 listener.stopListening(connectorArgs);
366 return vm;
367 } catch (IOException ioe) {
368 ioe.printStackTrace();
369 MessageOutput.fatalError("Unable to attach to target VM.");
370 } catch (IllegalConnectorArgumentsException icae) {
371 icae.printStackTrace();
372 MessageOutput.fatalError("Internal debugger error.");
373 }
374 return null; // Shuts up the compiler
375 }
376}