1 /* 2 * Copyright (c) 2003, 2004, 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 java.util.Map; 29 import java.util.HashMap; 30 import java.util.ArrayList; 31 import java.io.IOException; 32 33 import com.sun.jdi.Bootstrap; 34 import com.sun.jdi.VirtualMachine; 35 import com.sun.jdi.connect.*; 36 import com.sun.jdi.connect.spi.*; 37 38 /* 39 * A ListeningConnector to listen for connections from target VM 40 * using the configured transport service 41 */ 42 public class GenericListeningConnector 43 extends ConnectorImpl implements ListeningConnector 44 { 45 static final String ARG_ADDRESS = "address"; 46 static final String ARG_TIMEOUT = "timeout"; 47 48 Map<Map<String,? extends Connector.Argument>, TransportService.ListenKey> listenMap; 49 TransportService transportService; 50 Transport transport; 51 52 /** 53 * Initialize a new instance of this connector. The connector 54 * encapsulates a transport service, has a "timeout" connector argument, 55 * and optionally an "address" connector argument. 56 */ 57 private GenericListeningConnector(TransportService ts, 58 boolean addAddressArgument) 59 { 60 transportService = ts; 61 transport = new Transport() { 62 public String name() { 63 return transportService.name(); 64 } 65 }; 66 67 if (addAddressArgument) { 68 addStringArgument( 69 ARG_ADDRESS, 70 getString("generic_listening.address.label"), 71 getString("generic_listening.address"), 72 "", 73 false); 74 } 75 76 addIntegerArgument( 77 ARG_TIMEOUT, 78 getString("generic_listening.timeout.label"), 79 getString("generic_listening.timeout"), 80 "", 81 false, 82 0, Integer.MAX_VALUE); 83 84 listenMap = new HashMap<Map<String,? extends Connector.Argument>,TransportService.ListenKey>(10); 85 } 86 87 /** 88 * Initialize a new instance of this connector. This constructor is used 89 * when sub-classing - the resulting connector will a "timeout" connector 90 * argument. 91 */ 92 protected GenericListeningConnector(TransportService ts) { 93 this(ts, false); 94 } 95 96 /** 97 * Create an instance of this Connector. The resulting ListeningConnector will 98 * have "address" and "timeout" connector arguments. 99 */ 100 public static GenericListeningConnector create(TransportService ts) { 101 return new GenericListeningConnector(ts, true); 102 } 103 104 public String startListening(String address, Map<String,? extends Connector.Argument> args) 105 throws IOException, IllegalConnectorArgumentsException 106 { 107 TransportService.ListenKey listener = listenMap.get(args); 108 if (listener != null) { 109 throw new IllegalConnectorArgumentsException("Already listening", 110 new ArrayList<String>(args.keySet())); 111 } 112 113 listener = transportService.startListening(address); 114 listenMap.put(args, listener); 115 return listener.address(); 116 } 117 118 public String 119 startListening(Map<String,? extends Connector.Argument> args) 120 throws IOException, IllegalConnectorArgumentsException 121 { 122 String address = argument(ARG_ADDRESS, args).value(); 123 return startListening(address, args); 124 } 125 126 public void stopListening(Map<String,? extends Connector.Argument> args) 127 throws IOException, IllegalConnectorArgumentsException 128 { 129 TransportService.ListenKey listener = listenMap.get(args); 130 if (listener == null) { 131 throw new IllegalConnectorArgumentsException("Not listening", 132 new ArrayList<String>(args.keySet())); 133 } 134 transportService.stopListening(listener); 135 listenMap.remove(args); 136 } 137 138 public VirtualMachine 139 accept(Map<String,? extends Connector.Argument> args) 140 throws IOException, IllegalConnectorArgumentsException 141 { 142 String ts = argument(ARG_TIMEOUT, args).value(); 143 int timeout = 0; 144 if (ts.length() > 0) { 145 timeout = Integer.decode(ts).intValue(); 146 } 147 148 TransportService.ListenKey listener = listenMap.get(args); 149 Connection connection; 150 if (listener != null) { 151 connection = transportService.accept(listener, timeout, 0); 152 } else { 153 /* 154 * Keep compatibility with previous releases - if the 155 * debugger hasn't called startListening then we do a 156 * once-off accept 157 */ 158 startListening(args); 159 listener = listenMap.get(args); 160 assert listener != null; 161 connection = transportService.accept(listener, timeout, 0); 162 stopListening(args); 163 } 164 return Bootstrap.virtualMachineManager().createVirtualMachine(connection); 165 } 166 167 public boolean supportsMultipleConnections() { 168 return transportService.capabilities().supportsMultipleConnections(); 169 } 170 171 public String name() { 172 return transport.name() + "Listen"; 173 } 174 175 public String description() { 176 return transportService.description(); 177 } 178 179 public Transport transport() { 180 return transport; 181 } 182 183 }