You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ol...@apache.org on 2011/09/21 15:39:48 UTC

svn commit: r1173634 - in /maven/wagon/trunk: ./ wagon-provider-test/src/main/java/org/apache/maven/wagon/ wagon-providers/wagon-ssh-common-test/src/main/java/org/apache/maven/wagon/providers/ssh/ wagon-providers/wagon-ssh-common/src/main/java/org/apac...

Author: olamy
Date: Wed Sep 21 13:39:47 2011
New Revision: 1173634

URL: http://svn.apache.org/viewvc?rev=1173634&view=rev
Log:
[WAGON-350] add unit test for wagon ssh with an embedded ssh server

Added:
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommand.java
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommandFactory.java
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/resources/log4j.xml
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase.pub
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa.pub
Modified:
    maven/wagon/trunk/pom.xml
    maven/wagon/trunk/wagon-provider-test/src/main/java/org/apache/maven/wagon/WagonTestCase.java
    maven/wagon/trunk/wagon-providers/wagon-ssh-common-test/src/main/java/org/apache/maven/wagon/providers/ssh/TestData.java
    maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/LSParser.java
    maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/ScpHelper.java
    maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/test/java/org/apache/maven/wagon/providers/ssh/LSParserTest.java
    maven/wagon/trunk/wagon-providers/wagon-ssh/pom.xml
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonTest.java
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonWithSshPrivateKeySearchTest.java
    maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/SftpWagonTest.java

Modified: maven/wagon/trunk/pom.xml
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/pom.xml?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/pom.xml (original)
+++ maven/wagon/trunk/pom.xml Wed Sep 21 13:39:47 2011
@@ -266,7 +266,7 @@ under the License.
       <dependency>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-utils</artifactId>
-        <version>2.0.7</version>
+        <version>3.0</version>
       </dependency>
 
       <!-- for slf4j -->
@@ -321,6 +321,7 @@ under the License.
           <artifactId>maven-surefire-plugin</artifactId>
           <version>2.9</version>
           <configuration>
+            <forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
             <systemPropertyVariables>
               <java.io.tmpdir>${project.build.outputDirectory}</java.io.tmpdir>
             </systemPropertyVariables>

Modified: maven/wagon/trunk/wagon-provider-test/src/main/java/org/apache/maven/wagon/WagonTestCase.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-provider-test/src/main/java/org/apache/maven/wagon/WagonTestCase.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-provider-test/src/main/java/org/apache/maven/wagon/WagonTestCase.java (original)
+++ maven/wagon/trunk/wagon-provider-test/src/main/java/org/apache/maven/wagon/WagonTestCase.java Wed Sep 21 13:39:47 2011
@@ -563,7 +563,7 @@ public abstract class WagonTestCase
 
             wagon.putDirectory( sourceFile, "." );
 
-            List resourceNames = new ArrayList( resources.length + 1 );
+            List<String> resourceNames = new ArrayList<String>( resources.length + 1 );
 
             resourceNames.add( resourceToCreate );
             for ( int i = 0; i < resources.length; i++ )
@@ -593,13 +593,13 @@ public abstract class WagonTestCase
         writeTestFile( resourceToCreate );
     }
 
