blob: 97131841074edbe40448c8ddbb54821ea3ce3768 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.tools.jdi;
27
28import com.sun.jdi.*;
29import com.sun.jdi.connect.*;
30import com.sun.jdi.connect.spi.*;
31import java.lang.reflect.Constructor;
32import java.lang.reflect.InvocationTargetException;
33import java.util.List;
34import java.util.ArrayList;
35import java.util.Collections;
36import java.util.Iterator;
37import java.util.ResourceBundle;
38import java.io.IOException;
39
40import java.util.ServiceLoader;
41
42/* Public for use by com.sun.jdi.Bootstrap */
43public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
44 private List<Connector> connectors = new ArrayList<Connector>();
45 private LaunchingConnector defaultConnector = null;
46 private List<VirtualMachine> targets = new ArrayList<VirtualMachine>();
47 private final ThreadGroup mainGroupForJDI;
48 private ResourceBundle messages = null;
49 private int vmSequenceNumber = 0;
50 private static final int majorVersion = 1;
51 private static final int minorVersion = 6;
52
53 private static final Object lock = new Object();
54 private static VirtualMachineManagerImpl vmm;
55
56 public static VirtualMachineManager virtualMachineManager() {
57 SecurityManager sm = System.getSecurityManager();
58 if (sm != null) {
59 JDIPermission vmmPermission =
60 new JDIPermission("virtualMachineManager");
61 sm.checkPermission(vmmPermission);
62 }
63 synchronized (lock) {
64 if (vmm == null) {
65 vmm = new VirtualMachineManagerImpl();
66 }
67 }
68 return vmm;
69 }
70
71 protected VirtualMachineManagerImpl() {
72
73 /*
74 * Create a top-level thread group
75 */
76 ThreadGroup top = Thread.currentThread().getThreadGroup();
77 ThreadGroup parent = null;
78 while ((parent = top.getParent()) != null) {
79 top = parent;
80 }
81 mainGroupForJDI = new ThreadGroup(top, "JDI main");
82
83 /*
84 * Load the connectors
85 */
86 ServiceLoader<Connector> connectorLoader =
87 ServiceLoader.load(Connector.class, Connector.class.getClassLoader());
88
89 Iterator<Connector> connectors = connectorLoader.iterator();
90
91 while (connectors.hasNext()) {
92 Connector connector;
93
94 try {
95 connector = (Connector)connectors.next();
96 } catch (ThreadDeath x) {
97 throw x;
98 } catch (Exception x) {
99 System.err.println(x);
100 continue;
101 } catch (Error x) {
102 System.err.println(x);
103 continue;
104 }
105
106 addConnector(connector);
107 }
108
109 /*
110 * Load any transport services and encapsulate them with
111 * an attaching and listening connector.
112 */
113 ServiceLoader<TransportService> transportLoader =
114 ServiceLoader.load(TransportService.class,
115 TransportService.class.getClassLoader());
116
117 Iterator<TransportService> transportServices =
118 transportLoader.iterator();
119
120 while (transportServices.hasNext()) {
121 TransportService transportService;
122
123 try {
124 transportService = (TransportService)transportServices.next();
125 } catch (ThreadDeath x) {
126 throw x;
127 } catch (Exception x) {
128 System.err.println(x);
129 continue;
130 } catch (Error x) {
131 System.err.println(x);
132 continue;
133 }
134
135 addConnector(GenericAttachingConnector.create(transportService));
136 addConnector(GenericListeningConnector.create(transportService));
137 }
138
139 // no connectors found
140 if (allConnectors().size() == 0) {
141 throw new Error("no Connectors loaded");
142 }
143
144 // Set the default launcher. In order to be compatible
145 // 1.2/1.3/1.4 we try to make the default launcher
146 // "com.sun.jdi.CommandLineLaunch". If this connector
147 // isn't found then we arbitarly pick the first connector.
148 //
149 boolean found = false;
150 List<LaunchingConnector> launchers = launchingConnectors();
151 for (LaunchingConnector lc: launchers) {
152 if (lc.name().equals("com.sun.jdi.CommandLineLaunch")) {
153 setDefaultConnector(lc);
154 found = true;
155 break;
156 }
157 }
158 if (!found && launchers.size() > 0) {
159 setDefaultConnector(launchers.get(0));
160 }
161
162 }
163
164 public LaunchingConnector defaultConnector() {
165 if (defaultConnector == null) {
166 throw new Error("no default LaunchingConnector");
167 }
168 return defaultConnector;
169 }
170
171 public void setDefaultConnector(LaunchingConnector connector) {
172 defaultConnector = connector;
173 }
174
175 public List<LaunchingConnector> launchingConnectors() {
176 List<LaunchingConnector> launchingConnectors = new ArrayList<LaunchingConnector>(connectors.size());
177 for (Connector connector: connectors) {
178 if (connector instanceof LaunchingConnector) {
179 launchingConnectors.add((LaunchingConnector)connector);
180 }
181 }
182 return Collections.unmodifiableList(launchingConnectors);
183 }
184
185 public List<AttachingConnector> attachingConnectors() {
186 List<AttachingConnector> attachingConnectors = new ArrayList<AttachingConnector>(connectors.size());
187 for (Connector connector: connectors) {
188 if (connector instanceof AttachingConnector) {
189 attachingConnectors.add((AttachingConnector)connector);
190 }
191 }
192 return Collections.unmodifiableList(attachingConnectors);
193 }
194
195 public List<ListeningConnector> listeningConnectors() {
196 List<ListeningConnector> listeningConnectors = new ArrayList<ListeningConnector>(connectors.size());
197 for (Connector connector: connectors) {
198 if (connector instanceof ListeningConnector) {
199 listeningConnectors.add((ListeningConnector)connector);
200 }
201 }
202 return Collections.unmodifiableList(listeningConnectors);
203 }
204
205 public List<Connector> allConnectors() {
206 return Collections.unmodifiableList(connectors);
207 }
208
209 public List<VirtualMachine> connectedVirtualMachines() {
210 return Collections.unmodifiableList(targets);
211 }
212
213 public void addConnector(Connector connector) {
214 connectors.add(connector);
215 }
216
217 public void removeConnector(Connector connector) {
218 connectors.remove(connector);
219 }
220
221 public synchronized VirtualMachine createVirtualMachine(
222 Connection connection,
223 Process process) throws IOException {
224
225 if (!connection.isOpen()) {
226 throw new IllegalStateException("connection is not open");
227 }
228
229 VirtualMachine vm;
230 try {
231 vm = new VirtualMachineImpl(this, connection, process,
232 ++vmSequenceNumber);
233 } catch (VMDisconnectedException e) {
234 throw new IOException(e.getMessage());
235 }
236 targets.add(vm);
237 return vm;
238 }
239
240 public VirtualMachine createVirtualMachine(Connection connection) throws IOException {
241 return createVirtualMachine(connection, null);
242 }
243
244 public void addVirtualMachine(VirtualMachine vm) {
245 targets.add(vm);
246 }
247
248 void disposeVirtualMachine(VirtualMachine vm) {
249 targets.remove(vm);
250 }
251
252 public int majorInterfaceVersion() {
253 return majorVersion;
254 }
255
256 public int minorInterfaceVersion() {
257 return minorVersion;
258 }
259
260 ThreadGroup mainGroupForJDI() {
261 return mainGroupForJDI;
262 }
263
264 String getString(String key) {
265 if (messages == null) {
266 messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
267 }
268 return messages.getString(key);
269 }
270
271}