KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdi > internal > connect > SocketTransportService


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Ivan Popov - Bug 184211: JDI connectors throw NullPointerException if used separately
11  * from Eclipse
12  *******************************************************************************/

13 package org.eclipse.jdi.internal.connect;
14
15 import java.io.DataInputStream JavaDoc;
16 import java.io.EOFException JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.InputStream JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.net.ServerSocket JavaDoc;
21 import java.net.Socket JavaDoc;
22 import java.net.SocketTimeoutException JavaDoc;
23 import java.util.Arrays JavaDoc;
24
25 import org.eclipse.jdi.TimeoutException;
26
27 import com.sun.jdi.connect.TransportTimeoutException;
28 import com.sun.jdi.connect.spi.ClosedConnectionException;
29 import com.sun.jdi.connect.spi.Connection;
30 import com.sun.jdi.connect.spi.TransportService;
31
32 public class SocketTransportService extends TransportService {
33     /** Handshake bytes used just after connecting VM. */
34     private static final byte[] handshakeBytes = "JDWP-Handshake".getBytes(); //$NON-NLS-1$
35

36     private Capabilities fCapabilities = new Capabilities() {
37         public boolean supportsAcceptTimeout() {
38             return true;
39         }
40
41         public boolean supportsAttachTimeout() {
42             return true;
43         }
44
45         public boolean supportsHandshakeTimeout() {
46             return true;
47         }
48
49         public boolean supportsMultipleConnections() {
50             return false;
51         }
52     };
53
54     private class SocketListenKey extends ListenKey {
55         private String JavaDoc fAddress;
56
57         SocketListenKey(String JavaDoc address) {
58             fAddress = address;
59         }
60
61         /*
62          * (non-Javadoc)
63          *
64          * @see com.sun.jdi.connect.spi.TransportService.ListenKey#address()
65          */

66         public String JavaDoc address() {
67             return fAddress;
68         }
69     }
70
71     // for attaching connector
72
private Socket JavaDoc fSocket;
73
74     private InputStream JavaDoc fInput;
75
76     private OutputStream JavaDoc fOutput;
77
78     // for listening or accepting connectors
79
private ServerSocket JavaDoc fServerSocket;
80
81     /*
82      * (non-Javadoc)
83      *
84      * @see com.sun.jdi.connect.spi.TransportService#accept(com.sun.jdi.connect.spi.TransportService.ListenKey,
85      * long, long)
86      */

87     public Connection accept(ListenKey listenKey, long attachTimeout, long handshakeTimeout) throws IOException JavaDoc {
88         if (attachTimeout > 0){
89             if (attachTimeout > Integer.MAX_VALUE) {
90                 attachTimeout = Integer.MAX_VALUE; //approx 25 days!
91
}
92             fServerSocket.setSoTimeout((int) attachTimeout);
93         }
94         try {
95             fSocket = fServerSocket.accept();
96         } catch (SocketTimeoutException JavaDoc e) {
97             throw new TransportTimeoutException();
98         }
99         fInput = fSocket.getInputStream();
100         fOutput = fSocket.getOutputStream();
101         performHandshake(fInput, fOutput, handshakeTimeout);
102         return new SocketConnection(this);
103     }
104
105     /*
106      * (non-Javadoc)
107      *
108      * @see com.sun.jdi.connect.spi.TransportService#attach(java.lang.String,
109      * long, long)
110      */

111     public Connection attach(String JavaDoc address, long attachTimeout, long handshakeTimeout) throws IOException JavaDoc {
112         String JavaDoc[] strings = address.split(":"); //$NON-NLS-1$
113
String JavaDoc host = "localhost"; //$NON-NLS-1$
114
int port = 0;
115         if (strings.length == 2) {
116             host = strings[0];
117             port = Integer.parseInt(strings[1]);
118         } else {
119             port = Integer.parseInt(strings[0]);
120         }
121
122         return attach(host, port, attachTimeout, handshakeTimeout);
123     }
124
125     public Connection attach(final String JavaDoc host, final int port, long attachTimeout, final long handshakeTimeout) throws IOException JavaDoc {
126         if (attachTimeout > 0){
127             if (attachTimeout > Integer.MAX_VALUE) {
128                 attachTimeout = Integer.MAX_VALUE; //approx 25 days!
129
}
130         }
131         
132         final IOException JavaDoc[] ex = new IOException JavaDoc[1];
133         Thread JavaDoc attachThread = new Thread JavaDoc(new Runnable JavaDoc() {
134             public void run() {
135                 try {
136                     fSocket = new Socket JavaDoc(host, port);
137                     fInput = fSocket.getInputStream();
138                     fOutput = fSocket.getOutputStream();
139                     performHandshake(fInput, fOutput, handshakeTimeout);
140                 } catch (IOException JavaDoc e) {
141                     ex[0] = e;
142                 }
143             }
144         }, ConnectMessages.SocketTransportService_0);
145         attachThread.setDaemon(true);
146         attachThread.start();
147         try {
148             attachThread.join(attachTimeout);
149             if (attachThread.isAlive()) {
150                 attachThread.interrupt();
151                 throw new TimeoutException JavaDoc();
152             }
153         } catch (InterruptedException JavaDoc e) {
154         }
155         
156         if (ex[0] != null) {
157             throw ex[0];
158         }
159
160         
161         return new SocketConnection(this);
162     }
163
164     void performHandshake(final InputStream JavaDoc in, final OutputStream JavaDoc out, final long timeout) throws IOException JavaDoc {
165         final IOException JavaDoc[] ex = new IOException JavaDoc[1];
166         final boolean[] handshakeCompleted = new boolean[1];
167         
168         Thread JavaDoc t = new Thread JavaDoc(new Runnable JavaDoc() {
169             public void run() {
170                 try {
171                     writeHandshake(out);
172                     readHandshake(in);
173                     handshakeCompleted[0] = true;
174                 } catch (IOException JavaDoc e) {
175                     ex[0] = e;
176                 }
177             }
178         }, ConnectMessages.SocketTransportService_1);
179         t.setDaemon(true);
180         t.start();
181         try {
182             t.join(timeout);
183         } catch (InterruptedException JavaDoc e1) {
184         }
185                 
186         if (handshakeCompleted[0])
187             return;
188
189         try {
190             in.close();
191             out.close();
192         } catch (IOException JavaDoc e) {
193         }
194         
195         if (ex[0] != null)
196             throw ex[0];
197
198         throw new TransportTimeoutException();
199     }
200     
201     private void readHandshake(InputStream JavaDoc input) throws IOException JavaDoc {
202         try {
203             DataInputStream JavaDoc in = new DataInputStream JavaDoc(input);
204             byte[] handshakeInput = new byte[handshakeBytes.length];
205             in.readFully(handshakeInput);
206             if (!Arrays.equals(handshakeInput, handshakeBytes))
207                 throw new IOException JavaDoc("Received invalid handshake"); //$NON-NLS-1$
208
} catch (EOFException JavaDoc e) {
209             throw new ClosedConnectionException();
210         }
211     }
212
213     private void writeHandshake(OutputStream JavaDoc out) throws IOException JavaDoc {
214         out.write(handshakeBytes);
215     }
216
217     /*
218      * (non-Javadoc)
219      *
220      * @see com.sun.jdi.connect.spi.TransportService#capabilities()
221      */

222     public Capabilities capabilities() {
223         return fCapabilities;
224     }
225
226     /*
227      * (non-Javadoc)
228      *
229      * @see com.sun.jdi.connect.spi.TransportService#description()
230      */

231     public String JavaDoc description() {
232         return "org.eclipse.jdt.debug: Socket Implementation of TransportService"; //$NON-NLS-1$
233
}
234
235     /*
236      * (non-Javadoc)
237      *
238      * @see com.sun.jdi.connect.spi.TransportService#name()
239      */

240     public String JavaDoc name() {
241         return "org.eclipse.jdt.debug_SocketTransportService"; //$NON-NLS-1$
242
}
243
244     /*
245      * (non-Javadoc)
246      *
247      * @see com.sun.jdi.connect.spi.TransportService#startListening()
248      */

249     public ListenKey startListening() throws IOException JavaDoc {
250         // not used by jdt debug.
251
return startListening(null);
252     }
253
254     /*
255      * (non-Javadoc)
256      *
257      * @see com.sun.jdi.connect.spi.TransportService#startListening(java.lang.String)
258      */

259     public ListenKey startListening(String JavaDoc address) throws IOException JavaDoc {
260         String JavaDoc host = null;
261         int port = 0; // jdt debugger will always specify an address in
262
// the form localhost:port
263
if (address != null) {
264             String JavaDoc[] strings = address.split(":"); //$NON-NLS-1$
265
host = "localhost"; //$NON-NLS-1$
266
if (strings.length == 2) {
267                 host = strings[0];
268                 port = Integer.parseInt(strings[1]);
269             } else {
270                 port = Integer.parseInt(strings[0]);
271             }
272         }
273         if (host == null) {
274             host = "localhost"; //$NON-NLS-1$
275
}
276
277         fServerSocket = new ServerSocket JavaDoc(port);
278         port = fServerSocket.getLocalPort();
279         ListenKey listenKey = new SocketListenKey(host + ":" + port); //$NON-NLS-1$
280
return listenKey;
281     }
282
283     /*
284      * (non-Javadoc)
285      *
286      * @see com.sun.jdi.connect.spi.TransportService#stopListening(com.sun.jdi.connect.spi.TransportService.ListenKey)
287      */

288     public void stopListening(ListenKey arg1) throws IOException JavaDoc {
289         if (fServerSocket != null) {
290             try {
291                 fServerSocket.close();
292             } catch (IOException JavaDoc e) {
293             }
294         }
295         fServerSocket = null;
296     }
297
298     public void close() {
299         if (fSocket != null) {
300             try {
301                 fSocket.close();
302             } catch (IOException JavaDoc e) {
303             }
304         }
305  
306         fServerSocket = null;
307         fSocket = null;
308         fInput = null;
309         fOutput = null;
310     }
311
312     /**
313      * @return
314      */

315     public InputStream JavaDoc getInputStream() {
316         return fInput;
317     }
318
319     /**
320      * @return
321      */

322     public OutputStream JavaDoc getOutputStream() {
323         return fOutput;
324     }
325 }
326
Popular Tags