Java tutorial
/* */ package org.taverna.server.master.localworker; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import static java.io.File.separator; import static java.lang.System.getProperty; import static java.rmi.registry.Registry.REGISTRY_PORT; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; import static org.taverna.server.master.defaults.Default.EXTRA_ARGUMENTS; import static org.taverna.server.master.defaults.Default.PASSWORD_FILE; import static org.taverna.server.master.defaults.Default.REGISTRY_JAR; import static org.taverna.server.master.defaults.Default.RMI_PREFIX; import static org.taverna.server.master.defaults.Default.RUN_LIFE_MINUTES; import static org.taverna.server.master.defaults.Default.RUN_OPERATING_LIMIT; import static org.taverna.server.master.defaults.Default.SECURE_FORK_IMPLEMENTATION_JAR; import static org.taverna.server.master.defaults.Default.SERVER_WORKER_IMPLEMENTATION_JAR; import static org.taverna.server.master.defaults.Default.SUBPROCESS_START_POLL_SLEEP; import static org.taverna.server.master.defaults.Default.SUBPROCESS_START_WAIT; import static org.taverna.server.master.localworker.PersistedState.KEY; import static org.taverna.server.master.localworker.PersistedState.makeInstance; import java.io.File; import java.io.FilenameFilter; import java.net.URI; import java.util.List; import javax.annotation.PostConstruct; import javax.jdo.annotations.PersistenceAware; import org.springframework.beans.factory.annotation.Required; import org.taverna.server.master.common.Status; import org.taverna.server.master.defaults.Default; import org.taverna.server.master.utils.JDOSupport; import org.taverna.server.master.worker.WorkerModel; /** * The persistent state of a local worker factory. * * @author Donal Fellows */ @PersistenceAware public class LocalWorkerState extends JDOSupport<PersistedState> implements WorkerModel { public LocalWorkerState() { super(PersistedState.class); } private LocalWorkerState self; @Required public void setSelf(LocalWorkerState self) { this.self = self; } /** Initial lifetime of runs, in minutes. */ int defaultLifetime; /** * Maximum number of runs to exist at once. Note that this includes when * they are just existing for the purposes of file transfer ( * {@link Status#Initialized}/{@link Status#Finished} states). */ int maxRuns; /** * Prefix to use for RMI names. */ String factoryProcessNamePrefix; /** * Full path name of the script used to start running a workflow; normally * expected to be "<i>somewhere/</i><tt>executeWorkflow.sh</tt>". */ String executeWorkflowScript; /** Default value for {@link #executeWorkflowScript}. */ private transient String defaultExecuteWorkflowScript; /** * Full path name of the file containing the password used to launch workers * as other users. The file is normally expected to contain a single line, * the password, and to be thoroughly locked down so only the user running * the server (e.g., "<tt>tomcat</tt>") can read it; it will probably reside * in either the user's home directory or in a system configuration * directory. */ String passwordFile; /** Default value for {@link #passwordFile}. */ private transient String defaultPasswordFile = PASSWORD_FILE; /** * The extra arguments to pass to the subprocess. */ String[] extraArgs; /** * How long to wait for subprocess startup, in seconds. */ int waitSeconds; /** * Polling interval to use during startup, in milliseconds. */ int sleepMS; /** * Full path name to the worker process's implementation JAR. */ String serverWorkerJar; private static final String DEFAULT_WORKER_JAR = LocalWorkerState.class.getClassLoader() .getResource(SERVER_WORKER_IMPLEMENTATION_JAR).getFile(); /** * Full path name to the Java binary to use to run the subprocess. */ String javaBinary; private static final String DEFAULT_JAVA_BINARY = getProperty("java.home") + separator + "bin" + separator + "java"; /** * Full path name to the secure fork process's implementation JAR. */ String serverForkerJar; private static final String DEFAULT_FORKER_JAR = LocalWorkerState.class.getClassLoader() .getResource(SECURE_FORK_IMPLEMENTATION_JAR).getFile(); String registryHost; int registryPort; int operatingLimit; URI[] permittedWorkflows; private String registryJar; private static final String DEFAULT_REGISTRY_JAR = LocalWorkerState.class.getClassLoader() .getResource(REGISTRY_JAR).getFile(); @Override public void setDefaultLifetime(int defaultLifetime) { this.defaultLifetime = defaultLifetime; if (loadedState) self.store(); } @Override public int getDefaultLifetime() { return defaultLifetime < 1 ? RUN_LIFE_MINUTES : defaultLifetime; } @Override public void setMaxRuns(int maxRuns) { this.maxRuns = maxRuns; if (loadedState) self.store(); } @Override public int getMaxRuns() { return maxRuns < 1 ? Default.RUN_COUNT_MAX : maxRuns; } @Override public int getOperatingLimit() { return operatingLimit < 1 ? RUN_OPERATING_LIMIT : operatingLimit; } @Override public void setOperatingLimit(int operatingLimit) { this.operatingLimit = operatingLimit; if (loadedState) self.store(); } @Override public void setFactoryProcessNamePrefix(String factoryProcessNamePrefix) { this.factoryProcessNamePrefix = factoryProcessNamePrefix; if (loadedState) self.store(); } @Override public String getFactoryProcessNamePrefix() { return factoryProcessNamePrefix == null ? RMI_PREFIX : factoryProcessNamePrefix; } @Override public void setExecuteWorkflowScript(String executeWorkflowScript) { this.executeWorkflowScript = executeWorkflowScript; if (loadedState) self.store(); } @Override public String getExecuteWorkflowScript() { return executeWorkflowScript == null ? defaultExecuteWorkflowScript : executeWorkflowScript; } private static String guessWorkflowScript() { File utilDir = new File(DEFAULT_WORKER_JAR).getParentFile(); File[] dirs = utilDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith("taverna-commandline-"); } }); assert dirs.length > 0; return new File(dirs[0], "executeworkflow.sh").toString(); } /** * Set what executeworkflow script to use by default. This is the value that * is used if not overridden by the administration interface. * * @param defaultScript * Full path to the script to use. */ public void setDefaultExecuteWorkflowScript(String defaultScript) { if (defaultScript.startsWith("${") || defaultScript.equals("NONE")) { this.defaultExecuteWorkflowScript = guessWorkflowScript(); return; } this.defaultExecuteWorkflowScript = defaultScript; } String getDefaultExecuteWorkflowScript() { return defaultExecuteWorkflowScript; } @Override public void setExtraArgs(String[] extraArgs) { this.extraArgs = extraArgs.clone(); if (loadedState) self.store(); } @Override public String[] getExtraArgs() { return extraArgs == null ? EXTRA_ARGUMENTS : extraArgs.clone(); } @Override public void setWaitSeconds(int waitSeconds) { this.waitSeconds = waitSeconds; if (loadedState) self.store(); } @Override public int getWaitSeconds() { return waitSeconds < 1 ? SUBPROCESS_START_WAIT : waitSeconds; } @Override public void setSleepMS(int sleepMS) { this.sleepMS = sleepMS; if (loadedState) self.store(); } @Override public int getSleepMS() { return sleepMS < 1 ? SUBPROCESS_START_POLL_SLEEP : sleepMS; } @Override public void setServerWorkerJar(String serverWorkerJar) { this.serverWorkerJar = serverWorkerJar; if (loadedState) self.store(); } @Override public String getServerWorkerJar() { return serverWorkerJar == null ? DEFAULT_WORKER_JAR : serverWorkerJar; } @Override public void setServerForkerJar(String serverForkerJar) { this.serverForkerJar = serverForkerJar; if (loadedState) self.store(); } @Override public String getServerForkerJar() { return serverForkerJar == null ? DEFAULT_FORKER_JAR : serverForkerJar; } @Override public void setJavaBinary(String javaBinary) { this.javaBinary = javaBinary; if (loadedState) self.store(); } @Override public String getJavaBinary() { return javaBinary == null ? DEFAULT_JAVA_BINARY : javaBinary; } @Override public void setPasswordFile(String passwordFile) { this.passwordFile = passwordFile; if (loadedState) self.store(); } @Override public String getPasswordFile() { return passwordFile == null ? defaultPasswordFile : passwordFile; } void setDefaultPasswordFile(String defaultPasswordFile) { this.defaultPasswordFile = defaultPasswordFile; } @Override public void setRegistryHost(String registryHost) { this.registryHost = (registryHost == null ? "" : registryHost); if (loadedState) self.store(); } @Override public String getRegistryHost() { return (registryHost == null || registryHost.isEmpty()) ? null : registryHost; } @Override public void setRegistryPort(int registryPort) { this.registryPort = ((registryPort < 1 || registryPort > 65534) ? REGISTRY_PORT : registryPort); if (loadedState) self.store(); } @Override public int getRegistryPort() { return registryPort == 0 ? REGISTRY_PORT : registryPort; } @Override public String getRegistryJar() { return registryJar == null ? DEFAULT_REGISTRY_JAR : registryJar; } @Override public void setRegistryJar(String rmiRegistryJar) { this.registryJar = (rmiRegistryJar == null || rmiRegistryJar.isEmpty()) ? null : rmiRegistryJar; if (loadedState) self.store(); } @Override public List<URI> getPermittedWorkflowURIs() { if (permittedWorkflows == null || permittedWorkflows.length == 0) return emptyList(); return unmodifiableList(asList(permittedWorkflows)); } @Override public void setPermittedWorkflowURIs(List<URI> permittedWorkflows) { if (permittedWorkflows == null || permittedWorkflows.isEmpty()) this.permittedWorkflows = new URI[0]; else this.permittedWorkflows = permittedWorkflows.toArray(new URI[permittedWorkflows.size()]); if (loadedState) self.store(); } public static final boolean DEFAULT_GENERATE_PROVENANCE = false; private Boolean generateProvenance; @Override public boolean getGenerateProvenance() { Boolean g = generateProvenance; return g == null ? DEFAULT_GENERATE_PROVENANCE : (boolean) g; } @Override public void setGenerateProvenance(boolean generate) { this.generateProvenance = generate; if (loadedState) self.store(); } // -------------------------------------------------------------- private boolean loadedState; @PostConstruct @WithinSingleTransaction public void load() { if (loadedState || !isPersistent()) return; WorkerModel state = getById(KEY); if (state == null) { store(); return; } defaultLifetime = state.getDefaultLifetime(); executeWorkflowScript = state.getExecuteWorkflowScript(); extraArgs = state.getExtraArgs(); factoryProcessNamePrefix = state.getFactoryProcessNamePrefix(); javaBinary = state.getJavaBinary(); maxRuns = state.getMaxRuns(); serverWorkerJar = state.getServerWorkerJar(); serverForkerJar = state.getServerForkerJar(); passwordFile = state.getPasswordFile(); sleepMS = state.getSleepMS(); waitSeconds = state.getWaitSeconds(); registryHost = state.getRegistryHost(); registryPort = state.getRegistryPort(); operatingLimit = state.getOperatingLimit(); List<URI> pwu = state.getPermittedWorkflowURIs(); permittedWorkflows = (URI[]) pwu.toArray(new URI[pwu.size()]); registryJar = state.getRegistryJar(); generateProvenance = state.getGenerateProvenance(); loadedState = true; } @WithinSingleTransaction public void store() { if (!isPersistent()) return; WorkerModel state = getById(KEY); if (state == null) state = persist(makeInstance()); state.setDefaultLifetime(defaultLifetime); state.setExecuteWorkflowScript(executeWorkflowScript); state.setExtraArgs(extraArgs); state.setFactoryProcessNamePrefix(factoryProcessNamePrefix); state.setJavaBinary(javaBinary); state.setMaxRuns(maxRuns); state.setServerWorkerJar(serverWorkerJar); state.setServerForkerJar(serverForkerJar); state.setPasswordFile(passwordFile); state.setSleepMS(sleepMS); state.setWaitSeconds(waitSeconds); state.setRegistryHost(registryHost); state.setRegistryPort(registryPort); state.setOperatingLimit(operatingLimit); if (permittedWorkflows != null) state.setPermittedWorkflowURIs(asList(permittedWorkflows)); state.setRegistryJar(registryJar); if (generateProvenance != null) state.setGenerateProvenance(generateProvenance); loadedState = true; } }