View Javadoc

1   /*
2    * $Id: DefaultCommandLineParameterAdapter.java,v 1.4 2004/12/18 15:43:57 jdt Exp $
3    * 
4    * Created on 20-Aug-2004 by Paul Harrison (pah@jb.man.ac.uk)
5    * Copyright 2004 AstroGrid. All rights reserved.
6    *
7    * This software is published under the terms of the AstroGrid 
8    * Software License version 1.2, a copy of which has been included 
9    * with this distribution in the LICENSE.txt file.  
10   *
11   */
12  
13  package org.astrogrid.applications.commandline;
14  
15  import org.apache.commons.logging.Log;
16  import org.apache.commons.logging.LogFactory;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileOutputStream;
21  import java.io.FileReader;
22  import java.io.FileWriter;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.InputStreamReader;
26  import java.io.OutputStream;
27  import java.io.PrintWriter;
28  import java.io.Reader;
29  import java.io.StringWriter;
30  import java.io.Writer;
31  import java.util.List;
32  
33  import org.astrogrid.applications.CeaException;
34  import org.astrogrid.applications.beans.v1.parameters.ParameterValue;
35  import org.astrogrid.applications.description.ApplicationInterface;
36  import org.astrogrid.applications.description.ParameterDirection;
37  import org.astrogrid.applications.description.exception.ParameterNotInInterfaceException;
38  import org.astrogrid.applications.parameter.AbstractParameterAdapter;
39  import org.astrogrid.applications.parameter.ParameterAdapter;
40  import org.astrogrid.applications.parameter.ParameterAdapterException;
41  import org.astrogrid.applications.parameter.ParameterWriteBackException;
42  import org.astrogrid.applications.parameter.protocol.ExternalValue;
43  import org.astrogrid.io.Piper;
44  
45  /***
46   * Does the specialized job for the CommandLine parameters. The Main differences
47   * from the
48   * 
49   * @link org.astrogrid.applications.parameter.DefaultParameterAdapter are
50   *       <ul>
51   *       <li>need to be able to deal with the extra possible "indirection"
52   *       level that the command line parameter can appear as a file for the
53   *       command line application, even when presented as a direct parameter to
54   *       the
55   * @link org.astrogrid.applications.service.v1.cea.CommonExecutionConnector
56   *       interface.
57   *       <li>needs to be able to activate the "command line decoration" -
58   *       switches etc.
59   *       </ul>
60   * @author Paul Harrison (pah@jb.man.ac.uk) 20-Aug-2004
61   * @version $Name:  $
62   * @since iteration6
63   */
64  public class DefaultCommandLineParameterAdapter extends AbstractParameterAdapter implements CommandLineParameterAdapter {
65      /***
66       * Logger for this class
67       */
68      private static final Log logger = LogFactory
69              .getLog(DefaultCommandLineParameterAdapter.class);
70  
71      protected boolean isOutputOnly;
72  
73   
74      protected File referenceFile = null;
75  
76      protected final CommandLineApplicationEnvironment env;
77  
78      /*** This is the raw value of the parameter that should be passed to the commandLine -i.e. after processing, but before having the commandline switches added. 
79       */
80      protected String commandLineVal;
81  
82      protected final CommandLineParameterDescription cmdParamDesc;
83  
84      public DefaultCommandLineParameterAdapter(ApplicationInterface appInterface,
85              ParameterValue pval, CommandLineParameterDescription desc,
86              ExternalValue indirect, CommandLineApplicationEnvironment env) {
87         super(pval,desc, indirect);
88          this.cmdParamDesc = desc;
89          this.env = env;
90          if (cmdParamDesc.getLocalFileName() == null) {
91           this.referenceFile = env.getTempFile();
92        }
93          else // use the file name that the application generates
94          {
95             this.referenceFile = new File(env.getExecutionDirectory(), cmdParamDesc.getLocalFileName());
96          }
97          try {
98              this.isOutputOnly = appInterface.getParameterDirection(
99                      val.getName()).equals(ParameterDirection.OUTPUT);
100         }
101         catch (ParameterNotInInterfaceException e) {
102             // very unlikely.
103             this.isOutputOnly = false;
104         }
105     }
106 
107     public File getReferenceFile() {
108         return referenceFile;
109     }
110 
111     /***
112      * copies the parameter value (either direct, or indirect) into a file (or
113      * onto the command line) in the commandline environment
114      * 
115      * @return the name of the file the value has been written to.
116      * @see org.astrogrid.applications.parameter.ParameterAdapter#process()
117      */
118     public Object process() throws CeaException {
119         
120         commandLineVal = val.getValue();
121         if (logger.isDebugEnabled()) {
122             logger.debug("process() - start "+val.getName()+"="+val.getValue());
123         }
124 
125         if (!isOutputOnly) {
126             InputStreamReader ir = null;
127             PrintWriter pw = null;
128             InputStream is = null;
129             OutputStream os = null;
130             try {
131 
132                 if (externalVal == null) {
133                     if (cmdParamDesc.isFileRef()) // but the commandline app expects a
134                     // file
135                     {
136 
137                         String value = val.getValue();
138                         pw = new PrintWriter(new FileWriter(
139                                 referenceFile));
140                         pw.println(value);
141                         pw.close();
142 
143                         if (logger.isDebugEnabled()) {
144                             logger.debug("process() local copied - " + val.getName() + "="
145                                     + val.getValue() + " direct, fileref="
146                                     + referenceFile.getName());
147                         }
148                         commandLineVal = referenceFile.getName();
149 
150                     }
151                     else {
152                         if (logger.isDebugEnabled()) {
153                             logger.debug("process() - local copied - " + val.getName() + "="
154                                     + val.getValue() + " direct");
155                         }
156                         commandLineVal = val.getValue();
157 
158                     }
159                 }
160                 else {
161                     if (cmdParamDesc.isFileRef()) { //a externalVal param/ file ref cmdline 
162                         is = externalVal.read();
163                         os = new FileOutputStream(referenceFile);
164                         Piper.bufferedPipe(is, os);
165                         is.close();
166                         os.close();
167                         if (logger.isDebugEnabled()) {
168                             logger.debug("process() - local copied - " + val.getName() + "="
169                                     + val.getValue() + " externalVal, fileref="
170                                     + referenceFile.getName());
171                         }
172                         commandLineVal = referenceFile.getName();
173                     }
174                     else // an externalVal param/ direct cmdline
175                     {
176                         //TODO - does this deal with new lines in the way that we might want?
177                         ir = new InputStreamReader(externalVal
178                                 .read());
179                         StringWriter sw = new StringWriter();
180                         Piper.pipe(ir, sw);
181                         ir.close();
182                         sw.close();
183                         val.setValue(sw.toString()); //TODO do we really want to set this - or is just 
184                         if (logger.isDebugEnabled()) {
185                             logger.debug("process() - local copied - " + val.getName() + "="
186                                     + val.getValue() + " externalVal");
187                         }
188 
189                         commandLineVal = val.getValue();
190 
191                     }
192                 }
193             }
194 
195             catch (IOException e) {
196                 throw new ParameterAdapterException(
197                         "Could not process parameter " + val.getName(), e);
198             }
199             finally // close all open resources
200             {
201               closeIO(pw, ir, is, os);   
202             }
203         }
204         else {
205             /* this is an output parameter - must write to a file*/
206             commandLineVal = referenceFile.getName();
207             if (logger.isDebugEnabled()) {
208                 logger.debug("process() - local copied - " + val.getName() + "="
209                         + val.getValue() + " output fileref="+commandLineVal);
210             }
211 
212             
213         }
214         return commandLineVal;
215     }
216 
217     /***
218      * ignore the value passed , copy contents of reference file back to the
219      * original parameter (direct or externalVal)
220      * 
221      * @see org.astrogrid.applications.parameter.ParameterAdapter#writeBack(java.lang.Object)
222      */
223     public void writeBack(Object arg0) throws CeaException {
224         StringWriter sw = null;
225         Reader r = null;
226         InputStream is = null;
227         OutputStream os = null;
228         assert arg0 == null : "the writeback parameter is ignored in DefaultCommandLineParameterAdapter - it should be null";
229         try {
230             if (cmdParamDesc.isFileRef()) {
231                 if (externalVal == null) {
232                     sw = new StringWriter();
233                     r = new FileReader(referenceFile);
234 
235                     Piper.pipe(r, sw);
236                     r.close();
237                     sw.close();
238                     val.setValue(sw.toString());
239                     if (logger.isDebugEnabled()) {
240                         logger.debug("writeBack() - direct/fileref "
241                                 + cmdParamDesc.getName() + "=" + val.getValue()
242                                 + " from file "
243                                 + referenceFile.getAbsolutePath());
244                     }
245                 }
246                 else {
247                     is = new FileInputStream(referenceFile);
248                     if (logger.isDebugEnabled()) {
249                         logger.debug("writeBack() - externalVal " + cmdParamDesc.getName()
250                                 + "="+val.getValue()+" from file "
251                                 + referenceFile.getAbsolutePath());
252                     }
253 
254                     os = externalVal.write();
255                     Piper.bufferedPipe(is, os);
256                     is.close();
257                     os.close();
258                 }
259             }
260             else {
261                 //this is not possible in command-line as the app has to write output to a file. Someone could try to configure such a thing though.
262                 new ParameterWriteBackException(
263                         "configuration error - attempting a writeback of non file-referenced parameter "
264                                 + cmdParamDesc.getName());
265             }
266 
267         }
268         catch (IOException e) {
269             throw new ParameterWriteBackException(
270                     "Could not write back parameter" + val.getName(), e);
271         }
272         finally // ensure that all the streams have been closed
273         {
274             closeIO(sw, r, is, os);
275             
276         }
277     }
278 
279     /***
280      * Close any streams and readers/writers that might have been left open.
281      * @param sw
282      * @param r
283      * @param is
284      * @param os
285      */
286     private void closeIO(Writer sw, Reader r, InputStream is, OutputStream os) {
287         if(r != null)
288         {
289             try {
290                 r.close();
291             }
292             catch (IOException e1) {
293                logger.warn("cannot close reader", e1);
294             }
295         }
296         if(sw != null)
297         {
298             try {
299                 sw.close();
300             }
301             catch (IOException e1) {
302                 logger.warn("could not close string writer", e1);
303             }
304         }
305         if(is != null)
306         {
307             try {
308                 is.close();
309             }
310             catch (IOException e1) {
311                logger.warn("could not close input stream", e1);
312             }
313             
314         }
315         if(os != null)
316         {
317             try {
318                 os.close();
319             }
320             catch (IOException e1) {
321                logger.warn("could not close output stream", e1);
322             }
323         }
324     }
325 
326  
327     /* (non-Javadoc)
328      * @see org.astrogrid.applications.parameter.CommandLineParameterAdapter#addSwitches()
329      */
330     public List addSwitches() throws CeaException {
331        return cmdParamDesc.addCmdlineAdornment(commandLineVal);
332     }
333     
334     
335 
336 }