Clean up logging system
[jabaws.git] / engine / compbio / engine / client / ConfExecutable.java
1 /* Copyright (c) 2009 Peter Troshin\r
2  *  \r
3  *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0     \r
4  * \r
5  *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
6  *  Apache License version 2 as published by the Apache Software Foundation\r
7  * \r
8  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
9  *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
10  *  License for more details.\r
11  * \r
12  *  A copy of the license is in apache_license.txt. It is also available here:\r
13  * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
14  * \r
15  * Any republication or derived work distributed in source code form\r
16  * must include this copyright and license notice.\r
17  */\r
18 \r
19 package compbio.engine.client;\r
20 \r
21 import java.io.File;\r
22 import java.io.FileInputStream;\r
23 import java.io.IOException;\r
24 import java.io.InputStream;\r
25 import java.util.ArrayList;\r
26 import java.util.Collections;\r
27 import java.util.List;\r
28 import java.util.Map;\r
29 \r
30 import javax.xml.bind.JAXBException;\r
31 \r
32 import org.apache.log4j.Logger;\r
33 \r
34 import compbio.engine.conf.PropertyHelperManager;\r
35 import compbio.engine.conf.RunnerConfigMarshaller;\r
36 import compbio.metadata.Limit;\r
37 import compbio.metadata.LimitsManager;\r
38 import compbio.metadata.PresetManager;\r
39 import compbio.metadata.ResultNotAvailableException;\r
40 import compbio.metadata.RunnerConfig;\r
41 import compbio.metadata.UnsupportedRuntimeException;\r
42 import compbio.util.FileUtil;\r
43 import compbio.util.PropertyHelper;\r
44 import compbio.util.SysPrefs;\r
45 import compbio.util.Util;\r
46 \r
47 public class ConfExecutable<T> implements ConfiguredExecutable<T> {\r
48 \r
49         private static final Logger log = Logger.getLogger(ConfExecutable.class);\r
50 \r
51         private static final PropertyHelper ph = PropertyHelperManager\r
52                         .getPropertyHelper();\r
53         public final static String CLUSTER_TASK_ID_PREFIX = "@";\r
54 \r
55         private String workDirectory;\r
56         private String taskDirectory;\r
57 \r
58         private ExecProvider provider;\r
59         private Executable<T> exec;\r
60 \r
61         public ConfExecutable(Executable<T> executable, String taskDirectory) {\r
62                 this.exec = executable;\r
63                 assert !compbio.util.Util.isEmpty(taskDirectory);\r
64                 this.taskDirectory = taskDirectory;\r
65         }\r
66 \r
67         // TODO think about appropriate exception here\r
68         ConfExecutable(RunConfiguration rconf) {\r
69                 try {\r
70                         exec = (Executable<T>) Class.forName(rconf.runnerClassName).newInstance();\r
71                 } catch (InstantiationException e) {\r
72                         e.printStackTrace();\r
73                 } catch (IllegalAccessException e) {\r
74                         e.printStackTrace();\r
75                 } catch (ClassNotFoundException e) {\r
76                         e.printStackTrace();\r
77                 }\r
78                 exec.loadRunConfiguration(rconf);\r
79                 setWorkDirectory(rconf.workDirectory);\r
80                 this.taskDirectory = rconf.taskId;\r
81         }\r
82 \r
83         @Override\r
84         public ExecProvider getExecProvider() {\r
85                 return provider;\r
86         }\r
87 \r
88         public void setExecProvider(ExecProvider provider) {\r
89                 assert provider != null && provider != ExecProvider.Any;\r
90                 this.provider = provider;\r
91                 if (provider == Executable.ExecProvider.Cluster) {\r
92                         this.taskDirectory = CLUSTER_TASK_ID_PREFIX + taskDirectory;\r
93                 }\r
94         }\r
95 \r
96         @Override\r
97         public String getCommand(ExecProvider provider)\r
98                         throws UnsupportedRuntimeException {\r
99                 String command = compbio.engine.client.Util.getCommand(provider,\r
100                                 exec.getClass());\r
101                 if (Util.isEmpty(command)) {\r
102                         throw new UnsupportedRuntimeException(\r
103                                         "Executable "\r
104                                                         + this.exec.getClass().getSimpleName()\r
105                                                         + " is not supported by the current runtime environment! Current runtime environment is "\r
106                                                         + (SysPrefs.isWindows\r
107                                                                         ? "Windows "\r
108                                                                         : "Linux/Unix/Mac"));\r
109                 }\r
110                 return command;\r
111         }\r
112 \r
113         @Override\r
114         public ExecProvider getSupportedRuntimes() {\r
115                 return compbio.engine.client.Util.getSupportedRuntimes(exec.getClass());\r
116         }\r
117 \r
118         @Override\r
119         public Limit<T> getLimit(String presetName) {\r
120                 return exec.getLimit(presetName);\r
121         }\r
122 \r
123         @Override\r
124         public LimitsManager<T> getLimits() {\r
125                 return exec.getLimits();\r
126         }\r
127 \r
128         @Override\r
129         public String getTaskId() {\r
130                 return taskDirectory;\r
131         }\r
132 \r
133         @Override\r
134         public void setWorkDirectory(String workDirectory) {\r
135                 assert !compbio.util.Util.isEmpty(workDirectory);\r
136                 this.workDirectory = workDirectory;\r
137         }\r
138 \r
139         @Override\r
140         public String getWorkDirectory() {\r
141                 return this.workDirectory;\r
142         }\r
143 \r
144         @Override\r
145         public Executable<T> addParameters(List<String> parameters) {\r
146                 exec.addParameters(parameters);\r
147                 return exec;\r
148         }\r
149 \r
150         @Override\r
151         public String getOutput() {\r
152                 return exec.getOutput();\r
153         }\r
154 \r
155         @Override\r
156         public String getError() {\r
157                 return exec.getError();\r
158         }\r
159 \r
160         @Override\r
161         public List<String> getCreatedFiles() {\r
162                 return getFullPath(exec.getCreatedFiles());\r
163         }\r
164 \r
165         List<String> getFullPath(List<String> fileNames) {\r
166                 List<String> files = new ArrayList<String>();\r
167                 for (String fileName : fileNames) {\r
168                         files.add(compbio.engine.client.Util.getFullPath(workDirectory,\r
169                                         fileName));\r
170                 }\r
171                 return files;\r
172         }\r
173 \r
174         /**\r
175          * Not all input paths are relative! Input path could be absolute!\r
176          * \r
177          * @see compbio.engine.client.Executable#getInputFiles()\r
178          */\r
179         @Override\r
180         public String getInput() {\r
181                 String path = exec.getInput();\r
182                 if (PathValidator.isAbsolutePath(path)) {\r
183                         return path;\r
184                 }\r
185                 return compbio.engine.client.Util.getFullPath(workDirectory, path);\r
186         }\r
187 \r
188         @Override\r
189         public CommandBuilder<T> getParameters() {\r
190                 return exec.getParameters(provider);\r
191         }\r
192 \r
193         @Override\r
194         public CommandBuilder<T> getParameters(\r
195                         compbio.engine.client.Executable.ExecProvider provider) {\r
196                 return getParameters();\r
197         }\r
198 \r
199         @Override\r
200         public Executable<T> getExecutable() {\r
201                 return exec;\r
202         }\r
203 \r
204         @Override\r
205         public <V> V getResults() throws ResultNotAvailableException {\r
206                 return (V) exec.getResults(workDirectory);\r
207         }\r
208 \r
209         /*\r
210          * This is just a pass through method (non-Javadoc)\r
211          * \r
212          * @see compbio.runner.Executable#getResults(java.lang.String)\r
213          */\r
214         @Override\r
215         public <V> V getResults(String directory)\r
216                         throws ResultNotAvailableException {\r
217                 return (V) exec.getResults(directory);\r
218         }\r
219 \r
220         /*\r
221          * This method should be executed once and result of its execution reused.\r
222          * If not used carefully it could slow down the system!\r
223          */\r
224         public static <V> RunnerConfig<V> getRunnerOptions(\r
225                         Class<? extends Executable<V>> clazz) throws IOException {\r
226                 String parametersFile = clazz.getSimpleName().toLowerCase() + ".parameters.file";\r
227                 return (RunnerConfig<V>) getRunnerConfiguration(clazz, RunnerConfig.class, parametersFile);\r
228         }\r
229 \r
230         /*\r
231          * This method should be executed once and result of its execution reused.\r
232          * If not used carefully it could slow down the system!\r
233          */\r
234         public static <V> PresetManager<V> getRunnerPresets(\r
235                         Class<? extends Executable<V>> clazz) throws IOException {\r
236                 String parametersFile = clazz.getSimpleName().toLowerCase() + ".presets.file";\r
237                 PresetManager<V> presets = (PresetManager<V>) getRunnerConfiguration(clazz, PresetManager.class, parametersFile);\r
238                 return presets;\r
239         }\r
240 \r
241         /**\r
242          * This method should be executed once and result of its execution reused.\r
243          * If not used carefully it could slow down the system!\r
244          * \r
245          * @param <V>\r
246          * @param clazz\r
247          * @return LimitsManager instance\r
248          * @throws IOException\r
249          */\r
250         public static <V> LimitsManager<V> getRunnerLimits(Class<V> clazz)\r
251                         throws IOException {\r
252                 String parametersFile = clazz.getSimpleName().toLowerCase() + ".limits.file";\r
253                 LimitsManager<V> limits = (LimitsManager<V>) getRunnerConfiguration(clazz, LimitsManager.class, parametersFile);\r
254                 return limits;\r
255         }\r
256 \r
257         static <V> Object getRunnerConfiguration(Class<V> clazz,\r
258                         Class<?> configurationHolder, String propertyName)\r
259                         throws IOException {\r
260 \r
261                 Object rconf = null;\r
262                 FileInputStream confFileStream = null;\r
263                 try {\r
264                         RunnerConfigMarshaller<V> rcm = new RunnerConfigMarshaller<V>(\r
265                                         configurationHolder);\r
266                         String path = ph.getProperty(propertyName);\r
267                         if (compbio.util.Util.isEmpty(path)) {\r
268                                 log.debug("Configuration " + path + " is not provided");\r
269                                 return null;\r
270                         }\r
271                         log.debug("Loading Configuration from " + path + " Config type:"\r
272                                         + configurationHolder);\r
273                         File confFile = new File(PropertyHelperManager.getLocalPath()\r
274                                         + path);\r
275                         confFileStream = new FileInputStream(confFile);\r
276                         rconf = rcm.read(confFileStream, configurationHolder);\r
277                         confFileStream.close();\r
278                 } catch (JAXBException e) {\r
279                         log.error(e.getLocalizedMessage(), e.getCause());\r
280                 } finally {\r
281                         FileUtil.closeSilently(log, confFileStream);\r
282                 }\r
283                 return rconf;\r
284         }\r
285 \r
286         @Override\r
287         public Map<String, String> getEnvironment() {\r
288                 String envProperty = ph.getProperty(exec.getClass().getSimpleName()\r
289                                 .toLowerCase()\r
290                                 + ".bin.env");\r
291                 if (envProperty == null) {\r
292                         return Collections.emptyMap();\r
293                 }\r
294 \r
295                 return EnvVariableProcessor.getEnvVariables(envProperty,\r
296                                 this.getClass());\r
297         }\r
298 \r
299         @Override\r
300         public ConfiguredExecutable<?> loadRunConfiguration(RunConfiguration rconf) {\r
301                 if (rconf == null) {\r
302                         throw new NullPointerException("RunConfiguration is expected!");\r
303                 }\r
304                 return new ConfExecutable(rconf);\r
305         }\r
306 \r
307         public static ConfiguredExecutable<?> newConfExecutable(\r
308                         RunConfiguration rconf) {\r
309                 if (rconf == null) {\r
310                         throw new NullPointerException("RunConfiguration is expected!");\r
311                 }\r
312                 return new ConfExecutable(rconf);\r
313         }\r
314 \r
315         @Override\r
316         public boolean saveRunConfiguration() throws IOException {\r
317                 RunConfiguration rconf = getRunConfiguration();\r
318                 return RunConfiguration.write(rconf);\r
319         }\r
320 \r
321         public RunConfiguration getRunConfiguration() {\r
322                 /*\r
323                  * Distinguish between dynamic settings and static settings (set in conf\r
324                  * or class) The latter does not need saving (as if they change there\r
325                  * were a good reason for this and it make it impossible/dangerous to\r
326                  * rerun the task with old settings)\r
327                  */\r
328                 // Set within Executable\r
329                 // String taskId = executable.getTaskId();\r
330 \r
331                 /*\r
332                  * All things below are handled by Executable\r
333                  * \r
334                  * getInput() && getOutput()\r
335                  * \r
336                  * // Handle PipedExecutables String error = executable.getError(); if\r
337                  * (error != null) {\r
338                  * \r
339                  * } String output = executable.getOutput(); if (output != null) {\r
340                  * \r
341                  * } List<String> outputs = executable.getCreatedFiles(); List<String>\r
342                  * inputs = executable.getInputFiles();\r
343                  * \r
344                  * /* Environment is defined only declaratively. Map<String,String> env\r
345                  * = executable.getEnvironment();\r
346                  * \r
347                  * List<String> params = executable.getParameters();\r
348                  */\r
349                 RunConfiguration rconf = new RunConfiguration(this);\r
350                 return rconf;\r
351         }\r
352 \r
353         @Override\r
354         public ConfiguredExecutable<?> loadRunConfiguration(InputStream input)\r
355                         throws IOException {\r
356                 RunConfiguration rconf = RunConfiguration.load(input);\r
357                 log.info("Loaded saved RunConfiguration " + rconf);\r
358                 return new ConfExecutable(rconf);\r
359         }\r
360 \r
361         @Override\r
362         public String toString() {\r
363                 String value = "Work dir: " + this.workDirectory + "\n";\r
364                 value += "TaskId: " + this.taskDirectory + "\n";\r
365                 value += "Params: " + this.getParameters() + "\n";\r
366                 value += exec.toString();\r
367                 return value;\r
368         }\r
369 \r
370         @Override\r
371         public String getClusterJobSettings() {\r
372                 return exec.getClusterJobSettings();\r
373         }\r
374 }\r