001/* 002 * Copyright (c) 2002-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2012-11-26 22:19:36 +0000 (Mon, 26 Nov 2012) $' 007 * '$Revision: 31113 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.geon; 031 032import java.io.File; 033import java.io.FileInputStream; 034import java.io.FileOutputStream; 035import java.io.IOException; 036 037import org.apache.commons.net.ftp.FTP; 038 039import ptolemy.actor.TypedAtomicActor; 040import ptolemy.actor.TypedIOPort; 041import ptolemy.data.StringToken; 042import ptolemy.data.Token; 043import ptolemy.data.expr.StringParameter; 044import ptolemy.data.type.BaseType; 045import ptolemy.kernel.CompositeEntity; 046import ptolemy.kernel.util.Attribute; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.NameDuplicationException; 049import ptolemy.kernel.util.StringAttribute; 050 051////////////////////////////////////////////////////////////////////////// 052//// FTPClient 053/** 054 * This actor serves as an interface for FTP operations (currently only upload 055 * and download are supported). 056 */ 057 058public class FTPClient extends TypedAtomicActor { 059 060 public FTPClient(CompositeEntity container, String name) 061 throws IllegalActionException, NameDuplicationException { 062 super(container, name); 063 064 arguments = new TypedIOPort(this, "arguments", true, false); 065 arguments.setMultiport(true); 066 arguments.setTypeEquals(BaseType.STRING); 067 068 // trigger = new TypedIOPort(this, "trigger", false, true); 069 // trigger.setTypeEquals(BaseType.STRING); 070 071 url = new TypedIOPort(this, "url", false, true); 072 url.setTypeEquals(BaseType.STRING); 073 074 operation = new StringParameter(this, "operation"); 075 operation.setExpression("GET"); 076 operation.addChoice("PUT"); 077 mode = new StringParameter(this, "mode"); 078 mode.setExpression("ASC"); 079 mode.addChoice("BIN"); 080 081 host = new StringAttribute(this, "host"); 082 remotePath = new StringAttribute(this, "remote path"); 083 username = new StringAttribute(this, "username"); 084 password = new StringAttribute(this, "password"); 085 localPath = new StringParameter(this, "localPath"); 086 localPath.setExpression(System.getProperty("user.dir")); 087 088 _attachText("_iconDescription", "<svg>\n" 089 + "<rect x=\"-25\" y=\"-20\" " + "width=\"50\" height=\"40\" " 090 + "style=\"fill:white\"/>\n" 091 + "<polygon points=\"-15,-10 -12,-10 -8,-14 -1,-14 3,-10" 092 + " 15,-10 15,10, -15,10\" " + "style=\"fill:red\"/>\n" 093 + "</svg>\n"); 094 } 095 096 // ///////////////////////////////////////////////////////////////// 097 // // ports and parameters //// 098 /** 099 * The input port, which is a multiport. 100 */ 101 // public TypedIOPort trigger; 102 /** Source or destination files to be uploaded/downloaded. */ 103 public TypedIOPort arguments; 104 105 /** URL of the uploaded/downloaded file. */ 106 public TypedIOPort url; 107 108 /** Operation performed: put/get */ 109 public StringParameter operation; 110 111 /** Transfer mode: asc/bin */ 112 public StringParameter mode; 113 114 /** host server name. */ 115 public StringAttribute host; 116 117 /** path to remote file (begins and ends with '/'). */ 118 public StringAttribute remotePath; 119 120 /** Authentication username */ 121 public StringAttribute username; 122 123 /** Authentication password */ 124 public StringAttribute password; 125 126 /** Local directory */ 127 public StringParameter localPath; 128 129 // ///////////////////////////////////////////////////////////////// 130 // // public methods //// 131 132 /** 133 * If the specified attribute is <i>fileOrURL</i> and there is an open file 134 * being read, then close that file and open the new one; if the attribute 135 * is <i>numberOfLinesToSkip</i> and its value is negative, then throw an 136 * exception. In the case of <i>fileOrURL</i>, do nothing if the file name 137 * is the same as the previous value of this attribute. 138 * 139 * @param attribute 140 * The attribute that has changed. 141 * @exception IllegalActionException 142 * If the specified attribute is <i>fileOrURL</i> and the 143 * file cannot be opened, or the previously opened file 144 * cannot be closed; or if the attribute is 145 * <i>numberOfLinesToSkip</i> and its value is negative. 146 */ 147 148 /** 149 * Determine the output format 150 * 151 * @param attribute 152 * The attribute that changed. 153 * @exception IllegalActionException 154 * If the output type is not recognized. 155 */ 156 public void attributeChanged(Attribute attribute) 157 throws IllegalActionException { 158 try { 159 if (attribute == operation) { 160 String strOperation = operation.getExpression(); 161 if (strOperation.equals("GET")) { 162 _operation = _GET; 163 } else if (strOperation.equals("PUT")) { 164 _operation = _PUT; 165 } else { 166 throw new IllegalActionException(this, 167 "Unrecognized operation function: " + strOperation); 168 } 169 } else if (attribute == mode) { 170 String strMode = mode.getExpression(); 171 if (strMode.equals("ASC")) { 172 _mode = _ASC; 173 } else if (strMode.equals("BIN")) { 174 _mode = _BIN; 175 } else { 176 throw new IllegalActionException(this, 177 "Unrecognized mode function: " + strMode); 178 } 179 } else { 180 super.attributeChanged(attribute); 181 } 182 } catch (Exception nameDuplication) { 183 /* 184 * throw new InternalErrorException(this, nameDuplication, 185 * "Unexpected name duplication"); 186 */ 187 } 188 } 189 190 /** 191 * Output the data lines into an array. 192 * 193 * @exception IllegalActionException 194 * If there's no director. 195 */ 196 197 public void fire() throws IllegalActionException { 198 super.fire(); 199 200 String _host = host.getExpression(); 201 String _remotePath = remotePath.getExpression(); 202 String _username = username.getExpression(); 203 String _password = password.getExpression(); 204 205 String localPathStr = System.getProperty("user.dir"); 206 Token token = localPath.getToken(); 207 if(token != null) { 208 localPathStr = ((StringToken)token).stringValue(); 209 } 210 211 String failMsg = "FTP transfer failed because of: "; 212 try { 213 org.apache.commons.net.ftp.FTPClient f = new org.apache.commons.net.ftp.FTPClient(); 214 f.connect(_host); 215 f.login(_username, _password); 216 f.changeWorkingDirectory(_remotePath); 217 f.cwd(localPathStr); 218 if (_mode == _BIN) { 219 f.setFileType(FTP.BINARY_FILE_TYPE); 220 } 221 222 // for all channels get input... 223 int argsWidth = arguments.getWidth(); 224 for (int i = 0; i < argsWidth; i++) { 225 String _arg = ((StringToken) arguments.get(i)).stringValue(); 226 _debug("argument(" + i + ") = " + _arg); 227 File argFile = new File(localPathStr, _arg); 228 _debug("file exist? " + argFile.exists()); 229 // extract filename 230 _debug("_remotePath = " + _remotePath + argFile.getName()); 231 if (_operation == _GET) { 232 FileOutputStream os = new FileOutputStream(argFile); 233 f.retrieveFile(argFile.getName(), os); 234 os.close(); 235 } else if (_operation == _PUT && argFile.exists()) { 236 // TODO: add if get fails then put. 237 FileInputStream is = new FileInputStream(argFile); 238 f.storeFile(argFile.getName(), is); 239 is.close(); 240 } else { 241 _url = "invalid command"; 242 } 243 } 244 f.disconnect(); 245 } catch (IOException ioe) { 246 throw new IllegalActionException(failMsg + ioe.toString()); 247 } 248 url.broadcast(new StringToken(_url)); 249 } 250 251 /** 252 * Post fire the actor. Return false to indicated that the process has 253 * finished. If it returns true, the process will continue indefinitely. 254 */ 255 256 public boolean postfire() { 257 return false; 258 } 259 260 // ///////////////////////////////////////////////////////////////// 261 // // private variables //// 262 /** 263 * Output indicator parameter. 264 */ 265 private int _operation; 266 private int _mode; 267 268 // Constants used for more efficient execution. 269 private static final int _GET = 0; 270 private static final int _PUT = 1; 271 272 private static final int _ASC = 0; 273 private static final int _BIN = 1; 274 275 /** Result string Variable. */ 276 private String _url = new String(""); 277 278}