001    /*
002     * BashApplication.java
003     *
004     * Created on July 10, 2003, 11:22 AM
005     *
006     * This file is part of the STAR Scheduler.
007     * Copyright (c) 2002-2006 STAR Collaboration - Brookhaven National Laboratory
008     *
009     * STAR Scheduler is free software; you can redistribute it and/or modify
010     * it under the terms of the GNU General Public License as published by
011     * the Free Software Foundation; either version 2 of the License, or
012     * (at your option) any later version.
013     *
014     * STAR Scheduler is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017     * GNU General Public License for more details.
018     *
019     * You should have received a copy of the GNU General Public License
020     * along with STAR Scheduler; if not, write to the Free Software
021     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
022     */
023    package gov.bnl.star.offline.scheduler.Dispatchers.xgrid;
024    
025    import gov.bnl.star.offline.scheduler.*;
026    import gov.bnl.star.offline.scheduler.request.Request;
027    import gov.bnl.star.offline.scheduler.catalog.PhysicalFile;
028    //import gov.bnl.star.offline.scheduler.util.FileListToolkit;
029    //import gov.bnl.star.offline.scheduler.util.FilesystemToolkit;
030    //import gov.bnl.star.offline.scheduler.util.VariablesToolkit;
031    //import gov.bnl.star.offline.scheduler.util.ConfigToolkit;
032    import gov.bnl.star.offline.scheduler.util.*;
033    
034    
035    import gov.bnl.star.offline.scheduler.util.sandbox.*;
036     
037    import java.io.File;
038    import java.io.FileOutputStream;
039    import java.io.PrintStream;
040    
041    import java.util.*;
042    import java.util.logging.Level;
043    import java.util.logging.Logger;
044    
045    
046    /**
047     * Application module for csh.
048     * <p/>
049     * This module defines the interface of a csh task, and prepare the task
050     * information in the following environment variables:
051     * <p/>
052     * $JOBID - the unique job id given by the scheduler<br>
053     * $FILESLIST - the file name of a text file containing the file list assigned to
054     * the job<br>
055     * $INPUTFILECOUNT - the number of files assigned to the job<br>
056     * $INPUTFILExx - the input files associated to the job<br>
057     * <p/>
058     *
059     * @author Gabriele Carcassi, Jerome Lauret, Levente Hajdu
060     * @version 1.0 2002/12/26
061     */
062    public class BashApplication implements java.io.Serializable {
063        static private Logger log = Logger.getLogger(BashApplication.class.getName());
064        private Request request;
065        private Job job;
066        private String scratchDir = "Not_defined_in_config_file";
067        private String submissionCommand;
068        private Map variables;
069        private boolean variablesSet = false; 
070    
071        /**
072         * Holds value of property recurseCopy.
073         */
074        private boolean recurseCopy = false;
075    
076        /**
077         * Holds the value for the property of EnvVariableLimit
078         */
079        private int EnvVariableLimit;
080        private boolean EnvVariableLimitNotReached = true; //Set false if in "any" job the EnvVariableLimit was reached
081        
082        /**
083         * Holds value of property copyScript.
084         */
085        private String copyScript;
086    
087        /**
088         * Holds value of property storageScript.
089         */
090        private String storageScript;
091    
092        /**
093         * Holds value of property registerScript.
094         */
095        private String registerScript;
096    
097        /**
098         * Creates a new instance of CSHApplication
099         */
100        public BashApplication() {
101        }
102    
103        /** Returns the CSH application module. In the future, the application should
104         * be taken directly from the component library. This method is provided
105         * for compatibility with the old framework.
106         * @return the CSH application module
107         */
108    //    public static CSHApplication getInstance() {
109    //       // System.out.println("getting copy for ComponentLibrary");
110    //        //called aboat 11 times/dispach 
111    //        return (CSHApplication) ComponentLibrary.getInstance().getComponent("CSHApplication");
112    //    }
113        
114        
115        
116        /**
117         * Prepares the task, by creating the script.
118         */
119        public void prepareJob() {
120            try {
121    
122                PrintStream inputFileList = new PrintStream(new FileOutputStream(new File(getInputFileListName())));
123                createInputFileList(inputFileList);
124            } catch (Exception e) {
125                log.log(Level.SEVERE, "Couldn't create the file list", e);
126                throw new RuntimeException("Couldn't create the file list " + getInputFileListName() + ": " + e.getMessage());
127            }
128    
129            try {
130                PrintStream cshScript = new PrintStream(new FileOutputStream(new File(getCSHScriptName())));
131                createCSHScript(cshScript);
132                makeScriptFileExecutable(getCSHScriptName());
133    
134                cshScript.close(); //close the CSH stream, or else the job will not run
135    
136    
137            } catch (Exception e) {
138                log.log(Level.SEVERE, "Couldn't create the script", e);
139                throw new RuntimeException("Couldn't create the script " + getCSHScriptName() + ": " + e.getMessage());
140            }
141        }
142    
143        /**
144         * Returns the command line to execute the task set by <CODE>setJob</CODE>.
145         *
146         * @return Command line to execute the task
147         */
148        public String getCommandLine() {
149            return getCSHScriptName();
150        }
151    
152        //Hold the chmod string from the config file
153        private String makeExecutableCommand;
154    
155        /**
156         * Returns the chmod command from the config file
157         */
158        public String getMakeExecutableCommand() {
159            return makeExecutableCommand;
160        }
161    
162        public void setMakeExecutableCommand(String makeExecutableCommand) {
163            this.makeExecutableCommand = makeExecutableCommand;
164        }
165    
166    
167        /** Calls chmod to make the script executable. **/
168        private void makeScriptFileExecutable(String fileName) {
169            // Hack to make the Unit tests work on windows.
170            // chmod doesn't exist on Windows (if you don't have cygwin)
171            if (System.getProperty("os.name").startsWith("Win")) return;
172    
173            try {
174                // TODO: chmod should be a variable. This routine
175                // itself should be OS-flavor independent.
176                
177                String chmod = getMakeExecutableCommand() + fileName;
178                //String chmod = "/bin/chmod +x " + fileName;
179                
180                log.info("Executing \"" + chmod + "\"");
181    
182                java.lang.Process shell = Runtime.getRuntime().exec(chmod);
183                shell.waitFor();
184            } catch (Exception e) {
185                log.log(Level.SEVERE, "Couldn't make the script executable", e);
186                throw new RuntimeException("Couldn't make the script " + fileName +
187                        " executable", e);
188            }
189        }
190    
191        /**
192         * Sets the task the application will have to prepare.
193         *
194         * @param request the request that originated the task
195         * @param job     the job to be executed
196         */
197        public void setJob(Request request, Job job) {
198            this.request = request;
199            this.job = job;
200            scratchDir = null;
201            submissionCommand = null;
202            variables = null;
203            variablesSet = false;
204            
205            
206            this.scratchDir = ConfigToolkit.findProgram("$SCRATCH", job);
207            
208    //        if (job.getQueueObj().getBatchSystem().getSite().getProgramLocations() == null)
209    //            System.out.println("\nCan't find \"ProgramLocations\" block in " + job.getQueueObj().getBatchSystem().getSite().getSiteName() + "(Site) -->" + job.getQueueObj().getBatchSystem().getName() + "(BatchSystem) block in config file $SCRATCH could not be set !. Please contact your SUMS systems administrator to modify the config file.");
210    //        else {
211    //            if (job.getQueueObj().getBatchSystem().getSite().getProgramLocations().containsKey("$SCRATCH"))
212    //                this.scratchDir = (String) job.getQueueObj().getBatchSystem().getSite().getProgramLocations().get("$SCRATCH");
213    //            else
214    //                System.out.println("\nThe \"$SCRATCH\" value could not be found in the ProgramLocations map of site=\"" + job.getQueueObj().getBatchSystem().getSite().getSiteName() + "\". Please contact your SUMS systems administrator to modify the config file.");
215    //        }
216            
217            
218    
219        }
220    
221        /** Sets the scratch directory for the temporary output files of the job.
222         * @param scratchDir the temporary output directory
223         */
224        /*
225        public void setScratchDir(String scratchDir) {
226            this.scratchDir = scratchDir;
227        } */
228    
229        /**
230         * Sets the submittion command used to submit the job. This will be included in the
231         * script for resubmission.
232         *
233         * @param submissionCommand the command line to submit the job to the batch system
234         */
235        public void setSubmissionCommand(String submissionCommand) {
236            this.submissionCommand = submissionCommand;
237        }
238    
239        /**
240         * Generates the csh script to be submitted through LSF.
241         *
242         * @param out the stream on which to print the script
243         */
244        private void createCSHScript(PrintStream out) {
245            // Sets the shell that will interpret the script
246            
247            ////////////test area////////////////
248            Map config = (Map) ComponentLibrary.getInstance().getComponent("registerScript");
249    
250            out.println("#!/bin/csh");
251            //out.println("#!/bin/sh");
252    
253            out.println("# -------------------------------------- ");
254            out.println("# Script generated  at " + new Date() +
255                    " by the STAR scheduler and submitted with");
256            out.println("# " + submissionCommand);
257            out.println("# -------------------------------------- ");
258            
259            out.println("\n" + getInitializationScript());
260    
261            Map env = getEnvironmentVariables();
262            Iterator variables = env.keySet().iterator();
263            Iterator FilesNameVariable = env.keySet().iterator();
264    
265            // Sets all the environment variable.
266            out.println();
267            out.println("# Preparing environment variables");
268    
269            String varName, varValue;
270    
271    
272            int counter = 0;
273            String padding = "";
274            while (variables.hasNext()) { //First pass prints all the environment variables that do not start with "INPUTFILE" 
275                varName = (String) variables.next();
276                varValue = (String) env.get(varName);
277                if ((!varName.startsWith("INPUTFILE")) || (varName.matches("INPUTFILECOUNT"))) {
278                    out.println(padding + "setenv " + varName + " " + varValue);
279                }
280            }
281    
282            while (FilesNameVariable.hasNext()) { //Second pass prints all the environment variables that start with "INPUTFILE"
283                varName = (String) FilesNameVariable.next();
284                varValue = (String) env.get(varName);
285                if (varName.startsWith("INPUTFILE") && (!varName.matches("INPUTFILECOUNT"))) {
286                    if (counter == EnvVariableLimit) {
287                        out.println("#");
288                        out.println("# Note: The configuration requested a limitation of the");
289                        out.println("# number of INPUTFILE(n) environemnt variables at " + EnvVariableLimit);
290                        out.println("# The rest of the variables will be commented.");
291                        out.println("#");
292                        padding = "# ";
293                        
294                        if(EnvVariableLimitNotReached){ //Print the warning to the user only one time then flip EnvVariableLimitNotReached to false 
295                            System.out.println("\n\n***************************************");
296                            System.out.println("The configuration requested a limitation of the number of INPUTFILE(n) environment variables at " + EnvVariableLimit + ", the rest will be commented out.\n");
297                            System.out.println("***************************************\n");
298                            EnvVariableLimitNotReached = false;
299                        }   
300                    }
301                    counter++;
302                    out.println(padding + "setenv " + varName + " " + varValue);
303                }
304            }
305    
306            /* MLM
307            // Creates the scratch directory
308            out.println();
309            out.println("# Creating the scratch directory, return failure status");
310            out.println("mkdir -p $SCRATCH");
311            out.println("set STS=$status");
312            out.println("if (! -d $SCRATCH) then");
313            out.println("    echo \"Scheduler:: Failed to create $SCRATCH on $HOST\"");
314            out.println("    exit $STS");
315            out.println("endif");
316             */
317            
318    
319            if(request.getSandbox() != null){
320                out.println();
321                out.println(importPakages());
322            }
323          
324            
325            out.println();
326            out.println("#Note: The default directory in which jobs start has be fix to $SCRATCH");
327            out.println("cd $SCRATCH"); //Note: This line sets the startup directory to $SCRATCH. It resolves the problem of different batch systems starting in different directories. 
328            
329    
330            out.println("echo \"--------------------------------\"");
331            out.println("echo \'" + gov.bnl.star.offline.scheduler.SchedulerCommandLine.getProgramName() + " we are starting in $SCRATCH :\' `/bin/pwd`");
332            out.println("echo \"--------------------------------\"");
333            out.println("/bin/ls -l");
334    
335            // soft linking to home dir removed for now because sandbox will replace this command 
336            //out.println("ln -s " + FilesystemToolkit.getCurrentDirectory() + "/* ."); //Note: This line sets the startup directory to $SCRATCH. It resolves the problem of different batch systems starting in different directories. 
337            
338    
339            // Adds the command to be executed
340            out.println();
341            out.println("###################################################");
342            //out.println("/bin/csh -s ___EOD"+job.getJobID()+"__");
343            out.println("# User command BEGIN ----------------------------->");
344            
345            //Let the RDLApplicationResolver try to resolve the test, if it can not use the back up
346            //if(request.getCommand() != null)
347            
348            
349            if (job.getQueueObj() != null && request.getCommand() == null) {
350                if (job.getQueueObj().getRDLApplicationResolver() != null)
351                    out.println(job.getQueueObj().getRDLApplicationResolver().resolve(request.getApplication(), request.getTask()));
352                else
353                    out.println(request.getCommand());
354            } else
355                out.println(request.getCommand());
356    
357    
358            out.println("# <------------------------------User command BEGIN");
359            //out.println("___EOD"+job.getJobID()+"__");
360            out.println("###################################################");
361    
362            // Copy output files
363            out.println();
364            out.println("# Copy output files (if any where specified)");
365            out.print(generateScriptFragment(request.getOutputList()));
366            
367            /* MLM
368            // Delete the scratch directory
369            out.println();
370            out.println("# Delete the scratch directory");
371            out.println("/bin/rm -fr $SCRATCH");
372             */
373        }
374    
375        String generateScriptFragment(List outputList) {
376            StringBuffer buffer = new StringBuffer();
377    
378            String scriptsString = " ";
379            for (int nOutput = 0; nOutput < outputList.size(); nOutput++) {
380                OutputFile output = (OutputFile) outputList.get(nOutput);
381                if (output.getActionList().size() != 0) {
382                    for (int nOutputAction = 0; nOutputAction < output.getActionList().size(); nOutputAction++) {
383                        String script = ((OutputAction) output.getActionList().get(nOutputAction)).getScriptName();
384                        if (scriptsString.indexOf(script) == -1)
385                            scriptsString = scriptsString.concat(script + " ");
386                    }
387                }
388            }
389            
390            //TODO think about how this can be moved to the config file
391            
392            //copy output actions sripts to the local site
393            /*
394            if (scriptsString.length() != 1) {
395                //This only should be used for pdsf, but its hard coded for testing now
396                buffer.append("setenv X509_CERT_DIR /auto/pkg/globus-common/certificates \n");
397                buffer.append("module use /usr/local/pkg/HRM/pkg/modules/rh8 \n");
398                buffer.append("module load hrm/1.2.8a \n");
399                buffer.append("module load globus/2.4.3 orbacus \n");
400                buffer.append("module load rrs \n");
401                buffer.append("module load gcc/2.95.3-thread \n");
402                buffer.append("foreach file (" + scriptsString + ")\n" +
403                        "   globus-url-copy -p 25 gsiftp://" + ConfigToolkit.getToolkit().myLocalFileGateKeeper().getName() + getHelperScripts() + "$file  file:$SCRATCH/$file \n" +
404                        "   chmod +x $file\n" +
405                        "end \n");
406            } */
407            
408    
409            for (int nOutput = 0; nOutput < outputList.size(); nOutput++) {
410    
411                OutputFile output = (OutputFile) outputList.get(nOutput);
412                if (output.getActionList().size() != 0) {
413    
414                    //buffer.append("setenv OUTPUTFILE").append(nOutput).append(" file:/$SCRATCH/").append(output.getFromScratch()).append("\n");
415                    
416                  
417                    for (int nOutputAction = 0; nOutputAction < output.getActionList().size(); nOutputAction++) {
418    
419    
420                        // if (output.getActionList().get(nOutputAction) instanceof OutputCopyAction) {
421                        //     buffer.append(generateScriptFragment(nOutput, (OutputCopyAction) output.getActionList().get(nOutputAction)));
422                        // } else if (output.getActionList().get(nOutputAction) instanceof OutputRegisterAction) {
423                        //     buffer.append(generateScriptFragment(nOutput, (OutputRegisterAction) output.getActionList().get(nOutputAction)));
424                        // } else {
425                        //     log.severe("Unsupported OutputAction time found: " + output.getActionList().get(nOutputAction).getClass().getName());
426                        //     throw new RuntimeException("Unsupported OutputAction time found");
427                        // }
428                        
429                        OutputAction outputAction = (OutputAction) output.getActionList().get(nOutputAction);
430                        buffer.append(outputAction.makeScriptString(output.getFromScratch(), ConfigToolkit.getToolkit().myLocalFileGateKeeper().getName()));
431    
432                        //System.out.println(" " + outputAction.getScriptName());
433                        //outputAction.getScriptName();
434    
435                    }
436                } else {
437    
438                    //This code copys files back from FromScratch at the uers request //the path has should be added
439                    //String gridCopy = "globus-url-copy file://$SCRATCH/".concat(output.getFromScratch()).concat(" ").concat("gsiftp://").concat(getGatekeepr()).concat("/").concat(output.getToURL().getPath()).concat("\n");
440                    String gridCopy = FillCopyCommand(getGridCopyCommand(), output.getFromScratch(), output.getToURL().getPath(), true) + "\n";
441                    String cpCopy = FillCopyCommand(getCopyCommand(), output.getFromScratch(), output.getToURL().getPath(), false) + "\n";
442                    if (recurseCopy) cpCopy = FillCopyCommand(getRecursiveCopyCommand(), output.getFromScratch(), output.getToURL().getPath(), false) + "\n";
443                    
444                    
445                    
446                    
447                    /* This code was replaced with the code below. With the configuration file reshape, the type of queue (local/grid) can be determined by looking at the user�s local site and the queues local site.
448                    if(output.getToURL().toString().toLowerCase().startsWith("gsiftp:")){
449                        buffer.append(gridCopy);
450                    }
451                    //else if the user starts his request with file: then use cp
452                    else if(output.getToURL().toString().toLowerCase().startsWith("file:")){
453                        buffer.append(cpCopy);
454                    } 
455                    // else if the jobs is sent to a queue that has Implementation = "grid" than use globus-url-copy
456                    else if (((Queue) job.getQueueObj()).getImplementation().startsWith("grid")){
457                        buffer.append(gridCopy);
458                    }
459                    else{ //just use cp if all else fails
460                        buffer.append(cpCopy);
461                    } 
462                    */
463                    
464                    
465                    if (ConfigToolkit.getToolkit().isLocalQueue(job.getQueueObj())) {
466                        buffer.append(cpCopy);
467                    } else {
468                        buffer.append(gridCopy);
469                    }
470    
471    
472                }
473            }
474            return buffer.toString();
475        }
476    
477        
478        /** deprecated  **/
479        String generateScriptFragment(int nOutput, OutputCopyAction action) {
480            /*
481          StringBuffer fragment = new StringBuffer();
482             if (action.getFileRef() != null) {
483                 if (action.getStorageService() != null) {
484                     fragment.append("setenv OUTPUTFILE").append(nOutput).append('_').
485                     append(action.getFileRef()).append(" `").append(getStorageScript()).
486                     append(" \"").append(action.getStorageService()).append("\" `").
487                     append(action.getURI().getPath()).append("\n");
488    
489                 } else {
490                     fragment.append("setenv OUTPUTFILE").append(nOutput).append('_').
491                     append(action.getFileRef()).append(" ").
492                     append(action.getURI()).append("\n");
493                 }
494                 fragment.append(getCopyScript()).append(" $OUTPUTFILE").append(nOutput).
495                 append(" $OUTPUTFILE").append(nOutput).append('_').append(action.getFileRef()).
496                 append("\n");
497             } else {
498                 fragment.append(getCopyScript()).append(" $OUTPUTFILE").append(nOutput);
499                 if (action.getStorageService() != null) {
500                     fragment.append(" `").append(getStorageScript()).append(" \"").append(action.getStorageService()).append("\" `").append(action.getURI().getPath()).append("\n");
501                 } else {
502                     fragment.append(" ").append(action.getURI()).append("\n");
503                 }
504             }
505             return fragment.toString();
506             */ return " ";
507        }
508    
509        /** deprecated  **/
510        String generateScriptFragment(int nOutput, OutputRegisterAction action) {
511            /*
512            StringBuffer fragment = new StringBuffer();
513            fragment.append(getRegisterScript()).append(" $OUTPUTFILE").append(nOutput);
514            if (action.getFileRef() != null) {
515                fragment.append('_'). append(action.getFileRef());
516            }
517            int queryStart = action.getURI().getSchemeSpecificPart().indexOf('?');
518            queryStart++;
519            fragment.append(" '").append(action.getURI().getSchemeSpecificPart().substring(queryStart)).append("'\n");
520            return fragment.toString();
521             */ return " ";
522        }
523    
524        /**
525         * Generates the input file list. It consists of full path names, one line for each
526         * one.
527         *
528         * @param out the stream on which to print the file list
529         */
530        private void createInputFileList(PrintStream out) {        
531            //printJobInputList(job.getInput());
532            
533            variables = new TreeMap();
534            
535            if ("paths".equals(request.getFileListType())) {
536                FileListToolkit.createPathsFileList(out, job.getInput(), variables);
537            } else if ("rootd".equals(request.getFileListType())) {
538                FileListToolkit.createLocalRemoteFileList(out, job.getInput(), variables, false);
539            } else if ("xrootd".equals(request.getFileListType())) {
540                FileListToolkit.createLocalRemoteFileList(out, job.getInput(), variables, true);
541            }
542        }
543        private void printJobInputList(List jobList){
544            System.out.println("-----------------------------------------------");
545            for (int i = 0; i < jobList.size(); i++) {
546              PhysicalFile physicalFile = (PhysicalFile) jobList.get(i);
547              System.out.println("File n."+i+ "is:"+physicalFile.getStorage()+"::"+physicalFile.getPath()+"::"+physicalFile.getFilename());
548              System.out.println("\n");
549          }
550            System.out.println("------------------------------------------------\n");
551        }
552    
553        /**
554         * Returns the path and name for the csh script.
555         *
556         * @return the csh script path and name
557         */
558        public String getCSHScriptName() {
559            
560            //return FilesystemToolkit.getCurrentDirectory() + "/sched" + job.getJobID() + ".csh";
561            return FilesystemToolkit.getCurrentDirectory() + "/" + getCSHScriptFileName();
562            
563        }
564    
565    
566        /**
567         * Returns the name for the csh script (without the path).
568         *
569         * @return the csh script name (without the path)
570         */
571        public String getCSHScriptFileName() {
572            /*
573           The path is being dropped because different drivers for mounting the PanFS path are reporting the path differently. Instated we will put �cd $path� before the command we execute.
574           Example:
575           /pdirect/star+institutions/data05/scratch/lbhajdu/p-w
576           /star/data05/scratch/lbhajdu/
577           */
578            return this.getJobName() + "sched" + job.getJobID() + ".csh";
579        }
580    
581    
582        /**
583         * Returns the name for the input file list file.
584         *
585         * @return the input file list name
586         */
587        public String getInputFileListName() {
588            //return FilesystemToolkit.getCurrentDirectory() + "/" + this.getJobName() + "sched" + job.getJobID() + ".list";
589            return "sched" + job.getJobID() + ".list";
590        }
591    
592    
593        private Map getEnvironmentVariables() {
594                    
595            if (variables == null) variables = new TreeMap();  //This can still be null if there is no filelist
596            if(variables.containsKey("JOBID")) return variables;  //if added one time do not add then again 
597            
598            variables.put("JOBID", job.getJobID());
599            
600            variables.put("REQUESTID", job.getRequestID());
601            variables.put("PROCESSID", job.getProcessID());
602    
603            // FIXME: scratch dir should be passed in a nicer way
604            variables.put("SCRATCH", scratchDir);
605            
606            variables.put("FILELIST", getInputFileListName());
607    
608            List inputList = job.getInput();
609            variables.put("INPUTFILECOUNT", Integer.toString(inputList.size()));
610    
611              //This is now done in FileListToolkit 
612    //        for (int nFile = 0; nFile < inputList.size(); nFile++) {
613    //            PhysicalFile file = (PhysicalFile) inputList.get(nFile);
614    //            variables.put("INPUTFILE" + nFile, file.getPath() + "/" + file.getFilename());
615    //        }
616            
617           
618            //If there is only one input file per csh make an Environment Variable called FILEBASENAME
619            if (inputList.size() == 1) {
620                PhysicalFile file = (PhysicalFile) inputList.get(0);
621                if (!(file.getFilename().indexOf(".") == -1))
622                    variables.put("FILEBASENAME", file.getFilename().substring(0, file.getFilename().indexOf(".")));
623                else
624                    variables.put("FILEBASENAME", file.getFilename());
625            } else { //All other times FILEBASENAME will be set to this value
626                //variables.put("FILEBASENAME", "FILEBASENAME.NOT.INITIALIZED." + job.getJobID());
627                variables.put("FILEBASENAME", "\"\"");  //Blank is better because people may use the variable FILEBASENAME. (JL, LH)
628            }
629            
630    
631            String APP = ConfigToolkit.findProgram("$APP", job);   //ComponentLibrary.getInstance().getProgramLocation(job.getQueueObj().getBatchSystem().getSite(), "$APP");
632            if(APP != null){
633                APP = APP.trim();
634                if(APP.trim() != "") variables.put("APP", APP);
635            }
636            
637            String DATA =  ConfigToolkit.findProgram("$DATA", job);  //ComponentLibrary.getInstance().getProgramLocation(job.getQueueObj().getBatchSystem().getSite(), "$DATA");
638            if(DATA != null){
639                DATA = DATA.trim();
640                if(DATA.trim().length() > 0) variables.put("DATA", DATA);
641            }
642    
643            return variables;
644        }
645    
646        /**
647         * Returns the file for standard input redirection.
648         *
649         * @return stdin file
650         */
651        public String getStdin() {
652            if (job.getStdin() != null) {
653                return VariablesToolkit.substituteVariables(job.getStdin().getPath(), this.getEnvironmentVariables());
654                //CSHApplication.getInstance().getEnvironmentVariables());
655            }
656    
657            return null;
658        }
659    
660        /**
661         * Returns the file for standard output redirection.
662         *
663         * @return stdout file
664         */
665        public String getStdout() {
666            if (job.getStdout() != null) {
667                if (job.getStdout() == Request.discard) {
668                    return "/dev/null";
669                }
670    
671                return VariablesToolkit.substituteVariables(job.getStdout().getPath(), this.getEnvironmentVariables());
672                // CSHApplication.getInstance().getEnvironmentVariables());
673            }
674    
675            return null;
676        }
677    
678        /**
679         * Returns the file for standard error redirection.
680         *
681         * @return stderr file
682         */
683        public String getStderr() {
684            if (job.getStderr() != null) {
685                if (job.getStderr() == Request.discard) {
686                    return "/dev/null";
687                }
688    
689                return VariablesToolkit.substituteVariables(job.getStderr().getPath(), this.getEnvironmentVariables());
690                //CSHApplication.getInstance().getEnvironmentVariables());
691            }
692    
693            return null;
694        }
695    
696        /**
697         * Returns the job name to be assigned to the batch system.
698         *
699         * @return the job name to be used by the batch system
700         */
701        public String getJobName() {
702            return request.getName();
703        }
704    
705        /**
706         * Getter for property recurseCopy.
707         *
708         * @return Value of property recurseCopy.
709         */
710        public boolean isRecurseCopy() {
711            return this.recurseCopy;
712        }
713    
714        /**
715         * Setter for property recurseCopy.
716         *
717         * @param recurseCopy New value of property recurseCopy.
718         */
719        public void setRecurseCopy(boolean recurseCopy) {
720            this.recurseCopy = recurseCopy;
721        }
722    
723    
724        /**
725         * Getter for property EnvVariableLimit.
726         *
727         * @return Value of property EnvVariableLimit.
728         */
729        public int getEnvVariableLimit() {
730            return this.EnvVariableLimit;
731        }
732    
733        /**
734         * Setter for property EnvVariableLimit.
735         *
736         * @param EnvVariableLimit New value of property EnvVariableLimit.
737         */
738        public void setEnvVariableLimit(int EnvVariableLimit) {
739            this.EnvVariableLimit = EnvVariableLimit;
740        }
741    
742    
743        /**
744         * Getter for property copyScript.
745         *
746         * @return Value of property copyScript.
747         */
748        public String getCopyScript() {
749            return this.copyScript;
750        }
751    
752        /**
753         * Setter for property copyScript.
754         *
755         * @param copyScript New value of property copyScript.
756         */
757        public void setCopyScript(String copyScript) {
758            this.copyScript = copyScript;
759        }
760    
761        /**
762         * Getter for property storageScript.
763         *
764         * @return Value of property storageScript.
765         */
766        public String getStorageScript() {
767            return this.storageScript;
768        }
769    
770        /**
771         * Setter for property storageScript.
772         *
773         * @param storageScript New value of property storageScript.
774         */
775        public void setStorageScript(String storageScript) {
776            this.storageScript = storageScript;
777        }
778    
779        /**
780         * Getter for property registerScript.
781         *
782         * @return Value of property registerScript.
783         */
784        public String getRegisterScript() {
785            return this.registerScript;
786        }
787    
788        /**
789         * Setter for property registerScript.
790         *
791         * @param registerScript New value of property registerScript.
792         */
793        public void setRegisterScript(String registerScript) {
794            this.registerScript = registerScript;
795        }
796    
797    
798        private String gridCopyCommand = "(gridCopyCommand not set in config file file!)";
799    
800        /**
801         * sets the command for copying files back, when the user asks for <output fromScratch="/path/x" toURL="gsiftp:/path/x"/>
802         * use (fromScratch) for source and (toURL) for destination.
803         * Example: globus-url-copy file://$SCRATCH/(fromScratch) gsiftp://stragrid04.star.bnl.gov/(toURL)
804         */
805        public void setGridCopyCommand(String gridCopyCommand) {
806            this.gridCopyCommand = gridCopyCommand;
807        }
808    
809        public String getGridCopyCommand() {
810            return gridCopyCommand;
811        }
812    
813        private String CopyCommand = "(CopyCommand not set in config file file!)";
814    
815        /**
816         * sets the command for copying files back, when the user asks for <output fromScratch=x toURL="file:/path/"/>
817         * use (fromScratch) for source and (toURL) for destination.
818         * Example: /bin/cp $SCRATCH/(fromScratch) (toURL)
819         */
820        public void setCopyCommand(String CopyCommand) {
821            this.CopyCommand = CopyCommand;
822        }
823    
824        public String getCopyCommand() {
825            return CopyCommand;
826        }
827    
828        private String recursiveCopyCommand = "(recursiveCopyCommand not set in config file file!)";
829    
830        /**
831         * sets the command for copying files back, when the user asks for <output fromScratch=x toURL="file:/path/"/>
832         * use (fromScratch) for source and (toURL) for destination.
833         * Example: /bin/cp -r $SCRATCH/(fromScratch) (toURL)
834         */
835        public void setRecursiveCopyCommand(String recursiveCopyCommand) {
836            this.recursiveCopyCommand = recursiveCopyCommand;
837        }
838    
839        public String getRecursiveCopyCommand() {
840            return recursiveCopyCommand;
841        }
842    
843        /**
844         * replaces the (fromScratch) and the (toURL) in the copy command with the true path
845         */
846        public String FillCopyCommand(String command, String fromScratch, String toURL, boolean isGrid) {
847    
848            if (!isGrid) {
849                if (fromScratch.matches("^\\Q./\\E.*"))
850                    fromScratch = fromScratch.replaceAll("(^\\Q.\\E)(.*)", "`pwd`$2");
851                else
852                    fromScratch = "$SCRATCH/".concat(fromScratch);
853            }
854    
855            StringBuffer buffer = new StringBuffer();
856            buffer.append(command);
857            while (buffer.indexOf("(fromScratch)") != -1) {
858                buffer.replace(buffer.indexOf("(fromScratch)"), (buffer.indexOf("(fromScratch)") + "(fromScratch)".length()), fromScratch);
859            }
860    
861            while (buffer.indexOf("(toURL)") != -1) {
862                buffer.replace(buffer.indexOf("(toURL)"), (buffer.indexOf("(toURL)") + "(toURL)".length()), toURL);
863            }
864    
865    
866            while (buffer.indexOf("(copyBackGateKeeper)") != -1) {
867                //ConfigToolkit.getToolkit().myLocalFileGateKeeper().getName();
868                buffer.replace(buffer.indexOf("(copyBackGateKeeper)"), (buffer.indexOf("(copyBackGateKeeper)") + "(copyBackGateKeeper)".length()), ConfigToolkit.getToolkit().myLocalFileGateKeeper().getName());
869            }
870            
871            //This did not working, it would fail with "Illegal group reference" when fromScratch or toURL had a '$' in it.
872            //return command.replaceAll("\\(fromScratch\\)", fromScratch).replaceAll("\\(toURL\\)", toURL); 
873            
874            return buffer.toString();
875    
876        }
877    
878    
879        private String helperScripts = "[helper_script_path_not_set]";
880    
881        public String getHelperScripts() {
882            return helperScripts;
883        }
884    
885        public void setHelperScripts(String helperScripts) {
886            this.helperScripts = helperScripts;
887        }
888        
889        private String initializationScript = "";
890        public String getInitializationScript(){return this.initializationScript; }
891        public void setInitializationScript(String initializationScript){this.initializationScript = initializationScript;    }
892        
893    
894        public String importPakages(){
895            String importPakagesText = "\n#import pakages \n";
896            
897            Sandbox sandbox = request.getSandbox();
898    
899            //Add warnings about special sandbox grid requirements here:
900            if(! ConfigToolkit.getToolkit().isLocalQueue(job.getQueueObj())){
901                
902                if(sandbox.getClass().getName().matches(".*ZipSandbox$")){
903                    if (! getEnvironmentVariables().containsKey("DATA")){
904                        String Warning = "Warning: Scheduler has no configuration information for $DATA at site " + job.getAccessPoint().getSite().getSiteName() + ". If $DATA is not set in the environment of the worker node the sandbox will fail. For more information please contact your scheduler administrator.";
905                        System.out.println("\n\n" + Warning + "\n");
906                        log.log(Level.SEVERE, Warning);
907                    } 
908                }        
909            }
910            
911            
912            
913            importPakagesText = importPakagesText.concat(sandbox.InitializationCommands()); 
914    
915            List packages = sandbox.getPackages();
916            
917            for(int i = 0; i != packages.size(); i++){
918                SandboxPackage sandboxPackage = (SandboxPackage) packages.get(i);
919    
920                if(! sandbox.PackageExists(sandboxPackage)){ //This to see if the package dose not exist
921                    //make the package
922                    sandbox.MakePackage(sandboxPackage, request);
923                }
924    
925                importPakagesText = importPakagesText.concat(sandbox.installCommand(sandboxPackage, job));
926            }
927                
928            return importPakagesText;
929        }
930    
931    }