/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive.scheduler.task.executors.forked.env; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.objectweb.proactive.core.config.CentralPAPropertyRepository; import org.ow2.proactive.resourcemanager.utils.OneJar; import org.ow2.proactive.scheduler.common.task.ForkEnvironment; import org.ow2.proactive.scheduler.common.util.VariableSubstitutor; import org.ow2.proactive.scheduler.core.properties.PASchedulerProperties; import org.ow2.proactive.scheduler.task.context.TaskContext; import org.ow2.proactive.scheduler.task.context.TaskContextVariableExtractor; import org.ow2.proactive.scheduler.task.executors.forked.env.command.JavaPrefixCommandExtractor; import org.ow2.proactive.scripting.ForkEnvironmentScriptResult; import org.ow2.proactive.scripting.ScriptResult; import com.google.common.base.Strings; public class ForkedJvmTaskExecutionCommandCreator implements Serializable { private final static String javaHomePostfixJavaExecutable = File.separatorChar + "bin" + File.separatorChar + "java"; private final TaskContextVariableExtractor taskContextVariableExtractor = new TaskContextVariableExtractor(); private final JavaPrefixCommandExtractor javaPrefixCommandExtractor = new JavaPrefixCommandExtractor(); /** * Creates a command to start a task inside a java virtual machine. * * @param taskContext TaskContext object describing the task. * @param forkEnvironmentScriptResult Result from a running fork environment script. If it is * of instance {@link ForkEnvironmentScriptResult}, the script return * variables will be used for the construction of the command. * @param serializedContextAbsolutePath The serialized TaskContext object which will be read by the virtual * machine to run the task. * @return A List, empty if the TaskContext is null, otherwise filled with a command. * @throws Exception If the {@link TaskContextVariableExtractor} could not extract all variables from the * TaskContext. */ public List<String> createForkedJvmTaskExecutionCommand(TaskContext taskContext, ScriptResult forkEnvironmentScriptResult, String serializedContextAbsolutePath) throws Exception { if (taskContext == null) { return new ArrayList<>(0); } Map<String, Serializable> variables = taskContextVariableExtractor.extractVariables(taskContext, true); String javaHome = System.getProperty("java.home"); ArrayList<String> jvmArguments = new ArrayList<>(1); ForkEnvironment forkEnvironment = null; if (taskContext.getInitializer() != null) { forkEnvironment = taskContext.getInitializer().getForkEnvironment(); } // set the task fork property so that script engines have a mean to know // if they are running in a forked task or not jvmArguments.add(PASchedulerProperties.TASK_FORK.getCmdLine() + "true"); StringBuilder classpath = new StringBuilder("." + File.pathSeparatorChar); if (!System.getProperty("java.class.path", "").contains("node.jar")) { // in case the class path of the node is not built with the node.jar, we // build the classpath with wildcards to avoid command too long errors on windows classpath.append(getStandardClassPathEntries(variables)); } for (String classpathEntry : OneJar.getClasspath()) { classpath.append(File.pathSeparatorChar).append(classpathEntry); } if (forkEnvironment != null) { for (String jvmArgument : forkEnvironment.getJVMArguments()) { jvmArguments.add(VariableSubstitutor.filterAndUpdate(jvmArgument, variables)); } for (String classpathEntry : forkEnvironment.getAdditionalClasspath()) { classpath.append(File.pathSeparatorChar) .append(VariableSubstitutor.filterAndUpdate(classpathEntry, variables)); } if (!Strings.isNullOrEmpty(forkEnvironment.getJavaHome())) { javaHome = VariableSubstitutor.filterAndUpdate(forkEnvironment.getJavaHome(), variables); } } List<String> prefixes = javaPrefixCommandExtractor.extractJavaPrefixCommandToCommandListFromScriptResult(forkEnvironmentScriptResult); List<String> javaCommand = new ArrayList<>(prefixes.size() + 3 + jvmArguments.size() + 2); javaCommand.addAll(prefixes); javaCommand.add(javaHome + javaHomePostfixJavaExecutable); javaCommand.add("-cp"); javaCommand.add(classpath.toString()); javaCommand.addAll(jvmArguments); javaCommand.add(ExecuteForkedTaskInsideNewJvm.class.getName()); javaCommand.add(serializedContextAbsolutePath); return javaCommand; } private StringBuilder getStandardClassPathEntries(Map<String, Serializable> variables) throws IOException { StringBuilder classpathEntries = new StringBuilder(); String schedulerHome; schedulerHome = System.getProperty(CentralPAPropertyRepository.PA_HOME.getName()); if (schedulerHome == null) { schedulerHome = (String) variables.get("PA_SCHEDULER_HOME"); } if (schedulerHome != null) { File paHome = new File(schedulerHome).getCanonicalFile(); File distLib = new File(paHome, "dist/lib").getCanonicalFile(); if (distLib.exists()) { File addons = new File(paHome, "addons").getCanonicalFile(); classpathEntries.append(distLib); classpathEntries.append(File.pathSeparatorChar); classpathEntries.append(new File(distLib, "*")); classpathEntries.append(File.pathSeparatorChar); classpathEntries.append(addons); classpathEntries.append(File.pathSeparatorChar); classpathEntries.append(new File(addons, "*")); } else { return getClassPathEntriesUsingJavaClassPath(); } } else { return getClassPathEntriesUsingJavaClassPath(); } return classpathEntries; } private StringBuilder getClassPathEntriesUsingJavaClassPath() { StringBuilder classpathEntries = new StringBuilder(); classpathEntries.append(System.getProperty("java.class.path", "")); return classpathEntries; } }