001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.optional.ssh;
020:
021: import com.jcraft.jsch.Session;
022: import com.jcraft.jsch.ChannelSftp;
023: import com.jcraft.jsch.JSchException;
024: import com.jcraft.jsch.SftpException;
025: import com.jcraft.jsch.SftpProgressMonitor;
026:
027: import java.io.File;
028: import java.io.IOException;
029: import java.util.List;
030: import java.util.Iterator;
031:
032: /**
033: * Utility class to carry out an upload by sftp.
034: */
035: public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/{
036:
037: private File localFile;
038: private String remotePath;
039: private List directoryList;
040:
041: /**
042: * Constructor for a local file to remote.
043: * @param verbose if true do verbose logging
044: * @param session the scp session to use
045: * @param aLocalFile the local file
046: * @param aRemotePath the remote path
047: * @since Ant 1.7
048: */
049: public ScpToMessageBySftp(boolean verbose, Session session,
050: File aLocalFile, String aRemotePath) {
051: this (verbose, session, aRemotePath);
052:
053: this .localFile = aLocalFile;
054: }
055:
056: /**
057: * Constructor for a local directories to remote.
058: * @param verbose if true do verbose logging
059: * @param session the scp session to use
060: * @param aDirectoryList a list of directories
061: * @param aRemotePath the remote path
062: * @since Ant 1.7
063: */
064: public ScpToMessageBySftp(boolean verbose, Session session,
065: List aDirectoryList, String aRemotePath) {
066: this (verbose, session, aRemotePath);
067:
068: this .directoryList = aDirectoryList;
069: }
070:
071: /**
072: * Constructor for ScpToMessage.
073: * @param verbose if true do verbose logging
074: * @param session the scp session to use
075: * @param aRemotePath the remote path
076: * @since Ant 1.6.2
077: */
078: private ScpToMessageBySftp(boolean verbose, Session session,
079: String aRemotePath) {
080: super (verbose, session);
081: this .remotePath = aRemotePath;
082: }
083:
084: /**
085: * Constructor for ScpToMessage.
086: * @param session the scp session to use
087: * @param aLocalFile the local file
088: * @param aRemotePath the remote path
089: */
090: public ScpToMessageBySftp(Session session, File aLocalFile,
091: String aRemotePath) {
092: this (false, session, aLocalFile, aRemotePath);
093: }
094:
095: /**
096: * Constructor for ScpToMessage.
097: * @param session the scp session to use
098: * @param aDirectoryList a list of directories
099: * @param aRemotePath the remote path
100: */
101: public ScpToMessageBySftp(Session session, List aDirectoryList,
102: String aRemotePath) {
103: this (false, session, aDirectoryList, aRemotePath);
104: }
105:
106: /**
107: * Carry out the transfer.
108: * @throws IOException on i/o errors
109: * @throws JSchException on errors detected by scp
110: */
111: public void execute() throws IOException, JSchException {
112: if (directoryList != null) {
113: doMultipleTransfer();
114: }
115: if (localFile != null) {
116: doSingleTransfer();
117: }
118: log("done.\n");
119: }
120:
121: private void doSingleTransfer() throws IOException, JSchException {
122: ChannelSftp channel = openSftpChannel();
123: try {
124: channel.connect();
125: try {
126: sendFileToRemote(channel, localFile, remotePath);
127: } catch (SftpException e) {
128: throw new JSchException(e.toString());
129: }
130: } finally {
131: if (channel != null) {
132: channel.disconnect();
133: }
134: }
135: }
136:
137: private void doMultipleTransfer() throws IOException, JSchException {
138: ChannelSftp channel = openSftpChannel();
139: try {
140: channel.connect();
141:
142: try {
143: channel.cd(remotePath);
144: for (Iterator i = directoryList.iterator(); i.hasNext();) {
145: Directory current = (Directory) i.next();
146: sendDirectory(channel, current);
147: }
148: } catch (SftpException e) {
149: throw new JSchException(e.toString());
150: }
151: } finally {
152: if (channel != null) {
153: channel.disconnect();
154: }
155: }
156: }
157:
158: private void sendDirectory(ChannelSftp channel, Directory current)
159: throws IOException, SftpException {
160: for (Iterator fileIt = current.filesIterator(); fileIt
161: .hasNext();) {
162: sendFileToRemote(channel, (File) fileIt.next(), null);
163: }
164: for (Iterator dirIt = current.directoryIterator(); dirIt
165: .hasNext();) {
166: Directory dir = (Directory) dirIt.next();
167: sendDirectoryToRemote(channel, dir);
168: }
169: }
170:
171: private void sendDirectoryToRemote(ChannelSftp channel,
172: Directory directory) throws IOException, SftpException {
173: String dir = directory.getDirectory().getName();
174: try {
175: channel.stat(dir);
176: } catch (SftpException e) {
177: // dir does not exist.
178: if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
179: channel.mkdir(dir);
180: }
181: }
182: channel.cd(dir);
183: sendDirectory(channel, directory);
184: channel.cd("..");
185: }
186:
187: private void sendFileToRemote(ChannelSftp channel, File localFile,
188: String remotePath) throws IOException, SftpException {
189: long filesize = localFile.length();
190:
191: if (remotePath == null) {
192: remotePath = localFile.getName();
193: }
194:
195: long startTime = System.currentTimeMillis();
196: long totalLength = filesize;
197:
198: // only track progress for files larger than 100kb in verbose mode
199: boolean trackProgress = getVerbose() && filesize > 102400;
200:
201: SftpProgressMonitor monitor = null;
202: if (trackProgress) {
203: monitor = getProgressMonitor();
204: }
205:
206: try {
207: if (this .getVerbose()) {
208: log("Sending: " + localFile.getName() + " : "
209: + filesize);
210: }
211: channel.put(localFile.getAbsolutePath(), remotePath,
212: monitor);
213: } finally {
214: if (this .getVerbose()) {
215: long endTime = System.currentTimeMillis();
216: logStats(startTime, endTime, (int) totalLength);
217: }
218: }
219: }
220:
221: /**
222: * Get the local file.
223: * @return the local file.
224: */
225: public File getLocalFile() {
226: return localFile;
227: }
228:
229: /**
230: * Get the remote path.
231: * @return the remote path.
232: */
233: public String getRemotePath() {
234: return remotePath;
235: }
236: }
|