org.taverna.server.master.localworker.LocalWorkerState.java Source code

Java tutorial

Introduction

Here is the source code for org.taverna.server.master.localworker.LocalWorkerState.java

Source

/*
 */
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;
    }
}