KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > core > connection > PServerConnection


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  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.core.connection;
12  
13 import java.io.*;
14 import java.net.Socket JavaDoc;
15
16 import org.eclipse.core.net.proxy.IProxyData;
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.jsch.core.IJSchService;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.team.internal.ccvs.core.*;
21 import org.eclipse.team.internal.ccvs.core.util.Util;
22 import org.eclipse.team.internal.core.streams.*;
23
24 import com.jcraft.jsch.Proxy;
25
26 /**
27  * A connection used to talk to an cvs pserver.
28  */

29 public class PServerConnection implements IServerConnection {
30     
31     public static final char NEWLINE= 0xA;
32     
33     /** default CVS pserver port */
34     private static final int DEFAULT_PORT= 2401;
35     
36     /** error line indicators */
37     private static final char ERROR_CHAR = 'E';
38     private static final String JavaDoc ERROR_MESSAGE = "error 0";//$NON-NLS-1$
39
private static final String JavaDoc NO_SUCH_USER = "no such user";//$NON-NLS-1$
40

41     private static final char[] SCRAMBLING_TABLE=new char[] {
42     0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
43     16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
44     114,120,53,79,96,109,72,108,70,64,76,67,116,74,68,87,
45     111,52,75,119,49,34,82,81,95,65,112,86,118,110,122,105,
46     41,57,83,43,46,102,40,89,38,103,45,50,42,123,91,35,
47     125,55,54,66,124,126,59,47,92,71,115,78,88,107,106,56,
48     36,121,117,104,101,100,69,73,99,63,94,93,39,37,61,48,
49     58,113,32,90,44,98,60,51,33,97,62,77,84,80,85,223,
50     225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
51     199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
52     174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
53     207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
54     192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
55     227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
56     182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
57     243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152
58     };
59
60     /** Communication strings */
61     private static final String JavaDoc BEGIN= "BEGIN AUTH REQUEST";//$NON-NLS-1$
62
private static final String JavaDoc END= "END AUTH REQUEST";//$NON-NLS-1$
63
private static final String JavaDoc LOGIN_OK= "I LOVE YOU";//$NON-NLS-1$
64
private static final String JavaDoc LOGIN_FAILED= "I HATE YOU";//$NON-NLS-1$
65

66     private String JavaDoc password;
67     private ICVSRepositoryLocation cvsroot;
68
69     private Socket JavaDoc fSocket;
70     
71     private InputStream inputStream;
72     private OutputStream outputStream;
73     
74     /**
75      * @see Connection#doClose()
76      */

77     public void close() throws IOException {
78         try {
79             if (inputStream != null) inputStream.close();
80         } finally {
81             inputStream = null;
82             try {
83                 if (outputStream != null) outputStream.close();
84             } finally {
85                 outputStream = null;
86                 try {
87                     if (fSocket != null) fSocket.close();
88                 } finally {
89                     fSocket = null;
90                 }
91             }
92         }
93     }
94
95     /**
96      * @see Connection#doOpen()
97      */

98     public void open(IProgressMonitor monitor) throws IOException, CVSAuthenticationException {
99         
100         monitor.subTask(CVSMessages.PServerConnection_authenticating);
101         monitor.worked(1);
102         
103         InputStream is = null;
104         OutputStream os = null;
105         
106         Proxy proxy = getProxy();
107         if (proxy!=null) {
108           String JavaDoc host = cvsroot.getHost();
109           int port = cvsroot.getPort();
110           if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) {
111             port = DEFAULT_PORT;
112           }
113           try {
114             int timeout = CVSProviderPlugin.getPlugin().getTimeout() * 1000;
115             IJSchService service = CVSProviderPlugin.getPlugin().getJSchService();
116             service.connect(proxy, host, port, timeout, monitor);
117           } catch( Exception JavaDoc ex) {
118             ex.printStackTrace();
119             throw new IOException(ex.getMessage());
120           }
121           is = proxy.getInputStream();
122           os = proxy.getOutputStream();
123           
124         } else {
125           fSocket = createSocket(monitor);
126           is = fSocket.getInputStream();
127           os = fSocket.getOutputStream();
128         }
129         
130         boolean connected = false;
131         try {
132             this.inputStream = new BufferedInputStream(new PollingInputStream(is,
133                 cvsroot.getTimeout(), monitor));
134             this.outputStream = new PollingOutputStream(new TimeoutOutputStream(
135                 os, 8192 /*bufferSize*/, 1000 /*writeTimeout*/, 1000 /*closeTimeout*/),
136                 cvsroot.getTimeout(), monitor);
137             authenticate();
138             connected = true;
139         } finally {
140             if (! connected) cleanUpAfterFailedConnection();
141         }
142     }
143
144     private Proxy getProxy() {
145         IJSchService service = CVSProviderPlugin.getPlugin().getJSchService();
146         if (service == null)
147             return null;
148         Proxy proxy = service.getProxyForHost(cvsroot.getHost(), IProxyData.SOCKS_PROXY_TYPE);
149         if (proxy == null)
150             proxy = service.getProxyForHost(cvsroot.getHost(), IProxyData.HTTPS_PROXY_TYPE);
151         return proxy;
152     }
153
154     /**
155      * @see Connection#getInputStream()
156      */

157     public InputStream getInputStream() {
158         return inputStream;
159     }
160     /**
161      * @see Connection#getOutputStream()
162      */

