blob: 394c963665e1b83797af04b249f65adfd6e2d01b [file] [log] [blame]
package org.apache.maven.scm.provider.cvslib.cvsjava.util;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import org.netbeans.lib.cvsclient.CVSRoot;
import org.netbeans.lib.cvsclient.command.CommandAbortedException;
import org.netbeans.lib.cvsclient.connection.AbstractConnection;
import org.netbeans.lib.cvsclient.connection.AuthenticationException;
import org.netbeans.lib.cvsclient.connection.ConnectionModifier;
import org.netbeans.lib.cvsclient.util.LoggedDataInputStream;
import org.netbeans.lib.cvsclient.util.LoggedDataOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
* @version $Id$
*/
public class ExtConnection
extends AbstractConnection
{
private String host;
private int port;
private String userName;
private String password;
private Connection connection;
private Session session;
private BufferedReader stderrReader;
public ExtConnection( CVSRoot cvsRoot )
{
this( cvsRoot.getHostName(), cvsRoot.getPort(), cvsRoot.getUserName(), cvsRoot.getPassword(),
cvsRoot.getRepository() );
}
public ExtConnection( String host, int port, String username, String password, String repository )
{
this.userName = username;
if ( this.userName == null )
{
this.userName = System.getProperty( "user.name" );
}
this.password = password;
this.host = host;
setRepository( repository );
this.port = port;
if ( this.port == 0 )
{
this.port = 22;
}
}
public void open()
throws AuthenticationException, CommandAbortedException
{
connection = new Connection( host, port );
/* TODO: add proxy support
ProxyData proxy = new HTTPProxyData( proxyHost, proxyPort, proxyUserName, proxyPassword );
connection.setProxyData( proxy );
*/
try
{
// TODO: connection timeout?
connection.connect();
}
catch ( IOException e )
{
String message = "Cannot connect. Reason: " + e.getMessage();
throw new AuthenticationException( message, e, message );
}
File privateKey = getPrivateKey();
try
{
boolean authenticated;
if ( privateKey != null && privateKey.exists() )
{
authenticated = connection.authenticateWithPublicKey( userName, privateKey, getPassphrase() );
}
else
{
authenticated = connection.authenticateWithPassword( userName, password );
}
if ( !authenticated )
{
String message = "Authentication failed.";
throw new AuthenticationException( message, message );
}
}
catch ( IOException e )
{
closeConnection();
String message = "Cannot authenticate. Reason: " + e.getMessage();
throw new AuthenticationException( message, e, message );
}
try
{
session = connection.openSession();
}
catch ( IOException e )
{
String message = "Cannot open session. Reason: " + e.getMessage();
throw new CommandAbortedException( message, message );
}
String command = "cvs server";
try
{
session.execCommand( command );
}
catch ( IOException e )
{
String message = "Cannot execute remote command: " + command;
throw new CommandAbortedException( message, message );
}
InputStream stdout = new StreamGobbler( session.getStdout() );
InputStream stderr = new StreamGobbler( session.getStderr() );
stderrReader = new BufferedReader( new InputStreamReader( stderr ) );
setInputStream( new LoggedDataInputStream( stdout ) );
setOutputStream( new LoggedDataOutputStream( session.getStdin() ) );
}
public void verify()
throws AuthenticationException
{
try
{
open();
verifyProtocol();
close();
}
catch ( Exception e )
{
String message = "Failed to verify the connection: " + e.getMessage();
throw new AuthenticationException( message, e, message );
}
}
private void closeConnection()
{
try
{
if ( stderrReader != null )
{
while ( true )
{
String line = stderrReader.readLine();
if ( line == null )
{
break;
}
System.err.println( line );
}
}
}
catch ( IOException e )
{
//nothing to do
}
if ( session != null )
{
System.out.println( "Exit code:" + session.getExitStatus().intValue() );
session.close();
}
if ( connection != null )
{
connection.close();
}
reset();
}
private void reset()
{
connection = null;
session = null;
stderrReader = null;
setInputStream( null );
setOutputStream( null );
}
public void close()
throws IOException
{
closeConnection();
}
public boolean isOpen()
{
return connection != null;
}
public int getPort()
{
return port;
}
public void modifyInputStream( ConnectionModifier modifier )
throws IOException
{
modifier.modifyInputStream( getInputStream() );
}
public void modifyOutputStream( ConnectionModifier modifier )
throws IOException
{
modifier.modifyOutputStream( getOutputStream() );
}
private File getPrivateKey()
{
// If user don't define a password, he want to use a private key
File privateKey = null;
if ( password == null )
{
String pk = System.getProperty( "maven.scm.cvs.java.ssh.privateKey" );
if ( pk != null )
{
privateKey = new File( pk );
}
else
{
privateKey = findPrivateKey();
}
}
return privateKey;
}
private String getPassphrase()
{
String passphrase = System.getProperty( "maven.scm.cvs.java.ssh.passphrase" );
if ( passphrase == null )
{
passphrase = "";
}
return passphrase;
}
private File findPrivateKey()
{
String privateKeyDirectory = System.getProperty( "maven.scm.ssh.privateKeyDirectory" );
if ( privateKeyDirectory == null )
{
privateKeyDirectory = System.getProperty( "user.home" );
}
File privateKey = new File( privateKeyDirectory, ".ssh/id_dsa" );
if ( !privateKey.exists() )
{
privateKey = new File( privateKeyDirectory, ".ssh/id_rsa" );
}
return privateKey;
}
}