New Linux binaries for ViennaRNA
[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)\r
71                                         .newInstance();\r
72                 } catch (InstantiationException e) {\r
73                         e.printStackTrace();\r
74                 } catch (IllegalAccessException e) {\r
75                         e.printStackTrace();\r
76                 } catch (ClassNotFoundException e) {\r
77                         e.printStackTrace();\r
78                 }\r
79                 exec.loadRunConfiguration(rconf);\r
80                 setWorkDirectory(rconf.workDirectory);\r
81                 this.taskDirectory = rconf.taskId;\r
82         }\r
83 \r
84         @Override\r
85         public ExecProvider getExecProvider() {\r
86                 return provider;\r
87         }\r
88 \r
89         public void setExecProvider(ExecProvider provider) {\r
90                 assert provider != null && provider != ExecProvider.Any;\r
91                 this.provider = provider;\r
92                 if (provider == Executable.ExecProvider.Cluster) {\r
93                         this.taskDirectory = CLUSTER_TASK_ID_PREFIX + taskDirectory;\r
94                 }\r
95         }\r
96 \r
97         @Override\r
98         public String getCommand(ExecProvider provider)\r
99                         throws UnsupportedRuntimeException {\r
100                 String command = compbio.engine.client.Util.getCommand(provider,\r
101                                 exec.getClass());\r
102                 if (Util.isEmpty(command)) {\r
103                         throw new UnsupportedRuntimeException(\r
104                                         "Executable "\r
105                                                         + this.exec.getClass().getSimpleName()\r
106                                                         + " is not supported by the current runtime environment! Current runtime environment is "\r
107                                                         + (SysPrefs.isWindows\r
108                                                                         ? "Windows "\r
109                                                                         : "Linux/Unix/Mac"));\r
110                 }\r
111                 return command;\r
112         }\r
113 \r
114         @Override\r
115         public ExecProvider getSupportedRuntimes() {\r
116                 return compbio.engine.client.Util.getSupportedRuntimes(exec.getClass());\r
117         }\r
118 \r
119         @Override\r
120         public Limit<T> getLimit(String presetName) {\r
121                 return exec.getLimit(presetName);\r
122         }\r
123 \r
124         @Override\r
125         public LimitsManager<T> getLimits() {\r
126                 return exec.getLimits();\r
127         }\r
128 \r
129         @Override\r
130         public String getTaskId() {\r
131                 return taskDirectory;\r
132         }\r
133 \r
134         @Override\r
135         public void setWorkDirectory(String workDirectory) {\r
136                 assert !compbio.util.Util.isEmpty(workDirectory);\r
137                 this.workDirectory = workDirectory;\r
138         }\r
139 \r
140         @Override\r
141         public String getWorkDirectory() {\r
142                 return this.workDirectory;\r
143         }\r
144 \r
145         @Override\r
146         public Executable<T> addParameters(List<String> parameters) {\r
147                 exec.addParameters(parameters);\r
148                 return exec;\r
149         }\r
150 \r
151         @Override\r
152         public String getOutput() {\r
153                 return exec.getOutput();\r
154         }\r
155 \r
156         @Override\r
157         public String getError() {\r
158                 return exec.getError();\r
159         }\r
160 \r
161         @Override\r
162         public List<String> getCreatedFiles() {\r
163                 return getFullPath(exec.getCreatedFiles());\r
164         }\r
165 \r
166         List<String> getFullPath(List<String> fileNames) {\r
167                 List<String> files = new ArrayList<String>();\r
168                 for (String fileName : fileNames) {\r
169                         files.add(compbio.engine.client.Util.getFullPath(workDirectory,\r
170                                         fileName));\r
171                 }\r
172                 return files;\r
173         }\r
174 \r
175         /**\r
176          * Not all input paths are relative! Input path could be absolute!\r
177          * \r
178          * @see compbio.engine.client.Executable#getInputFiles()\r
179          */\r
180         @Override\r
181         public String getInput() {\r
182                 String path = exec.getInput();\r
183                 if (PathValidator.isAbsolutePath(path)) {\r
184                         return path;\r
185                 }\r
186                 return compbio.engine.client.Util.getFullPath(workDirectory, path);\r
187         }\r
188 \r
189         @Override\r
190         public CommandBuilder<T> getParameters() {\r
191                 return exec.getParameters(provider);\r
192         }\r
193 \r
194         @Override\r
195         public CommandBuilder<T> getParameters(\r
196                         compbio.engine.client.Executable.ExecProvider provider) {\r
197                 return getParameters();\r
198         }\r
199 \r
200         @Override\r
201         public Executable<T> getExecutable() {\r
202                 return exec;\r
203         }\r
204 \r
205         @Override\r
206         public <V> V getResults() throws ResultNotAvailableException {\r
207                 return (V) exec.getResults(workDirectory);\r
208         }\r
209 \r
210         /*\r
211          * This is just a pass through method (non-Javadoc)\r
212          * \r
213          * @see compbio.runner.Executable#getResults(java.lang.String)\r
214          */\r
215         @Override\r
216         public <V> V getResults(String directory)\r
217                         throws ResultNotAvailableException {\r
218                 return (V) exec.getResults(directory);\r
219         }\r
220 \r
221         /*\r
222          * This method should be executed once and result of its execution reused.\r
223          * If not used carefully it could slow down the system!\r
224          */\r
225         public static <V> RunnerConfig<V> getRunnerOptions(\r
226                         Class<? extends Executable<V>> clazz) throws IOException {\r
227                 String parametersFile = clazz.getSimpleName().toLowerCase() + ".parameters.file";\r
228                 return (RunnerConfig<V>) getRunnerConfiguration(clazz, RunnerConfig.class, parametersFile);\r
229         }\r
230 \r
231         /*\r
232          * This method should be executed once and result of its execution reused.\r
233          * If not used carefully it could slow down the system!\r
234          */\r
235         public static <V> PresetManager<V> getRunnerPresets(\r
236                         Class<? extends Executable<V>> clazz) throws IOException {\r
237                 String parametersFile = clazz.getSimpleName().toLowerCase() + ".presets.file";\r
238                 PresetManager<V> presets = (PresetManager<V>) getRunnerConfiguration(clazz, PresetManager.class, parametersFile);\r
239                 return presets;\r
240         }\r
241 \r
242         /**\r
243          * This method should be executed once and result of its execution reused.\r
244          * If not used carefully it could slow down the system!\r
245          * \r
246          * @param <V>\r
247          * @param clazz\r
248          * @return LimitsManager instance\r
249          * @throws IOException\r
250          */\r
251         public static <V> LimitsManager<V> getRunnerLimits(Class<V> clazz)\r
252                         throws IOException {\r
253                 String parametersFile = clazz.getSimpleName().toLowerCase() + ".limits.file";\r
254                 LimitsManager<V> limits = (LimitsManager<V>) getRunnerConfiguration(clazz, LimitsManager.class, parametersFile);\r
255                 return limits;\r
256         }\r
257 \r
258         static <V> Object getRunnerConfiguration(Class<V> clazz,\r
259                         Class<?> configurationHolder, String propertyName)\r
260                         throws IOException {\r
261 \r
262                 Object rconf = null;\r
263                 FileInputStream confFileStream = null;\r
264                 try {\r
265                         RunnerConfigMarshaller<V> rcm = new RunnerConfigMarshaller<V>(\r
266                                         configurationHolder);\r
267                         String path = ph.getProperty(propertyName);\r
268                         if (compbio.util.Util.isEmpty(path)) {\r
269                                 log.debug("Configuration " + path + " is not provided");\r
270                                 return null;\r
271                         }\r
272                         log.debug("Loading Configuration from " + path + " Config type:"\r
273                                         + configurationHolder);\r
274                         File confFile = new File(PropertyHelperManager.getLocalPath()\r
275                                         + path);\r
276                         confFileStream = new FileInputStream(confFile);\r
277                         rconf = rcm.read(confFileStream, configurationHolder);\r
278                         confFileStream.close();\r
279                 } catch (JAXBException e) {\r
280                         log.error(e.getLocalizedMessage(), e.getCause());\r
281                 } finally {\r
282                         FileUtil.closeSilently(log, confFileStream);\r
283                 }\r
284                 return rconf;\r
285         }\r
286 \r
287         @Override\r
288         public Map<String, String> getEnvironment() {\r
289                 String envProperty = ph.getProperty(exec.getClass().getSimpleName()\r
290                                 .toLowerCase()\r
291                                 + ".bin.env");\r
292                 if (envProperty == null) {\r
293                         return Collections.emptyMap();\r
294                 }\r
295 \r
296                 return EnvVariableProcessor.getEnvVariables(envProperty,\r
297                                 this.getClass());\r
298         }\r
299 \r
300         @Override\r
301         public ConfiguredExecutable<?> loadRunConfiguration(RunConfiguration rconf) {\r
302                 if (rconf == null) {\r
303                         throw new NullPointerException("RunConfiguration is expected!");\r
304                 }\r
305                 return new ConfExecutable(rconf);\r
306         }\r
307 \r
308         public static ConfiguredExecutable<?> newConfExecutable(\r
309                         RunConfiguration rconf) {\r
310                 if (rconf == null) {\r
311                         throw new NullPointerException("RunConfiguration is expected!");\r
312                 }\r
313                 return new ConfExecutable(rconf);\r
314         }\r
315 \r
316         @Override\r
317         public boolean saveRunConfiguration() throws IOException {\r
318                 RunConfiguration rconf = getRunConfiguration();\r
319                 return RunConfiguration.write(rconf);\r
320         }\r
321 \r
322         public RunConfiguration getRunConfiguration() {\r
323                 /*\r
324                  * Distinguish between dynamic settings and static settings (set in conf\r
325                  * or class) The latter does not need saving (as if they change there\r
326                  * were a good reason for this and it make it impossible/dangerous to\r
327                  * rerun the task with old settings)\r
328                  */\r
329                 // Set within Executable\r
330                 // String taskId = executable.getTaskId();\r
331 \r
332                 /*\r
333                  * All things below are handled by Executable\r
334                  * \r
335                  * getInput() && getOutput()\r
336                  * \r
337                  * // Handle PipedExecutables String error = executable.getError(); if\r
338                  * (error != null) {\r
339                  * \r
340                  * } String output = executable.getOutput(); if (output != null) {\r
341                  * \r
342                  * } List<String> outputs = executable.getCreatedFiles(); List<String>\r
343                  * inputs = executable.getInputFiles();\r
344                  * \r
345                  * /* Environment is defined only declaratively. Map<String,String> env\r
346                  * = executable.getEnvironment();\r
347                  * \r
348                  * List<String> params = executable.getParameters();\r
349                  */\r
350                 RunConfiguration rconf = new RunConfiguration(this);\r
351                 return rconf;\r
352         }\r
353 \r
354         @Override\r
355         public ConfiguredExecutable<?> loadRunConfiguration(InputStream input)\r
356                         throws IOException {\r
357                 RunConfiguration rconf = RunConfiguration.load(input);\r
358                 log.info("Loaded saved RunConfiguration " + rconf);\r
359                 return new ConfExecutable(rconf);\r
360         }\r
361 \r
362         @Override\r
363         public String toString() {\r
364                 String value = "Work dir: " + this.workDirectory + "\n";\r
365                 value += "TaskId: " + this.taskDirectory + "\n";\r
366                 value += "Params: " + this.getParameters() + "\n";\r
367                 value += exec.toString();\r
368                 return value;\r
369         }\r
370 \r
371         @Override\r
372         public String getClusterJobSettings() {\r
373                 return exec.getClusterJobSettings();\r
374         }\r
375 }\r