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/jdi/AbstractLauncher.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/jdi/AbstractLauncher.java+273−0
@@ -0,0 +1,273 @@
1+/*
2+ * Copyright (c) 1999, 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.jdi;
27+
28+import com.sun.tools.jdi.*;
29+import com.sun.jdi.connect.*;
30+import com.sun.jdi.connect.spi.*;
31+import com.sun.jdi.*;
32+
33+import java.util.Map;
34+import java.util.StringTokenizer;
35+import java.util.List;
36+import java.util.ArrayList;
37+import java.io.IOException;
38+import java.io.InterruptedIOException;
39+
40+abstract class AbstractLauncher extends ConnectorImpl implements LaunchingConnector {
41+
42+ abstract public VirtualMachine
43+ launch(Map<String,? extends Connector.Argument> arguments)
44+ throws IOException,
45+ IllegalConnectorArgumentsException,
46+ VMStartException;
47+ abstract public String name();
48+ abstract public String description();
49+
50+ ThreadGroup grp;
51+
52+ AbstractLauncher() {
53+ super();
54+
55+ grp = Thread.currentThread().getThreadGroup();
56+ ThreadGroup parent = null;
57+ while ((parent = grp.getParent()) != null) {
58+ grp = parent;
59+ }
60+ }
61+
62+ String[] tokenizeCommand(String command, char quote) {
63+ String quoteStr = String.valueOf(quote); // easier to deal with
64+
65+ /*
66+ * Tokenize the command, respecting the given quote character.
67+ */
68+ StringTokenizer tokenizer = new StringTokenizer(command,
69+ quote + " \t\r\n\f",
70+ true);
71+ String quoted = null;
72+ String pending = null;
73+ List<String> tokenList = new ArrayList<String>();
74+ while (tokenizer.hasMoreTokens()) {
75+ String token = tokenizer.nextToken();
76+ if (quoted != null) {
77+ if (token.equals(quoteStr)) {
78+ tokenList.add(quoted);
79+ quoted = null;
80+ } else {
81+ quoted += token;
82+ }
83+ } else if (pending != null) {
84+ if (token.equals(quoteStr)) {
85+ quoted = pending;
86+ } else if ((token.length() == 1) &&
87+ Character.isWhitespace(token.charAt(0))) {
88+ tokenList.add(pending);
89+ } else {
90+ throw new InternalException("Unexpected token: " + token);
91+ }
92+ pending = null;
93+ } else {
94+ if (token.equals(quoteStr)) {
95+ quoted = "";
96+ } else if ((token.length() == 1) &&
97+ Character.isWhitespace(token.charAt(0))) {
98+ // continue
99+ } else {
100+ pending = token;
101+ }
102+ }
103+ }
104+
105+ /*
106+ * Add final token.
107+ */
108+ if (pending != null) {
109+ tokenList.add(pending);
110+ }
111+
112+ /*
113+ * An unclosed quote at the end of the command. Do an
114+ * implicit end quote.
115+ */
116+ if (quoted != null) {
117+ tokenList.add(quoted);
118+ }
119+
120+ String[] tokenArray = new String[tokenList.size()];
121+ for (int i = 0; i < tokenList.size(); i++) {
122+ tokenArray[i] = tokenList.get(i);
123+ }
124+ return tokenArray;
125+ }
126+
127+ protected VirtualMachine launch(String[] commandArray, String address,
128+ TransportService.ListenKey listenKey,
129+ TransportService ts)
130+ throws IOException, VMStartException {
131+ Helper helper = new Helper(commandArray, address, listenKey, ts);
132+ helper.launchAndAccept();
133+
134+ VirtualMachineManager manager =
135+ Bootstrap.virtualMachineManager();
136+
137+ return manager.createVirtualMachine(helper.connection(),
138+ helper.process());
139+ }
140+
141+ /**
142+ * This class simply provides a context for a single launch and
143+ * accept. It provides instance fields that can be used by
144+ * all threads involved. This stuff can't be in the Connector proper
145+ * because the connector is is a singleton and not specific to any
146+ * one launch.
147+ */
148+ private class Helper {
149+ private final String address;
150+ private TransportService.ListenKey listenKey;
151+ private TransportService ts;
152+ private final String[] commandArray;
153+ private Process process = null;
154+ private Connection connection = null;
155+ private IOException acceptException = null;
156+ private boolean exited = false;
157+
158+ Helper(String[] commandArray, String address, TransportService.ListenKey listenKey,
159+ TransportService ts) {
160+ this.commandArray = commandArray;
161+ this.address = address;
162+ this.listenKey = listenKey;
163+ this.ts = ts;
164+ }
165+
166+ String commandString() {
167+ String str = "";
168+ for (int i = 0; i < commandArray.length; i++) {
169+ if (i > 0) {
170+ str += " ";
171+ }
172+ str += commandArray[i];
173+ }
174+ return str;
175+ }
176+
177+ synchronized void launchAndAccept() throws
178+ IOException, VMStartException {
179+
180+ process = Runtime.getRuntime().exec(commandArray);
181+
182+ Thread acceptingThread = acceptConnection();
183+ Thread monitoringThread = monitorTarget();
184+ try {
185+ while ((connection == null) &&
186+ (acceptException == null) &&
187+ !exited) {
188+ wait();
189+ }
190+
191+ if (exited) {
192+ throw new VMStartException(
193+ "VM initialization failed for: " + commandString(), process);
194+ }
195+ if (acceptException != null) {
196+ // Rethrow the exception in this thread
197+ throw acceptException;
198+ }
199+ } catch (InterruptedException e) {
200+ throw new InterruptedIOException("Interrupted during accept");
201+ } finally {
202+ acceptingThread.interrupt();
203+ monitoringThread.interrupt();
204+ }
205+ }
206+
207+ Process process() {
208+ return process;
209+ }
210+
211+ Connection connection() {
212+ return connection;
213+ }
214+
215+ synchronized void notifyOfExit() {
216+ exited = true;
217+ notify();
218+ }
219+
220+ synchronized void notifyOfConnection(Connection connection) {
221+ this.connection = connection;
222+ notify();
223+ }
224+
225+ synchronized void notifyOfAcceptException(IOException acceptException) {
226+ this.acceptException = acceptException;
227+ notify();
228+ }
229+
230+ Thread monitorTarget() {
231+ Thread thread = new Thread(grp,
232+ "launched target monitor") {
233+ public void run() {
234+ try {
235+ process.waitFor();
236+ /*
237+ * Notify waiting thread of VM error termination
238+ */
239+ notifyOfExit();
240+ } catch (InterruptedException e) {
241+ // Connection has been established, stop monitoring
242+ }
243+ }
244+ };
245+ thread.setDaemon(true);
246+ thread.start();
247+ return thread;
248+ }
249+
250+ Thread acceptConnection() {
251+ Thread thread = new Thread(grp,
252+ "connection acceptor") {
253+ public void run() {
254+ try {
255+ Connection connection = ts.accept(listenKey, 0, 0);
256+ /*
257+ * Notify waiting thread of connection
258+ */
259+ notifyOfConnection(connection);
260+ } catch (InterruptedIOException e) {
261+ // VM terminated, stop accepting
262+ } catch (IOException e) {
263+ // Report any other exception to waiting thread
264+ notifyOfAcceptException(e);
265+ }
266+ }
267+ };
268+ thread.setDaemon(true);
269+ thread.start();
270+ return thread;
271+ }
272+ }
273+}