163     public OutputStream getOutputStream() {
164         return outputStream;
165     }
166
167     /**
168      * Creates a new <code>PServerConnection</code> for the given
169      * cvs root.
170      */

171     PServerConnection(ICVSRepositoryLocation cvsroot, String JavaDoc password) {
172         this.cvsroot = cvsroot;
173         this.password = password;
174     }
175     /**
176      * Does the actual authentication.
177      */

178     private void authenticate() throws IOException, CVSAuthenticationException {
179         String JavaDoc scrambledPassword = scramblePassword(password);
180     
181         String JavaDoc user = cvsroot.getUsername();
182         OutputStream out = getOutputStream();
183         
184         StringBuffer JavaDoc request = new StringBuffer JavaDoc();
185         request.append(BEGIN);
186         request.append(NEWLINE);
187         request.append(cvsroot.getRootDirectory());
188         request.append(NEWLINE);
189         request.append(user);
190         request.append(NEWLINE);
191         request.append(scrambledPassword);
192         request.append(NEWLINE);
193         request.append(END);
194         request.append(NEWLINE);
195         out.write(request.toString().getBytes());
196         out.flush();
197         String JavaDoc line = Connection.readLine(cvsroot, getInputStream()).trim();
198         
199         // Return if we succeeded
200
if (LOGIN_OK.equals(line))
201             return;
202         
203         // Otherwise, determine the type of error
204
if (line.length() == 0) {
205             throw new IOException(CVSMessages.PServerConnection_noResponse);
206         }
207         
208         // Accumulate a message from the error (E) stream
209
String JavaDoc message = "";//$NON-NLS-1$
210
String JavaDoc separator = ""; //$NON-NLS-1$
211

212         if(!CVSProviderPlugin.getPlugin().isUseProxy()) {
213           while (line.length() > 0 && line.charAt(0) == ERROR_CHAR) {
214             if (line.length() > 2) {
215                 message += separator + line.substring(2);
216                 separator = " "; //$NON-NLS-1$
217
}
218             line = Connection.readLine(cvsroot, getInputStream());
219           }
220         } else {
221             while (line.length() > 0) {
222                 message += separator + line;
223                 separator = "\n"; //$NON-NLS-1$
224
line = Connection.readLine(cvsroot, getInputStream());
225             }
226         }
227         
228         // If the last line is the login failed (I HATE YOU) message, return authentication failure
229
if (LOGIN_FAILED.equals(line)) {
230             if (message.length() == 0) {
231                 throw new CVSAuthenticationException(CVSMessages.PServerConnection_loginRefused, CVSAuthenticationException.RETRY,cvsroot);
232             } else {
233                 throw new CVSAuthenticationException(message, CVSAuthenticationException.RETRY,cvsroot);
234             }
235         }
236         
237         // Remove leading "error 0"
238
if (line.startsWith(ERROR_MESSAGE))
239             message += separator + line.substring(ERROR_MESSAGE.length() + 1);
240         else
241             message += separator + line;
242         if (message.indexOf(NO_SUCH_USER) != -1)
243             throw new CVSAuthenticationException(NLS.bind(CVSMessages.PServerConnection_invalidUser, (new Object JavaDoc[] {message})), CVSAuthenticationException.RETRY,cvsroot);
244         throw new IOException(NLS.bind(CVSMessages.PServerConnection_connectionRefused, (new Object JavaDoc[] { message })));
245     }
246     /*
247      * Called if there are exceptions when connecting.
248      * This method makes sure that all connections are closed.
249      */

250     private void cleanUpAfterFailedConnection() throws IOException {
251         try {
252             if (inputStream != null)
253                 inputStream.close();
254         } finally {
255             try {
256                 if (outputStream != null)
257                     outputStream.close();
258             } finally {
259                 try {
260                     if (fSocket != null)
261                         fSocket.close();
262                 } finally {
263                     fSocket = null;
264                 }
265             }
266         }
267     
268     }
269     /**
270      * Creates the actual socket
271      */

272     protected Socket JavaDoc createSocket(IProgressMonitor monitor) throws IOException {
273         // Determine what port to use
274
int port = cvsroot.getPort();
275         if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT)
276             port = DEFAULT_PORT;
277         // Make the connection
278
Socket JavaDoc result;
279         try {
280             result= Util.createSocket(cvsroot.getHost(), port, monitor);
281             // Bug 36351: disable buffering and send bytes immediately
282
result.setTcpNoDelay(true);
283         } catch (InterruptedIOException e) {
284             // If we get this exception, chances are the host is not responding
285
throw new InterruptedIOException(NLS.bind(CVSMessages.PServerConnection_socket, (new Object JavaDoc[] {cvsroot.getHost()})));
286         }
287         result.setSoTimeout(1000); // 1 second between timeouts
288
return result;
289     }
290
291     private String JavaDoc scramblePassword(String JavaDoc password) throws CVSAuthenticationException {
292         int length = password.length();
293         char[] out= new char[length];
294         for (int i= 0; i < length; i++) {
295             char value = password.charAt(i);
296             if( value < 0 || value > 255 )
297                 throwInValidCharacter();
298             out[i]= SCRAMBLING_TABLE[value];
299         }
300         return "A" + new String JavaDoc(out);//$NON-NLS-1$
301
}
302     
303     private void throwInValidCharacter() throws CVSAuthenticationException {
304         throw new CVSAuthenticationException(CVSMessages.PServerConnection_invalidChars, CVSAuthenticationException.RETRY, cvsroot);
305     }
306     
307 }
308
Popular Tags