View Javadoc

1   /*
2    * $HeadURL: $
3    * $Date: $
4    * $Revision: $
5    * $Author: $
6    * 
7    * Copyright (c) 2005 MindTree Consulting Ltd. 
8    * 
9    * This file is part of Insight.
10   * 
11   * Insight is free software: you can redistribute it and/or modify it under the 
12   * terms of the GNU General Public License as published by the Free Software 
13   * Foundation, either version 3 of the License, or (at your option) any later 
14   * version.
15   * 
16   * Insight is distributed in the hope that it will be useful, but 
17   * WITHOUT ANY WARRANTY; without even the implied warranty of 
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
19   * Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public License along with 
22   * Insight.  If not, see <http://www.gnu.org/licenses/>.
23   */
24  
25  package com.mindtree.techworks.insight.download;
26  
27  import java.io.File;
28  import java.io.FileNotFoundException;
29  import java.io.FileOutputStream;
30  import java.io.IOException;
31  import java.net.InetAddress;
32  import java.net.PasswordAuthentication;
33  import java.net.SocketException;
34  import java.net.URL;
35  import java.net.UnknownHostException;
36  import java.util.List;
37  import java.util.ArrayList;
38  
39  import org.apache.commons.net.ftp.FTPClient;
40  import org.apache.commons.net.ftp.FTPReply;
41  import org.apache.commons.net.ftp.FTPFile;
42  
43  import com.mindtree.techworks.insight.download.ftpbrowse.FTPBrowseException;
44  import com.mindtree.techworks.insight.receiver.WildCardMatcher;
45  
46  
47  
48  /**
49   * TODO
50   * 
51   * @see com.mindtree.techworks.insight.download.RemoteClientFactory RemoteClientFactory
52   * @see com.mindtree.techworks.insight.download.RemoteClient RemoteClient
53   * @author Bindul Bhowmik
54   * @version $Revision: 27 $ $Date: 2007-12-16 04:58:03 -0700 (Sun, 16 Dec 2007) $
55   */
56  public class FTPRemoteClient extends RemoteClient {
57  	
58  	//
59  	// Static block to register with the factory
60  	//
61  	static {
62  		// This class handles only FTP filesets
63  		RemoteClientFactory.registerClient("FTP_CLIENT", FTPRemoteClient.class);
64  	}
65  	
66  	//
67  	// Constants
68  	//
69  	
70  	/**
71  	 * Password Authentication to use for anonymous access
72  	 */
73  	public static final PasswordAuthentication anonPassAuth = new PasswordAuthentication(
74  			"anonymous", "insight@mindtree.com".toCharArray());
75  	
76  	//
77  	// Instance variables
78  	//
79  	
80  	/**
81  	 * The FTPFileset used to connect to the host
82  	 */
83  	private FTPFileset fileset;
84  	
85  	/**
86  	 * FTPClient used to connect to the host.
87  	 */
88  	private FTPClient ftpClient;
89  	
90  	//
91  	// Implemented abstract methods
92  	//
93  	
94  	/**
95  	 * @see com.mindtree.techworks.insight.download.RemoteClient#setFileset(com.mindtree.techworks.insight.download.Fileset)
96  	 */
97  	protected void setFileset (Fileset fileset) throws RemoteClientException {
98  		
99  		if (fileset.getType() != Fileset.FTP_FILESET
100 				|| !(fileset instanceof FTPFileset)) {
101 			throw new RemoteClientException(
102 			"This client can handle only FTPFileset");
103 		}
104 		this.fileset = (FTPFileset) fileset;
105 		
106 	}
107 	
108 	/**
109 	 * @see com.mindtree.techworks.insight.download.RemoteClient#downloadFile(java.lang.String)
110 	 */
111 	/*
112 	 * Signature changed in synchronization with RemoteClient
113 	 */
114 	protected String[] downloadFile (String fileName)
115 	throws RemoteClientException {
116 		
117 		isBusy = true;
118 		checkConnection();
119 		//Vector for storing the file names matching with the given pattern.
120 		List matchingFileNames = new ArrayList(5);
121 		//Vector for storing the file names of all the downloaded files.
122 		List downloadedFiles = new ArrayList(5);
123 		FTPFile[] remoteFiles;
124 		File destinationFile = null;
125 		FileOutputStream fos = null;
126 		
127 		//Checks whether the file name has any wild cards. 
128 		//Presently supporting only the wild card '*'.
129 		if(WildCardMatcher.hasWildCardEntries(fileName)){
130 			int fileSeperatorIndex = (fileName.lastIndexOf('\\') == -1) ? 
131 					fileName.lastIndexOf('/') : fileName.lastIndexOf('\\');  
132 					String remoteDirectory = (fileName.substring(0, fileSeperatorIndex));
133 					String pattern = (fileName.substring(fileSeperatorIndex + 1));
134 					try{
135 						//Fetches the file list from the remote directory
136 						remoteFiles = ftpClient.listFiles(remoteDirectory);
137 						List remoteFilesList = new ArrayList(remoteFiles.length);
138 						for(int i = 0; i < remoteFiles.length; i++){
139 							remoteFilesList.add(remoteFiles[i].getName());
140 						}
141 						//Gets the names of the files matching with the given pattern.
142 						matchingFileNames = getMatchingFiles(remoteFilesList, pattern);
143 					}
144 					catch(IOException ie){
145 						throw new RemoteClientException("Couldn't open a " +
146 								"connection with the remote client", ie);
147 					}
148 		}
149 		else{
150 			matchingFileNames.add(fileName);
151 		}
152 		
153 		for(int i = 0; i < matchingFileNames.size(); i++){
154 			fileName = (String)matchingFileNames.get(i);
155 			// Get the destination file
156 			try {
157 				destinationFile = getDestinationFile(fileName, '/');
158 				fos = new FileOutputStream(destinationFile);
159 			} catch (FileNotFoundException e) {
160 				// Should never get here...
161 				throw new RemoteClientException("Could not write to temporary file.", e);
162 			} catch (IOException e) {
163 				throw new RemoteClientException("Could not create temporary file.", e);
164 			}
165 			
166 			try {
167 				// Get the destination file
168 				if (!ftpClient.retrieveFile(fileName, fos)) {
169 					throw new RemoteClientException("Could not download file");
170 				}
171 				downloadedFiles.add(destinationFile.getAbsolutePath());
172 			} catch (IOException e) {
173 				throw new RemoteClientException("Could not download file", e);
174 			} finally {
175 				isBusy = false;
176 				try {
177 					// Close the streams
178 					fos.close();
179 				} catch (IOException e1) {
180 					// Cant do anything here... just ignore it
181 					e1.printStackTrace();
182 				}
183 			}
184 		}
185 		
186 		//Converts the vector downloaded Files to a string array.
187 		String[] downloadedFileNames = new String[downloadedFiles.size()];
188 		for(int i = 0; i < downloadedFiles.size(); i++){
189 			downloadedFileNames[i] = (String)downloadedFiles.get(i);
190 		}
191 		// Return the paths of all files to the downloaded file.
192 		return downloadedFileNames;
193 	}
194 	
195 	/**
196 	 * Returns a vector of filenames matching the given pattern. 
197 	 * @param remoteFiles	The list of remote files.
198 	 * @param pattern	The pattern to be matched with.
199 	 * @return	The matching file names as a vector.
200 	 */
201 	private List getMatchingFiles(List remoteFiles, String pattern){
202 		
203 		List matchingFiles = new ArrayList(5);
204 		
205 		for(int i = 0; i < remoteFiles.size(); i++){
206 			String filePath = (String)remoteFiles.get(i);
207 			int fileSeperatorIndex = (filePath.lastIndexOf('\\') == -1) ? filePath.lastIndexOf('/') : filePath.lastIndexOf('\\');
208 			String fileName = filePath.substring(fileSeperatorIndex + 1);
209 			//Checks whether the fileName matches the given wild card. 
210 			WildCardMatcher matcher = new WildCardMatcher(pattern);
211 			if(matcher.matches(fileName)){
212 				matchingFiles.add(filePath);
213 			}
214 			else{
215 			}
216 		}
217 		return matchingFiles;
218 	}
219 	
220 	/**
221 	 * @see com.mindtree.techworks.insight.download.RemoteClient#closeConnection()
222 	 */
223 	protected void closeConnection() throws RemoteClientException {
224 		if (null != ftpClient && ftpClient.isConnected()) {
225 			try {
226 				ftpClient.disconnect();
227 			} catch (IOException e) {
228 				throw new RemoteClientException("Problem closing connection.", e);
229 			}
230 		}
231 	}
232 	
233 	//
234 	// Private util methods
235 	//
236 	
237 	/**
238 	 * Creates an FTP Connection
239 	 * 
240 	 * @throws RemoteClientException If the connection cannot be opened
241 	 */
242 	private synchronized void createFTPConnection () throws RemoteClientException {
243 		
244 		ftpClient = new FTPClient();
245 		try {
246 			// Get the url and password from the fileset
247 			URL url = fileset.getHostURL();
248 			PasswordAuthentication passwordAuthentication = fileset
249 			.getPasswordAuthentication();
250 			
251 			// If the password is not set, use anonymous login
252 			if (null == passwordAuthentication) {
253 				passwordAuthentication = anonPassAuth;
254 			}
255 			
256 			InetAddress inetAddress = InetAddress.getByName(url.getHost());
257 			// The user might have specified the port to connect to (if other
258 			// than the default FTP port). URL API specifies that -1 is returned
259 			// if no port is set. Otherwise the use the port.
260 			if (url.getPort() == -1) {
261 				ftpClient.connect(inetAddress);
262 			} else {
263 				ftpClient.connect(inetAddress, url.getPort());
264 			}
265 			
266 			if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
267 				throw new FTPBrowseException(ftpClient.getReplyString());
268 			}
269 			ftpClient.login(passwordAuthentication.getUserName(),
270 					new StringBuffer().append(
271 							passwordAuthentication.getPassword()).toString());
272 			
273 			if (url.getPath().length() > 0) {
274 				ftpClient.changeWorkingDirectory(url.getPath());
275 			}
276 		} catch (UnknownHostException e) {
277 			throw new RemoteClientException("Host not found.", e);
278 		} catch (SocketException e) {
279 			throw new RemoteClientException("Socket cannot be opened.", e);
280 		} catch (IOException e) {
281 			throw new RemoteClientException("Socket cannot be opened.", e);
282 		}
283 	}
284 	
285 	/**
286 	 * Private method used to check if an open connection is present, else
287 	 * creates one.
288 	 *  
289 	 * @throws RemoteClientException is thrown if the connection
290 	 *             cannot be opened.
291 	 */
292 	private void checkConnection () throws RemoteClientException {
293 		
294 		if (null == ftpClient || !ftpClient.isConnected()) {
295 			createFTPConnection();
296 		}
297 	}
298 	
299 }