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 2014/12/28 00:35:39 UTC
maven-wagon git commit: [WAGON-429] add the missing
WagonScp.getTransfer() to support > 2G file
Repository: maven-wagon
Updated Branches:
refs/heads/master bcaf7300d -> dd623e806
[WAGON-429] add the missing WagonScp.getTransfer() to support > 2G file
Project: http://git-wip-us.apache.org/repos/asf/maven-wagon/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-wagon/commit/dd623e80
Tree: http://git-wip-us.apache.org/repos/asf/maven-wagon/tree/dd623e80
Diff: http://git-wip-us.apache.org/repos/asf/maven-wagon/diff/dd623e80
Branch: refs/heads/master
Commit: dd623e8069221940439c8d4dbc867be91c75885d
Parents: bcaf730
Author: dantran <da...@gmail.com>
Authored: Sat Dec 27 15:35:38 2014 -0800
Committer: dantran <da...@gmail.com>
Committed: Sat Dec 27 15:35:38 2014 -0800
----------------------------------------------------------------------
.../wagon/providers/ssh/jsch/ScpWagon.java | 894 ++++++++++---------
1 file changed, 451 insertions(+), 443 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-wagon/blob/dd623e80/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 9ce7561..c5290b2 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,443 +1,451 @@
-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();
- }
- }
-
- 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
- {
- 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;
+ }
+}
Re: maven-wagon git commit: [WAGON-429] add the missing
WagonScp.getTransfer() to support > 2G file
Posted by Dan Tran <da...@gmail.com>.
I checked out maven-wagon under windows and commit via my Eclipse Luna,
however it seems like I screw up the line ending. It is committed as
windows mode at git
However do I go about fix this issue?
Thanks
-D
On Sat, Dec 27, 2014 at 3:35 PM, <da...@apache.org> wrote:
> Repository: maven-wagon
> Updated Branches:
> refs/heads/master bcaf7300d -> dd623e806
>
>
> [WAGON-429] add the missing WagonScp.getTransfer() to support > 2G file
>
>
> Project: http://git-wip-us.apache.org/repos/asf/maven-wagon/repo
> Commit: http://git-wip-us.apache.org/repos/asf/maven-wagon/commit/dd623e80
> Tree: http://git-wip-us.apache.org/repos/asf/maven-wagon/tree/dd623e80
> Diff: http://git-wip-us.apache.org/repos/asf/maven-wagon/diff/dd623e80
>
> Branch: refs/heads/master
> Commit: dd623e8069221940439c8d4dbc867be91c75885d
> Parents: bcaf730
> Author: dantran <da...@gmail.com>
> Authored: Sat Dec 27 15:35:38 2014 -0800
> Committer: dantran <da...@gmail.com>
> Committed: Sat Dec 27 15:35:38 2014 -0800
>
> ----------------------------------------------------------------------
> .../wagon/providers/ssh/jsch/ScpWagon.java | 894 ++++++++++---------
> 1 file changed, 451 insertions(+), 443 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/maven-wagon/blob/dd623e80/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 9ce7561..c5290b2 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,443 +1,451 @@
> -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();
> - }
> - }
> -
> - 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
> - {
> - 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;
> + }
> +}
>
>