1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.applications.http;
12
13 import java.util.Enumeration;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.Map;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.astrogrid.applications.AbstractApplication;
21 import org.astrogrid.applications.CeaException;
22 import org.astrogrid.applications.Status;
23 import org.astrogrid.applications.beans.v1.Script;
24 import org.astrogrid.applications.beans.v1.SimpleParameter;
25 import org.astrogrid.applications.beans.v1.WebHttpApplicationSetup;
26 import org.astrogrid.applications.beans.v1.WebHttpCall;
27 import org.astrogrid.applications.beans.v1.types.HttpMethodType;
28 import org.astrogrid.applications.description.ApplicationInterface;
29 import org.astrogrid.applications.http.HttpServiceClient.HttpServiceType;
30 import org.astrogrid.applications.http.exceptions.HttpApplicationNetworkException;
31 import org.astrogrid.applications.http.exceptions.HttpApplicationWebServiceURLException;
32 import org.astrogrid.applications.http.script.IdentityPreprocessor;
33 import org.astrogrid.applications.http.script.Preprocessor;
34 import org.astrogrid.applications.http.script.XSLTPreprocessor;
35 import org.astrogrid.applications.parameter.ParameterAdapter;
36 import org.astrogrid.applications.parameter.protocol.ProtocolLibrary;
37 import org.astrogrid.registry.beans.cea.CeaHttpApplicationType;
38 import org.astrogrid.workflow.beans.v1.Tool;
39
40 /***
41 * An Application that calls an http service, such as a SIAP service. ?
42 * Responsible for extracting the relevant info from the application description
43 * and passing them to a HttpServiceClient that knows how to call the web
44 * service. Handles the threading (so execute doesn't block) and status settings
45 * during execution. ?
46 *
47 *
48 *
49 * @author jdt
50 */
51 public class HttpApplication extends AbstractApplication {
52 /***
53 * Commons Logger for this class
54 */
55 private static final Log log = LogFactory.getLog(HttpApplication.class);
56
57 /***
58 * Ctor
59 *
60 * @param id
61 * @param tool
62 * @param applicationInterface
63 * @param protocolLibrary
64 */
65 public HttpApplication(IDs id, Tool tool, ApplicationInterface applicationInterface, ProtocolLibrary protocolLibrary) {
66 super(id, tool, applicationInterface, protocolLibrary);
67 }
68
69 /***
70 * Combines a the Tool and Application docs and transforms to a doc suitable
71 * for calling the web service. For this we use the pre-processing element in the CeaHttpApplictionType
72 * doc, or a default if none is available.
73 */
74 private WebHttpCall createCallingDocument(final Tool tool, final CeaHttpApplicationType app) {
75 if (log.isTraceEnabled()) {
76 log.trace("createCallingDocument(Tool tool = " + tool + ", CeaHttpApplicationType app = " + app
77 + ") - start");
78 }
79
80 final WebHttpApplicationSetup httpAppInfo = app.getCeaHttpAdapterSetup();
81 final Script preprocessScript = httpAppInfo.getPreProcessScript();
82
83 log.debug("preprocessScript="+preprocessScript);
84 if (preprocessScript!=null) {
85 log.debug("preprocessScript lang="+preprocessScript.getLang());
86 log.debug("preprocessScript code="+preprocessScript.getCode());
87 }
88
89 Preprocessor preprocessor;
90 if (preprocessScript==null) {
91 log.debug("Preprocessing with identity preprocessor");
92 preprocessor = new IdentityPreprocessor();
93 } else {
94 String code = preprocessScript.getCode();
95 assert code!=null;
96 if (preprocessScript.getLang().equals(XSLTPreprocessor.xmlName)) {
97 log.debug("Preprocessing with XSLT preprocessor");
98 preprocessor = new XSLTPreprocessor(code);
99 throw new UnsupportedOperationException("preprocessing scripts have not been implemented yet");
100 } else {
101 log.debug("Non-xslt preprocessor - cannot process");
102 throw new UnsupportedOperationException("Non-xslt scripts have not been implemented yet");
103 }
104 }
105
106 WebHttpCall returnWebHttpCall = preprocessor.process(tool, app);
107 if (log.isTraceEnabled()) {
108 log.trace("createCallingDocument(Tool, CeaHttpApplicationType) - end - return value = "
109 + returnWebHttpCall);
110 }
111 return returnWebHttpCall;
112 }
113
114 public Runnable createExecutionTask() throws CeaException {
115 createAdapters();
116 log.debug("createExecutionTask() - creating worker thread");
117 Runnable task = new Exec();
118 setStatus(Status.INITIALIZED);
119 return task;
120 }
121
122 public boolean execute() throws CeaException {
123 if (log.isTraceEnabled()) {
124 log.trace("execute() - start");
125 }
126 log.debug("execute() - starting thread");
127 (new Thread(createExecutionTask())).start();
128 if (log.isTraceEnabled()) {
129 log.trace("execute() - end - return value = " + true);
130 }
131 return true;
132 }
133
134 private class Exec implements Runnable {
135
136 /***
137 * Where the action happens
138 */
139 public void run() {
140 if (log.isTraceEnabled()) {
141 log.trace("run() - start");
142 }
143
144
145
146 log.debug("Processing arguments");
147 try{
148 for (Iterator i = inputParameterAdapters(); i.hasNext();) {
149 ParameterAdapter a = (ParameterAdapter) i.next();
150 final String name = a.getWrappedParameter().getName();
151 final Object value = a.process();
152
153
154
155
156
157 a.getWrappedParameter().setValue((String) value);
158 log.debug(name + "=" + value);
159 }
160
161 final HttpApplicationDescription description = (HttpApplicationDescription) getApplicationDescription();
162 final CeaHttpApplicationType app = description.getApplication();
163 final WebHttpCall httpCall = createCallingDocument(getTool(),app);
164
165 final String url = httpCall.getURL().getContent();
166 final HttpMethodType requestedMethod = httpCall.getURL().getMethod();
167 HttpServiceClient.HttpServiceType method;
168 if (HttpMethodType.GET.equals(requestedMethod)) {
169 method = HttpServiceClient.HttpServiceType.GET;
170 log.debug("run() - Using http-get");
171 } else if (HttpMethodType.POST.equals(requestedMethod)) {
172 method = HttpServiceClient.HttpServiceType.POST;
173 log.debug("run() - using http-post");
174 } else {
175 reportError("Unknown http method requested");
176 return;
177 }
178 final Enumeration enum = httpCall.enumerateSimpleParameter();
179 Map inputArguments = new HashMap();
180 while (enum.hasMoreElements()) {
181 final SimpleParameter parameter = (SimpleParameter) enum.nextElement();
182 assert parameter!=null;
183 assert parameter.getName()!=null;
184 assert parameter.getValue()!=null;
185 inputArguments.put(parameter.getName(), parameter.getValue());
186 }
187
188 setStatus(Status.RUNNING);
189 log.info("calling url="+url);
190 HttpServiceClient client = new HttpServiceClient(url, method);
191 final String resultText = client.call(inputArguments);
192 log.debug("run() - unprocessed result: : resultText = " + resultText);
193
194 final String processedResult = postProcess(resultText);
195
196
197 setStatus(Status.WRITINGBACK);
198 Iterator outputParamsIt = outputParameterAdapters();
199 ParameterAdapter result = (ParameterAdapter) outputParamsIt.next();
200 assert !outputParamsIt.hasNext() : "Expect there to be only one output parameter for an HttpApplication";
201 result.writeBack(processedResult);
202 log.info("completed call successfully");
203 setStatus(Status.COMPLETED);
204 } catch (CeaException e) {
205 log.error("run() - failed to write back param values", e);
206 reportError("Failed to write back parameter values", e);
207 } catch (HttpApplicationWebServiceURLException e) {
208 log.error("run() - problem with service URL", e);
209 reportError("Error 404 - Not Found from the application's URL", e);
210 } catch (HttpApplicationNetworkException e) {
211 log.error("run()", e);
212 reportError("Network Error while contacting web server",e);
213 } catch (Throwable t) {
214 log.error("run()", t);
215
216 reportError("Something else gone wrong", t);
217 }
218
219 if (log.isTraceEnabled()) {
220 log.trace("run() - end");
221 }
222 }
223 }
224
225 /***
226 * @param result
227 * @return
228 * @TODO this method is incomplete
229 */
230 private String postProcess(final String result) {
231 if (log.isTraceEnabled()) {
232 log.trace("postProcess(String result = " + result + ") - start");
233 }
234
235 log.debug("No post-processing at present");
236
237 if (log.isTraceEnabled()) {
238 log.trace("postProcess(String) - end - return value = " + result);
239 }
240 return result;
241 }
242
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308