1 /* Copyright (c) 2009 Peter Troshin
\r
3 * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0
\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
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
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
15 * Any republication or derived work distributed in source code form
\r
16 * must include this copyright and license notice.
\r
19 package compbio.engine.client;
\r
21 import java.io.File;
\r
22 import java.io.FileInputStream;
\r
23 import java.io.FileNotFoundException;
\r
24 import java.io.FileWriter;
\r
25 import java.io.IOException;
\r
26 import java.security.InvalidParameterException;
\r
27 import java.util.Map;
\r
29 import org.apache.log4j.Logger;
\r
31 import compbio.engine.client.Executable.ExecProvider;
\r
32 import compbio.engine.conf.DirectoryManager;
\r
33 import compbio.engine.conf.PropertyHelperManager;
\r
34 import compbio.metadata.JobStatus;
\r
35 import compbio.metadata.LimitsManager;
\r
36 import compbio.metadata.ResultNotAvailableException;
\r
37 import compbio.util.FileUtil;
\r
38 import compbio.util.PropertyHelper;
\r
39 import compbio.util.SysPrefs;
\r
41 public final class Util {
\r
43 private static final PropertyHelper ph = PropertyHelperManager
\r
44 .getPropertyHelper();
\r
46 private static final Logger log = Logger.getLogger(Util.class);
\r
48 public static boolean isValidJobId(final String key) {
\r
49 if (compbio.util.Util.isEmpty(key)) {
\r
52 int delIdx = key.indexOf(DirectoryManager.DELIM);
\r
56 String id = key.substring(delIdx + DirectoryManager.DELIM.length());
\r
59 } catch (NumberFormatException e) {
\r
60 log.debug("Invalid key! " + e.getLocalizedMessage());
\r
66 public static void writeStatFile(String workDirectory,
\r
67 String fileAndEventName) {
\r
68 // never override old stat files!
\r
69 // Work directory could be null for cancelled or incomplete jobs, just
\r
71 if (!compbio.util.Util.isEmpty(workDirectory)) {
\r
72 writeFile(workDirectory, fileAndEventName, new Long(System
\r
73 .currentTimeMillis()).toString(), false);
\r
77 public static void writeFile(String workDirectory, String fileAndEventName,
\r
78 String content, boolean override) {
\r
80 if (compbio.util.Util.isEmpty(workDirectory)) {
\r
82 .debug("Calling compbio.engine.Util.writeFile() with not work directory."
\r
83 + " Skipping writing statistics!");
\r
86 assert !compbio.util.Util.isEmpty(content) : "Content expected!";
\r
87 FileWriter writer = null;
\r
89 file = new File(workDirectory, fileAndEventName);
\r
90 // Do not override existing files unless asked to do so !
\r
91 if (file.exists() && !override) {
\r
94 writer = new FileWriter(file);
\r
95 writer.write(content);
\r
97 log.debug("File " + fileAndEventName + " with content: " + content
\r
98 + " has been recorder successfully! ");
\r
99 } catch (IOException e) {
\r
100 log.error("Could not record the " + fileAndEventName + " file in "
\r
101 + workDirectory + " for local execution! Ignoring... "
\r
104 FileUtil.closeSilently(log, writer);
\r
108 public static final boolean writeMarker(String workDirectory,
\r
109 JobStatus fileType) {
\r
110 if (fileType == null) {
\r
111 throw new NullPointerException("MarkerType must be provided!");
\r
113 if (fileType == fileType.FINISHED || fileType == fileType.STARTED) {
\r
114 throw new IllegalArgumentException(
\r
115 "Please use Util.writeStatFile(workDirectory, fileAndEventName) to record FINISHED and STARTED statuses!");
\r
117 if (!PathValidator.isValidDirectory(workDirectory)) {
\r
118 // This is OK as some task could be cancelled even before they
\r
120 log.warn("Attempting to write " + fileType
\r
121 + " marker in the work directory " + workDirectory
\r
122 + " is not provided or does not exist!");
\r
126 File sfile = new File(workDirectory, fileType.toString());
\r
127 if (!sfile.exists()) {
\r
128 return sfile.createNewFile();
\r
130 } catch (IOException e) {
\r
131 log.error("Could not record stat marker file " + fileType
\r
132 + " into the directory " + workDirectory + " ! "
\r
133 + e.getMessage(), e.getCause());
\r
138 public static boolean isMarked(String workDirectory, JobStatus marker) {
\r
139 if (!PathValidator.isValidDirectory(workDirectory)) {
\r
140 throw new NullPointerException("Work directory " + workDirectory
\r
141 + " is not provided or does not exist!");
\r
143 return new File(workDirectory, marker.toString()).exists();
\r
146 public static Map<String, String> mergeEnvVariables(
\r
147 final Map<String, String> sysEnvTobeModified,
\r
148 final Map<String, String> variables) {
\r
149 if (variables.containsKey(EnvVariableProcessor.PATH)) {
\r
150 String propPath = variables.get(EnvVariableProcessor.PATH);
\r
151 String sysPATH = sysEnvTobeModified.get(EnvVariableProcessor.PATH);
\r
152 String syspath = sysEnvTobeModified.get(EnvVariableProcessor.PATH
\r
154 // This version appears surprisingly often on windows machines
\r
155 boolean added = false;
\r
156 String sysPath = sysEnvTobeModified.get("Path");
\r
157 if (sysPATH != null) {
\r
158 sysEnvTobeModified.put(EnvVariableProcessor.PATH, sysPATH
\r
159 + File.pathSeparator + propPath);
\r
162 if (syspath != null) {
\r
163 sysEnvTobeModified.put(EnvVariableProcessor.PATH.toLowerCase(),
\r
164 syspath + File.pathSeparator + propPath);
\r
167 if (sysPath != null) {
\r
168 sysEnvTobeModified.put("Path", sysPath + File.pathSeparator
\r
172 // If not path variable is found, then add it
\r
174 sysEnvTobeModified.put(EnvVariableProcessor.PATH, propPath);
\r
176 variables.remove(EnvVariableProcessor.PATH);
\r
178 sysEnvTobeModified.putAll(variables);
\r
179 return sysEnvTobeModified;
\r
182 public static String convertToAbsolute(String relativePath) {
\r
183 // If specified path is relative, than make it absolute
\r
184 String absolute = relativePath;
\r
185 if (!PathValidator.isAbsolutePath(relativePath)) {
\r
186 absolute = PropertyHelperManager.getLocalPath() + relativePath;
\r
188 .trace("Changing local path in enviromental variable to absolute: FROM "
\r
189 + relativePath + " TO " + absolute);
\r
194 public static String getExecProperty(String propertySpec, Executable<?> exec) {
\r
195 assert !compbio.util.Util.isEmpty(propertySpec);
\r
196 assert exec != null;
\r
197 return Util.getExecProperty(propertySpec, exec.getClass());
\r
200 public static String getExecProperty(String propertySpec, Class<?> clazz) {
\r
201 assert !compbio.util.Util.isEmpty(propertySpec);
\r
202 assert clazz != null;
\r
203 String property = clazz.getSimpleName().toLowerCase() + "."
\r
204 + propertySpec.toLowerCase();
\r
205 log.trace("Processing property: " + property);
\r
206 return ph.getProperty(property);
\r
209 public static String getFullPath(String workDirectory, String fileName) {
\r
210 assert !compbio.util.Util.isEmpty(fileName) : "Filename must be provided! ";
\r
211 assert !compbio.util.Util.isEmpty(workDirectory) : "Workdirectory must be provided! ";
\r
212 return workDirectory + File.separator + fileName;
\r
215 public static String getCommand(ExecProvider provider, Class<?> clazz) {
\r
216 if (provider == ExecProvider.Any) {
\r
217 throw new IllegalArgumentException(
\r
218 "A particular execution environment must be chosen");
\r
220 String execCommandName = clazz.getSimpleName().toLowerCase();
\r
222 if (provider == ExecProvider.Local) {
\r
223 if (SysPrefs.isWindows) {
\r
224 bin = ph.getProperty("local." + execCommandName
\r
227 bin = ph.getProperty("local." + execCommandName + ".bin");
\r
229 // If path to executable defined in the properties is not absolute,
\r
231 // as setting working directory of ProcessBuilder will make it
\r
233 // to find an executable otherwise
\r
234 if (!compbio.util.Util.isEmpty(bin)
\r
235 && !PathValidator.isAbsolutePath(bin)) {
\r
236 bin = PropertyHelperManager.getLocalPath() + bin;
\r
239 bin = ph.getProperty("cluster." + execCommandName + ".bin");
\r
241 return bin; // File.separator
\r
244 public static ExecProvider getSupportedRuntimes(Class<?> clazz) {
\r
245 boolean localRuntimeSupport = false;
\r
246 boolean clusterRuntimeSupport = false;
\r
247 String executableName = clazz.getSimpleName().toLowerCase();
\r
248 String localRuntime1 = ph.getProperty("local." + executableName
\r
250 String localRuntime2 = ph.getProperty("local." + executableName
\r
252 if (!compbio.util.Util.isEmpty(localRuntime1)
\r
253 || !compbio.util.Util.isEmpty(localRuntime2)) {
\r
254 localRuntimeSupport = true;
\r
256 String clusterRuntime = ph.getProperty("cluster." + executableName
\r
258 if (!compbio.util.Util.isEmpty(clusterRuntime)) {
\r
259 clusterRuntimeSupport = true;
\r
261 if (localRuntimeSupport && clusterRuntimeSupport) {
\r
262 return ExecProvider.Any;
\r
263 } else if (localRuntimeSupport) {
\r
264 return ExecProvider.Local;
\r
265 } else if (clusterRuntimeSupport) {
\r
266 return ExecProvider.Cluster;
\r
268 // Means executable cannot be executed -> is improperly configured
\r
269 // should be ignored
\r
270 throw new InvalidParameterException(
\r
271 "Executable is not provided for any runtime environments");
\r
274 public static ConfiguredExecutable<?> loadExecutable(String taskId)
\r
275 throws ResultNotAvailableException {
\r
276 String workDir = compbio.engine.Configurator.getWorkDirectory(taskId);
\r
277 // The results for this job has been collected once, or the JVM may
\r
278 // have been restarted,
\r
279 // so that the job is not in the job list
\r
280 // ->load a ConfiguredExercutable from saved run and return it
\r
281 FileInputStream fileInStream = null;
\r
282 ConfiguredExecutable<?> exec = null;
\r
284 fileInStream = new FileInputStream(workDir + File.separator
\r
285 + RunConfiguration.rconfigFile);
\r
286 RunConfiguration rconf = RunConfiguration.load(fileInStream);
\r
287 exec = ConfExecutable.newConfExecutable(rconf);
\r
288 fileInStream.close();
\r
289 } catch (FileNotFoundException e) {
\r
290 log.error("Could not find run configuration to load!"
\r
291 + e.getLocalizedMessage(), e.getCause());
\r
292 throw new ResultNotAvailableException(
\r
293 "Could not find run configuration to load!"
\r
294 + e.getMessage(), e.getCause());
\r
295 } catch (IOException e) {
\r
296 log.error("IO Exception while reading run configuration file!"
\r
297 + e.getLocalizedMessage(), e.getCause());
\r
298 throw new ResultNotAvailableException(
\r
299 "Could not load run configuration!" + e.getMessage(), e
\r
302 FileUtil.closeSilently(log, fileInStream);
\r
308 * For now just assume that all parameters which came in needs setting it
\r
309 * will be a client responsibility to prepare RunnerConfig object then
\r
314 * public static List<String> toOptionString(RunnerConfig<?>
\r
315 * rconfig) { String option = ""; List<String> options = new
\r
316 * ArrayList<String>(); for (Parameter<?> par :
\r
317 * rconfig.getParameters()) { if (par.getPossibleValues().isEmpty())
\r
318 * { option = par.getOptionName(); } else { option =
\r
319 * par.getOptionName() + "=" + par.getPossibleValues().get(0); } //
\r
320 * separate options options.add(option); } return options; }
\r
323 public static <T> LimitsManager<T> getLimits(Class<Executable<T>> clazz) {
\r
324 LimitsManager<T> limits = null;
\r
326 limits = ConfExecutable.getRunnerLimits(clazz);
\r
327 } catch (FileNotFoundException e) {
\r
329 "No limits are found for " + clazz + " executable! "
\r
330 + e.getLocalizedMessage(), e.getCause());
\r
331 // its ok, limit may not be initialized
\r
332 } catch (IOException e) {
\r
333 Util.log.warn("IO exception while attempting to read limits for "
\r
334 + clazz + " executable! " + e.getLocalizedMessage(),
\r