You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by da...@apache.org on 2015/09/04 05:46:06 UTC

maven-wagon git commit: line ending correction

Repository: maven-wagon
Updated Branches:
  refs/heads/master 302ae79cb -> 199e3de37


line ending correction


Project: http://git-wip-us.apache.org/repos/asf/maven-wagon/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-wagon/commit/199e3de3
Tree: http://git-wip-us.apache.org/repos/asf/maven-wagon/tree/199e3de3
Diff: http://git-wip-us.apache.org/repos/asf/maven-wagon/diff/199e3de3

Branch: refs/heads/master
Commit: 199e3de3725216ceeff5d119eedc26966bc957b7
Parents: 302ae79
Author: Dan Tran <da...@gmail.com>
Authored: Thu Sep 3 20:46:04 2015 -0700
Committer: Dan Tran <da...@gmail.com>
Committed: Thu Sep 3 20:46:04 2015 -0700

----------------------------------------------------------------------
 .../wagon/providers/ssh/jsch/ScpWagon.java      | 904 +++++++++----------
 1 file changed, 452 insertions(+), 452 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-wagon/blob/199e3de3/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java
----------------------------------------------------------------------
diff --git a/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java b/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java
index 1ee2fc0..be69880 100644
--- a/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java
+++ b/wagon-providers/wagon-ssh/src/main/java/org/apache/maven/wagon/providers/ssh/jsch/ScpWagon.java
@@ -1,452 +1,452 @@
-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 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;
-import org.apache.maven.wagon.ResourceDoesNotExistException;
-import org.apache.maven.wagon.TransferFailedException;
-import org.apache.maven.wagon.events.TransferEvent;
-import org.apache.maven.wagon.providers.ssh.ScpHelper;
-import org.apache.maven.wagon.repository.RepositoryPermissions;
-import org.apache.maven.wagon.resource.Resource;
-
-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.
- *
- *
- * @todo [BP] add compression flag
- * @plexus.component role="org.apache.maven.wagon.Wagon"
- * role-hint="scp"
- * instantiation-strategy="per-lookup"
- */
-public class ScpWagon
-    extends AbstractJschWagon
-{
-    private static final char COPY_START_CHAR = 'C';
-
-    private static final char ACK_SEPARATOR = ' ';
-
-    private static final String END_OF_FILES_MSG = "E\n";
-
-    private static final int LINE_BUFFER_SIZE = 8192;
-
-    private static final byte LF = '\n';
-
-    private ChannelExec channel;
-
-    private InputStream channelInputStream;
-
-    private OutputStream channelOutputStream;
-
-    private void setFileGroup( RepositoryPermissions permissions, String basedir, Resource resource )
-        throws CommandExecutionException
-    {
-        if ( permissions != null && permissions.getGroup() != null )
-        {
-            //executeCommand( "chgrp -f " + permissions.getGroup() + " " + getPath( basedir, resource.getName() ) );
-            executeCommand( "chgrp -f " + permissions.getGroup() + " \"" + getPath( basedir, resource.getName() )
-                + "\"" );
-        }
-    }
-
-    protected void cleanupPutTransfer( Resource resource )
-    {
-        if ( channel != null )
-        {
-            channel.disconnect();
-            channel = null;
-        }
-    }
-
-    protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
-        throws TransferFailedException
-    {
-        try
-        {
-            sendEom( output );
-
-            checkAck( channelInputStream );
-
-            // This came from SCPClient in Ganymede SSH2. It is sent after all files.
-            output.write( END_OF_FILES_MSG.getBytes() );
-            output.flush();
-        }
-        catch ( IOException e )
-        {
-            handleIOException( resource, e );
-        }
-
-        String basedir = getRepository().getBasedir();
-        try
-        {
-            setFileGroup( getRepository().getPermissions(), basedir, resource );
-        }
-        catch ( CommandExecutionException e )
-        {
-            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
-
-            throw new TransferFailedException( e.getMessage(), e );
-        }
-    }
-
-    private void checkAck( InputStream in )
-        throws IOException
-    {
-        int code = in.read();
-        if ( code == -1 )
-        {
-            throw new IOException( "Unexpected end of data" );
-        }
-        else if ( code == 1 )
-        {
-            String line = readLine( in );
-
-            throw new IOException( "SCP terminated with error: '" + line + "'" );
-        }
-        else if ( code == 2 )
-        {
-            throw new IOException( "SCP terminated with error (code: " + code + ")" );
-        }
-        else if ( code != 0 )
-        {
-            throw new IOException( "SCP terminated with unknown error code" );
-        }
-    }
-
-    protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
-        throws TransferFailedException
-    {
-        try
-        {
-            checkAck( input );
-
-            sendEom( channelOutputStream );
-        }
-        catch ( IOException e )
-        {
-            handleGetException( resource, e );
-        }
-    }
-
-    protected void cleanupGetTransfer( Resource resource )
-    {
-        if ( channel != null )
-        {
-            channel.disconnect();
-        }
-    }
-
-    @Deprecated
-    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 void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
-                                long maxSize )
-        throws TransferFailedException
-    {
-        super.getTransfer( resource, output, input, closeInput, resource.getContentLength() );
-    }
-
-    protected String readLine( InputStream in )
-        throws IOException
-    {
-        StringBuilder sb = new StringBuilder();
-
-        while ( true )
-        {
-            if ( sb.length() > LINE_BUFFER_SIZE )
-            {
-                throw new IOException( "Remote server sent a too long line" );
-            }
-
-            int c = in.read();
-
-            if ( c < 0 )
-            {
-                throw new IOException( "Remote connection terminated unexpectedly." );
-            }
-
-            if ( c == LF )
-            {
-                break;
-            }
-
-            sb.append( (char) c );
-        }
-        return sb.toString();
-    }
-
-    protected static void sendEom( OutputStream out )
-        throws IOException
-    {
-        out.write( 0 );
-
-        out.flush();
-    }
-
-    public void fillInputData( InputData inputData )
-        throws TransferFailedException, ResourceDoesNotExistException
-    {
-        Resource resource = inputData.getResource();
-
-        String path = getPath( getRepository().getBasedir(), resource.getName() );
-        //String cmd = "scp -p -f " + path;
-        String cmd = "scp -p -f \"" + path + "\"";
-
-        fireTransferDebug( "Executing command: " + cmd );
-
-        try
-        {
-            channel = (ChannelExec) session.openChannel( EXEC_CHANNEL );
-
-            channel.setCommand( cmd );
-
-            // get I/O streams for remote scp
-            channelOutputStream = channel.getOutputStream();
-
-            InputStream in = channel.getInputStream();
-            inputData.setInputStream( in );
-
-            channel.connect();
-
-            sendEom( channelOutputStream );
-
-            int exitCode = in.read();
-
-            if ( exitCode == 'T' )
-            {
-                String line = readLine( in );
-
-                String[] times = line.split( " " );
-
-                resource.setLastModified( Long.valueOf( times[0] ).longValue() * 1000 );
-
-                sendEom( channelOutputStream );
-
-                exitCode = in.read();
-            }
-
-            String line = readLine( in );
-
-            if ( exitCode != COPY_START_CHAR )
-            {
-                if ( exitCode == 1 && ( line.contains( "No such file or directory" )
-                    || line.indexOf( "no such file or directory" ) != 1 ) )
-                {
-                    throw new ResourceDoesNotExistException( line );
-                }
-                else
-                {
-                    throw new IOException( "Exit code: " + exitCode + " - " + line );
-                }
-            }
-
-            if ( line == null )
-            {
-                throw new EOFException( "Unexpected end of data" );
-            }
-
-            String perms = line.substring( 0, 4 );
-            fireTransferDebug( "Remote file permissions: " + perms );
-
-            if ( line.charAt( 4 ) != ACK_SEPARATOR && line.charAt( 5 ) != ACK_SEPARATOR )
-            {
-                throw new IOException( "Invalid transfer header: " + line );
-            }
-
-            int index = line.indexOf( ACK_SEPARATOR, 5 );
-            if ( index < 0 )
-            {
-                throw new IOException( "Invalid transfer header: " + line );
-            }
-
-            int filesize = Integer.valueOf( line.substring( 5, index ) ).intValue();
-            fireTransferDebug( "Remote file size: " + filesize );
-
-            resource.setContentLength( filesize );
-
-            String filename = line.substring( index + 1 );
-            fireTransferDebug( "Remote filename: " + filename );
-
-            sendEom( channelOutputStream );
-        }
-        catch ( JSchException e )
-        {
-            handleGetException( resource, e );
-        }
-        catch ( IOException e )
-        {
-            handleGetException( resource, e );
-        }
-    }
-
-    public void fillOutputData( OutputData outputData )
-        throws TransferFailedException
-    {
-        Resource resource = outputData.getResource();
-
-        String basedir = getRepository().getBasedir();
-
-        String path = getPath( basedir, resource.getName() );
-
-        String dir = ScpHelper.getResourceDirectory( resource.getName() );
-
-        try
-        {
-            sshTool.createRemoteDirectories( getPath( basedir, dir ), getRepository().getPermissions() );
-        }
-        catch ( CommandExecutionException e )
-        {
-            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
-
-            throw new TransferFailedException( e.getMessage(), e );
-        }
-
-        String octalMode = getOctalMode( getRepository().getPermissions() );
-
-        // exec 'scp -p -t rfile' remotely
-        String command = "scp";
-        if ( octalMode != null )
-        {
-            command += " -p";
-        }
-        command += " -t \"" + path + "\"";
-
-        fireTransferDebug( "Executing command: " + command );
-
-        String resourceName = resource.getName();
-
-        OutputStream out = null;
-        try
-        {
-            channel = (ChannelExec) session.openChannel( EXEC_CHANNEL );
-
-            channel.setCommand( command );
-
-            // get I/O streams for remote scp
-            out = channel.getOutputStream();
-            outputData.setOutputStream( out );
-
-            channelInputStream = channel.getInputStream();
-
-            channel.connect();
-
-            checkAck( channelInputStream );
-
-            // send "C0644 filesize filename", where filename should not include '/'
-            long filesize = resource.getContentLength();
-
-            String mode = octalMode == null ? "0644" : octalMode;
-            command = "C" + mode + " " + filesize + " ";
-
-            if ( resourceName.lastIndexOf( ScpHelper.PATH_SEPARATOR ) > 0 )
-            {
-                command += resourceName.substring( resourceName.lastIndexOf( ScpHelper.PATH_SEPARATOR ) + 1 );
-            }
-            else
-            {
-                command += resourceName;
-            }
-
-            command += "\n";
-
-            out.write( command.getBytes() );
-
-            out.flush();
-
-            checkAck( channelInputStream );
-        }
-        catch ( JSchException e )
-        {
-            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
-
-            String msg = "Error occurred while deploying '" + resourceName + "' to remote repository: "
-                + getRepository().getUrl() + ": " + e.getMessage();
-
-            throw new TransferFailedException( msg, e );
-        }
-        catch ( IOException e )
-        {
-            handleIOException( resource, e );
-        }
-    }
-
-    private void handleIOException( Resource resource, IOException e )
-        throws TransferFailedException
-    {
-        if ( e.getMessage().contains( "set mode: Operation not permitted" ) )
-        {
-            fireTransferDebug( e.getMessage() );
-        }
-        else
-        {
-            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 );
-        }
-    }
-
-    public String getOctalMode( RepositoryPermissions permissions )
-    {
-        String mode = null;
-        if ( permissions != null && permissions.getFileMode() != null )
-        {
-            if ( permissions.getFileMode().matches( "[0-9]{3,4}" ) )
-            {
-                mode = permissions.getFileMode();
-
-                if ( mode.length() == 3 )
-                {
-                    mode = "0" + mode;
-                }
-            }
-            else
-            {
-                // TODO: calculate?
-                // TODO: as warning
-                fireSessionDebug( "Not using non-octal permissions: " + permissions.getFileMode() );
-            }
-        }
-        return mode;
-    }
-}
+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 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;
+import org.apache.maven.wagon.ResourceDoesNotExistException;
+import org.apache.maven.wagon.TransferFailedException;
+import org.apache.maven.wagon.events.TransferEvent;
+import org.apache.maven.wagon.providers.ssh.ScpHelper;
+import org.apache.maven.wagon.repository.RepositoryPermissions;
+import org.apache.maven.wagon.resource.Resource;
+
+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.
+ *
+ *
+ * @todo [BP] add compression flag
+ * @plexus.component role="org.apache.maven.wagon.Wagon"
+ * role-hint="scp"
+ * instantiation-strategy="per-lookup"
+ */
+public class ScpWagon
+    extends AbstractJschWagon
+{
+    private static final char COPY_START_CHAR = 'C';
+
+    private static final char ACK_SEPARATOR = ' ';
+
+    private static final String END_OF_FILES_MSG = "E\n";
+
+    private static final int LINE_BUFFER_SIZE = 8192;
+
+    private static final byte LF = '\n';
+
+    private ChannelExec channel;
+
+    private InputStream channelInputStream;
+
+    private OutputStream channelOutputStream;
+
+    private void setFileGroup( RepositoryPermissions permissions, String basedir, Resource resource )
+        throws CommandExecutionException
+    {
+        if ( permissions != null && permissions.getGroup() != null )
+        {
+            //executeCommand( "chgrp -f " + permissions.getGroup() + " " + getPath( basedir, resource.getName() ) );
+            executeCommand( "chgrp -f " + permissions.getGroup() + " \"" + getPath( basedir, resource.getName() )
+                + "\"" );
+        }
+    }
+
+    protected void cleanupPutTransfer( Resource resource )
+    {
+        if ( channel != null )
+        {
+            channel.disconnect();
+            channel = null;
+        }
+    }
+
+    protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
+        throws TransferFailedException
+    {
+        try
+        {
+            sendEom( output );
+
+            checkAck( channelInputStream );
+
+            // This came from SCPClient in Ganymede SSH2. It is sent after all files.
+            output.write( END_OF_FILES_MSG.getBytes() );
+            output.flush();
+        }
+        catch ( IOException e )
+        {
+            handleIOException( resource, e );
+        }
+
+        String basedir = getRepository().getBasedir();
+        try
+        {
+            setFileGroup( getRepository().getPermissions(), basedir, resource );
+        }
+        catch ( CommandExecutionException e )
+        {
+            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
+
+            throw new TransferFailedException( e.getMessage(), e );
+        }
+    }
+
+    private void checkAck( InputStream in )
+        throws IOException
+    {
+        int code = in.read();
+        if ( code == -1 )
+        {
+            throw new IOException( "Unexpected end of data" );
+        }
+        else if ( code == 1 )
+        {
+            String line = readLine( in );
+
+            throw new IOException( "SCP terminated with error: '" + line + "'" );
+        }
+        else if ( code == 2 )
+        {
+            throw new IOException( "SCP terminated with error (code: " + code + ")" );
+        }
+        else if ( code != 0 )
+        {
+            throw new IOException( "SCP terminated with unknown error code" );
+        }
+    }
+
+    protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
+        throws TransferFailedException
+    {
+        try
+        {
+            checkAck( input );
+
+            sendEom( channelOutputStream );
+        }
+        catch ( IOException e )
+        {
+            handleGetException( resource, e );
+        }
+    }
+
+    protected void cleanupGetTransfer( Resource resource )
+    {
+        if ( channel != null )
+        {
+            channel.disconnect();
+        }
+    }
+
+    @Deprecated
+    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 void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
+                                long maxSize )
+        throws TransferFailedException
+    {
+        super.getTransfer( resource, output, input, closeInput, resource.getContentLength() );
+    }
+
+    protected String readLine( InputStream in )
+        throws IOException
+    {
+        StringBuilder sb = new StringBuilder();
+
+        while ( true )
+        {
+            if ( sb.length() > LINE_BUFFER_SIZE )
+            {
+                throw new IOException( "Remote server sent a too long line" );
+            }
+
+            int c = in.read();
+
+            if ( c < 0 )
+            {
+                throw new IOException( "Remote connection terminated unexpectedly." );
+            }
+
+            if ( c == LF )
+            {
+                break;
+            }
+
+            sb.append( (char) c );
+        }
+        return sb.toString();
+    }
+
+    protected static void sendEom( OutputStream out )
+        throws IOException
+    {
+        out.write( 0 );
+
+        out.flush();
+    }
+
+    public void fillInputData( InputData inputData )
+        throws TransferFailedException, ResourceDoesNotExistException
+    {
+        Resource resource = inputData.getResource();
+
+        String path = getPath( getRepository().getBasedir(), resource.getName() );
+        //String cmd = "scp -p -f " + path;
+        String cmd = "scp -p -f \"" + path + "\"";
+
+        fireTransferDebug( "Executing command: " + cmd );
+
+        try
+        {
+            channel = (ChannelExec) session.openChannel( EXEC_CHANNEL );
+
+            channel.setCommand( cmd );
+
+            // get I/O streams for remote scp
+            channelOutputStream = channel.getOutputStream();
+
+            InputStream in = channel.getInputStream();
+            inputData.setInputStream( in );
+
+            channel.connect();
+
+            sendEom( channelOutputStream );
+
+            int exitCode = in.read();
+
+            if ( exitCode == 'T' )
+            {
+                String line = readLine( in );
+
+                String[] times = line.split( " " );
+
+                resource.setLastModified( Long.valueOf( times[0] ).longValue() * 1000 );
+
+                sendEom( channelOutputStream );
+
+                exitCode = in.read();
+            }
+
+            String line = readLine( in );
+
+            if ( exitCode != COPY_START_CHAR )
+            {
+                if ( exitCode == 1 && ( line.contains( "No such file or directory" )
+                    || line.indexOf( "no such file or directory" ) != 1 ) )
+                {
+                    throw new ResourceDoesNotExistException( line );
+                }
+                else
+                {
+                    throw new IOException( "Exit code: " + exitCode + " - " + line );
+                }
+            }
+
+            if ( line == null )
+            {
+                throw new EOFException( "Unexpected end of data" );
+            }
+
+            String perms = line.substring( 0, 4 );
+            fireTransferDebug( "Remote file permissions: " + perms );
+
+            if ( line.charAt( 4 ) != ACK_SEPARATOR && line.charAt( 5 ) != ACK_SEPARATOR )
+            {
+                throw new IOException( "Invalid transfer header: " + line );
+            }
+
+            int index = line.indexOf( ACK_SEPARATOR, 5 );
+            if ( index < 0 )
+            {
+                throw new IOException( "Invalid transfer header: " + line );
+            }
+
+            int filesize = Integer.valueOf( line.substring( 5, index ) ).intValue();
+            fireTransferDebug( "Remote file size: " + filesize );
+
+            resource.setContentLength( filesize );
+
+            String filename = line.substring( index + 1 );
+            fireTransferDebug( "Remote filename: " + filename );
+
+            sendEom( channelOutputStream );
+        }
+        catch ( JSchException e )
+        {
+            handleGetException( resource, e );
+        }
+        catch ( IOException e )
+        {
+            handleGetException( resource, e );
+        }
+    }
+
+    public void fillOutputData( OutputData outputData )
+        throws TransferFailedException
+    {
+        Resource resource = outputData.getResource();
+
+        String basedir = getRepository().getBasedir();
+
+        String path = getPath( basedir, resource.getName() );
+
+        String dir = ScpHelper.getResourceDirectory( resource.getName() );
+
+        try
+        {
+            sshTool.createRemoteDirectories( getPath( basedir, dir ), getRepository().getPermissions() );
+        }
+        catch ( CommandExecutionException e )
+        {
+            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
+
+            throw new TransferFailedException( e.getMessage(), e );
+        }
+
+        String octalMode = getOctalMode( getRepository().getPermissions() );
+
+        // exec 'scp -p -t rfile' remotely
+        String command = "scp";
+        if ( octalMode != null )
+        {
+            command += " -p";
+        }
+        command += " -t \"" + path + "\"";
+
+        fireTransferDebug( "Executing command: " + command );
+
+        String resourceName = resource.getName();
+
+        OutputStream out = null;
+        try
+        {
+            channel = (ChannelExec) session.openChannel( EXEC_CHANNEL );
+
+            channel.setCommand( command );
+
+            // get I/O streams for remote scp
+            out = channel.getOutputStream();
+            outputData.setOutputStream( out );
+
+            channelInputStream = channel.getInputStream();
+
+            channel.connect();
+
+            checkAck( channelInputStream );
+
+            // send "C0644 filesize filename", where filename should not include '/'
+            long filesize = resource.getContentLength();
+
+            String mode = octalMode == null ? "0644" : octalMode;
+            command = "C" + mode + " " + filesize + " ";
+
+            if ( resourceName.lastIndexOf( ScpHelper.PATH_SEPARATOR ) > 0 )
+            {
+                command += resourceName.substring( resourceName.lastIndexOf( ScpHelper.PATH_SEPARATOR ) + 1 );
+            }
+            else
+            {
+                command += resourceName;
+            }
+
+            command += "\n";
+
+            out.write( command.getBytes() );
+
+            out.flush();
+
+            checkAck( channelInputStream );
+        }
+        catch ( JSchException e )
+        {
+            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
+
+            String msg = "Error occurred while deploying '" + resourceName + "' to remote repository: "
+                + getRepository().getUrl() + ": " + e.getMessage();
+
+            throw new TransferFailedException( msg, e );
+        }
+        catch ( IOException e )
+        {
+            handleIOException( resource, e );
+        }
+    }
+
+    private void handleIOException( Resource resource, IOException e )
+        throws TransferFailedException
+    {
+        if ( e.getMessage().contains( "set mode: Operation not permitted" ) )
+        {
+            fireTransferDebug( e.getMessage() );
+        }
+        else
+        {
+            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 );
+        }
+    }
+
+    public String getOctalMode( RepositoryPermissions permissions )
+    {
+        String mode = null;
+        if ( permissions != null && permissions.getFileMode() != null )
+        {
+            if ( permissions.getFileMode().matches( "[0-9]{3,4}" ) )
+            {
+                mode = permissions.getFileMode();
+
+                if ( mode.length() == 3 )
+                {
+                    mode = "0" + mode;
+                }
+            }
+            else
+            {
+                // TODO: calculate?
+                // TODO: as warning
+                fireSessionDebug( "Not using non-octal permissions: " + permissions.getFileMode() );
+            }
+        }
+        return mode;
+    }
+}