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+
26+package com.sun.tools.example.debug.tty;
27+
28+import com.sun.jdi.*;
29+import com.sun.jdi.connect.*;
30+import com.sun.jdi.request.EventRequestManager;
31+import com.sun.jdi.request.ThreadStartRequest;
32+import com.sun.jdi.request.ThreadDeathRequest;
33+
34+import java.util.*;
35+import java.util.regex.*;
36+import java.io.*;
37+
38+class 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+}