001 /**
002 *
003 */
004 package de.jw.cloud42.webapp;
005
006 import java.io.File;
007
008 import java.util.ArrayList;
009 import java.util.List;
010 import java.util.logging.Logger;
011
012 import javax.faces.application.FacesMessage;
013 import javax.faces.context.ExternalContext;
014 import javax.servlet.ServletOutputStream;
015 import javax.servlet.http.HttpServletResponse;
016
017
018 import org.jboss.seam.ScopeType;
019 import org.jboss.seam.annotations.In;
020 import org.jboss.seam.annotations.Name;
021 import org.jboss.seam.annotations.Out;
022
023 import org.jboss.seam.annotations.Scope;
024 import org.jboss.seam.annotations.Synchronized;
025
026 import org.jboss.seam.faces.FacesMessages;
027 import org.richfaces.event.UploadEvent;
028 import org.richfaces.model.UploadItem;
029
030
031 import de.jw.cloud42.core.domain.RemoteResult;
032 import de.jw.cloud42.core.remoting.RemoteControl;
033 import de.jw.cloud42.webapp.utils.FileUtils;
034
035 /**
036 * Seam component wrapper around file transfer functions of Cloud42.
037 *
038 * @author fbitzer
039 *
040 */
041 @Name("filetransferManager")
042 @Scope(ScopeType.SESSION)
043 @Synchronized(timeout=1000000000)
044 public class FiletransferManager {
045
046 @In
047 UserManager userManager;
048
049 /**
050 * Inject faces messages to trigger error and success messages.
051 */
052 @In
053 FacesMessages facesMessages;
054
055
056 //Inject FacesContext and externalContext to be able to create custom responses for file download
057 @In(value="#{facesContext.externalContext}")
058 private ExternalContext extCtx;
059 @In(value="#{facesContext}")
060 javax.faces.context.FacesContext facesContext;
061
062
063 //input fields used in the view (filetransfer dialog)
064 private String targetDirContent;
065 private String targetDir;
066 private boolean uploadFromURL;
067 private String uploadURL;
068
069 private List<UploadItem> files = new ArrayList<UploadItem>();
070
071
072 private String targetFilename = "";
073
074
075
076 private String downloadDirContent;
077 private String downloadFilename;
078
079
080 /**
081 * Uploads a file to an AMI instance.
082 * @param dnsName Hostname of instance.
083 * @param keyName Name of keypair to use. Actual key is retreived from stored private keys, if existing.
084 */
085 public void uploadFile(String dnsName, String keyName){
086
087 //check input first
088 if (!uploadFromURL) {
089 if (this.files.size()<1){
090 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No file.");
091 return;
092 }
093 } else {
094 if (this.uploadURL.equals("")){
095 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No URL.");
096 return;
097 }
098
099
100 if (this.targetFilename.equals("")){
101 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No target file.");
102 return;
103 }
104 }
105
106 RemoteControl c = new RemoteControl();
107
108 //get the private key for the keyname
109 String privateKey = userManager.getKeyForName(keyName);
110
111 RemoteResult r = new RemoteResult();
112
113 boolean success = false;
114
115 //decide whether to upload a local file or a file from an URL
116 if (this.uploadFromURL) {
117
118 //adjust the target directory
119 if (!targetDir.startsWith("/")) {
120 targetDir = "~/" + targetDir;
121 }
122
123 r = c.uploadFileFromURL(dnsName, privateKey, targetDir, targetFilename, uploadURL);
124
125 if (r.getExceptionMessage() == null && r.getExitCode() == 0) success = true;
126
127 } else {
128
129 //iterate through uploaded files
130
131 for (UploadItem item : files){
132
133 String filename = FileUtils.extractFilename(item.getFileName());
134
135 try {
136 byte[] filedata = FileUtils.getBytesFromFile(item.getFile());
137
138 r = c.uploadFile(dnsName, privateKey, targetDir, filename, filedata);
139
140 if (r.getExceptionMessage() == null && (r.getExitCode() == 0)){
141 success = true;
142 } else {
143 success = false;
144 break;
145 }
146 } catch (Exception ex){
147 success = false;
148 break;
149 }
150
151 }
152
153
154 }
155
156 if (!success){
157 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_fileNotUploaded");
158 Logger.getAnonymousLogger().severe("Error uploading file: " + r.getExceptionMessage());
159 } else {
160 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "msg_fileUploaded");
161
162 }
163
164 //reset file after upload (the directory is kept in case the user wants to upload another file
165 //to the same dir)
166 this.files = new ArrayList<UploadItem>();
167 targetFilename="";
168
169 }
170
171 /**
172 * List the contents of a folder by remotely executing a ls -a.
173 * Stores the result in the corresponding member variable in order to provide access from the Facelets view.
174 * @param dnsName Hostname of instance.
175 * @param keyName Name of keypair to use.
176 * @param download boolean flag indicating whether the listing should be for file download or
177 * file upload area. In case of file download, a wildcard is inserted into the command (ls -a xyz*).
178 */
179 public void listFolder(String dnsName, String keyName, boolean download){
180
181 //get the private key for the keyname
182 String privateKey = userManager.getKeyForName(keyName);
183
184 String result = "";
185
186 String dir="";
187 if (!download){
188 dir = targetDir;
189 } else {
190 dir = downloadFilename + "*";
191 }
192
193 if (privateKey != null){
194
195 RemoteControl c = new RemoteControl();
196
197 RemoteResult r = c.executeCommand(dnsName, privateKey, "ls -a " + dir);
198
199 if (r.getExceptionMessage() != null){
200 result = "Exception: " + r.getExceptionMessage();
201 } else if (!r.getStdErr().equals("")){
202 result = "Error: " + r.getStdErr();
203 } else {
204 result = r.getStdOut();
205 }
206 }
207
208 if (!download){
209 targetDirContent = result;
210 } else {
211 downloadDirContent = result;
212 }
213
214 }
215
216 /**
217 * Resets the file dialog by resetting the member variables for displayment in the UI.
218 */
219 public void resetFileDialog(){
220
221 this.targetDirContent = "";
222 targetDir = "";
223 targetFilename = "";
224
225 uploadFromURL = false;
226 uploadURL = "";
227
228
229 this.downloadDirContent="";
230 downloadFilename="";
231
232 this.clearUpload();
233
234
235 }
236 /**
237 * Resets the list of uploaded files.
238 */
239 public void clearUpload(){
240 files = new ArrayList<UploadItem>();
241 }
242
243
244 /**
245 * Download a file from an AMI instance and send it to the client using HTTP.
246 * @param dnsName Hostname of instance.
247 * @param keyName Name of keypair to use.
248 */
249 public void downloadFile(String dnsName, String keyName){
250
251
252 //check input first
253 if (this.downloadFilename.equals("")) {
254
255 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No file.");
256 return;
257
258 }
259
260 RemoteControl c = new RemoteControl();
261
262 //get the private key for the keyname
263 String privateKey = userManager.getKeyForName(keyName);
264
265 byte[] file = c.downloadFile(dnsName, privateKey, downloadFilename);
266
267 if (file != null){
268 //Create a HTTPResponse and send it back skipping the usual JSF lifecycle
269 HttpServletResponse response = (HttpServletResponse)extCtx.getResponse();
270
271 //response.setContentType(?);//content-type is unknown
272
273 //the Header Content-Disposition causes a browser to display a download dialog instead
274 //of trying to display the file directly. This way, content-type becomes irrelevant.
275 //Use original filename as proposed filename for download dialog.
276 String fname = downloadFilename.split("/")[downloadFilename.split("/").length - 1];
277 response.setHeader( "Content-Disposition", "attachment; filename=\""
278 + fname + "\";");
279
280 //write file into response stream.
281 try {
282 ServletOutputStream os = response.getOutputStream();
283 os.write(file);
284 os.flush();
285 os.close();
286 facesContext.responseComplete();
287 } catch(Exception e) {
288 Logger.getAnonymousLogger().severe("Error serving downloaded file: " + e.getMessage());
289 }
290 } else {
291 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_fileNotDownloaded");
292 Logger.getAnonymousLogger().severe("Error downloading file.");
293 }
294
295 }
296
297
298
299 //getters and setters for bean properties...
300
301 /**
302 * @return the targetDirContent
303 */
304 public String getTargetDirContent() {
305 return targetDirContent;
306 }
307
308 /**
309 * @param targetDirContent the targetDirContent to set
310 */
311 public void setTargetDirContent(String targetDirContent) {
312 this.targetDirContent = targetDirContent;
313 }
314
315 /**
316 * @return the userManager
317 */
318 public UserManager getUserManager() {
319 return userManager;
320 }
321
322 /**
323 * @param userManager the userManager to set
324 */
325 public void setUserManager(UserManager userManager) {
326 this.userManager = userManager;
327 }
328
329 /**
330 * @return the targetDir
331 */
332 public String getTargetDir() {
333 return targetDir;
334 }
335
336 /**
337 * @param targetDir the targetDir to set
338 */
339 public void setTargetDir(String targetDir) {
340 this.targetDir = targetDir;
341 }
342
343 /**
344 * @return the targetFilename
345 */
346 public String getTargetFilename() {
347
348 return targetFilename;
349 }
350
351 /**
352 * @param targetFilename the targetFilename to set
353 */
354 public void setTargetFilename(String targetFilename) {
355
356 this.targetFilename = targetFilename;
357 }
358
359 /**
360 * @return the uploadFromURL
361 */
362 public boolean isUploadFromURL() {
363 return uploadFromURL;
364 }
365
366 /**
367 * @param uploadFromURL the uploadFromURL to set
368 */
369 public void setUploadFromURL(boolean uploadFromURL) {
370 this.uploadFromURL = uploadFromURL;
371 }
372
373
374
375
376 /**
377 * @return the uploadURL
378 */
379 public String getUploadURL() {
380 return uploadURL;
381 }
382
383 /**
384 * @param uploadURL the uploadURL to set
385 */
386 public void setUploadURL(String uploadURL) {
387 this.uploadURL = uploadURL;
388 }
389
390 /**
391 * @return the downloadFilename
392 */
393 public String getDownloadFilename() {
394 return downloadFilename;
395 }
396
397 /**
398 * @param downloadFilename the downloadFilename to set
399 */
400 public void setDownloadFilename(String downloadFilename) {
401 this.downloadFilename = downloadFilename;
402 }
403
404 /**
405 * @return the downloadDirContent
406 */
407 public String getDownloadDirContent() {
408 return downloadDirContent;
409 }
410
411 /**
412 * @param downloadDirContent the downloadDirContent to set
413 */
414 public void setDownloadDirContent(String downloadDirContent) {
415 this.downloadDirContent = downloadDirContent;
416 }
417
418 public List<UploadItem> getFiles() {
419 return files;
420 }
421
422 public void setFiles(List<UploadItem> files) {
423 this.files = files;
424 }
425 }