001/* 002 * Copyright (c) 2002-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 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; 036import java.io.InputStream; 037import java.io.OutputStream; 038 039import ptolemy.actor.TypedAtomicActor; 040import ptolemy.actor.TypedIOPort; 041import ptolemy.data.BooleanToken; 042import ptolemy.data.StringToken; 043import ptolemy.data.expr.FileParameter; 044import ptolemy.data.expr.Parameter; 045import ptolemy.data.type.BaseType; 046import ptolemy.gui.GraphicalMessageHandler; 047import ptolemy.kernel.CompositeEntity; 048import ptolemy.kernel.util.IllegalActionException; 049import ptolemy.kernel.util.NameDuplicationException; 050 051////////////////////////////////////////////////////////////////////////// 052//// FileCopy 053/** 054 * This actor copies a source file to a destination file and outputs the 055 * destination file URL. 056 * 057 * The source and destination file paths can be accepted either through a port 058 * or a parameter. 059 * 060 * If the append attribute has value true, then the file will be appended to. If 061 * it has value false, then if the file exists, the user will be queried for 062 * permission to overwrite, and if granted, the file will be overwritten. 063 * 064 * If the confirmOverwrite parameter has value false, then this actor will 065 * overwrite the specified file if it exists without asking. If true (the 066 * default), then if the file exists, then this actor will ask for confirmation 067 * before overwriting. 068 * 069 * @see FileParameter 070 * @author Efrat Jaeger 071 * @version $Id: FileCopy.java 24234 2010-05-06 05:21:26Z welker $ 072 * @since Ptolemy II 4.0.1 073 */ 074 075public class FileCopy extends TypedAtomicActor { 076 077 /** 078 * Construct an actor with the given container and name. 079 * 080 * @param container 081 * The container. 082 * @param name 083 * The name of this actor. 084 * @exception IllegalActionException 085 * If the actor cannot be contained by the proposed 086 * container. 087 * @exception NameDuplicationException 088 * If the container already has an actor with this name. 089 */ 090 public FileCopy(CompositeEntity container, String name) 091 throws IllegalActionException, NameDuplicationException { 092 super(container, name); 093 094 sourceFile = new TypedIOPort(this, "sourceFile", true, false); 095 sourceFile.setTypeEquals(BaseType.STRING); 096 097 destinationFile = new TypedIOPort(this, "destinationFile", true, false); 098 destinationFile.setTypeEquals(BaseType.STRING); 099 100 outputFile = new TypedIOPort(this, "outputFile", false, true); 101 outputFile.setTypeEquals(BaseType.STRING); 102 103 sourceFileParam = new FileParameter(this, "sourceFileParam"); 104 sourceFileParam.setDisplayName("source File"); 105 106 destFileParam = new FileParameter(this, "destFileParam"); 107 destFileParam.setDisplayName("destination File"); 108 109 new Parameter(sourceFileParam, "allowDirectories", BooleanToken.TRUE); 110 new Parameter(destFileParam, "allowDirectories", BooleanToken.TRUE); 111 112 append = new Parameter(this, "append"); 113 append.setTypeEquals(BaseType.BOOLEAN); 114 append.setToken(BooleanToken.FALSE); 115 116 confirmOverwrite = new Parameter(this, "confirmOverwrite"); 117 confirmOverwrite.setTypeEquals(BaseType.BOOLEAN); 118 confirmOverwrite.setToken(BooleanToken.TRUE); 119 120 recursive = new Parameter(this, "recursive"); 121 recursive.setTypeEquals(BaseType.BOOLEAN); 122 recursive.setToken(BooleanToken.TRUE); 123 124 _attachText("_iconDescription", "<svg>\n" 125 + "<rect x=\"-25\" y=\"-20\" " + "width=\"50\" height=\"40\" " 126 + "style=\"fill:white\"/>\n" 127 + "<polygon points=\"-15,-10 -12,-10 -8,-14 -1,-14 3,-10" 128 + " 15,-10 15,10, -15,10\" " + "style=\"fill:red\"/>\n" 129 + "</svg>\n"); 130 } 131 132 // ///////////////////////////////////////////////////////////////// 133 // // ports and parameters //// 134 135 /** 136 * Source file. 137 */ 138 public TypedIOPort sourceFile; 139 140 /** 141 * Destination file. 142 */ 143 public TypedIOPort destinationFile; 144 145 /** 146 * Output destination file URL. 147 */ 148 public TypedIOPort outputFile; 149 150 /** 151 * Source file name or URL. This is a string with any form accepted by 152 * FileParameter. 153 * 154 * @see FileParameter 155 */ 156 public FileParameter sourceFileParam; 157 158 /** 159 * Destination file name or URL. This is a string with any form accepted by 160 * FileParameter. 161 * 162 * @see FileParameter 163 */ 164 public FileParameter destFileParam; 165 166 /** 167 * If true, then append to the specified file. If false (the default), then 168 * overwrite any preexisting file after asking the user for permission. 169 */ 170 public Parameter append; 171 172 /** 173 * If false, then overwrite the specified file if it exists without asking. 174 * If true (the default), then if the file exists, ask for confirmation 175 * before overwriting. 176 */ 177 public Parameter confirmOverwrite; 178 179 /** 180 * If false, then only copy the files, not the sub-directories, in the source location. 181 */ 182 public Parameter recursive; 183 184 /** 185 * Copy the source file to the destination file. Broadcast the destination 186 * file path. 187 * 188 * @exception IllegalActionException 189 * If there's no director. 190 */ 191 public void fire() throws IllegalActionException { 192 File _sourceFile = null, _destFile = null; 193 String fileName = ""; 194 195 // get source file. 196 if (sourceFile.getWidth() > 0) { 197 fileName = ((StringToken) sourceFile.get(0)).stringValue(); 198 int lineEndInd = fileName.indexOf("\n"); 199 if (lineEndInd != -1) { // The string contains a CR. 200 fileName = fileName.substring(0, lineEndInd); 201 } 202 sourceFileParam.setExpression(fileName); 203 } 204 _sourceFile = sourceFileParam.asFile(); 205 206 if (!_sourceFile.exists()) { 207 throw new IllegalActionException(this, "file " + fileName 208 + " doesn't exist."); 209 } 210 211 // get dest file. 212 fileName = ""; 213 if (destinationFile.getWidth() > 0) { 214 fileName = ((StringToken) destinationFile.get(0)).stringValue(); 215 int lineEndInd = fileName.indexOf("\n"); 216 if (lineEndInd != -1) { // The string contains a CR. 217 fileName = fileName.substring(0, lineEndInd); 218 } 219 destFileParam.setExpression(fileName); 220 } 221 _destFile = destFileParam.asFile(); 222 223 boolean appendValue = ((BooleanToken) append.getToken()).booleanValue(); 224 boolean confirmOverwriteValue = ((BooleanToken) confirmOverwrite 225 .getToken()).booleanValue(); 226 boolean recursiveValue = ((BooleanToken) recursive 227 .getToken()).booleanValue(); 228 // Don't ask for confirmation in append mode, since there 229 // will be no loss of data. 230 if (_destFile.exists() && !appendValue && confirmOverwriteValue) { 231 // Query for overwrite. 232 // FIXME: This should be called in the event thread! 233 // There is a chance of deadlock since it is not. 234 if (!GraphicalMessageHandler.yesNoQuestion("OK to overwrite " 235 + _destFile + "?")) { 236 throw new IllegalActionException(this, 237 "Please select another file name."); 238 } 239 } 240 241 try { 242 copyFiles(_sourceFile,_destFile, recursiveValue); 243 244 } catch (Exception ex) { 245 throw new IllegalActionException(this, ex, "Error copying " 246 + _sourceFile.getPath() + " to " + _destFile.getPath() 247 + "."); 248 } 249 outputFile.broadcast(new StringToken(_destFile.getAbsolutePath())); 250 } 251 252 void copyFiles(File sourceLocation , File targetLocation, boolean recursive) 253 throws IOException { 254 255 if (sourceLocation.isDirectory()) { 256 if (!targetLocation.exists()) { 257 targetLocation.mkdir(); 258 } 259 260 String[] children = sourceLocation.list(); 261 for (int i=0; i<children.length; i++) { 262 File sourceChildFile = new File(sourceLocation, children[i]); 263 if (recursive) 264 copyFiles(sourceChildFile, 265 new File(targetLocation, children[i]), true); 266 else 267 { 268 if (sourceChildFile.isFile()) 269 copyFiles(sourceChildFile, 270 new File(targetLocation, children[i]), false); 271 } 272 } 273 } else { 274 275 InputStream in = new FileInputStream(sourceLocation); 276 OutputStream out = new FileOutputStream(targetLocation); 277 278 // Copy the bits from instream to outstream 279 byte[] buf = new byte[1024]; 280 int len; 281 while ((len = in.read(buf)) > 0) { 282 out.write(buf, 0, len); 283 } 284 in.close(); 285 out.close(); 286 } 287 } 288 289 void copyFile(File sourceLocation , File targetLocation) 290 throws IOException { 291 InputStream in = new FileInputStream(sourceLocation); 292 OutputStream out = new FileOutputStream(targetLocation); 293 294 // Copy the bits from instream to outstream 295 byte[] buf = new byte[1024]; 296 int len; 297 while ((len = in.read(buf)) > 0) { 298 out.write(buf, 0, len); 299 } 300 in.close(); 301 out.close(); 302 } 303 304}