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