001/*
002 * Copyright (c) 2004-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.sdm.spa;
031
032import java.io.ByteArrayOutputStream;
033import java.io.File;
034
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.kepler.io.DirectoryListing;
038import org.kepler.io.FileInfo;
039import org.kepler.io.MappedLog;
040import org.kepler.io.SharedLog;
041import org.kepler.ssh.ExecException;
042import org.kepler.ssh.ExecFactory;
043import org.kepler.ssh.ExecInterface;
044
045import ptolemy.actor.TypedAtomicActor;
046import ptolemy.actor.TypedIOPort;
047import ptolemy.data.ArrayToken;
048import ptolemy.data.BooleanToken;
049import ptolemy.data.IntToken;
050import ptolemy.data.LongToken;
051import ptolemy.data.RecordToken;
052import ptolemy.data.StringToken;
053import ptolemy.data.Token;
054import ptolemy.data.expr.FileParameter;
055import ptolemy.data.expr.Parameter;
056import ptolemy.data.type.ArrayType;
057import ptolemy.data.type.BaseType;
058import ptolemy.data.type.RecordType;
059import ptolemy.data.type.Type;
060import ptolemy.kernel.CompositeEntity;
061import ptolemy.kernel.util.IllegalActionException;
062import ptolemy.kernel.util.NameDuplicationException;
063import ptolemy.kernel.util.Settable;
064import ptolemy.kernel.util.StringAttribute;
065
066//////////////////////////////////////////////////////////////////////////
067//// ProcessFileRT
068/**
069 * <p>
070 * no documentation yet.
071 * </p>
072 * 
073 * @author Norbert Podhorszki
074 * @version $Revision: 24234 $
075 * @category.name remote
076 * @category.name connection
077 * @category.name external execution
078 */
079
080public class ProcessFileRT extends TypedAtomicActor {
081
082        /**
083         * Construct an ExecuteCmd actor with the given container and name. Create
084         * the parameters, initialize their values.
085         * 
086         * @param container
087         *            The container.
088         * @param name
089         *            The name of this actor.
090         * @exception IllegalActionException
091         *                If the entity cannot be contained by the proposed
092         *                container.
093         * @exception NameDuplicationException
094         *                If the container already has an actor with this name.
095         */
096        public ProcessFileRT(CompositeEntity container, String name)
097                        throws NameDuplicationException, IllegalActionException {
098                super(container, name);
099
100                String[] labels = { "name", "size", "date" };
101                Type[] ctypes = { BaseType.STRING, BaseType.LONG, BaseType.LONG };
102                _etype = new RecordType(labels, ctypes);
103
104                // INPUT PORT: receiving a file recordtoken
105                filein = new TypedIOPort(this, "filein", true, false);
106                filein.setTypeEquals(_etype);
107                new Parameter(filein, "_showName", BooleanToken.TRUE);
108
109                // OUTPUT PORT: emitting a file recordtoken
110                fileout = new TypedIOPort(this, "fileout", false, true);
111                fileout.setTypeEquals(_etype);
112                new Parameter(fileout, "_showName", BooleanToken.TRUE);
113
114                String[] sublabels = { "name", "value" };
115                Type[] subtypes = { BaseType.STRING, BaseType.STRING };
116                _substype = new RecordType(sublabels, subtypes);
117
118                // INPUT PORT: substitution token: an array of recordtokens
119                subs = new TypedIOPort(this, "subs", true, false);
120                subs.setTypeEquals(new ArrayType(_substype));
121                new Parameter(subs, "_showName", BooleanToken.TRUE);
122
123                // OUTPUT PORT: emitting a file recordtoken for provenance purposes
124                // info should come back from the executed command
125                provenanceout = new TypedIOPort(this, "provenanceout", false, true);
126                provenanceout.setTypeEquals(_etype);
127                new Parameter(provenanceout, "_showName", BooleanToken.FALSE);
128                new Parameter(provenanceout, "_hide", BooleanToken.TRUE);
129                // new Parameter(provenanceout, "_cardinal", new StringToken("SOUTH"));
130                StringAttribute portDirection;
131                portDirection = (StringAttribute) getAttribute("_cardinal");
132                if (portDirection == null)
133                        portDirection = new StringAttribute(this, "_cardinal");
134                portDirection.setExpression("south");
135
136                // PARAMETERS
137
138                // target selects the machine where to connect to
139                RemoteMachine = new Parameter(this, "RemoteMachine", new StringToken(
140                                "Execution host as [user@]host[:port]"));
141
142                Command = new Parameter(
143                                this,
144                                "Command",
145                                new StringToken(
146                                                "The command string, using _INFILE_, _OUTFILE_, _INPATH_, _OUTPATH_ and _HOST_ as macros"));
147
148                InDir = new Parameter(this, "InDir", new StringToken(
149                                "Directory of the incoming file (input dir)"));
150
151                OutRemoteMachine = new Parameter(
152                                this,
153                                "OutRemoteMachine",
154                                new StringToken(
155                                                "Target host of the expected output file (usually same as RemoteMachine)"));
156
157                OutDir = new Parameter(this, "OutDir", new StringToken(
158                                "Directory of the expected output file"));
159
160                Ext = new Parameter(this, "Ext", new StringToken(
161                                "output file extension (replacing the input file extension)"));
162
163                ReplaceExt = new Parameter(this, "ReplaceExt", new BooleanToken(false));
164                doProcessing = new Parameter(this, "doProcessing", new BooleanToken(
165                                true));
166                doCkpt = new Parameter(this, "doCkpt", new BooleanToken(true));
167                doCheckOutput = new Parameter(this, "doCheckOutput", new BooleanToken(
168                                true));
169
170                LogHeader = new Parameter(this, "LogHeader", new StringToken(
171                                "Header string for logging"));
172
173                LogFile = new FileParameter(this, "LogFile");
174                LogFile.setExpression("$CWD" + File.separator + "kepler.log");
175
176                ErrorLogFile = new FileParameter(this, "ErrorLogFile");
177                ErrorLogFile.setExpression("$CWD" + File.separator + "kepler.err");
178
179                LogFormat = new Parameter(this, "LogFormat", new StringToken(
180                                "txt | xml"));
181
182                CkptFile = new FileParameter(this, "CkptFile");
183                CkptFile.setExpression("$CWD" + File.separator + "kepler.ckp");
184
185                StopFile = new Parameter(this, "StopFile", new StringToken(
186                                "Special file name which is bypassed in this actor"));
187
188                ErrorTokenName = new Parameter(this, "ErrorTokenName", new StringToken(
189                                "Special (file) name which is bypassed in this actor"));
190
191                HostStr = new Parameter(this, "HostStr", new StringToken(
192                                "replaces _HOST_ in the command string"));
193
194                timeoutSeconds = new Parameter(this, "timeoutSeconds", new IntToken(0));
195                timeoutSeconds.setTypeEquals(BaseType.INT);
196
197                cleanupAfterError = new Parameter(this, "cleanupAfterError",
198                                new BooleanToken(false));
199                cleanupAfterError.setTypeEquals(BaseType.BOOLEAN);
200
201                /* Hidden, expert Parameter */
202                thirdParty = new Parameter(this, "thirdParty", new StringToken(""));
203                thirdParty.setVisibility(Settable.EXPERT);
204
205        }
206
207        // //////////////// Public ports and parameters ///////////////////////
208
209        /**
210         * Input file to work on (recordtype {name=string, data=long, size=long})
211         */
212        public TypedIOPort filein;
213
214        /**
215         * Output file as result (recordtype {name=string, data=long, size=long})
216         */
217        public TypedIOPort fileout;
218
219        /**
220         * Substitutions (array of recordtype {name=string, value=string})
221         */
222        public TypedIOPort subs;
223
224        /**
225         * Output file as result (recordtype {name=string, data=long, size=long}).
226         * For provenance purposes. Info comes from the remote command.
227         */
228        public TypedIOPort provenanceout;
229
230        /**
231         * Target in user@host:port format. If user is not provided, the local
232         * username will be used. If port is not provided, the default port 22 will
233         * be applied. If target is "local" or empty string, the command will be
234         * executed locally, using Java Runtime.
235         */
236        public Parameter RemoteMachine;
237
238        /**
239         * The command to be executed on the remote host. It needs to be provided as
240         * a string.
241         */
242        public Parameter Command;
243
244        public Parameter InDir;
245        public Parameter OutRemoteMachine;
246        public Parameter OutDir;
247        public Parameter Ext;
248        public Parameter ReplaceExt;
249        public Parameter doProcessing;
250        public Parameter doCkpt;
251        public Parameter doCheckOutput;
252        public Parameter LogHeader;
253        public FileParameter LogFile;
254        public FileParameter ErrorLogFile;
255        public Parameter LogFormat;
256        public FileParameter CkptFile;
257        public Parameter StopFile;
258        public Parameter ErrorTokenName;
259        public Parameter HostStr;
260
261        /**
262         * Timeout in seconds for the command to be executed. 0 means waiting
263         * indefinitely for command termination.
264         */
265        public Parameter timeoutSeconds;
266
267        /**
268         * Enforce killing remote process(es) after an error or timeout. Unix
269         * specific solution is used, therefore you should not set this flag if
270         * connecting to other servers. But it is very useful for unix as timeout
271         * leaves processes living there, and sometimes errors too. All processes
272         * belonging to the same group as the remote command (i.e. its children)
273         * will be killed.
274         */
275        public Parameter cleanupAfterError;
276
277        /**
278         * Third party target in user@host:port format. If user is not provided, the
279         * local username will be used. If port is not provided, the default port 22
280         * will be applied.
281         */
282        public Parameter thirdParty;
283
284        // /////////////////////////////////////////////////////////////////
285        // // public methods ////
286
287        /**
288         * initialize() runs once before first exec
289         * 
290         * @exception IllegalActionException
291         *                If the parent class throws it.
292         */
293        public void initialize() throws IllegalActionException {
294                super.initialize();
295                _p = new Params(); // private class to store all actor parameters
296                _mappedLog = new MappedLog(); // for checkpoint file
297                boolean _xmlFormat = _p.strLogFormat.trim().equalsIgnoreCase("xml");
298                _sharedLog = new SharedLog(_xmlFormat); // for log and error log files
299
300        }
301
302        /**
303         * Send the token in the <i>value</i> parameter to the output.
304         * 
305         * @exception IllegalActionException
306         *                If it is thrown by the send() method sending out the
307         *                token.
308         */
309        public void fire() throws IllegalActionException {
310                super.fire();
311
312                // get the input token
313                RecordToken fileInToken = (RecordToken) filein.get(0);
314                String fileInName = getColumnString(fileInToken, "name");
315
316                // get the substitution record if connected
317                Token subsArray[] = null;
318                if (subs.getWidth() > 0) {
319                        ArrayToken subsArrayToken = (ArrayToken) subs.get(0);
320                        subsArray = subsArrayToken.arrayValue();
321                }
322
323                // get parameters
324                _p.update();
325
326                // cases when we just pass the token and do nothing
327                if (fileInName == null || fileInName.equals(_p.strStopFile) || // pass
328                                                                                                                                                // on
329                                                                                                                                                // Stop
330                                                                                                                                                // File
331                                fileInName.equals(_p.strErrorTokenName) || // pass on error
332                                                                                                                        // token
333                                !_p.bDoProcessing) { // pass on if doProcessing = false
334
335                        if (isDebugging)
336                                log.debug(_p.strLogHeader + ": Pass on token with name: "
337                                                + fileInName);
338                        // just send the incoming token out untouched
339                        fileout.send(0, fileInToken);
340                        return;
341                }
342
343                // get the expected output file name (replacing ext if requested)
344                String fileOutName = getOutfileName(fileInName);
345                if (isDebugging)
346                        log.debug(_p.strLogHeader + ": File output name = " + fileOutName);
347
348                // prepare the command string
349                // replace _INPUT_ _OUTPUT_ _INPATH_ _OUTPATH_ _HOST_ with the actual
350                // values
351                String command = prepareCommand(fileInName, fileOutName);
352                if (isDebugging)
353                        log.debug(_p.strLogHeader + ": Command = " + command);
354
355                // process the substitutions
356                command = substituteCommand(command, subsArray);
357                if (isDebugging)
358                        log.debug(_p.strLogHeader + ": Command = " + command);
359
360                // check if command was not executed already (checkpoint)
361                boolean ckptDone = _p.bDoCkpt
362                                && _mappedLog.check(CkptFile.asFile(), command);
363                if (isDebugging)
364                        log.debug(_p.strLogHeader + ":"
365                                        + (ckptDone ? " skip: " : " start: ") + command);
366                // make log statement no. 1: start or skip this command
367                _sharedLog.print(LogFile.asFile(), _p.strLogHeader,
368                                (ckptDone ? " skip: " : " start: ") + command);
369
370                // Execute command
371                int exitCode = 0;
372                if (!ckptDone) {
373                        exitCode = execCmd(command);
374                        if (isDebugging)
375                                log.debug(_p.strLogHeader + ":"
376                                                + (exitCode == 0 ? " succ: " : " fail: ") + command);
377                        // make log statement no. 2: succ'd or failed this command
378                        _sharedLog.print(LogFile.asFile(), _p.strLogHeader,
379                                        (exitCode == 0 ? " succ: " : " fail: ") + command);
380                }
381
382                // on success, add command to checkpoint (if requested)
383                if (exitCode == 0 && _p.bDoCkpt)
384                        _mappedLog.add(CkptFile.asFile(), command);
385
386                FileInfo outFile;
387                // produce the output token
388                if (exitCode == 0) { // successful execution
389                        // check the output file if requested
390                        if (_p.bDoCheckOutput) {
391
392                                outFile = checkOutputFile(fileOutName, command);
393
394                        } else { // just emit the name without checking it
395                                outFile = new FileInfo(fileOutName, getColumnLong(fileInToken,
396                                                "size"), getColumnLong(fileInToken, "date"));
397
398                        }
399                } else { // failed operation: emit an error token
400                        outFile = new FileInfo(_p.strErrorTokenName);
401                }
402
403                // send output file
404                fileout.send(0, createRecordToken(outFile));
405
406        } // end-method fire()
407
408        /**
409         * List file using DirectoryListing. Note: command is passed only for error
410         * logging purposes
411         */
412        private FileInfo checkOutputFile(String fname, String command)
413                        throws IllegalActionException {
414                String masks[] = new String[1];
415                masks[0] = fname;
416                DirectoryListing dl = new DirectoryListing(_p.strOutRemoteMachine,
417                                _p.strOutDir, masks);
418                FileInfo fi;
419
420                try {
421                        int n = dl.list();
422                        if (n > 0) {
423                                FileInfo files[] = dl.getList();
424                                if (files.length > 1) {
425                                        log.warn(_p.strLogHeader + ": Found more than one file ("
426                                                        + files.length + ") in " + _p.strOutRemoteMachine
427                                                        + ":" + _p.strOutDir + " with mask: " + fname);
428                                        _sharedLog.print(ErrorLogFile.asFile(), _p.strLogHeader,
429                                                        "WARNING at command: " + command
430                                                                        + "\nFound more than one file ("
431                                                                        + files.length + ") in "
432                                                                        + _p.strOutRemoteMachine + ":"
433                                                                        + _p.strOutDir + " with mask: " + fname);
434                                }
435                                fi = files[0];
436                        } else {
437                                // did not find result: send an error token
438                                log.error(_p.strLogHeader
439                                                + ": No output file is found with mask " + fname
440                                                + " in " + _p.strOutRemoteMachine + ":" + _p.strOutDir);
441                                _sharedLog.print(ErrorLogFile.asFile(), _p.strLogHeader,
442                                                "ERROR after command: " + command
443                                                                + "\nNo output file is found with mask "
444                                                                + fname + " in " + _p.strOutRemoteMachine + ":"
445                                                                + _p.strOutDir);
446                                fi = new FileInfo(_p.strErrorTokenName);
447                        }
448                } catch (ExecException ex) {
449                        log.error(_p.strLogHeader
450                                        + ": Error when trying to list output directory "
451                                        + _p.strOutRemoteMachine + ":" + _p.strOutDir + " :" + ex);
452                        _sharedLog.print(ErrorLogFile.asFile(), _p.strLogHeader,
453                                        "ERROR at command: " + command
454                                                        + "\nError when trying to list output directory "
455                                                        + _p.strOutRemoteMachine + ":" + _p.strOutDir
456                                                        + " :" + ex);
457                        fi = new FileInfo(_p.strErrorTokenName);
458                }
459                return fi;
460        }
461
462        /**
463         * Execute the command. Host and other parameters are taken from the global
464         * params. Return the exitcode, -32767 on ssh related error
465         */
466        private int execCmd(String command) throws IllegalActionException {
467                // Execute command on the remote machine (which can be the local
468                // machine)
469
470                int exitCode = 0;
471                ByteArrayOutputStream cmdStdout = new ByteArrayOutputStream();
472                ByteArrayOutputStream cmdStderr = new ByteArrayOutputStream();
473
474                // execute command
475                try {
476                        ExecInterface execObj = ExecFactory.getExecObject(_p.strRemoteMachine);
477                        execObj.setTimeout(_p.iTimeoutSeconds, false, false);
478                        execObj.setForcedCleanUp(_p.bCleanupAfterError);
479                        log.info("Exec cmd: " + command);
480                        exitCode = execObj.executeCmd(command, cmdStdout, cmdStderr,
481                                        _p.strThirdParty);
482                        if (exitCode != 0) {
483                                // print stdErr to error log if exitcode is non-zero (usually
484                                // means error)
485                                _sharedLog.print(ErrorLogFile.asFile(), _p.strLogHeader,
486                                                "ERROR at command: " + command + "\nExit code = "
487                                                                + exitCode + "\nStderr: " + cmdStderr);
488                        } else {
489                                // do some provenance`
490                                provenanceInfo(cmdStdout.toString(), command);
491                        }
492                } catch (ExecException e) {
493                        exitCode = -32767;
494                        String errText = new String("ExecuteCmd error:\n" + e.getMessage());
495                        if (isDebugging)
496                                log.debug(_p.strLogHeader + ":" + errText);
497                        _sharedLog.print(ErrorLogFile.asFile(), _p.strLogHeader,
498                                        "EXEC ERROR when trying to execute command: " + command
499                                                        + "\n" + errText);
500                }
501                return exitCode;
502        }
503
504        /**
505         * Provenance stuff. Prototype. expect lines like: --ProvenanceInfo
506         * name=ion__density.0001.jpg, date=1923982434, size=2855
507         */
508        private void provenanceInfo(String text, String command)
509                        throws IllegalActionException {
510                String lines[] = text.split("\n");
511                for (int i = 0; i < lines.length; i++) {
512                        String fields[] = lines[i].trim().split("( )+", 9);
513                        if (fields[0].startsWith("--ProvenanceInfo")) {
514                                String name = null;
515                                long date = -1, size = -1;
516                                int idx;
517                                int end = (fields.length < 3 ? 3 : fields.length - 1);
518                                // log.debug("--Provenance: end="+end+" field[1]="+fields[1]);
519                                for (int j = 1; j <= end; j++) {
520                                        idx = fields[j].indexOf("=");
521                                        if (idx != -1) {
522                                                String n = fields[j].substring(0, idx);
523                                                String v = fields[j].substring(idx + 1);
524                                                // log.debug("n="+n+"  v="+v);
525                                                if (n.equals("name"))
526                                                        name = v;
527                                                if (n.equals("date"))
528                                                        date = Long.parseLong(v);
529                                                if (n.equals("size"))
530                                                        size = Long.parseLong(v);
531                                        }
532                                }
533                                if (name != null) {
534                                        // send output file
535                                        provenanceout.send(0, createRecordToken(new FileInfo(name,
536                                                        size, date)));
537                                } else {
538                                        log.error(_p.strLogHeader
539                                                        + ": Invalid provenance info line from command '"
540                                                        + command + "': " + lines[i]);
541                                _sharedLog.print(ErrorLogFile.asFile(), _p.strLogHeader,
542                                                        "Invalid provenance info line from command '"
543                                                        + command + "': " + lines[i]);
544
545                                }
546                        }
547                }
548
549        }
550
551        /** RecordToken f --> String f.name */
552        private String getColumnString(RecordToken rt, String label) {
553                if (rt == null)
554                        return null;
555                StringToken st = (StringToken) rt.get(label);
556                if (st == null)
557                        return null;
558                return st.stringValue();
559        }
560
561        /** RecordToken f --> long f.<field> */
562        private long getColumnLong(RecordToken rt, String label) {
563                if (rt == null)
564                        return 0L;
565                LongToken lt = (LongToken) rt.get(label);
566                if (lt == null)
567                        return 0L;
568                return lt.longValue();
569        }
570
571        /**
572         * Replace the file extension of the file name if requested. extension and
573         * the boolean are taken from the global params.
574         */
575        private String getOutfileName(String in) {
576                if (!_p.bReplaceExt)
577                        return in;
578
579                int idx = in.lastIndexOf('.');
580                if (idx < 0)
581                        idx = in.length(); // no extension: append extension to the end of
582                                                                // name
583
584                return new String(in.substring(0, idx) + "." + _p.strExt);
585        }
586
587        /**
588         * Make the actual command string from the parameter command using other
589         * parameters and the actual input/output file names. Replace _INPUT_
590         * _OUTPUT_ _INPATH_ _OUTPATH_ _HOST_ with the actual values inName : input
591         * file's name outName : output file's expected name
592         */
593        private String prepareCommand(String inName, String outName) {
594                String cmd = _p.strCommand.replaceAll("_INFILE_", inName);
595                cmd = cmd.replaceAll("_OUTFILE_", outName);
596                cmd = cmd.replaceAll("_INPATH_", _p.strInDir + "/" + inName);
597                cmd = cmd.replaceAll("_OUTPATH_", _p.strOutDir + "/" + outName);
598                cmd = cmd.replaceAll("_HOST_", _p.strHost);
599                return cmd;
600        }
601
602        /**
603         * Make the actual command string from the parameter command by substituting
604         * name/value pairs in the string. command : the command string to be
605         * processed subsArray: array of RecordTokens of {name, value} In command,
606         * each 'name' found will be replaced by the corresponding value at all
607         * places.
608         */
609        private String substituteCommand(String command, Token subs[]) {
610                if (subs == null || subs.length == 0)
611                        return command;
612                String cmd = command;
613                for (int i = 0; i < subs.length; i++) {
614                        RecordToken rt = (RecordToken) subs[i];
615                        String name = getColumnString(rt, "name");
616                        String value = getColumnString(rt, "value");
617                        cmd = cmd.replaceAll(name, value);
618                }
619                return cmd;
620        }
621
622        /*
623         * Create one RecordToken of format {name=String, size=long, date=long} from
624         * the FileInfo struct.
625         */
626        private RecordToken createRecordToken(FileInfo fi) {
627                String[] labels = { "name", "size", "date" };
628                Token[] values = new Token[3];
629                values[0] = new StringToken(fi.getName());
630                values[1] = new LongToken(fi.getSize());
631                values[2] = new LongToken(fi.getDate());
632                RecordToken rt = null;
633                try {
634                        rt = new RecordToken(labels, values);
635                } catch (IllegalActionException ex) {
636                        log.error(_p.strLogHeader
637                                        + ": Error at creating a record token for fileinfo: " + fi
638                                        + "\nlabels = " + labels + "\nvalues = " + values);
639                }
640                return rt;
641        }
642
643        private class Params {
644
645                public String strRemoteMachine;
646                public String strCommand;
647                public String strInDir;
648                public String strOutRemoteMachine;
649                public String strOutDir;
650                public String strExt;
651                public boolean bReplaceExt;
652                public boolean bDoProcessing;
653                public boolean bDoCkpt;
654                public boolean bDoCheckOutput;
655                public String strLogHeader;
656                public String strLogFormat;
657                public String strStopFile;
658                public String strErrorTokenName;
659                public String strHost;
660                public int iTimeoutSeconds;
661                public boolean bCleanupAfterError;
662                public String strThirdParty;
663
664                public Params() throws IllegalActionException {
665                        this.update();
666                }
667
668                // process inputs
669                public void update() throws IllegalActionException {
670
671                        strRemoteMachine = ((StringToken) RemoteMachine.getToken())
672                                        .stringValue();
673                        strCommand = ((StringToken) Command.getToken()).stringValue();
674                        strInDir = ((StringToken) InDir.getToken()).stringValue();
675                        strOutRemoteMachine = ((StringToken) OutRemoteMachine.getToken())
676                                        .stringValue();
677                        strOutDir = ((StringToken) OutDir.getToken()).stringValue();
678                        strExt = ((StringToken) Ext.getToken()).stringValue();
679                        bReplaceExt = ((BooleanToken) ReplaceExt.getToken()).booleanValue();
680                        bDoProcessing = ((BooleanToken) doProcessing.getToken())
681                                        .booleanValue();
682                        bDoCkpt = ((BooleanToken) doCkpt.getToken()).booleanValue();
683                        bDoCheckOutput = ((BooleanToken) doCheckOutput.getToken())
684                                        .booleanValue();
685                        strLogHeader = ((StringToken) LogHeader.getToken()).stringValue();
686                        strLogFormat = ((StringToken) LogFormat.getToken()).stringValue();
687                        strStopFile = ((StringToken) StopFile.getToken()).stringValue();
688                        strHost = ((StringToken) HostStr.getToken()).stringValue();
689                        strErrorTokenName = ((StringToken) ErrorTokenName.getToken())
690                                        .stringValue();
691                        iTimeoutSeconds = ((IntToken) timeoutSeconds.getToken()).intValue();
692                        bCleanupAfterError = ((BooleanToken) cleanupAfterError.getToken())
693                                        .booleanValue();
694                        strThirdParty = ((StringToken) thirdParty.getToken()).stringValue();
695
696                        if (isDebugging)
697                                log.debug(strLogHeader + ": Parameters" +
698                                // "\nRemoteMachine = "+strRemoteMachine+
699                                                // "\nOutRemoteMachine = "+strOutRemoteMachine+
700                                                "\nCommand = " + strCommand +
701                                                // "\nInDir = "+strInDir+
702                                                // "\nOutDir = "+strOutDir+
703                                                "\ndoProcessing = " + bDoProcessing + "");
704
705                }
706
707        } // end class Params
708
709        private Type _etype; // in/out token type (a record)
710        private Type _substype; // substitution token type (a record)
711        private Params _p; // actor parameters stored in private class
712        private MappedLog _mappedLog; // checkpoint file (with memory hash)
713        private SharedLog _sharedLog; // log file and error log file
714
715        private static final Log log = LogFactory.getLog(ProcessFileRT.class
716                        .getName());
717        private static final boolean isDebugging = log.isDebugEnabled();
718}
719
720// vim: sw=4 ts=4 et