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.jdi; 27 28 import com.sun.jdi.*; 29 import com.sun.jdi.connect.*; 30 import com.sun.jdi.connect.spi.*; 31 import java.lang.reflect.Constructor; 32 import java.lang.reflect.InvocationTargetException; 33 import java.util.List; 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.Iterator; 37 import java.util.ResourceBundle; 38 import java.io.IOException; 39 40 import java.util.ServiceLoader; 41 42 /* Public for use by com.sun.jdi.Bootstrap */ 43 public 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 = 8; 52 53 private static final Object lock = new Object(); 54 private static VirtualMachineManagerImpl vmm; 55 virtualMachineManager()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 VirtualMachineManagerImpl()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 = 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 = 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 defaultConnector()164 public LaunchingConnector defaultConnector() { 165 if (defaultConnector == null) { 166 throw new Error("no default LaunchingConnector"); 167 } 168 return defaultConnector; 169 } 170 setDefaultConnector(LaunchingConnector connector)171 public void setDefaultConnector(LaunchingConnector connector) { 172 defaultConnector = connector; 173 } 174 launchingConnectors()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 attachingConnectors()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 listeningConnectors()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 allConnectors()205 public List<Connector> allConnectors() { 206 return Collections.unmodifiableList(connectors); 207 } 208 connectedVirtualMachines()209 public List<VirtualMachine> connectedVirtualMachines() { 210 return Collections.unmodifiableList(targets); 211 } 212 addConnector(Connector connector)213 public void addConnector(Connector connector) { 214 connectors.add(connector); 215 } 216 removeConnector(Connector connector)217 public void removeConnector(Connector connector) { 218 connectors.remove(connector); 219 } 220 createVirtualMachine( Connection connection, Process process)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 createVirtualMachine(Connection connection)240 public VirtualMachine createVirtualMachine(Connection connection) throws IOException { 241 return createVirtualMachine(connection, null); 242 } 243 addVirtualMachine(VirtualMachine vm)244 public void addVirtualMachine(VirtualMachine vm) { 245 targets.add(vm); 246 } 247 disposeVirtualMachine(VirtualMachine vm)248 void disposeVirtualMachine(VirtualMachine vm) { 249 targets.remove(vm); 250 } 251 majorInterfaceVersion()252 public int majorInterfaceVersion() { 253 return majorVersion; 254 } 255 minorInterfaceVersion()256 public int minorInterfaceVersion() { 257 return minorVersion; 258 } 259 mainGroupForJDI()260 ThreadGroup mainGroupForJDI() { 261 return mainGroupForJDI; 262 } 263 getString(String key)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 } 272