-    protected void assertResourcesAreInRemoteSide( Wagon wagon, List resourceNames )
+    protected void assertResourcesAreInRemoteSide( Wagon wagon, List<String> resourceNames )
         throws IOException, TransferFailedException, ResourceDoesNotExistException, AuthorizationException
     {
-        Iterator iter = resourceNames.iterator();
+        Iterator<String> iter = resourceNames.iterator();
         while ( iter.hasNext() )
         {
-            String resourceName = (String) iter.next();
+            String resourceName = iter.next();
 
             File destFile = FileTestUtils.createUniqueFile( getName(), resourceName );
 

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh-common-test/src/main/java/org/apache/maven/wagon/providers/ssh/TestData.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh-common-test/src/main/java/org/apache/maven/wagon/providers/ssh/TestData.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh-common-test/src/main/java/org/apache/maven/wagon/providers/ssh/TestData.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh-common-test/src/main/java/org/apache/maven/wagon/providers/ssh/TestData.java Wed Sep 21 13:39:47 2011
@@ -32,12 +32,12 @@ public class TestData
 {
     public static String getTempDirectory()
     {
-        return System.getProperty( "java.io.tmpdir", "/tmp" );
+        return System.getProperty( "java.io.tmpdir", "target" );
     }
-    
-    public static String getTestRepositoryUrl()
+
+    public static String getTestRepositoryUrl( int port )
     {
-        return "scp://" + getHostname() + getTempDirectory() + "/wagon-ssh-test/" + getUserName();
+        return "scp://" + getHostname() + ":" + port + getTempDirectory() + "/wagon-ssh-test/" + getUserName();
     }
 
     public static String getUserName()
@@ -47,7 +47,7 @@ public class TestData
 
     public static File getPrivateKey()
     {
-        return new File( System.getProperty( "user.home" ), "/.ssh/id_dsa" );
+        return new File( System.getProperty( "sshKeysPath", "src/test/ssh-keys" ), "id_rsa" );
     }
 
     public static String getHostname()
@@ -59,7 +59,9 @@ public class TestData
     {
         try
         {
-            return FileUtils.fileRead( "/etc/ssh_host_rsa_key.pub" ).substring( "ssh-rsa".length() ).trim();
+            return FileUtils.fileRead(
+                new File( System.getProperty( "sshKeysPath" ), "id_rsa.pub" ).getPath() ).substring(
+                "ssh-rsa".length() ).trim();
         }
         catch ( IOException e )
         {

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/LSParser.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/LSParser.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/LSParser.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/LSParser.java Wed Sep 21 13:39:47 2011
@@ -19,6 +19,8 @@ package org.apache.maven.wagon.providers
  * under the License.
  */
 
+import org.apache.maven.wagon.TransferFailedException;
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.StringReader;
@@ -27,31 +29,29 @@ import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.maven.wagon.TransferFailedException;
-
 /**
- * LSParser 
+ * LSParser
  *
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  * @version $Id$
  */
 public class LSParser
 {
-    private static final Pattern PATTERN = Pattern.compile( ".+\\s+[0-9]+\\s+.+\\s+.+\\s+[0-9]+\\s+"
-                                                   + "([0-9]{4}-[0-9]{2}-[0-9]{2}|.+\\s+[0-9]+)\\s+[0-9:]+\\s+(.+?)" );
-    
+    private static final Pattern PATTERN = Pattern.compile(
+        ".+\\s+[0-9]+\\s+.+\\s+.+\\s+[0-9]+\\s+" + "([0-9]{4}-[0-9]{2}-[0-9]{2}|.+\\s+[0-9]+)\\s+[0-9:]+\\s+(.+?)" );
+
     /**
      * Parse a raw "ls -la", and obtain the list of files.
-     * 
-     * @todo use ls -1a and do away with the method all together
-     * 
+     *
      * @param rawLS the raw LS to parse.
      * @return the list of files found.
      * @throws TransferFailedException
+     * @todo use ls -1a and do away with the method all together
      */
     public List<String> parseFiles( String rawLS )
         throws TransferFailedException
     {
+        System.out.println( "LSParser raw : " + rawLS );
         List<String> ret = new ArrayList<String>();
         try
         {
@@ -62,7 +62,7 @@ public class LSParser
             while ( line != null )
             {
                 line = line.trim();
-                
+
                 Matcher m = PATTERN.matcher( line );
                 if ( m.matches() )
                 {

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/ScpHelper.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/ScpHelper.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/ScpHelper.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/main/java/org/apache/maven/wagon/providers/ssh/ScpHelper.java Wed Sep 21 13:39:47 2011
@@ -279,7 +279,7 @@ public class ScpHelper
         {
             String path = getPath( repository.getBasedir(), destinationDirectory );
             Streams streams = executor.executeCommand( "ls -FlA " + path, false );
-            
+
             return new LSParser().parseFiles( streams.getOut() );
         }
         catch ( CommandExecutionException e )

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/test/java/org/apache/maven/wagon/providers/ssh/LSParserTest.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/test/java/org/apache/maven/wagon/providers/ssh/LSParserTest.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/test/java/org/apache/maven/wagon/providers/ssh/LSParserTest.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh-common/src/test/java/org/apache/maven/wagon/providers/ssh/LSParserTest.java Wed Sep 21 13:39:47 2011
@@ -61,6 +61,13 @@ public class LSParserTest
             + "drwxr-xr-x   7  joakim  joakim   476 Dec 11 10:31 .svn\n"
             + "drwxr-xr-x   3  joakim  joakim   238 Dec 11 08:39 target\n";
 
+                total 40
+                -rw-r--r--  1 olamy  staff  11 21 sep 00:34 .index.txt
+                -rw-r--r--  1 olamy  staff  19 21 sep 00:34 more-resources.dat
+                -rw-r--r--  1 olamy  staff  20 21 sep 00:34 test-resource b.txt
+                -rw-r--r--  1 olamy  staff  18 21 sep 00:34 test-resource.pom
+                -rw-r--r--  1 olamy  staff  18 21 sep 00:34 test-resource.txt
+
         LSParser parser = new LSParser();
         List files = parser.parseFiles( rawLS );
         assertNotNull( files );

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh/pom.xml
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/pom.xml?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/pom.xml (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/pom.xml Wed Sep 21 13:39:47 2011
@@ -54,6 +54,35 @@ under the License.
       <artifactId>jetty</artifactId>
       <scope>test</scope>
     </dependency>
+
+    <dependency>
+      <groupId>org.apache.sshd</groupId>
+      <artifactId>sshd-core</artifactId>
+      <version>0.6.0</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <version>1.6.1</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcprov-jdk15</artifactId>
+      <version>140</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-exec</artifactId>
+      <version>1.1</version>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
   <profiles>
@@ -76,6 +105,11 @@ under the License.
                 <exclude>**/KnownHostsProviderTest.*</exclude>
                 <exclude>**/ScpWagon*Test.*</exclude>
               </excludes>
+              <systemPropertyVariables>
+                <java.io.tmpdir>${project.build.outputDirectory}</java.io.tmpdir>
+                <sshKeysPath>${basedir}/src/test/ssh-keys</sshKeysPath>
+                <test.user>olamy</test.user>
+              </systemPropertyVariables>
             </configuration>
           </plugin>
         </plugins>

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java Wed Sep 21 13:39:47 2011
@@ -19,11 +19,8 @@ package org.apache.maven.wagon.providers
  * under the License.
  */
 
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.JSchException;
 import org.apache.maven.wagon.CommandExecutionException;
 import org.apache.maven.wagon.InputData;
 import org.apache.maven.wagon.OutputData;
@@ -34,25 +31,26 @@ import org.apache.maven.wagon.providers.
 import org.apache.maven.wagon.repository.RepositoryPermissions;
 import org.apache.maven.wagon.resource.Resource;
 
-import com.jcraft.jsch.ChannelExec;
-import com.jcraft.jsch.JSchException;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 
 /**
  * SCP protocol wagon.
- * 
+ * <p/>
  * Note that this implementation is <i>not</i> thread-safe, and multiple channels can not be used on the session at
  * the same time.
- * 
+ * <p/>
  * See <a href="http://blogs.sun.com/janp/entry/how_the_scp_protocol_works">
  * http://blogs.sun.com/janp/entry/how_the_scp_protocol_works</a>
  * for information on how the SCP protocol works.
  *
  * @version $Id$
  * @todo [BP] add compression flag
- * 
- * @plexus.component role="org.apache.maven.wagon.Wagon" 
- *   role-hint="scp"
- *   instantiation-strategy="per-lookup"
+ * @plexus.component role="org.apache.maven.wagon.Wagon"
+ * role-hint="scp"
+ * instantiation-strategy="per-lookup"
  */
 public class ScpWagon
     extends AbstractJschWagon
@@ -144,7 +142,7 @@ public class ScpWagon
         {
             throw new IOException( "SCP terminated with unknown error code" );
         }
-    }    
+    }
 
     protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
         throws TransferFailedException
@@ -152,7 +150,7 @@ public class ScpWagon
         try
         {
             checkAck( input );
-    
+
             sendEom( channelOutputStream );
         }
         catch ( IOException e )
@@ -160,7 +158,7 @@ public class ScpWagon
             handleGetException( resource, e );
         }
     }
-    
+
     protected void cleanupGetTransfer( Resource resource )
     {
         if ( channel != null )
@@ -168,14 +166,14 @@ public class ScpWagon
             channel.disconnect();
         }
     }
-    
+
     protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
                                 int maxSize )
         throws TransferFailedException
     {
         super.getTransfer( resource, output, input, closeInput, (int) resource.getContentLength() );
     }
-    
+
     protected String readLine( InputStream in )
         throws IOException
     {
@@ -217,7 +215,7 @@ public class ScpWagon
         throws TransferFailedException, ResourceDoesNotExistException
     {
         Resource resource = inputData.getResource();
-        
+
         String path = getPath( getRepository().getBasedir(), resource.getName() );
         String cmd = "scp -p -f " + path;
 
@@ -231,7 +229,7 @@ public class ScpWagon
 
             // get I/O streams for remote scp
             channelOutputStream = channel.getOutputStream();
-            
+
             InputStream in = channel.getInputStream();
             inputData.setInputStream( in );
 
@@ -244,13 +242,13 @@ public class ScpWagon
             if ( exitCode == 'T' )
             {
                 String line = readLine( in );
-                
+
                 String[] times = line.split( " " );
-                
+
                 resource.setLastModified( Long.valueOf( times[0] ).longValue() * 1000 );
 
                 sendEom( channelOutputStream );
-                
+
                 exitCode = in.read();
             }
 
@@ -258,7 +256,8 @@ public class ScpWagon
 
             if ( exitCode != COPY_START_CHAR )
             {
-                if ( exitCode == 1 && line.indexOf( "No such file or directory" ) != -1 )
+                if ( exitCode == 1 && ( line.indexOf( "No such file or directory" ) != -1
+                    || line.indexOf( "no such file or directory" ) != 1 ) )
                 {
                     throw new ResourceDoesNotExistException( line );
                 }
@@ -311,7 +310,7 @@ public class ScpWagon
         throws TransferFailedException
     {
         Resource resource = outputData.getResource();
-        
+
         String basedir = getRepository().getBasedir();
 
         String path = getPath( basedir, resource.getName() );
@@ -328,9 +327,9 @@ public class ScpWagon
 
             throw new TransferFailedException( e.getMessage(), e );
         }
-        
+
         String octalMode = getOctalMode( getRepository().getPermissions() );
-        
+
         // exec 'scp -p -t rfile' remotely
         String command = "scp";
         if ( octalMode != null )
@@ -385,8 +384,8 @@ public class ScpWagon
         }
         catch ( JSchException e )
         {
-            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );            
-            
+            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
+
             String msg = "Error occurred while deploying '" + resourceName + "' to remote repository: "
                 + getRepository().getUrl() + ": " + e.getMessage();
 
@@ -403,15 +402,15 @@ public class ScpWagon
     {
         if ( e.getMessage().indexOf( "set mode: Operation not permitted" ) >= 0 )
         {
-            fireTransferDebug( e.getMessage() );                
+            fireTransferDebug( e.getMessage() );
         }
         else
         {
-            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );            
-            
+            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
+
             String msg = "Error occurred while deploying '" + resource.getName() + "' to remote repository: "
                 + getRepository().getUrl() + ": " + e.getMessage();
-   
+
             throw new TransferFailedException( msg, e );
         }
     }

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommand.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommand.java?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommand.java (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommand.java Wed Sep 21 13:39:47 2011
@@ -0,0 +1,588 @@
+package org.apache.maven.wagon.providers.ssh.jsch;
+
+/*
+ * 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 org.apache.sshd.common.util.DirectoryScanner;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+import org.apache.sshd.server.FileSystemAware;
+import org.apache.sshd.server.FileSystemView;
+import org.apache.sshd.server.SshFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+/**
+ * This commands provide SCP support on both server and client side.
+ * Permissions and preservation of access / modification times on files
+ * are not supported.
+ * olamy : copy of a class from mina for changing return codes in case of file not found 1 warning instead of 2
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ScpCommand
+    implements Command, Runnable, FileSystemAware
+{
+
+    protected static final Logger log = LoggerFactory.getLogger( ScpCommand.class );
+
+    protected static final int OK = 0;
+
+    protected static final int WARNING = 1;
+
+    protected static final int ERROR = 2;
+
+    protected String name;
+
+    protected boolean optR;
+
+    protected boolean optT;
+
+    protected boolean optF;
+
+    protected boolean optV;
+
+    protected boolean optD;
+
+    protected boolean optP;
+
+    protected FileSystemView root;
+
+    protected String path;
+
+    protected InputStream in;
+
+    protected OutputStream out;
+
+    protected OutputStream err;
+
+    protected ExitCallback callback;
+
+    protected IOException error;
+
+    public ScpCommand( String[] args )
+    {
+        name = Arrays.asList( args ).toString();
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Executing command {}", name );
+        }
+        path = ".";
+        for ( int i = 1; i < args.length; i++ )
+        {
+            if ( args[i].charAt( 0 ) == '-' )
+            {
+                for ( int j = 1; j < args[i].length(); j++ )
+                {
+                    switch ( args[i].charAt( j ) )
+                    {
+                        case 'f':
+                            optF = true;
+                            break;
+                        case 'p':
+                            optP = true;
+                            break;
+                        case 'r':
+                            optR = true;
+                            break;
+                        case 't':
+                            optT = true;
+                            break;
+                        case 'v':
+                            optV = true;
+                            break;
+                        case 'd':
+                            optD = true;
+                            break;
+//                          default:
+//                            error = new IOException("Unsupported option: " + args[i].charAt(j));
+//                            return;
+                    }
+                }
+            }
+            else if ( i == args.length - 1 )
+            {
+                path = args[args.length - 1];
+            }
+        }
+        if ( !optF && !optT )
+        {
+            error = new IOException( "Either -f or -t option should be set" );
+        }
+    }
+
+    public void setInputStream( InputStream in )
+    {
+        this.in = in;
+    }
+
+    public void setOutputStream( OutputStream out )
+    {
+        this.out = out;
+    }
+
+    public void setErrorStream( OutputStream err )
+    {
+        this.err = err;
+    }
+
+    public void setExitCallback( ExitCallback callback )
+    {
+        this.callback = callback;
+    }
+
+    public void start( Environment env )
+        throws IOException
+    {
+        if ( error != null )
+        {
+            throw error;
+        }
+        new Thread( this, "ScpCommand: " + name ).start();
+    }
+
+    public void destroy()
+    {
+    }
+
+    public void run()
+    {
+        int exitValue = OK;
+        String exitMessage = null;
+
+        try
+        {
+            if ( optT )
+            {
+                ack();
+                for (; ; )
+                {
+                    String line;
+                    boolean isDir = false;
+                    int c = readAck( true );
+                    switch ( c )
+                    {
+                        case -1:
+                            return;
+                        case 'D':
+                            isDir = true;
+                        case 'C':
+                            line = ( (char) c ) + readLine();
+                            break;
+                        case 'E':
+                            readLine();
+                            return;
+                        default:
+                            //a real ack that has been acted upon already
+                            continue;
+                    }
+
+                    if ( optR && isDir )
+                    {
+                        writeDir( line, root.getFile( path ) );
+                    }
+                    else
+                    {
+                        writeFile( line, root.getFile( path ) );
+                    }
+                }
+            }
+            else if ( optF )
+            {
+                String pattern = path;
+                int idx = pattern.indexOf( '*' );
+                if ( idx >= 0 )
+                {
+                    String basedir = "";
+                    int lastSep = pattern.substring( 0, idx ).lastIndexOf( '/' );
+                    if ( lastSep >= 0 )
+                    {
+                        basedir = pattern.substring( 0, lastSep );
+                        pattern = pattern.substring( lastSep + 1 );
+                    }
+                    String[] included = new DirectoryScanner( basedir, pattern ).scan();
+                    for ( String path : included )
+                    {
+                        SshFile file = root.getFile( basedir + "/" + path );
+                        if ( file.isFile() )
+                        {
+                            readFile( file );
+                        }
+                        else if ( file.isDirectory() )
+                        {
+                            if ( !optR )
+                            {
+                                out.write( WARNING );
+                                out.write( ( path + " not a regular file\n" ).getBytes() );
+                            }
+                            else
+                            {
+                                readDir( file );
+                            }
+                        }
+                        else
+                        {
+                            out.write( WARNING );
+                            out.write( ( path + " unknown file type\n" ).getBytes() );
+                        }
+                    }
+                }
+                else
+                {
+                    String basedir = "";
+                    int lastSep = pattern.lastIndexOf( '/' );
+                    if ( lastSep >= 0 )
+                    {
+                        basedir = pattern.substring( 0, lastSep );
+                        pattern = pattern.substring( lastSep + 1 );
+                    }
+                    SshFile file = root.getFile( basedir + "/" + pattern );
+                    if ( !file.doesExist() )
+                    {
+                        exitValue = WARNING;
+                        throw new IOException( file + ": no such file or directory" );
+                    }
+                    if ( file.isFile() )
+                    {
+                        readFile( file );
+                    }
+                    else if ( file.isDirectory() )
+                    {
+                        if ( !optR )
+                        {
+                            throw new IOException( file + " not a regular file" );
+                        }
+                        else
+                        {
+                            readDir( file );
+                        }
+                    }
+                    else
+                    {
+                        throw new IOException( file + ": unknown file type" );
+                    }
+                }
+            }
+            else
+            {
+                throw new IOException( "Unsupported mode" );
+            }
+        }
+        catch ( IOException e )
+        {
+            try
+            {
+                exitValue = ( exitValue != OK ? exitValue : ERROR );
+                exitMessage = e.getMessage();
+                out.write( exitValue );
+                out.write( exitMessage.getBytes() );
+                out.write( '\n' );
+                out.flush();
+            }
+            catch ( IOException e2 )
+            {
+                // Ignore
+            }
+            log.info( "Error in scp command", e );
+        }
+        finally
+        {
+            if ( callback != null )
+            {
+                callback.onExit( exitValue, exitMessage );
+            }
+        }
+    }
+
+    protected void writeDir( String header, SshFile path )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Writing dir {}", path );
+        }
+        if ( !header.startsWith( "D" ) )
+        {
+            throw new IOException( "Expected a D message but got '" + header + "'" );
+        }
+
+        String perms = header.substring( 1, 5 );
+        int length = Integer.parseInt( header.substring( 6, header.indexOf( ' ', 6 ) ) );
+        String name = header.substring( header.indexOf( ' ', 6 ) + 1 );
+
+        if ( length != 0 )
+        {
+            throw new IOException( "Expected 0 length for directory but got " + length );
+        }
+        SshFile file;
+        if ( path.doesExist() && path.isDirectory() )
+        {
+            file = root.getFile( path, name );
+        }
+        else if ( !path.doesExist() && path.getParentFile().doesExist() && path.getParentFile().isDirectory() )
+        {
+            file = path;
+        }
+        else
+        {
+            throw new IOException( "Can not write to " + path );
+        }
+        if ( !( file.doesExist() && file.isDirectory() ) && !file.mkdir() )
+        {
+            throw new IOException( "Could not create directory " + file );
+        }
+
+        ack();
+
+        for (; ; )
+        {
+            header = readLine();
+            if ( header.startsWith( "C" ) )
+            {
+                writeFile( header, file );
+            }
+            else if ( header.startsWith( "D" ) )
+            {
+                writeDir( header, file );
+            }
+            else if ( header.equals( "E" ) )
+            {
+                ack();
+                break;
+            }
+            else
+            {
+                throw new IOException( "Unexpected message: '" + header + "'" );
+            }
+        }
+
+    }
+
+    protected void writeFile( String header, SshFile path )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Writing file {}", path );
+        }
+        if ( !header.startsWith( "C" ) )
+        {
+            throw new IOException( "Expected a C message but got '" + header + "'" );
+        }
+
+        String perms = header.substring( 1, 5 );
+        long length = Long.parseLong( header.substring( 6, header.indexOf( ' ', 6 ) ) );
+        String name = header.substring( header.indexOf( ' ', 6 ) + 1 );
+
+        SshFile file;
+        if ( path.doesExist() && path.isDirectory() )
+        {
+            file = root.getFile( path, name );
+        }
+        else if ( path.doesExist() && path.isFile() )
+        {
+            file = path;
+        }
+        else if ( !path.doesExist() && path.getParentFile().doesExist() && path.getParentFile().isDirectory() )
+        {
+            file = path;
+        }
+        else
+        {
+            throw new IOException( "Can not write to " + path );
+        }
+        if ( file.doesExist() && file.isDirectory() )
+        {
+            throw new IOException( "File is a directory: " + file );
+        }
+        else if ( file.doesExist() && !file.isWritable() )
+        {
+            throw new IOException( "Can not write to file: " + file );
+        }
+        OutputStream os = file.createOutputStream( 0 );
+        try
+        {
+            ack();
+
+            byte[] buffer = new byte[8192];
+            while ( length > 0 )
+            {
+                int len = (int) Math.min( length, buffer.length );
+                len = in.read( buffer, 0, len );
+                if ( len <= 0 )
+                {
+                    throw new IOException( "End of stream reached" );
+                }
+                os.write( buffer, 0, len );
+                length -= len;
+            }
+        }
+        finally
+        {
+            os.close();
+        }
+
+        ack();
+        readAck( false );
+    }
+
+    protected String readLine()
+        throws IOException
+    {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        for (; ; )
+        {
+            int c = in.read();
+            if ( c == '\n' )
+            {
+                return baos.toString();
+            }
+            else if ( c == -1 )
+            {
+                throw new IOException( "End of stream" );
+            }
+            else
+            {
+                baos.write( c );
+            }
+        }
+    }
+
+    protected void readFile( SshFile path )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Reading file {}", path );
+        }
+        StringBuffer buf = new StringBuffer();
+        buf.append( "C" );
+        buf.append( "0644" ); // what about perms
+        buf.append( " " );
+        buf.append( path.getSize() ); // length
+        buf.append( " " );
+        buf.append( path.getName() );
+        buf.append( "\n" );
+        out.write( buf.toString().getBytes() );
+        out.flush();
+        readAck( false );
+
+        InputStream is = path.createInputStream( 0 );
+        try
+        {
+            byte[] buffer = new byte[8192];
+            for (; ; )
+            {
+                int len = is.read( buffer, 0, buffer.length );
+                if ( len == -1 )
+                {
+                    break;
+                }
+                out.write( buffer, 0, len );
+            }
+        }
+        finally
+        {
+            is.close();
+        }
+        ack();
+        readAck( false );
+    }
+
+    protected void readDir( SshFile path )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Reading directory {}", path );
+        }
+        StringBuffer buf = new StringBuffer();
+        buf.append( "D" );
+        buf.append( "0755" ); // what about perms
+        buf.append( " " );
+        buf.append( "0" ); // length
+        buf.append( " " );
+        buf.append( path.getName() );
+        buf.append( "\n" );
+        out.write( buf.toString().getBytes() );
+        out.flush();
+        readAck( false );
+
+        for ( SshFile child : path.listSshFiles() )
+        {
+            if ( child.isFile() )
+            {
+                readFile( child );
+            }
+            else if ( child.isDirectory() )
+            {
+                readDir( child );
+            }
+        }
+
+        out.write( "E\n".getBytes() );
+        out.flush();
+        readAck( false );
+    }
+
+    protected void ack()
+        throws IOException
+    {
+        out.write( 0 );
+        out.flush();
+    }
+
+    protected int readAck( boolean canEof )
+        throws IOException
+    {
+        int c = in.read();
+        switch ( c )
+        {
+            case -1:
+                if ( !canEof )
+                {
+                    throw new EOFException();
+                }
+                break;
+            case OK:
+                break;
+            case WARNING:
+                log.warn( "Received warning: " + readLine() );
+                break;
+            case ERROR:
+                throw new IOException( "Received nack: " + readLine() );
+            default:
+                break;
+        }
+        return c;
+    }
+
+    public void setFileSystemView( FileSystemView view )
+    {
+        this.root = view;
+    }
+}

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommandFactory.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommandFactory.java?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommandFactory.java (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpCommandFactory.java Wed Sep 21 13:39:47 2011
@@ -0,0 +1,94 @@
+package org.apache.maven.wagon.providers.ssh.jsch;
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.CommandFactory;
+
+/**
+ * This <code>CommandFactory</code> can be used as a standalone command factory
+ * or can be used to augment another <code>CommandFactory</code> and provides
+ * <code>SCP</code> support.
+ *
+ * @see ScpCommand
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ScpCommandFactory implements CommandFactory {
+
+    private CommandFactory delegate;
+
+    public ScpCommandFactory() {
+    }
+
+    public ScpCommandFactory(CommandFactory delegate) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * Parses a command string and verifies that the basic syntax is
+     * correct. If parsing fails the responsibility is delegated to
+     * the configured {@link CommandFactory} instance; if one exist.
+     *
+     * @param command command to parse 
+     * @return configured {@link Command} instance
+     * @throws IllegalArgumentException
+     */
+    public Command createCommand(String command) {
+        try {
+            return new ScpCommand(splitCommandString(command));
+        } catch (IllegalArgumentException iae) {
+            if (delegate != null) {
+                return delegate.createCommand(command);
+            }
+            throw iae;
+        }
+    }
+
+    private String[] splitCommandString(String command) {
+        if (!command.trim().startsWith("scp")) {
+            throw new IllegalArgumentException("Unknown command, does not begin with 'scp'");
+        }
+
+        String[] args = command.split(" ");
+        List<String> parts = new ArrayList<String>();
+        parts.add(args[0]);
+        for (int i = 1; i < args.length; i++) {
+            if (!args[i].trim().startsWith("-")) {
+                parts.add(concatenateWithSpace(args, i));
+                break;
+            } else {
+                parts.add(args[i]);
+            }
+        }
+        return parts.toArray(new String[parts.size()]);
+    }
+
+    private String concatenateWithSpace(String[] args, int from) {
+        StringBuilder sb = new StringBuilder();
+
+        for (int i = from; i < args.length; i++) {
+            sb.append(args[i] + " ");
+        }
+        return sb.toString().trim();
+    }
+}

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonTest.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonTest.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonTest.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonTest.java Wed Sep 21 13:39:47 2011
@@ -19,13 +19,48 @@ package org.apache.maven.wagon.providers
  * under the License.
  */
 
+import org.apache.commons.exec.DefaultExecutor;
+import org.apache.commons.exec.Executor;
+import org.apache.commons.exec.LogOutputStream;
+import org.apache.commons.exec.PumpStreamHandler;
 import org.apache.maven.wagon.StreamingWagonTestCase;
+import org.apache.maven.wagon.Wagon;
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 import org.apache.maven.wagon.providers.ssh.TestData;
+import org.apache.maven.wagon.providers.ssh.knownhost.KnownHostsProvider;
 import org.apache.maven.wagon.repository.Repository;
 import org.apache.maven.wagon.resource.Resource;
+import org.apache.mina.core.session.IoSession;
+import org.apache.sshd.SshServer;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.CommandFactory;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+import org.apache.sshd.server.FileSystemFactory;
+import org.apache.sshd.server.FileSystemView;
+import org.apache.sshd.server.PublickeyAuthenticator;
+import org.apache.sshd.server.SshFile;
+import org.apache.sshd.server.auth.UserAuthPassword;
+import org.apache.sshd.server.auth.UserAuthPublicKey;
+import org.apache.sshd.server.filesystem.NativeSshFile;
+import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.server.session.SessionFactory;
+import org.apache.sshd.server.shell.ProcessShellFactory;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.cli.CommandLineUtils;
+import org.codehaus.plexus.util.cli.Commandline;
 
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
@@ -34,19 +69,148 @@ import java.io.File;
 public class ScpWagonTest
     extends StreamingWagonTestCase
 {
+
+    final SshServer sshd = SshServer.setUpDefaultServer();
+
+    @Override
+    protected Wagon getWagon()
+        throws Exception
+    {
+        ScpWagon scpWagon = (ScpWagon) super.getWagon();
+        scpWagon.setInteractive( false );
+        scpWagon.setKnownHostsProvider( new KnownHostsProvider()
+        {
+            public void storeKnownHosts( String contents )
+                throws IOException
+            {
+
+            }
+
+            public void setHostKeyChecking( String hostKeyChecking )
+            {
+            }
+
+            public String getHostKeyChecking()
+            {
+                return "no";
+            }
+
+            public String getContents()
+            {
+                return null;
+            }
+        } );
+        return scpWagon;
+    }
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        sshd.setPort( 0 );
+
+        sshd.setUserAuthFactories( Arrays.asList( new UserAuthPublicKey.Factory(), new UserAuthPassword.Factory() ) );
+
+        sshd.setPublickeyAuthenticator( new PublickeyAuthenticator()
+        {
+            public boolean authenticate( String s, PublicKey publicKey, ServerSession serverSession )
+            {
+                return true;
+            }
+        } );
+
+        FileKeyPairProvider fileKeyPairProvider = new FileKeyPairProvider();
+        File sshKey = new File( System.getProperty( "sshKeysPath", "src/test/ssh-keys" ), "id_rsa" );
+        fileKeyPairProvider.setFiles( Arrays.asList( sshKey.getPath() ).toArray( new String[1] ) );
+
+        sshd.setKeyPairProvider( fileKeyPairProvider );
+        SessionFactory sessionFactory = new SessionFactory()
+        {
+            @Override
+            protected AbstractSession doCreateSession( IoSession ioSession )
+                throws Exception
+            {
+                System.out.println( "doCreateSession" );
+                return super.doCreateSession( ioSession );
+            }
+        };
+        sshd.setSessionFactory( sessionFactory );
+
+        //sshd.setFileSystemFactory(  );
+
+        final ProcessShellFactory processShellFactory =
+            new ProcessShellFactory( new String[]{ "/bin/sh", "-i", "-l" } );
+        sshd.setShellFactory( processShellFactory );
+
+        CommandFactory delegateCommandFactory = new CommandFactory()
+        {
+            public Command createCommand( String command )
+            {
+                return new ShellCommand( command );
+            }
+        };
+
+        ScpCommandFactory commandFactory = new ScpCommandFactory( delegateCommandFactory );
+        sshd.setCommandFactory( commandFactory );
+
+        FileSystemFactory fileSystemFactory = new FileSystemFactory()
+        {
+            public FileSystemView createFileSystemView( Session session )
+                throws IOException
+            {
+                return new FileSystemView()
+                {
+                    // Executing command: scp -t "/Users/olamy/dev/sources/maven/maven-wagon/wagon-providers/wagon-ssh/target/classes/wagon-ssh-test/olamy/test-resource"
+                    public SshFile getFile( String file )
+                    {
+                        file = file.replace( "\\", "" );
+                        file = file.replace( "\"", "" );
+                        File f = new File( FileUtils.normalize( file ) );
+
+                        return new TestSshFile( f.getAbsolutePath(), f, System.getProperty( "user.name" ) );
+                    }
+
+                    public SshFile getFile( SshFile baseDir, String file )
+                    {
+                        file = file.replace( "\\", "" );
+                        file = file.replace( "\"", "" );
+                        File f = new File( FileUtils.normalize( file ) );
+                        return new TestSshFile( f.getAbsolutePath(), f, System.getProperty( "user.name" ) );
+                    }
+                };
+            }
+        };
+        sshd.setNioWorkers( 0 );
+        //sshd.setScheduledExecutorService(  );
+        sshd.setFileSystemFactory( fileSystemFactory );
+        sshd.start();
+        System.out.println( "sshd on port " + sshd.getPort() );
+    }
+
+    @Override
+    protected void tearDownWagonTestingFixtures()
+        throws Exception
+    {
+        sshd.stop( true );
+    }
+
     protected String getProtocol()
     {
         return "scp";
     }
 
     @Override
-    protected int getTestRepositoryPort() {
-        return 0;  // not used
+    protected int getTestRepositoryPort()
+    {
+        return sshd.getPort();
     }
 
+
     public String getTestRepositoryUrl()
     {
-        return TestData.getTestRepositoryUrl();
+        return TestData.getTestRepositoryUrl( sshd.getPort() );
     }
 
     protected AuthenticationInfo getAuthInfo()
@@ -72,4 +236,148 @@ public class ScpWagonTest
         return new File( repository.getBasedir(), resource.getName() ).lastModified();
     }
 
+
+    protected static class ShellCommand
+        implements Command
+    {
+
+        protected static final int OK = 0;
+
+        protected static final int WARNING = 1;
+
+        protected static final int ERROR = 2;
+
+        private InputStream in;
+
+        private OutputStream out;
+
+        private OutputStream err;
+
+        private ExitCallback callback;
+
+        private Thread thread;
+
+        private String commandLine;
+
+        ShellCommand( String commandLine )
+        {
+            this.commandLine = commandLine;
+        }
+
+        public void setInputStream( InputStream in )
+        {
+            this.in = in;
+        }
+
+        public void setOutputStream( OutputStream out )
+        {
+            this.out = out;
+        }
+
+        public void setErrorStream( OutputStream err )
+        {
+            this.err = err;
+        }
+
+        public void setExitCallback( ExitCallback callback )
+        {
+            this.callback = callback;
+        }
+
+        public void start( Environment env )
+            throws IOException
+        {
+            int exitValue = 0;
+            SystemLogOutputStream systemOut = new SystemLogOutputStream( 1 );
+            SystemLogOutputStream errOut = new SystemLogOutputStream( 1 );
+            CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
+            CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
+            try
+            {
+
+                Executor exec = new DefaultExecutor();
+                exec.setStreamHandler( new PumpStreamHandler( systemOut, errOut ) );
+                // hackhish defaut commandline tools not support ; or && so write a file with the script
+                // and /bin/sh -xe file
+                File tmpFile = File.createTempFile( "wagon", "test-sh" );
+                FileUtils.fileWrite( tmpFile, commandLine );
+
+                String execScript = "/bin/sh -e " + tmpFile.getPath();
+
+                /*
+            CommandLine cl = CommandLine.parse( execScript );
+            exitValue = exec.execute( cl );*/
+                Commandline cl = new Commandline();
+
+                cl.setExecutable( "/bin/sh" );
+                cl.createArg().setValue( "-e" );
+                cl.createArg().setValue( tmpFile.getPath() );
+
+                exitValue = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
+
+                tmpFile.deleteOnExit();
+
+                out.write( stdout.getOutput().getBytes() );
+                out.write( '\n' );
+                out.flush();
+                this.callback.onExit( exitValue, stdout.getOutput() );
+
+            }
+            catch ( Exception e )
+            {
+                exitValue = ERROR;
+                e.printStackTrace();
+                err.write( stderr.getOutput().getBytes() );
+
+            }
+            finally
+            {
+                callback.onExit( exitValue, stderr.getOutput() );
+            }
+
+            out.write( exitValue );
+            out.write( '\n' );
+            out.flush();
+
+        }
+
+        public void destroy()
+        {
+
+        }
+    }
+
+    static class TestSshFile
+        extends NativeSshFile
+    {
+        public TestSshFile( String fileName, File file, String userName )
+        {
+
+            super( FileUtils.normalize( fileName ), file, userName );
+        }
+    }
+
+    static class SystemLogOutputStream
+        extends LogOutputStream
+    {
+
+        private List<String> lines = new ArrayList<String>();
+
+        private SystemLogOutputStream( int level )
+        {
+            super( level );
+        }
+
+        protected void processLine( String line, int level )
+        {
+            lines.add( line );
+        }
+    }
+
+    public void testWagonGetFileList()
+        throws Exception
+    {
+        super.testWagonGetFileList();
+    }
+
 }

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonWithSshPrivateKeySearchTest.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonWithSshPrivateKeySearchTest.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonWithSshPrivateKeySearchTest.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagonWithSshPrivateKeySearchTest.java Wed Sep 21 13:39:47 2011
@@ -49,7 +49,7 @@ public class ScpWagonWithSshPrivateKeySe
 
     public String getTestRepositoryUrl()
     {
-        return TestData.getTestRepositoryUrl();
+        return TestData.getTestRepositoryUrl(0);
     }
 
     protected AuthenticationInfo getAuthInfo()

Modified: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/SftpWagonTest.java
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/SftpWagonTest.java?rev=1173634&r1=1173633&r2=1173634&view=diff
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/SftpWagonTest.java (original)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/java/org/apache/maven/wagon/providers/ssh/jsch/SftpWagonTest.java Wed Sep 21 13:39:47 2011
@@ -46,7 +46,7 @@ public class SftpWagonTest
 
     public String getTestRepositoryUrl()
     {
-        return TestData.getTestRepositoryUrl();
+        return TestData.getTestRepositoryUrl(0);
     }
 
     protected AuthenticationInfo getAuthInfo()

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/resources/log4j.xml
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/resources/log4j.xml?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/resources/log4j.xml (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/resources/log4j.xml Wed Sep 21 13:39:47 2011
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+  <appender name="console" class="org.apache.log4j.ConsoleAppender">
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
+    </layout>
+  </appender>
+  <logger name="org.apache.sshd.server">
+    <level value="INFO"/>
+  </logger>
+
+
+
+  <root>
+    <priority value ="info" />
+    <appender-ref ref="console" />
+  </root>
+
+</log4j:configuration>

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa Wed Sep 21 13:39:47 2011
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAxfO9GTAb3OnzJ9o93sH9Z+4vQiVGBFSWmABf0RIa6K9XfDli
+ferhTbQUewLK3zqKvrsTEsyVEPzL0dXbOks007Gd+pLhAYBKaJ0iNGsPv+PsL2gL
+zpgSnwMrhRvAztJoQgArYIUhn/GlLC06uqnCj16hOx7kC/jeyM7u3t67PIsoy4NO
+MBfJGyJ1IgBHX5HbU68Z7dnH2kMNy2tkiFgDZGyDNVOICLXRp32Afp+0L0BAL0p3
+nUrHJn/2XJi2Uw6ooRCxnyisZIQ3QJd2OkHwuuu8SInvmaDWNE+7IP+1F7b7TiEp
+juz9+GsPrmaXYuah68d4ERAsI6SR1MAHITBjswIDAQABAoIBAQCLQiqBAshHRMqL
++cvW31A/gl/6v7AfMcbzzieaNIt7sIbyXIh+nvO7r3lNBKzmGBAtl/wWGJix57YX
+u8RLoUbburOx6Qyj+rXeHNVIXR0qWNT6kM7lmzRWa2t9bAXbOkigTfA2KdJ67AvQ
+JU2Qrgayx9bTearjBUTtri572eOM9fg8zqLdqUzFjVpfqaKI4kLgeRfrdVR4sP72
+5udKMDYN96dsibgPYiDCEWAoJmACJ5sR9NNI54Ns8Z0YUff/jugWeQqIdr1eCeyu
+ycP1GrCZflyJPWS/seLyCYkawuzasFHM/y7YArscRiALYU9TPoWLiyBtcuh+MhZ5
+IU3lzQtpAoGBAOvFDBhTqSZ0ODyg/e+JB/TgtHJqI8jHAAJnN0mHTYud2neBNvMt
+Uy0Yw6Ft8cv/DR1PAbpgDFkWia0X7J/LbH1Df9MLU62WVCelxb/b6Nvd3fk6dBaD
+FT23FtU1luuyoMdOhJ8xXfhxqFUzZ4tY42jn9vGd+bXsN2JyccUv2u0fAoGBANbv
+++9FGixYRJxpJ8b6/JhIK08hsMQrDrggRNb8Ip1SKykUvHgcY02CXBwfoR5ci2SF
+TP26XEXkiQ/ZioVn1xN0QigUSHSywEGpm9IgXezKLk4jKFrM7/AKxUQADbMJc7/o
+4pCC1GfOb+eqC+thq+NPoBAQ7v6gEQacR/G2o2LtAoGABNw4Bpxa5U8KBb3v3is9
+/b9QGPe1KyNnDaWhDyP55kHnygTg5BxwFYLoLYC9tk3YsFz7lSL7vi5nwii3GQgx
+gVeN4ATgwbhSncqeC/l1kGq/c67Py9MB8ha/IsALD2rMQ6+LrlhvLnrxVGhN3yKC
+9ZuqjIqMJkLrVV00mTMGWVMCgYBJjJFvTPwp1IKV6z3bTyOEkJ2RVHwChKFizFgC
+IQFPSEDQq/HaQAyTB1qxnPkrRIvGd/7ijBTrLcrhC5XlFKV6WLwSru4kUM6NKZbS
+jpTVZFH4FvvGJn6sa2MZY9NMQp3DO9Pbk4lPhEqywXOWtjN1c1fYZ5MAupFY672K
+ru61+QKBgBfFcTO/Xjed8kSls99iIj5aZvHle1wLonZNPxu8yOiFnwJQ2QnR4+ir
+4GSdEAYVdl9+M/6PwjtZdRy/tGof7TwSvv5wDn+NL3PYVEqJXqVoQ77NvNSAcAXN
+k/L/3GvGQHGik2hV1uOlAGEdf6CKwP6HqA6wzdad8PeQ+YWUE4t6
+-----END RSA PRIVATE KEY-----

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase Wed Sep 21 13:39:47 2011
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,6487A91073F20F136496E505B62C0E30
+
+JG2Cc7/8malkPUs4HLkMGHwFm3dIlGiYqbIVWbRPTYy7lIgXUj8BZOKyaqIFJQrz
+05GVhBkTgJToqBxCnxJA3Y50TEUWtrgYFp3gEA7UIiR6y5dPcVWndSVd974fj4o2
+Xbn+ObbFLwh8WuVlfBeuH3zgwXFVriJg3rgBEJyxp+0/6N+VrCLM3CCJ3L1Lcyyo
+SeJxplROrt3laTztB9rdI2oqB6FoIUharWHka7BUWJ603lJ3HgiJxtSOSV1gE5iq
+LpkE5dU3EDZifBIt4o/pLnisTeXw/jbrYUu0pEN1MLp9h3fdjZFanIj3U+/1XQPC
+SwJ87cHmvfBe+hxEKctAhjELspUULRT//RiwEpv786zqFU0GDyFzQQFPo8/y0Wof
+Q/Xabbt/fcrz5AYeYyqtBmg8Buw3VoJSZz6pV3nkqraYLKB4VPDi/Upo5ILGH0HB
+QwbUhVjVUT6scJ7A1CyEiUlBiTGJNb1tNgeHjflZzn5FY13duOE6Kqn4WHb4Gr3q
+HNcKyQ2NrORBUx5LvCbzQSwvDK6fDoEFUVb4QKee47bhxvsr0hnlfZXhK2mty56h
+ecJ8ofN5UmSokdSjtWcUqKwlPcuxshjcrDmcfvDd99C00ZSD0ZF2V1goMHcXqJMm
+Mjc0N6PVUsGrUY8YMFTB59a836GOPWE8jnzDXd/POLd7+A+uZI4yeNCzONxKhTsv
+bHdi/m2IqiVhZCVOW7sYksh+KvXyP/RaW4wRagbYAqV9cvDv0zmZEiwec5ci7Vuw
+crwO1ZAed47yanqZTb4UfjmF33+IhPncTcfbnNGYZN/zO7jXa6G2CzAizXhL1kNE
+5H9ceEizyMq84ryhngh5XyC0Y6IAbleRWMQOZK7k9Aoq600GA1yFshovopszjPLu
+7OZLT6rZ3Gaf2/rpz0cq82V9sLx+Cl5oZrhNxXPgB9ZaFyl9Nac8Nt9G/i+Us2QI
+j0Fu0q4NekPRSQwICR1oW+FWcMuEy4FdDktr8E/PF/RmFn/ZDS+a0YWB2Ro7lCHv
+ZvrS2NSQLCVWVqtk8o8bhTXXjSUTi1uTteC7wcY1EVtxdYhFwUmT25o6izbH4AdF
+8o/wguO+qYc0pwDnCenrFld3SsuOd2pjSzTQDXukwRsrbKES8p5VPomaXahmhVEy
+cuQbU0B4oqy7r5ObRXaW48EB9pPtM8GI1/Krba1w0cigTUL9FwlXiwkHT4UxuN+O
+o9A7XqBF6UMUUSlmBN8DKW5W7uqHQlmyU8lsydEUDC6kmo72CaGe39vUpuy1OJ3/
+HYXYxA3qotPH1Wf+KcqSnk/qiekgpSvksnG2i68mKpLD7bLd5GuoLiAnv/oYwJe+
+5VZz7iM119cnuJjYN2ThHE2hE1rzH7kSq1X49LPqFg25NivNMZ0BYpdPAxLsEfjO
+88bnA47HUM6f+tG3iF/9cyhIPhjs0s/Cf1FTm8aRvuWrrjxv0oyvFgeQY+PLAJtu
+hF5hgGj8bwGcKiXa7VBCnSJY060nOIm/H2vKFCBfENmtrnj2nLhIztp+/6FTURqR
+0ERyESkJjsQFV4Gv/z4mo42Ul7FYKusVx4i/oukaQGOXc5wDJIXoZrEFdDnhylSp
+-----END RSA PRIVATE KEY-----

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase.pub
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase.pub?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase.pub (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa-passphrase.pub Wed Sep 21 13:39:47 2011
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2/NhGN0RJX0Fep/rUxjyoxHM78AXz1nSHeA0dOa2MLAKe12nIrBozRakQj7IAqKmJNDs8DqwzZANmVzWaApjX/CTHYZpYU1TSTN60ZevnHxyvFCcTYAy9ANeFKZZ86iwHke3pPu59cd/KfI5wn/xWw9zXEN4Q5BpC59aTKKggFsx/7p40S4R5vvK0Aqds8R1Qos6m6nfEgZHEe+vS6oHUn8/ab6inB3eK5DXp8K7sPpYpQiXameF6iYeTmcnAIct6zepdqgxqN/rrzStxnrQpfstf0hC+vdPzB4QmrtryqX0fzbe3H0RPUhdK7DbMMrUh5iZr8GNKkymDFSj4yCdh olamy@MacBook-Pro-de-Olivier.local

Added: maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa.pub
URL: http://svn.apache.org/viewvc/maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa.pub?rev=1173634&view=auto
==============================================================================
--- maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa.pub (added)
+++ maven/wagon/trunk/wagon-providers/wagon-ssh/src/test/ssh-keys/id_rsa.pub Wed Sep 21 13:39:47 2011
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDF870ZMBvc6fMn2j3ewf1n7i9CJUYEVJaYAF/REhror1d8OWJ96uFNtBR7AsrfOoq+uxMSzJUQ/MvR1ds6SzTTsZ36kuEBgEponSI0aw+/4+wvaAvOmBKfAyuFG8DO0mhCACtghSGf8aUsLTq6qcKPXqE7HuQL+N7Izu7e3rs8iyjLg04wF8kbInUiAEdfkdtTrxnt2cfaQw3La2SIWANkbIM1U4gItdGnfYB+n7QvQEAvSnedSscmf/ZcmLZTDqihELGfKKxkhDdAl3Y6QfC667xIie+ZoNY0T7sg/7UXtvtOISmO7P34aw+uZpdi5qHrx3gRECwjpJHUwAchMGOz olamy@MacBook-Pro-de-Olivier.local