View Javadoc

1   /*$Id: CatApplicationDescription.java,v 1.8 2004/11/27 13:20:02 pah Exp $
2    * Created on 16-Aug-2004
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid 
7    * Software License version 1.2, a copy of which has been included 
8    * with this distribution in the LICENSE.txt file.  
9    *
10  **/
11  package org.astrogrid.applications.apps;
12  
13  import org.apache.commons.logging.Log;
14  import org.apache.commons.logging.LogFactory;
15  
16  import java.io.ByteArrayInputStream;
17  import java.io.ByteArrayOutputStream;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.io.OutputStream;
21  import java.util.ArrayList;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.astrogrid.applications.AbstractApplication;
26  import org.astrogrid.applications.Application;
27  import org.astrogrid.applications.CeaException;
28  import org.astrogrid.applications.DefaultIDs;
29  import org.astrogrid.applications.Status;
30  import org.astrogrid.applications.beans.v1.parameters.ParameterValue;
31  import org.astrogrid.applications.beans.v1.parameters.types.ParameterTypes;
32  import org.astrogrid.applications.description.ApplicationInterface;
33  import org.astrogrid.applications.description.Cardinality;
34  import org.astrogrid.applications.description.ParameterDescription;
35  import org.astrogrid.applications.description.base.AbstractApplicationDescription;
36  import org.astrogrid.applications.description.base.ApplicationDescriptionEnvironment;
37  import org.astrogrid.applications.description.base.BaseApplicationInterface;
38  import org.astrogrid.applications.description.base.BaseParameterDescription;
39  import org.astrogrid.applications.description.exception.ParameterDescriptionNotFoundException;
40  import org.astrogrid.applications.parameter.DefaultParameterAdapter;
41  import org.astrogrid.applications.parameter.ParameterAdapter;
42  import org.astrogrid.applications.parameter.protocol.ExternalValue;
43  import org.astrogrid.applications.parameter.protocol.ProtocolLibrary;
44  import org.astrogrid.community.User;
45  import org.astrogrid.component.descriptor.ComponentDescriptor;
46  import org.astrogrid.io.Piper;
47  import org.astrogrid.workflow.beans.v1.Tool;
48  
49  import junit.framework.Test;
50  
51  /*** Simple application that behaves a bit like unix 'cat' - concatenates a bunch of files together.
52   * @author Noel Winstanley nw@jb.man.ac.uk 16-Aug-2004
53   *
54   */
55  public class CatApplicationDescription extends AbstractApplicationDescription
56          implements ComponentDescriptor {
57      /***
58       * Commons Logger for this class
59       */
60      private static final Log logger = LogFactory
61              .getLog(CatApplicationDescription.class);
62  
63      /*** Construct a new CatApplicationDescription
64       * @param env
65       */
66      public CatApplicationDescription(ApplicationDescriptionEnvironment env) {
67          super(env);
68          this.setMetaData();        
69      }
70      
71      /*** set up metadata for this instance */
72      private final void setMetaData() {
73          StringBuffer thename = new StringBuffer(env.getAuthIDResolver().getAuthorityID());
74          thename.append("/concat");
75          setName(thename.toString());
76          BaseParameterDescription result = new BaseParameterDescription();
77          result.setName("result");
78          result.setDisplayName("Result");
79          result.setDisplayDescription("result of concatenating data together");
80          result.setType(ParameterTypes.BINARY);
81          this.addParameterDescription(result);
82          
83          BaseParameterDescription src = new BaseParameterDescription();
84          src.setName("src");
85          src.setDisplayName("Source");
86          src.setDisplayDescription("an input to concatenate");
87          src.setType(ParameterTypes.BINARY);
88          this.addParameterDescription(src);
89          
90          BaseApplicationInterface intf = new BaseApplicationInterface("basic",this);
91          try {
92              intf.addInputParameter(src.getName(),Cardinality.MANDATORY_REPEATED);
93              intf.addOutputParameter(result.getName());
94              
95          } catch (ParameterDescriptionNotFoundException e) {
96              logger.fatal("Programming error",e); // really shouldn't happen
97              throw new RuntimeException("Programming Error",e);
98          }
99          this.addInterface(intf);
100         
101     }
102 
103     /***
104      * @see org.astrogrid.component.descriptor.ComponentDescriptor#getDescription()
105      */
106     public String getDescription() {
107         return "Cat application\n" + this.toString();
108     }
109 
110     /***
111      * @see org.astrogrid.component.descriptor.ComponentDescriptor#getInstallationTest()
112      */
113     public Test getInstallationTest() {
114         return null;
115     }
116 
117     /***
118      * @see org.astrogrid.applications.description.ApplicationDescription#initializeApplication(java.lang.String, org.astrogrid.community.User, org.astrogrid.workflow.beans.v1.Tool)
119      */
120     public Application initializeApplication(String callerAssignedID,
121             User user, Tool tool) throws Exception {
122         String newID = env.getIdGen().getNewID();
123         final DefaultIDs ids = new DefaultIDs(callerAssignedID,newID,user);
124         ApplicationInterface iface = this.getInterface(tool.getInterface());
125         return new CatApplication(ids,tool,iface,env.getProtocolLib());
126         
127     }
128     
129     public static class CatApplication extends AbstractApplication {
130 
131         /*** Construct a new CatApplication
132          * @param ids
133          * @param tool
134          * @param applicationInterface
135          * @param lib
136          */
137         public CatApplication(IDs ids, Tool tool, ApplicationInterface applicationInterface, ProtocolLibrary lib) {
138             super(ids, tool, applicationInterface, lib);
139         }
140         public Runnable createExecutionTask() throws CeaException {
141             createAdapters();
142             setStatus(Status.INITIALIZED);
143             Runnable r = new Runnable() {
144                 public void run() {
145                     try {
146                         setStatus(Status.RUNNING);
147                         List streams = new ArrayList();
148                         for (Iterator i = inputParameterAdapters(); i.hasNext();) {
149                                 ParameterAdapter input = (ParameterAdapter)i.next();
150                                 reportMessage("reading in parameter " + input.getWrappedParameter().getValue());
151                                 streams.add(input.process());
152                         }            
153                         setStatus(Status.WRITINGBACK);
154                         ParameterAdapter out= (ParameterAdapter)outputParameterAdapters().next(); // we know there's just the one.
155                         out.writeBack(streams);
156                         setStatus(Status.COMPLETED);
157                     } catch (CeaException e) {
158                         reportError("something failed",e);
159                     }
160                 }
161             };
162             return r;            
163         }
164         protected ParameterAdapter instantiateAdapter(ParameterValue pval,
165                 ParameterDescription descr, ExternalValue indirectVal) {
166             return new StreamParameterAdapter(pval, descr, indirectVal);
167         }
168 
169     }
170 
171     /*** parameter adapter that produces and consumes streams, rather than string values - for efficiency when handling large amounts of data.
172      * @todo maybe a candidate for factoring out into a package of useful parameter adapters later.*/
173     public static class StreamParameterAdapter extends DefaultParameterAdapter {
174         /*** always returns an InputStream */
175         public Object process() throws CeaException {
176             if (externalVal == null) {
177                 return new ByteArrayInputStream(val.getValue().getBytes());
178             } else {
179                 return externalVal.read();
180             }
181         }
182         
183         /*** expects a list of input streams */
184         public void writeBack(Object o) throws CeaException {
185             if (! (o instanceof List)) {
186                 throw new CeaException("Programming error - expected List of Streams, got " + o.getClass().getName());                
187             }
188             OutputStream os = null;
189             if (externalVal == null) {
190                 os = new ByteArrayOutputStream();
191             } else {
192                 os  = externalVal.write();
193             }
194             try {
195                 InputStream is = null;
196                 for (Iterator i = ((List)o).iterator(); i.hasNext(); ) {
197                     try {
198                         is = (InputStream)i.next();                
199                         Piper.pipe(is,os); // hope this doesn't close the os.
200                     } finally {
201                         if (is != null) {
202                             try {
203                                 is.close();
204                             } catch (IOException e) {
205                                 logger.warn("failed to close input stream",e);
206                             }
207                     }
208                 }
209                 }
210             } catch (IOException e) {
211                 throw new CeaException("Faled to write back",e);
212             } finally {
213                 if (os != null) {
214                     try {
215                         os.close();
216                     } catch (IOException e) {
217                         logger.warn("failed to close output stream",e);
218                 }
219             }
220             }
221                 if (externalVal == null) {
222                     val.setValue(os.toString()); // uses byteArrayOutputStream's overloaded toString().
223                 }                
224         }
225         public StreamParameterAdapter(ParameterValue val, ParameterDescription description, ExternalValue externalVal) {
226             super(val, description, externalVal);
227         }
228 
229 
230     }
231 
232 }
233 
234 
235 /* 
236 $Log: CatApplicationDescription.java,v $
237 Revision 1.8  2004/11/27 13:20:02  pah
238 result of merge of pah_cea_bz561 branch
239 
240 Revision 1.7.10.1  2004/11/09 09:21:16  pah
241 initial attempt to rationalise authorityID use & self registering
242 
243 Revision 1.7  2004/09/22 10:52:50  pah
244 getting rid of some unused imports
245 
246 Revision 1.6  2004/09/17 10:59:53  nw
247 made sure streams are closed
248 
249 Revision 1.5  2004/09/17 01:21:12  nw
250 altered to work with new threadpool
251 
252 Revision 1.4.10.1  2004/09/14 13:46:04  nw
253 upgraded to new threading practice.
254 
255 Revision 1.4  2004/09/07 12:54:55  nw
256 put body in new thread - needs to be really.
257 
258 Revision 1.3  2004/09/03 13:19:14  nw
259 added some progress messages
260 
261 Revision 1.2  2004/08/17 15:07:25  nw
262 added concat application
263 
264 Revision 1.1  2004/08/16 11:03:46  nw
265 first stab at a cat application
266  
267 */