View Javadoc
1   package org.apache.maven.scm.provider.cvslib.cvsjava.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import ch.ethz.ssh2.Connection;
23  import ch.ethz.ssh2.Session;
24  import ch.ethz.ssh2.StreamGobbler;
25  import org.netbeans.lib.cvsclient.CVSRoot;
26  import org.netbeans.lib.cvsclient.command.CommandAbortedException;
27  import org.netbeans.lib.cvsclient.connection.AbstractConnection;
28  import org.netbeans.lib.cvsclient.connection.AuthenticationException;
29  import org.netbeans.lib.cvsclient.connection.ConnectionModifier;
30  import org.netbeans.lib.cvsclient.util.LoggedDataInputStream;
31  import org.netbeans.lib.cvsclient.util.LoggedDataOutputStream;
32  
33  import java.io.BufferedReader;
34  import java.io.File;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.InputStreamReader;
38  
39  /**
40   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
41   *
42   */
43  public class ExtConnection
44      extends AbstractConnection
45  {
46      private String host;
47  
48      private int port;
49  
50      private String userName;
51  
52      private String password;
53  
54      private Connection connection;
55  
56      private Session session;
57  
58      private BufferedReader stderrReader;
59  
60      public ExtConnection( CVSRoot cvsRoot )
61      {
62          this( cvsRoot.getHostName(), cvsRoot.getPort(), cvsRoot.getUserName(), cvsRoot.getPassword(),
63                cvsRoot.getRepository() );
64      }
65  
66      public ExtConnection( String host, int port, String username, String password, String repository )
67      {
68          this.userName = username;
69  
70          if ( this.userName == null )
71          {
72              this.userName = System.getProperty( "user.name" );
73          }
74  
75          this.password = password;
76  
77          this.host = host;
78  
79          setRepository( repository );
80  
81          this.port = port;
82  
83          if ( this.port == 0 )
84          {
85              this.port = 22;
86          }
87      }
88  
89      /** {@inheritDoc} */
90      public void open()
91          throws AuthenticationException, CommandAbortedException
92      {
93          connection = new Connection( host, port );
94  
95          /* TODO: add proxy support
96          ProxyData proxy = new HTTPProxyData( proxyHost, proxyPort, proxyUserName, proxyPassword );
97  
98          connection.setProxyData( proxy );
99          */
100 
101         try
102         {
103             // TODO: connection timeout?
104             connection.connect();
105         }
106         catch ( IOException e )
107         {
108             String message = "Cannot connect. Reason: " + e.getMessage();
109             throw new AuthenticationException( message, e, message );
110         }
111 
112         File privateKey = getPrivateKey();
113 
114         try
115         {
116             boolean authenticated;
117             if ( privateKey != null && privateKey.exists() )
118             {
119                 authenticated = connection.authenticateWithPublicKey( userName, privateKey, getPassphrase() );
120             }
121             else
122             {
123                 authenticated = connection.authenticateWithPassword( userName, password );
124             }
125 
126             if ( !authenticated )
127             {
128                 String message = "Authentication failed.";
129                 throw new AuthenticationException( message, message );
130             }
131         }
132         catch ( IOException e )
133         {
134             closeConnection();
135             String message = "Cannot authenticate. Reason: " + e.getMessage();
136             throw new AuthenticationException( message, e, message );
137         }
138 
139         try
140         {
141             session = connection.openSession();
142         }
143         catch ( IOException e )
144         {
145             String message = "Cannot open session. Reason: " + e.getMessage();
146             throw new CommandAbortedException( message, message );
147         }
148 
149         String command = "cvs server";
150         try
151         {
152             session.execCommand( command );
153         }
154         catch ( IOException e )
155         {
156             String message = "Cannot execute remote command: " + command;
157             throw new CommandAbortedException( message, message );
158         }
159 
160         InputStream stdout = new StreamGobbler( session.getStdout() );
161         InputStream stderr = new StreamGobbler( session.getStderr() );
162         stderrReader = new BufferedReader( new InputStreamReader( stderr ) );
163         setInputStream( new LoggedDataInputStream( stdout ) );
164         setOutputStream( new LoggedDataOutputStream( session.getStdin() ) );
165     }
166 
167     /** {@inheritDoc} */
168     public void verify()
169         throws AuthenticationException
170     {
171         try
172         {
173             open();
174             verifyProtocol();
175             close();
176         }
177         catch ( Exception e )
178         {
179             String message = "Failed to verify the connection: " + e.getMessage();
180             throw new AuthenticationException( message, e, message );
181         }
182     }
183 
184     private void closeConnection()
185     {
186         try
187         {
188             if ( stderrReader != null )
189             {
190                 while ( true )
191                 {
192                     String line = stderrReader.readLine();
193                     if ( line == null )
194                     {
195                         break;
196                     }
197 
198                     System.err.println( line );
199                 }
200             }
201         }
202         catch ( IOException e )
203         {
204             //nothing to do
205         }
206 
207         if ( session != null )
208         {
209             System.out.println( "Exit code:" + session.getExitStatus().intValue() );
210             session.close();
211         }
212 
213         if ( connection != null )
214         {
215             connection.close();
216         }
217 
218         reset();
219     }
220 
221     private void reset()
222     {
223         connection = null;
224         session = null;
225         stderrReader = null;
226         setInputStream( null );
227         setOutputStream( null );
228     }
229 
230     /** {@inheritDoc} */
231     public void close()
232         throws IOException
233     {
234         closeConnection();
235     }
236 
237     /** {@inheritDoc} */
238     public boolean isOpen()
239     {
240         return connection != null;
241     }
242 
243     /** {@inheritDoc} */
244     public int getPort()
245     {
246         return port;
247     }
248 
249     /** {@inheritDoc} */
250     public void modifyInputStream( ConnectionModifier modifier )
251         throws IOException
252     {
253         modifier.modifyInputStream( getInputStream() );
254     }
255 
256     /** {@inheritDoc} */
257     public void modifyOutputStream( ConnectionModifier modifier )
258         throws IOException
259     {
260         modifier.modifyOutputStream( getOutputStream() );
261     }
262 
263     private File getPrivateKey()
264     {
265         // If user don't define a password, he want to use a private key
266         File privateKey = null;
267         if ( password == null )
268         {
269             String pk = System.getProperty( "maven.scm.cvs.java.ssh.privateKey" );
270             if ( pk != null )
271             {
272                 privateKey = new File( pk );
273             }
274             else
275             {
276                 privateKey = findPrivateKey();
277             }
278         }
279         return privateKey;
280     }
281 
282     private String getPassphrase()
283     {
284         String passphrase = System.getProperty( "maven.scm.cvs.java.ssh.passphrase" );
285 
286         if ( passphrase == null )
287         {
288             passphrase = "";
289         }
290 
291         return passphrase;
292     }
293 
294     private File findPrivateKey()
295     {
296         String privateKeyDirectory = System.getProperty( "maven.scm.ssh.privateKeyDirectory" );
297 
298         if ( privateKeyDirectory == null )
299         {
300             privateKeyDirectory = System.getProperty( "user.home" );
301         }
302 
303         File privateKey = new File( privateKeyDirectory, ".ssh/id_dsa" );
304 
305         if ( !privateKey.exists() )
306         {
307             privateKey = new File( privateKeyDirectory, ".ssh/id_rsa" );
308         }
309 
310         return privateKey;
311     }
312 }