| /* |
| * 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 |
| * |
| * https://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. |
| * |
| */ |
| |
| package org.apache.tools.ant.taskdefs.optional.ssh; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.List; |
| import org.apache.tools.ant.util.FileUtils; |
| |
| import com.jcraft.jsch.ChannelSftp; |
| import com.jcraft.jsch.JSchException; |
| import com.jcraft.jsch.Session; |
| import com.jcraft.jsch.SftpATTRS; |
| import com.jcraft.jsch.SftpException; |
| import com.jcraft.jsch.SftpProgressMonitor; |
| |
| /** |
| * A helper object representing an scp download. |
| */ |
| public class ScpFromMessageBySftp extends ScpFromMessage { |
| |
| private static final int HUNDRED_KILOBYTES = 102400; |
| |
| private String remoteFile; |
| private final File localFile; |
| @SuppressWarnings("unused") |
| private boolean isRecursive = false; |
| @SuppressWarnings("unused") |
| private boolean verbose = false; |
| |
| /** |
| * Constructor for ScpFromMessageBySftp. |
| * @param verbose if true log extra information |
| * @param session the Scp session to use |
| * @param aRemoteFile the remote file name |
| * @param aLocalFile the local file |
| * @param recursive if true use recursion |
| * @since Ant 1.7 |
| */ |
| public ScpFromMessageBySftp(final boolean verbose, |
| final Session session, |
| final String aRemoteFile, |
| final File aLocalFile, |
| final boolean recursive) { |
| this(verbose, session, aRemoteFile, aLocalFile, recursive, false); |
| } |
| |
| /** |
| * Constructor for ScpFromMessageBySftp. |
| * @param session the Scp session to use |
| * @param aRemoteFile the remote file name |
| * @param aLocalFile the local file |
| * @param recursive if true use recursion |
| */ |
| public ScpFromMessageBySftp(final Session session, |
| final String aRemoteFile, |
| final File aLocalFile, |
| final boolean recursive) { |
| this(false, session, aRemoteFile, aLocalFile, recursive); |
| } |
| |
| /** |
| * Constructor for ScpFromMessageBySftp. |
| * @param verbose if true log extra information |
| * @param session the Scp session to use |
| * @param aRemoteFile the remote file name |
| * @param aLocalFile the local file |
| * @param recursive if true use recursion |
| * @param preserveLastModified whether to preserve file |
| * modification times |
| * @since Ant 1.8.0 |
| */ |
| public ScpFromMessageBySftp(final boolean verbose, |
| final Session session, |
| final String aRemoteFile, |
| final File aLocalFile, |
| final boolean recursive, |
| final boolean preserveLastModified) { |
| super(verbose, session, aRemoteFile, aLocalFile, recursive, |
| preserveLastModified); |
| this.verbose = verbose; |
| this.remoteFile = aRemoteFile; |
| this.localFile = aLocalFile; |
| this.isRecursive = recursive; |
| } |
| |
| /** |
| * Carry out the transfer. |
| * @throws IOException on i/o errors |
| * @throws JSchException on errors detected by scp |
| */ |
| @Override |
| public void execute() throws IOException, JSchException { |
| final ChannelSftp channel = openSftpChannel(); |
| try { |
| channel.connect(); |
| try { |
| final SftpATTRS attrs = channel.stat(remoteFile); |
| if (attrs.isDir() && !remoteFile.endsWith("/")) { |
| remoteFile += "/"; |
| } |
| } catch (final SftpException ee) { |
| // Ignored |
| } |
| getDir(channel, remoteFile, localFile); |
| } catch (final SftpException e) { |
| throw new JSchException("Could not get '" + remoteFile + "' to '" |
| + localFile + "' - " + e.toString(), e); |
| } finally { |
| if (channel != null) { |
| channel.disconnect(); |
| } |
| } |
| log("done\n"); |
| } |
| |
| private void getDir(final ChannelSftp channel, |
| final String remoteFile, |
| final File localFile) throws SftpException { |
| String pwd = remoteFile; |
| if (remoteFile.lastIndexOf('/') != -1) { |
| if (remoteFile.length() > 1) { |
| pwd = remoteFile.substring(0, remoteFile.lastIndexOf('/')); |
| } |
| } |
| channel.cd(pwd); |
| if (!localFile.exists()) { |
| localFile.mkdirs(); |
| } |
| @SuppressWarnings("unchecked") |
| final List<ChannelSftp.LsEntry> files = channel.ls(remoteFile); |
| for (ChannelSftp.LsEntry le : files) { |
| final String name = le.getFilename(); |
| if (le.getAttrs().isDir()) { |
| if (".".equals(name) || "..".equals(name)) { |
| continue; |
| } |
| getDir(channel, |
| channel.pwd() + "/" + name + "/", |
| new File(localFile, le.getFilename())); |
| } else { |
| getFile(channel, le, localFile); |
| } |
| } |
| channel.cd(".."); |
| } |
| |
| private void getFile(final ChannelSftp channel, |
| final ChannelSftp.LsEntry le, |
| File localFile) throws SftpException { |
| final String remoteFile = le.getFilename(); |
| if (!localFile.exists()) { |
| final String path = localFile.getAbsolutePath(); |
| final int i = path.lastIndexOf(File.pathSeparator); |
| if (i != -1) { |
| if (path.length() > File.pathSeparator.length()) { |
| new File(path.substring(0, i)).mkdirs(); |
| } |
| } |
| } |
| |
| if (localFile.isDirectory()) { |
| localFile = new File(localFile, remoteFile); |
| } |
| |
| final long startTime = System.currentTimeMillis(); |
| final long totalLength = le.getAttrs().getSize(); |
| |
| SftpProgressMonitor monitor = null; |
| final boolean trackProgress = getVerbose() && totalLength > HUNDRED_KILOBYTES; |
| if (trackProgress) { |
| monitor = getProgressMonitor(); |
| } |
| try { |
| log("Receiving: " + remoteFile + " : " + le.getAttrs().getSize()); |
| channel.get(remoteFile, localFile.getAbsolutePath(), monitor); |
| } finally { |
| final long endTime = System.currentTimeMillis(); |
| logStats(startTime, endTime, (int) totalLength); |
| } |
| if (getPreserveLastModified()) { |
| FileUtils.getFileUtils().setFileLastModified(localFile, |
| ((long) le.getAttrs().getMTime()) * 1000); |
| } |
| } |
| } |