You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 16:37:25 UTC
[25/49] incubator-taverna-server git commit: taverna-* module names
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
deleted file mode 100644
index adf3ea7..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.lang.Runtime.getRuntime;
-import static java.lang.System.getProperty;
-import static java.lang.System.out;
-import static java.lang.management.ManagementFactory.getRuntimeMXBean;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.UUID.randomUUID;
-import static org.apache.commons.io.FileUtils.forceDelete;
-import static org.apache.commons.io.FileUtils.forceMkdir;
-import static org.apache.commons.io.FileUtils.writeByteArrayToFile;
-import static org.apache.commons.io.FileUtils.writeLines;
-import static org.taverna.server.localworker.api.Constants.HELIO_TOKEN_NAME;
-import static org.taverna.server.localworker.api.Constants.KEYSTORE_FILE;
-import static org.taverna.server.localworker.api.Constants.KEYSTORE_PASSWORD;
-import static org.taverna.server.localworker.api.Constants.SECURITY_DIR_NAME;
-import static org.taverna.server.localworker.api.Constants.SHARED_DIR_PROP;
-import static org.taverna.server.localworker.api.Constants.SUBDIR_LIST;
-import static org.taverna.server.localworker.api.Constants.SYSTEM_ENCODING;
-import static org.taverna.server.localworker.api.Constants.TRUSTSTORE_FILE;
-import static org.taverna.server.localworker.impl.utils.FilenameVerifier.getValidatedFile;
-import static org.taverna.server.localworker.remote.RemoteStatus.Finished;
-import static org.taverna.server.localworker.remote.RemoteStatus.Initialized;
-import static org.taverna.server.localworker.remote.RemoteStatus.Operating;
-import static org.taverna.server.localworker.remote.RemoteStatus.Stopped;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.api.WorkerFactory;
-import org.taverna.server.localworker.remote.IllegalStateTransitionException;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteInput;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteSecurityContext;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.remote.StillWorkingOnItException;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-/**
- * This class implements one side of the connection between the Taverna Server
- * master server and this process. It delegates to a {@link Worker} instance the
- * handling of actually running a workflow.
- *
- * @author Donal Fellows
- * @see DirectoryDelegate
- * @see FileDelegate
- * @see WorkerCore
- */
-@SuppressWarnings("serial")
-public class LocalWorker extends UnicastRemoteObject implements RemoteSingleRun {
- // ----------------------- CONSTANTS -----------------------
-
- /** Handle to the directory containing the security info. */
- static final File SECURITY_DIR;
- static final String SLASHTEMP;
- static {
- SLASHTEMP = getProperty("java.io.tmpdir");
- File home = new File(getProperty("user.home"));
- // If we can't write to $HOME (i.e., we're in an odd deployment) use
- // the official version of /tmp/$PID as a fallback.
- if (!home.canWrite())
- home = new File(SLASHTEMP, getRuntimeMXBean().getName());
- SECURITY_DIR = new File(home, SECURITY_DIR_NAME);
- }
-
- // ----------------------- VARIABLES -----------------------
-
- /**
- * Magic flag used to turn off problematic code when testing inside CI
- * environment.
- */
- static boolean DO_MKDIR = true;
-
- /** What to use to run a workflow engine. */
- private final String executeWorkflowCommand;
- /** What workflow to run. */
- private final byte[] workflow;
- /** The remote access object for the working directory. */
- private final DirectoryDelegate baseDir;
- /** What inputs to pass as files. */
- final Map<String, String> inputFiles;
- /** What inputs to pass as files (as file refs). */
- final Map<String, File> inputRealFiles;
- /** What inputs to pass as direct values. */
- final Map<String, String> inputValues;
- /** What delimiters to use. */
- final Map<String, String> inputDelimiters;
- /** The interface to the workflow engine subprocess. */
- private final Worker core;
- /** Our descriptor token (UUID). */
- private final String masterToken;
- /**
- * The root working directory for a workflow run, or <tt>null</tt> if it has
- * been deleted.
- */
- private File base;
- /**
- * When did this workflow start running, or <tt>null</tt> for
- * "never/not yet".
- */
- private Date start;
- /**
- * When did this workflow finish running, or <tt>null</tt> for
- * "never/not yet".
- */
- private Date finish;
- /** The cached status of the workflow run. */
- RemoteStatus status;
- /**
- * The name of the input Baclava document, or <tt>null</tt> to not do it
- * that way.
- */
- String inputBaclava;
- /**
- * The name of the output Baclava document, or <tt>null</tt> to not do it
- * that way.
- */
- String outputBaclava;
- /**
- * The file containing the input Baclava document, or <tt>null</tt> to not
- * do it that way.
- */
- private File inputBaclavaFile;
- /**
- * The file containing the output Baclava document, or <tt>null</tt> to not
- * do it that way.
- */
- private File outputBaclavaFile;
- /**
- * Registered shutdown hook so that we clean up when this process is killed
- * off, or <tt>null</tt> if that is no longer necessary.
- */
- Thread shutdownHook;
- /** Location for security information to be written to. */
- File securityDirectory;
- /**
- * Password to use to encrypt security information.
- */
- char[] keystorePassword = KEYSTORE_PASSWORD;
- /** Additional server-specified environment settings. */
- Map<String, String> environment = new HashMap<>();
- /** Additional server-specified java runtime settings. */
- List<String> runtimeSettings = new ArrayList<>();
- URL interactionFeedURL;
- URL webdavURL;
- URL publishURL;//FIXME
- private boolean doProvenance = true;
-
- // ----------------------- METHODS -----------------------
-
- /**
- * @param executeWorkflowCommand
- * The script used to execute workflows.
- * @param workflow
- * The workflow to execute.
- * @param workerClass
- * The class to instantiate as our local representative of the
- * run.
- * @param urReceiver
- * The remote class to report the generated usage record(s) to.
- * @param id
- * The UUID to use, or <tt>null</tt> if we are to invent one.
- * @param seedEnvironment
- * The key/value pairs to seed the worker subprocess environment
- * with.
- * @param javaParams
- * Parameters to pass to the worker subprocess java runtime
- * itself.
- * @param workerFactory
- * How to make instances of the low-level worker objects.
- * @throws RemoteException
- * If registration of the worker fails.
- * @throws ImplementationException
- * If something goes wrong during local setup.
- */
- protected LocalWorker(String executeWorkflowCommand, byte[] workflow,
- UsageRecordReceiver urReceiver, UUID id,
- Map<String, String> seedEnvironment, List<String> javaParams,
- WorkerFactory workerFactory) throws RemoteException,
- ImplementationException {
- super();
- if (id == null)
- id = randomUUID();
- masterToken = id.toString();
- this.workflow = workflow;
- this.executeWorkflowCommand = executeWorkflowCommand;
- String sharedDir = getProperty(SHARED_DIR_PROP, SLASHTEMP);
- base = new File(sharedDir, masterToken);
- out.println("about to create " + base);
- try {
- forceMkdir(base);
- for (String subdir : SUBDIR_LIST) {
- new File(base, subdir).mkdir();
- }
- } catch (IOException e) {
- throw new ImplementationException(
- "problem creating run working directory", e);
- }
- baseDir = new DirectoryDelegate(base, null);
- inputFiles = new HashMap<>();
- inputRealFiles = new HashMap<>();
- inputValues = new HashMap<>();
- inputDelimiters = new HashMap<>();
- environment.putAll(seedEnvironment);
- runtimeSettings.addAll(javaParams);
- try {
- core = workerFactory.makeInstance();
- } catch (Exception e) {
- out.println("problem when creating core worker implementation");
- e.printStackTrace(out);
- throw new ImplementationException(
- "problem when creating core worker implementation", e);
- }
- core.setURReceiver(urReceiver);
- Thread t = new Thread(new Runnable() {
- /**
- * Kill off the worker launched by the core.
- */
- @Override
- public void run() {
- try {
- shutdownHook = null;
- destroy();
- } catch (ImplementationException e) {
- // Absolutely nothing we can do here
- }
- }
- });
- getRuntime().addShutdownHook(t);
- shutdownHook = t;
- status = Initialized;
- }
-
- @Override
- public void destroy() throws ImplementationException {
- killWorkflowSubprocess();
- removeFromShutdownHooks();
- // Is this it?
- deleteWorkingDirectory();
- deleteSecurityManagerDirectory();
- core.deleteLocalResources();
- }
-
- private void killWorkflowSubprocess() {
- if (status != Finished && status != Initialized)
- try {
- core.killWorker();
- if (finish == null)
- finish = new Date();
- } catch (Exception e) {
- out.println("problem when killing worker");
- e.printStackTrace(out);
- }
- }
-
- private void removeFromShutdownHooks() throws ImplementationException {
- try {
- if (shutdownHook != null)
- getRuntime().removeShutdownHook(shutdownHook);
- } catch (RuntimeException e) {
- throw new ImplementationException("problem removing shutdownHook",
- e);
- } finally {
- shutdownHook = null;
- }
- }
-
- private void deleteWorkingDirectory() throws ImplementationException {
- try {
- if (base != null)
- forceDelete(base);
- } catch (IOException e) {
- out.println("problem deleting working directory");
- e.printStackTrace(out);
- throw new ImplementationException(
- "problem deleting working directory", e);
- } finally {
- base = null;
- }
- }
-
- private void deleteSecurityManagerDirectory()
- throws ImplementationException {
- try {
- if (securityDirectory != null)
- forceDelete(securityDirectory);
- } catch (IOException e) {
- out.println("problem deleting security directory");
- e.printStackTrace(out);
- throw new ImplementationException(
- "problem deleting security directory", e);
- } finally {
- securityDirectory = null;
- }
- }
-
- @Override
- public void addListener(RemoteListener listener) throws RemoteException,
- ImplementationException {
- throw new ImplementationException("not implemented");
- }
-
- @Override
- public String getInputBaclavaFile() {
- return inputBaclava;
- }
-
- @Override
- public List<RemoteInput> getInputs() throws RemoteException {
- ArrayList<RemoteInput> result = new ArrayList<>();
- for (String name : inputFiles.keySet())
- result.add(new InputDelegate(name));
- return result;
- }
-
- @Override
- public List<String> getListenerTypes() {
- return emptyList();
- }
-
- @Override
- public List<RemoteListener> getListeners() {
- return singletonList(core.getDefaultListener());
- }
-
- @Override
- public String getOutputBaclavaFile() {
- return outputBaclava;
- }
-
- class SecurityDelegate extends UnicastRemoteObject implements
- RemoteSecurityContext {
- private void setPrivatePerms(File dir) {
- if (!dir.setReadable(false, false) || !dir.setReadable(true, true)
- || !dir.setExecutable(false, false)
- || !dir.setExecutable(true, true)
- || !dir.setWritable(false, false)
- || !dir.setWritable(true, true)) {
- out.println("warning: "
- + "failed to set permissions on security context directory");
- }
- }
-
- protected SecurityDelegate(String token) throws IOException {
- super();
- if (DO_MKDIR) {
- securityDirectory = new File(SECURITY_DIR, token);
- forceMkdir(securityDirectory);
- setPrivatePerms(securityDirectory);
- }
- }
-
- /**
- * Write some data to a given file in the context directory.
- *
- * @param name
- * The name of the file to write.
- * @param data
- * The bytes to put in the file.
- * @throws RemoteException
- * If anything goes wrong.
- * @throws ImplementationException
- */
- protected void write(String name, byte[] data) throws RemoteException,
- ImplementationException {
- try {
- File f = new File(securityDirectory, name);
- writeByteArrayToFile(f, data);
- } catch (IOException e) {
- throw new ImplementationException("problem writing " + name, e);
- }
- }
-
- /**
- * Write some data to a given file in the context directory.
- *
- * @param name
- * The name of the file to write.
- * @param data
- * The lines to put in the file. The
- * {@linkplain LocalWorker#SYSTEM_ENCODING system encoding}
- * will be used to do the writing.
- * @throws RemoteException
- * If anything goes wrong.
- * @throws ImplementationException
- */
- protected void write(String name, Collection<String> data)
- throws RemoteException, ImplementationException {
- try {
- File f = new File(securityDirectory, name);
- writeLines(f, SYSTEM_ENCODING, data);
- } catch (IOException e) {
- throw new ImplementationException("problem writing " + name, e);
- }
- }
-
- /**
- * Write some data to a given file in the context directory.
- *
- * @param name
- * The name of the file to write.
- * @param data
- * The line to put in the file. The
- * {@linkplain LocalWorker#SYSTEM_ENCODING system encoding}
- * will be used to do the writing.
- * @throws RemoteException
- * If anything goes wrong.
- * @throws ImplementationException
- */
- protected void write(String name, char[] data) throws RemoteException,
- ImplementationException {
- try {
- File f = new File(securityDirectory, name);
- writeLines(f, SYSTEM_ENCODING, asList(new String(data)));
- } catch (IOException e) {
- throw new ImplementationException("problem writing " + name, e);
- }
- }
-
- @Override
- public void setKeystore(byte[] keystore) throws RemoteException,
- ImplementationException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (keystore == null)
- throw new IllegalArgumentException("keystore may not be null");
- write(KEYSTORE_FILE, keystore);
- }
-
- @Override
- public void setPassword(char[] password) throws RemoteException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (password == null)
- throw new IllegalArgumentException("password may not be null");
- keystorePassword = password.clone();
- }
-
- @Override
- public void setTruststore(byte[] truststore) throws RemoteException,
- ImplementationException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (truststore == null)
- throw new IllegalArgumentException("truststore may not be null");
- write(TRUSTSTORE_FILE, truststore);
- }
-
- @Override
- public void setUriToAliasMap(Map<URI, String> uriToAliasMap)
- throws RemoteException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (uriToAliasMap == null)
- return;
- ArrayList<String> lines = new ArrayList<>();
- for (Entry<URI, String> site : uriToAliasMap.entrySet())
- lines.add(site.getKey().toASCIIString() + " " + site.getValue());
- // write(URI_ALIAS_MAP, lines);
- }
-
- @Override
- public void setHelioToken(String helioToken) throws RemoteException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- out.println("registering HELIO CIS token for export");
- environment.put(HELIO_TOKEN_NAME, helioToken);
- }
- }
-
- @Override
- public RemoteSecurityContext getSecurityContext() throws RemoteException,
- ImplementationException {
- try {
- return new SecurityDelegate(masterToken);
- } catch (RemoteException e) {
- if (e.getCause() != null)
- throw new ImplementationException(
- "problem initializing security context", e.getCause());
- throw e;
- } catch (IOException e) {
- throw new ImplementationException(
- "problem initializing security context", e);
- }
- }
-
- @Override
- public RemoteStatus getStatus() {
- // only state that can spontaneously change to another
- if (status == Operating) {
- status = core.getWorkerStatus();
- if (status == Finished && finish == null)
- finish = new Date();
- }
- return status;
- }
-
- @Override
- public RemoteDirectory getWorkingDirectory() {
- return baseDir;
- }
-
- File validateFilename(String filename) throws RemoteException {
- if (filename == null)
- throw new IllegalArgumentException("filename must be non-null");
- try {
- return getValidatedFile(base, filename.split("/"));
- } catch (IOException e) {
- throw new IllegalArgumentException("failed to validate filename", e);
- }
- }
-
- class InputDelegate extends UnicastRemoteObject implements RemoteInput {
- private String name;
-
- InputDelegate(String name) throws RemoteException {
- super();
- this.name = name;
- if (!inputFiles.containsKey(name)) {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputFiles.put(name, null);
- inputRealFiles.put(name, null);
- inputValues.put(name, null);
- inputDelimiters.put(name, null);
- }
- }
-
- @Override
- public String getFile() {
- return inputFiles.get(name);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getValue() {
- return inputValues.get(name);
- }
-
- @Override
- public String getDelimiter() throws RemoteException {
- return inputDelimiters.get(name);
- }
-
- @Override
- public void setFile(String file) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputRealFiles.put(name, validateFilename(file));
- inputValues.put(name, null);
- inputFiles.put(name, file);
- inputBaclava = null;
- }
-
- @Override
- public void setValue(String value) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputValues.put(name, value);
- inputFiles.put(name, null);
- inputRealFiles.put(name, null);
- inputBaclava = null;
- }
-
- @Override
- public void setDelimiter(String delimiter) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- if (inputBaclava != null)
- throw new IllegalStateException("input baclava file set");
- if (delimiter != null) {
- if (delimiter.length() > 1)
- throw new IllegalStateException(
- "multi-character delimiter not permitted");
- if (delimiter.charAt(0) == 0)
- throw new IllegalStateException(
- "may not use NUL for splitting");
- if (delimiter.charAt(0) > 127)
- throw new IllegalStateException(
- "only ASCII characters supported for splitting");
- }
- inputDelimiters.put(name, delimiter);
- }
- }
-
- @Override
- public RemoteInput makeInput(String name) throws RemoteException {
- return new InputDelegate(name);
- }
-
- @Override
- public RemoteListener makeListener(String type, String configuration)
- throws RemoteException {
- throw new RemoteException("listener manufacturing unsupported");
- }
-
- @Override
- public void setInputBaclavaFile(String filename) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputBaclavaFile = validateFilename(filename);
- for (String input : inputFiles.keySet()) {
- inputFiles.put(input, null);
- inputRealFiles.put(input, null);
- inputValues.put(input, null);
- }
- inputBaclava = filename;
- }
-
- @Override
- public void setOutputBaclavaFile(String filename) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- if (filename != null)
- outputBaclavaFile = validateFilename(filename);
- else
- outputBaclavaFile = null;
- outputBaclava = filename;
- }
-
- @Override
- public void setGenerateProvenance(boolean prov) {
- doProvenance = prov;
- }
-
- @Override
- public void setStatus(RemoteStatus newStatus)
- throws IllegalStateTransitionException, RemoteException,
- ImplementationException, StillWorkingOnItException {
- if (status == newStatus)
- return;
-
- switch (newStatus) {
- case Initialized:
- throw new IllegalStateTransitionException(
- "may not move back to start");
- case Operating:
- switch (status) {
- case Initialized:
- boolean started;
- try {
- started = createWorker();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem creating executing workflow", e);
- }
- if (!started)
- throw new StillWorkingOnItException(
- "workflow start in process");
- break;
- case Stopped:
- try {
- core.startWorker();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem continuing workflow run", e);
- }
- break;
- case Finished:
- throw new IllegalStateTransitionException("already finished");
- default:
- break;
- }
- status = Operating;
- break;
- case Stopped:
- switch (status) {
- case Initialized:
- throw new IllegalStateTransitionException(
- "may only stop from Operating");
- case Operating:
- try {
- core.stopWorker();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem stopping workflow run", e);
- }
- break;
- case Finished:
- throw new IllegalStateTransitionException("already finished");
- default:
- break;
- }
- status = Stopped;
- break;
- case Finished:
- switch (status) {
- case Operating:
- case Stopped:
- try {
- core.killWorker();
- if (finish == null)
- finish = new Date();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem killing workflow run", e);
- }
- default:
- break;
- }
- status = Finished;
- break;
- }
- }
-
- private boolean createWorker() throws Exception {
- start = new Date();
- char[] pw = keystorePassword;
- keystorePassword = null;
- /*
- * Do not clear the keystorePassword array here; its ownership is
- * *transferred* to the worker core which doesn't copy it but *does*
- * clear it after use.
- */
- return core.initWorker(this, executeWorkflowCommand, workflow, base,
- inputBaclavaFile, inputRealFiles, inputValues, inputDelimiters,
- outputBaclavaFile, securityDirectory, pw, doProvenance,
- environment, masterToken, runtimeSettings);
- }
-
- @Override
- public Date getFinishTimestamp() {
- return finish == null ? null : new Date(finish.getTime());
- }
-
- @Override
- public Date getStartTimestamp() {
- return start == null ? null : new Date(start.getTime());
- }
-
- @Override
- public void setInteractionServiceDetails(URL feed, URL webdav, URL publish) {
- interactionFeedURL = feed;
- webdavURL = webdav;
- publishURL = publish;
- }
-
- @Override
- public void ping() {
- // Do nothing here; this *should* be empty
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
deleted file mode 100644
index 03ee69d..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.lang.Runtime.getRuntime;
-import static java.lang.System.exit;
-import static java.lang.System.getProperty;
-import static java.lang.System.out;
-import static java.lang.System.setProperty;
-import static java.lang.System.setSecurityManager;
-import static java.rmi.registry.LocateRegistry.getRegistry;
-import static org.taverna.server.localworker.api.Constants.DEATH_DELAY;
-import static org.taverna.server.localworker.api.Constants.LOCALHOST;
-import static org.taverna.server.localworker.api.Constants.RMI_HOST_PROP;
-import static org.taverna.server.localworker.api.Constants.SECURITY_POLICY_FILE;
-import static org.taverna.server.localworker.api.Constants.SEC_POLICY_PROP;
-import static org.taverna.server.localworker.api.Constants.UNSECURE_PROP;
-
-import java.io.ByteArrayInputStream;
-import java.net.URI;
-import java.rmi.RMISecurityManager;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.taverna.server.localworker.api.RunAccounting;
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.api.WorkerFactory;
-import org.taverna.server.localworker.remote.RemoteRunFactory;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
-
-/**
- * The registered factory for runs, this class is responsible for constructing
- * runs that are suitable for particular users. It is also the entry point for
- * this whole process.
- *
- * @author Donal Fellows
- * @see LocalWorker
- */
-@SuppressWarnings("serial")
-public class TavernaRunManager extends UnicastRemoteObject implements
- RemoteRunFactory, RunAccounting, WorkerFactory {
- String command;
- Map<String, String> seedEnvironment = new HashMap<>();
- List<String> javaInitParams = new ArrayList<>();
- private WorkflowBundleIO io;
- private int activeRuns = 0;
- // Hacks!
- public static String interactionHost;
- public static String interactionPort;
- public static String interactionWebdavPath;
- public static String interactionFeedPath;
-
- /**
- * How to get the actual workflow document from the XML document that it is
- * contained in.
- *
- * @param containerDocument
- * The document sent from the web interface.
- * @return The element describing the workflow, as expected by the Taverna
- * command line executor.
- */
- protected Element unwrapWorkflow(Document containerDocument) {
- return (Element) containerDocument.getDocumentElement().getFirstChild();
- }
-
- private static final String usage = "java -jar server.worker.jar workflowExecScript ?-Ekey=val...? ?-Jconfig? UUID";
-
- /**
- * An RMI-enabled factory for runs.
- *
- * @param command
- * What command to call to actually run a run.
- * @throws RemoteException
- * If anything goes wrong during creation of the instance.
- */
- public TavernaRunManager(String command) throws RemoteException {
- this.command = command;
- this.io = new WorkflowBundleIO();
- }
-
- @Override
- public RemoteSingleRun make(byte[] workflow, String creator,
- UsageRecordReceiver urReceiver, UUID id) throws RemoteException {
- if (creator == null)
- throw new RemoteException("no creator");
- try {
- URI wfid = io.readBundle(new ByteArrayInputStream(workflow), null)
- .getMainWorkflow().getWorkflowIdentifier();
- out.println("Creating run from workflow <" + wfid + "> for <"
- + creator + ">");
- return new LocalWorker(command, workflow, urReceiver, id,
- seedEnvironment, javaInitParams, this);
- } catch (RemoteException e) {
- throw e;
- } catch (Exception e) {
- throw new RemoteException("bad instance construction", e);
- }
- }
-
- private static boolean shuttingDown;
- private static String factoryName;
- private static Registry registry;
-
- static synchronized void unregisterFactory() {
- if (!shuttingDown) {
- shuttingDown = true;
- try {
- if (factoryName != null && registry != null)
- registry.unbind(factoryName);
- } catch (Exception e) {
- e.printStackTrace(out);
- }
- }
- }
-
- @Override
- public void shutdown() {
- unregisterFactory();
- new Thread(new DelayedDeath()).start();
- }
-
- static class DelayedDeath implements Runnable {
- @Override
- public void run() {
- try {
- Thread.sleep(DEATH_DELAY);
- } catch (InterruptedException e) {
- } finally {
- exit(0);
- }
- }
- }
-
- private void addArgument(String arg) {
- if (arg.startsWith("-E")) {
- String trimmed = arg.substring(2);
- int idx = trimmed.indexOf('=');
- if (idx > 0) {
- addEnvironmentDefinition(trimmed.substring(0, idx),
- trimmed.substring(idx + 1));
- return;
- }
- } else if (arg.startsWith("-D")) {
- if (arg.indexOf('=') > 0) {
- addJavaParameter(arg);
- return;
- }
- } else if (arg.startsWith("-J")) {
- addJavaParameter(arg.substring(2));
- return;
- }
- throw new IllegalArgumentException("argument \"" + arg
- + "\" must start with -D, -E or -J; "
- + "-D and -E must contain a \"=\"");
- }
-
- /**
- * @param args
- * The arguments from the command line invocation.
- * @throws Exception
- * If we can't connect to the RMI registry, or if we can't read
- * the workflow, or if we can't build the worker instance, or
- * register it. Also if the arguments are wrong.
- */
- public static void main(String[] args) throws Exception {
- if (args.length < 2)
- throw new Exception("wrong # args: must be \"" + usage + "\"");
- if (!getProperty(UNSECURE_PROP, "no").equals("yes")) {
- setProperty(SEC_POLICY_PROP, LocalWorker.class.getClassLoader()
- .getResource(SECURITY_POLICY_FILE).toExternalForm());
- setProperty(RMI_HOST_PROP, LOCALHOST);
- }
- setSecurityManager(new RMISecurityManager());
- factoryName = args[args.length - 1];
- TavernaRunManager man = new TavernaRunManager(args[0]);
- for (int i = 1; i < args.length - 1; i++)
- man.addArgument(args[i]);
- registry = getRegistry(LOCALHOST);
-
- registry.bind(factoryName, man);
- getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run() {
- unregisterFactory();
- }
- });
- out.println("registered RemoteRunFactory with ID " + factoryName);
- }
-
- private void addJavaParameter(String string) {
- this.javaInitParams.add(string);
- }
-
- private void addEnvironmentDefinition(String key, String value) {
- this.seedEnvironment.put(key, value);
- }
-
- @Override
- public void setInteractionServiceDetails(String host, String port,
- String webdavPath, String feedPath) throws RemoteException {
- if (host == null || port == null || webdavPath == null
- || feedPath == null)
- throw new IllegalArgumentException("all params must be non-null");
- interactionHost = host;
- interactionPort = port;
- interactionWebdavPath = webdavPath;
- interactionFeedPath = feedPath;
- }
-
- @Override
- public synchronized int countOperatingRuns() {
- return (activeRuns < 0 ? 0 : activeRuns);
- }
-
- @Override
- public synchronized void runStarted() {
- activeRuns++;
- }
-
- @Override
- public synchronized void runCeased() {
- activeRuns--;
- }
-
- @Override
- public Worker makeInstance() throws Exception {
- return new WorkerCore(this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
deleted file mode 100644
index 1a6cff8..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.io.File.createTempFile;
-import static java.io.File.pathSeparator;
-import static java.lang.Boolean.parseBoolean;
-import static java.lang.Double.parseDouble;
-import static java.lang.Integer.parseInt;
-import static java.lang.Long.parseLong;
-import static java.lang.Runtime.getRuntime;
-import static java.lang.System.out;
-import static java.net.InetAddress.getLocalHost;
-import static org.apache.commons.io.FileUtils.forceDelete;
-import static org.apache.commons.io.FileUtils.sizeOfDirectory;
-import static org.apache.commons.io.FileUtils.write;
-import static org.apache.commons.io.IOUtils.copy;
-import static org.taverna.server.localworker.api.Constants.CREDENTIAL_MANAGER_DIRECTORY;
-import static org.taverna.server.localworker.api.Constants.CREDENTIAL_MANAGER_PASSWORD;
-import static org.taverna.server.localworker.api.Constants.DEATH_TIME;
-import static org.taverna.server.localworker.api.Constants.DEFAULT_LISTENER_NAME;
-import static org.taverna.server.localworker.api.Constants.KEYSTORE_PASSWORD;
-import static org.taverna.server.localworker.api.Constants.START_WAIT_TIME;
-import static org.taverna.server.localworker.api.Constants.SYSTEM_ENCODING;
-import static org.taverna.server.localworker.api.Constants.TIME;
-import static org.taverna.server.localworker.impl.Status.Aborted;
-import static org.taverna.server.localworker.impl.Status.Completed;
-import static org.taverna.server.localworker.impl.Status.Failed;
-import static org.taverna.server.localworker.impl.Status.Held;
-import static org.taverna.server.localworker.impl.Status.Started;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionFeedPath;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionHost;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionPort;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionWebdavPath;
-import static org.taverna.server.localworker.impl.WorkerCore.pmap;
-import static org.taverna.server.localworker.remote.RemoteStatus.Finished;
-import static org.taverna.server.localworker.remote.RemoteStatus.Initialized;
-import static org.taverna.server.localworker.remote.RemoteStatus.Operating;
-import static org.taverna.server.localworker.remote.RemoteStatus.Stopped;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.ws.Holder;
-
-import org.ogf.usage.JobUsageRecord;
-import org.taverna.server.localworker.api.RunAccounting;
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.impl.utils.TimingOutTask;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-/**
- * The core class that connects to a Taverna command-line workflow execution
- * engine. This implementation always registers a single listener, &lquo;
- * <tt>io</tt> &rquo;, with two properties representing the stdout and stderr of
- * the run and one representing the exit code. The listener is
- * remote-accessible. It does not support attaching any other listeners.
- *
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-public class WorkerCore extends UnicastRemoteObject implements Worker,
- RemoteListener {
- @Nonnull
- static final Map<String, Property> pmap = new HashMap<>();
- /**
- * Regular expression to extract the detailed timing information from the
- * output of /usr/bin/time
- */
- @Nonnull
- private static final Pattern TimeRE;
- static {
- final String TIMERE = "([0-9.:]+)";
- final String TERMS = "(real|user|system|sys|elapsed)";
- TimeRE = Pattern.compile(TIMERE + " *" + TERMS + "[ \t]*" + TIMERE
- + " *" + TERMS + "[ \t]*" + TIMERE + " *" + TERMS);
- }
-
- /**
- * Environment variables to remove before any fork (because they're large or
- * potentially leaky).
- */
- // TODO Conduct a proper survey of what to remove
- @Nonnull
- private static final String[] ENVIRONMENT_TO_REMOVE = { "SUDO_COMMAND",
- "SUDO_USER", "SUDO_GID", "SUDO_UID", "DISPLAY", "LS_COLORS",
- "XFILESEARCHPATH", "SSH_AGENT_PID", "SSH_AUTH_SOCK" };
-
- @Nullable
- Process subprocess;
- @Nonnull
- final StringWriter stdout;
- @Nonnull
- final StringWriter stderr;
- @Nullable
- Integer exitCode;
- boolean readyToSendEmail;
- @Nullable
- String emailAddress;
- @Nullable
- Date start;
- @Nonnull
- final RunAccounting accounting;
- @Nonnull
- final Holder<Integer> pid;
-
- private boolean finished;
- @Nullable
- private JobUsageRecord ur;
- @Nullable
- private File wd;
- @Nullable
- private UsageRecordReceiver urreceiver;
- @Nullable
- private File workflowFile;
- private boolean stopped;
-
- /**
- * @param accounting
- * Object that looks after how many runs are executing.
- * @throws RemoteException
- */
- public WorkerCore(@Nonnull RunAccounting accounting) throws RemoteException {
- super();
- stdout = new StringWriter();
- stderr = new StringWriter();
- pid = new Holder<>();
- this.accounting = accounting;
- }
-
- private int getPID() {
- synchronized (pid) {
- if (pid.value == null)
- return -1;
- return pid.value;
- }
- }
-
- /**
- * Fire up the workflow. This causes a transition into the operating state.
- *
- * @param executeWorkflowCommand
- * The command to run to execute the workflow.
- * @param workflow
- * The workflow document to execute.
- * @param workingDir
- * What directory to use as the working directory.
- * @param inputBaclava
- * The baclava file to use for inputs, or <tt>null</tt> to use
- * the other <b>input*</b> arguments' values.
- * @param inputFiles
- * A mapping of input names to files that supply them. Note that
- * we assume that nothing mapped here will be mapped in
- * <b>inputValues</b>.
- * @param inputValues
- * A mapping of input names to values to supply to them. Note
- * that we assume that nothing mapped here will be mapped in
- * <b>inputFiles</b>.
- * @param outputBaclava
- * What baclava file to write the output from the workflow into,
- * or <tt>null</tt> to have it written into the <tt>out</tt>
- * subdirectory.
- * @param token
- * The name of the workflow run.
- * @return <tt>true</tt> if the worker started, or <tt>false</tt> if a
- * timeout occurred.
- * @throws IOException
- * If any of quite a large number of things goes wrong.
- */
- @Override
- public boolean initWorker(
- @Nonnull final LocalWorker local,
- @Nonnull final String executeWorkflowCommand,
- @Nonnull final byte[] workflow,
- @Nonnull final File workingDir,
- @Nullable final File inputBaclava,
- @Nonnull final Map<String, File> inputFiles,
- @Nonnull final Map<String, String> inputValues,
- @Nonnull final Map<String, String> inputDelimiters,
- @Nullable final File outputBaclava,
- @Nonnull final File securityDir,
- @Nullable final char[] password,
- final boolean generateProvenance,
- @Nonnull final Map<String, String> environment,
- @Nullable final String token,
- @Nonnull final List<String> runtime) throws IOException {
- try {
- new TimingOutTask() {
- @Override
- public void doIt() throws IOException {
- startExecutorSubprocess(
- createProcessBuilder(local, executeWorkflowCommand,
- workflow, workingDir, inputBaclava,
- inputFiles, inputValues, inputDelimiters,
- outputBaclava, securityDir, password,
- generateProvenance, environment, token,
- runtime), password);
- }
- }.doOrTimeOut(START_WAIT_TIME);
- } catch (IOException e) {
- throw e;
- } catch (Exception e) {
- throw new IOException(e);
- }
- return subprocess != null;
- }
-
- private void startExecutorSubprocess(@Nonnull ProcessBuilder pb,
- @Nullable char[] password) throws IOException {
- // Start the subprocess
- out.println("starting " + pb.command() + " in directory "
- + pb.directory() + " with environment " + pb.environment());
- subprocess = pb.start();
- if (subprocess == null)
- throw new IOException("unknown failure creating process");
- start = new Date();
- accounting.runStarted();
-
- // Capture its stdout and stderr
- new AsyncCopy(subprocess.getInputStream(), stdout, pid);
- new AsyncCopy(subprocess.getErrorStream(), stderr);
- if (password != null)
- new PasswordWriterThread(subprocess, password);
- }
-
- /**
- * Assemble the process builder. Does not launch the subprocess.
- *
- * @param local
- * The local worker container.
- * @param executeWorkflowCommand
- * The reference to the workflow engine implementation.
- * @param workflow
- * The workflow to execute.
- * @param workingDir
- * The working directory to use.
- * @param inputBaclava
- * What file to read a baclava document from (or <tt>null</tt>)
- * @param inputFiles
- * The mapping from inputs to files.
- * @param inputValues
- * The mapping from inputs to literal values.
- * @param outputBaclava
- * What file to write a baclava document to (or <tt>null</tt>)
- * @param securityDir
- * The credential manager directory.
- * @param password
- * The password for the credential manager.
- * @param environment
- * The seed environment
- * @param token
- * The run identifier that the server wants to use.
- * @param runtime
- * Any runtime parameters to Java.
- * @return The configured process builder.
- * @throws IOException
- * If file handling fails
- * @throws UnsupportedEncodingException
- * If we can't encode any text (unlikely)
- * @throws FileNotFoundException
- * If we can't write the workflow out (unlikely)
- */
- @Nonnull
- ProcessBuilder createProcessBuilder(@Nonnull LocalWorker local,
- @Nonnull String executeWorkflowCommand, @Nonnull byte[] workflow,
- @Nonnull File workingDir, @Nullable File inputBaclava,
- @Nonnull Map<String, File> inputFiles,
- @Nonnull Map<String, String> inputValues,
- @Nonnull Map<String, String> inputDelimiters,
- @Nullable File outputBaclava, @Nonnull File securityDir,
- @Nonnull char[] password, boolean generateProvenance,
- @Nonnull Map<String, String> environment, @Nonnull String token,
- @Nonnull List<String> runtime) throws IOException,
- UnsupportedEncodingException, FileNotFoundException {
- ProcessBuilder pb = new ProcessBuilder();
- pb.command().add(TIME);
- /*
- * WARNING! HERE THERE BE DRAGONS! BE CAREFUL HERE!
- *
- * Work around _Maven_ bug with permissions in zip files! The executable
- * bit is stripped by Maven's handling of file permissions, and there's
- * no practical way to work around it without massively increasing the
- * pain in other ways. Only want this on Unix - Windows isn't affected
- * by this - so we use the file separator as a proxy for whether this is
- * a true POSIX system. Ugly! Ugly ugly ugly...
- *
- * http://jira.codehaus.org/browse/MASSEMBLY-337 is relevant, but not
- * the whole story as we don't want to use a non-standard packaging
- * method as there's a real chance of it going wrong in an unexpected
- * way then. Other parts of the story are that the executable bit isn't
- * preserved when unpacking with the dependency plugin, and there's no
- * way to be sure that the servlet container will preserve the bit
- * either (as that's probably using a Java-based ZIP engine).
- */
- if (File.separatorChar == '/')
- pb.command().add("/bin/sh");
- pb.command().add(executeWorkflowCommand);
- if (runtime != null)
- pb.command().addAll(runtime);
-
- // Enable verbose logging
- pb.command().add("-logfile");
- pb.command().add(
- new File(new File(workingDir, "logs"), "detail.log")
- .getAbsolutePath());
-
- if (securityDir != null) {
- pb.command().add(CREDENTIAL_MANAGER_DIRECTORY);
- pb.command().add(securityDir.getAbsolutePath());
- out.println("security dir location: " + securityDir);
- }
- if (password != null) {
- pb.command().add(CREDENTIAL_MANAGER_PASSWORD);
- out.println("password of length " + password.length
- + " will be written to subprocess stdin");
- }
-
- // Add arguments denoting inputs
- if (inputBaclava != null) {
- pb.command().add("-inputdoc");
- pb.command().add(inputBaclava.getAbsolutePath());
- if (!inputBaclava.exists())
- throw new IOException("input baclava file doesn't exist");
- } else {
- for (Entry<String, File> port : inputFiles.entrySet()) {
- if (port.getValue() == null)
- continue;
- pb.command().add("-inputfile");
- pb.command().add(port.getKey());
- pb.command().add(port.getValue().getAbsolutePath());
- if (!port.getValue().exists())
- throw new IOException("input file for port \"" + port
- + "\" doesn't exist");
- }
- for (Entry<String, String> port : inputValues.entrySet()) {
- if (port.getValue() == null)
- continue;
- pb.command().add("-inputfile");
- pb.command().add(port.getKey());
- File f = createTempFile(".tav_in_", null, workingDir);
- pb.command().add(f.getAbsolutePath());
- write(f, port.getValue(), "UTF-8");
- }
- for (Entry<String, String> delim : inputDelimiters.entrySet()) {
- if (delim.getValue() == null)
- continue;
- pb.command().add("-inputdelimiter");
- pb.command().add(delim.getKey());
- pb.command().add(delim.getValue());
- }
- }
-
- // Add arguments denoting outputs
- if (outputBaclava != null) {
- pb.command().add("-outputdoc");
- pb.command().add(outputBaclava.getAbsolutePath());
- if (!outputBaclava.getParentFile().exists())
- throw new IOException(
- "parent directory of output baclava file does not exist");
- if (outputBaclava.exists())
- throw new IOException("output baclava file exists");
- // Provenance cannot be supported when using baclava output
- } else {
- File out = new File(workingDir, "out");
- if (!out.mkdir())
- throw new IOException("failed to make output directory \"out\"");
- // Taverna needs the dir to *not* exist now
- forceDelete(out);
- pb.command().add("-outputdir");
- pb.command().add(out.getAbsolutePath());
- // Enable provenance generation
- if (generateProvenance) {
- pb.command().add("-embedded");
- pb.command().add("-provenance");
- pb.command().add("-provbundle");
- pb.command().add("out.bundle.zip");
- }
- }
-
- // Add an argument holding the workflow
- File tmp = createTempFile(".wf_", ".scufl2", workingDir);
- try (OutputStream os = new FileOutputStream(tmp)) {
- os.write(workflow);
- }
- pb.command().add(workflowFile.getAbsolutePath());
-
- // Indicate what working directory to use
- pb.directory(workingDir);
- wd = workingDir;
-
- Map<String, String> env = pb.environment();
- for (String name : ENVIRONMENT_TO_REMOVE)
- env.remove(name);
-
- // Merge any options we have had imposed on us from outside
- env.putAll(environment);
-
- // Patch the environment to deal with TAVUTILS-17
- assert env.get("PATH") != null;
- env.put("PATH", new File(System.getProperty("java.home"), "bin")
- + pathSeparator + env.get("PATH"));
- // Patch the environment to deal with TAVSERV-189
- env.put("TAVERNA_APPHOME", workingDir.getCanonicalPath());
- // Patch the environment to deal with TAVSERV-224
- env.put("TAVERNA_RUN_ID", token);
- if (interactionHost != null || local.interactionFeedURL != null
- || local.webdavURL != null) {
- env.put("INTERACTION_HOST", makeInterHost(local.interactionFeedURL));
- env.put("INTERACTION_PORT", makeInterPort(local.interactionFeedURL));
- env.put("INTERACTION_FEED", makeInterPath(local.interactionFeedURL));
- env.put("INTERACTION_WEBDAV",
- local.webdavURL != null ? local.webdavURL.getPath()
- : interactionWebdavPath);
- String pub = makeInterPublish(local.publishURL);
- if (pub != null && !pub.isEmpty())
- env.put("INTERACTION_PUBLISH", pub);
- }
- return pb;
- }
-
- @Nullable
- private static String makeInterHost(@Nullable URL url) {
- if (url == null)
- return interactionHost;
- return url.getProtocol() + "://" + url.getHost();
- }
-
- @Nullable
- private static String makeInterPort(@Nullable URL url) {
- if (url == null)
- return interactionPort;
- int port = url.getPort();
- if (port == -1)
- port = url.getDefaultPort();
- return Integer.toString(port);
- }
-
- @Nullable
- private static String makeInterPublish(@Nullable URL url)
- throws IOException {
- if (url == null)
- return null;
- try {
- URI uri = url.toURI();
- int port = uri.getPort();
- if (port == -1)
- return uri.getScheme() + "://" + uri.getHost();
- else
- return uri.getScheme() + "://" + uri.getHost() + ":" + port;
- } catch (URISyntaxException e) {
- throw new IOException("problem constructing publication url", e);
- }
- }
-
- @Nullable
- private static String makeInterPath(@Nullable URL url) {
- if (url == null)
- return interactionFeedPath;
- return url.getPath();
- }
-
- /**
- * Kills off the subprocess if it exists and is alive.
- */
- @Override
- public void killWorker() {
- if (!finished && subprocess != null) {
- final Holder<Integer> code = new Holder<>();
- for (TimingOutTask tot : new TimingOutTask[] { new TimingOutTask() {
- /** Check if the workflow terminated of its own accord */
- @Override
- public void doIt() throws IOException {
- code.value = subprocess.exitValue();
- accounting.runCeased();
- buildUR(code.value == 0 ? Completed : Failed, code.value);
- }
- }, new TimingOutTask() {
- /** Tell the workflow to stop */
- @Override
- public void doIt() throws IOException {
- code.value = killNicely();
- accounting.runCeased();
- buildUR(code.value == 0 ? Completed : Aborted, code.value);
- }
- }, new TimingOutTask() {
- /** Kill the workflow, kill it with fire */
- @Override
- public void doIt() throws IOException {
- code.value = killHard();
- accounting.runCeased();
- buildUR(code.value == 0 ? Completed : Aborted, code.value);
- }
- } }) {
- try {
- tot.doOrTimeOut(DEATH_TIME);
- } catch (Exception e) {
- }
- if (code.value != null)
- break;
- }
- finished = true;
- setExitCode(code.value);
- readyToSendEmail = true;
- }
- }
-
- /**
- * Integrated spot to handle writing/logging of the exit code.
- *
- * @param code
- * The exit code.
- */
- private void setExitCode(int code) {
- exitCode = code;
- if (code > 256 - 8) {
- out.println("workflow aborted, Raven issue = " + (code - 256));
- } else if (code > 128) {
- out.println("workflow aborted, signal=" + (code - 128));
- } else {
- out.println("workflow exited, code=" + code);
- }
- }
-
- @Nonnull
- private JobUsageRecord newUR() throws DatatypeConfigurationException {
- try {
- if (wd != null)
- return new JobUsageRecord(wd.getName());
- } catch (RuntimeException e) {
- }
- return new JobUsageRecord("unknown");
- }
-
- /**
- * Fills in the accounting information from the exit code and stderr.
- *
- * @param exitCode
- * The exit code from the program.
- */
- private void buildUR(@Nonnull Status status, int exitCode) {
- try {
- Date now = new Date();
- long user = -1, sys = -1, real = -1;
- Matcher m = TimeRE.matcher(stderr.toString());
- ur = newUR();
- while (m.find())
- for (int i = 1; i < 6; i += 2)
- if (m.group(i + 1).equals("user"))
- user = parseDuration(m.group(i));
- else if (m.group(i + 1).equals("sys")
- || m.group(i + 1).equals("system"))
- sys = parseDuration(m.group(i));
- else if (m.group(i + 1).equals("real")
- || m.group(i + 1).equals("elapsed"))
- real = parseDuration(m.group(i));
- if (user != -1)
- ur.addCpuDuration(user).setUsageType("user");
- if (sys != -1)
- ur.addCpuDuration(sys).setUsageType("system");
- ur.addUser(System.getProperty("user.name"), null);
- ur.addStartAndEnd(start, now);
- if (real != -1)
- ur.addWallDuration(real);
- else
- ur.addWallDuration(now.getTime() - start.getTime());
- ur.setStatus(status.toString());
- ur.addHost(getLocalHost().getHostName());
- ur.addResource("exitcode", Integer.toString(exitCode));
- ur.addDisk(sizeOfDirectory(wd)).setStorageUnit("B");
- if (urreceiver != null)
- urreceiver.acceptUsageRecord(ur.marshal());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private long parseDuration(@Nonnull String durationString) {
- try {
- return (long) (parseDouble(durationString) * 1000);
- } catch (NumberFormatException nfe) {
- // Not a double; maybe MM:SS.mm or HH:MM:SS.mm
- }
- long dur = 0;
- for (String d : durationString.split(":"))
- try {
- dur = 60 * dur + parseLong(d);
- } catch (NumberFormatException nfe) {
- // Assume that only one thing is fractional, and that it is last
- return 60000 * dur + (long) (parseDouble(d) * 1000);
- }
- return dur * 1000;
- }
-
- private void signal(@Nonnull String signal) throws Exception {
- int pid = getPID();
- if (pid > 0
- && getRuntime().exec("kill -" + signal + " " + pid).waitFor() == 0)
- return;
- throw new Exception("failed to send signal " + signal + " to process "
- + pid);
- }
-
- @Nullable
- private Integer killNicely() {
- try {
- signal("TERM");
- return subprocess.waitFor();
- } catch (Exception e) {
- return null;
- }
- }
-
- @Nullable
- private Integer killHard() {
- try {
- signal("QUIT");
- return subprocess.waitFor();
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Move the worker out of the stopped state and back to operating.
- *
- * @throws Exception
- * if it fails.
- */
- @Override
- public void startWorker() throws Exception {
- signal("CONT");
- stopped = false;
- }
-
- /**
- * Move the worker into the stopped state from the operating state.
- *
- * @throws Exception
- * if it fails.
- */
- @Override
- public void stopWorker() throws Exception {
- signal("STOP");
- stopped = true;
- }
-
- /**
- * @return The status of the workflow run. Note that this can be an
- * expensive operation.
- */
- @Override
- public RemoteStatus getWorkerStatus() {
- if (subprocess == null)
- return Initialized;
- if (finished)
- return Finished;
- try {
- setExitCode(subprocess.exitValue());
- } catch (IllegalThreadStateException e) {
- if (stopped)
- return Stopped;
- return Operating;
- }
- finished = true;
- readyToSendEmail = true;
- accounting.runCeased();
- buildUR(exitCode.intValue() == 0 ? Completed : Failed, exitCode);
- return Finished;
- }
-
- @Override
- public String getConfiguration() {
- return "";
- }
-
- @Override
- public String getName() {
- return DEFAULT_LISTENER_NAME;
- }
-
- @Override
- public String getProperty(String propName) throws RemoteException {
- switch (Property.is(propName)) {
- case STDOUT:
- return stdout.toString();
- case STDERR:
- return stderr.toString();
- case EXIT_CODE:
- return (exitCode == null) ? "" : exitCode.toString();
- case EMAIL:
- return emailAddress;
- case READY_TO_NOTIFY:
- return Boolean.toString(readyToSendEmail);
- case USAGE:
- try {
- JobUsageRecord toReturn;
- if (subprocess == null) {
- toReturn = newUR();
- toReturn.setStatus(Held.toString());
- } else if (ur == null) {
- toReturn = newUR();
- toReturn.setStatus(Started.toString());
- toReturn.addStartAndEnd(start, new Date());
- toReturn.addUser(System.getProperty("user.name"), null);
- } else {
- toReturn = ur;
- }
- /*
- * Note that this record is not to be pushed to the server. That
- * is done elsewhere (when a proper record is produced)
- */
- return toReturn.marshal();
- } catch (Exception e) {
- e.printStackTrace();
- return "";
- }
- default:
- throw new RemoteException("unknown property");
- }
- }
-
- @Override
- public String getType() {
- return DEFAULT_LISTENER_NAME;
- }
-
- @Override
- public String[] listProperties() {
- return Property.names();
- }
-
- @Override
- public void setProperty(String propName, String value)
- throws RemoteException {
- switch (Property.is(propName)) {
- case EMAIL:
- emailAddress = value;
- return;
- case READY_TO_NOTIFY:
- readyToSendEmail = parseBoolean(value);
- return;
- case STDOUT:
- case STDERR:
- case EXIT_CODE:
- case USAGE:
- throw new RemoteException("property is read only");
- default:
- throw new RemoteException("unknown property");
- }
- }
-
- @Override
- public RemoteListener getDefaultListener() {
- return this;
- }
-
- @Override
- public void setURReceiver(@Nonnull UsageRecordReceiver receiver) {
- urreceiver = receiver;
- }
-
- @Override
- public void deleteLocalResources() throws ImplementationException {
- try {
- if (workflowFile != null && workflowFile.getParentFile().exists())
- forceDelete(workflowFile);
- } catch (IOException e) {
- throw new ImplementationException("problem deleting workflow file",
- e);
- }
- }
-}
-
-/**
- * An engine for asynchronously copying from an {@link InputStream} to a
- * {@link Writer}.
- *
- * @author Donal Fellows
- */
-class AsyncCopy extends Thread {
- @Nonnull
- private BufferedReader from;
- @Nonnull
- private Writer to;
- @Nullable
- private Holder<Integer> pidHolder;
-
- AsyncCopy(@Nonnull InputStream from, @Nonnull Writer to)
- throws UnsupportedEncodingException {
- this(from, to, null);
- }
-
- AsyncCopy(@Nonnull InputStream from, @Nonnull Writer to,
- @Nullable Holder<Integer> pid) throws UnsupportedEncodingException {
- this.from = new BufferedReader(new InputStreamReader(from,
- SYSTEM_ENCODING));
- this.to = to;
- this.pidHolder = pid;
- setDaemon(true);
- start();
- }
-
- @Override
- public void run() {
- try {
- if (pidHolder != null) {
- String line = from.readLine();
- if (line.matches("^pid:\\d+$"))
- synchronized (pidHolder) {
- pidHolder.value = parseInt(line.substring(4));
- }
- else
- to.write(line + System.getProperty("line.separator"));
- }
- copy(from, to);
- } catch (IOException e) {
- }
- }
-}
-
-/**
- * A helper for asynchronously writing a password to a subprocess's stdin.
- *
- * @author Donal Fellows
- */
-class PasswordWriterThread extends Thread {
- private OutputStream to;
- private char[] chars;
-
- PasswordWriterThread(@Nonnull Process to, @Nonnull char[] chars) {
- this.to = to.getOutputStream();
- assert chars != null;
- this.chars = chars;
- setDaemon(true);
- start();
- }
-
- @Override
- public void run() {
- try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(to,
- SYSTEM_ENCODING))) {
- pw.println(chars);
- } catch (UnsupportedEncodingException e) {
- // Not much we can do here
- e.printStackTrace();
- } finally {
- /*
- * We don't trust GC to clear password from memory. We also take
- * care not to clear the default password!
- */
- if (chars != KEYSTORE_PASSWORD)
- Arrays.fill(chars, '\00');
- }
- }
-}
-
-enum Property {
- STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
- "readyToNotify"), EMAIL("notificationAddress"), USAGE("usageRecord");
-
- private String s;
-
- private Property(String s) {
- this.s = s;
- pmap.put(s, this);
- }
-
- @Override
- public String toString() {
- return s;
- }
-
- public static Property is(@Nonnull String s) {
- return pmap.get(s);
- }
-
- @Nonnull
- public static String[] names() {
- return pmap.keySet().toArray(new String[pmap.size()]);
- }
-}
-
-enum Status {
- Aborted, Completed, Failed, Held, Queued, Started, Suspended
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
deleted file mode 100644
index fbc3a72..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl.utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Utility class that handles filename validation on different target platforms.
- *
- * @author Donal Fellows.
- */
-public abstract class FilenameVerifier {
- private FilenameVerifier(){}
-
- static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
-
- @SuppressWarnings("serial")
- private static final Set<String> ILLEGAL_NAMES = new HashSet<String>(){{
- add("");
- add("..");
- add(".");
- if (IS_WINDOWS) {
- add("con");
- add("prn");
- add("nul");
- add("aux");
- for (int i = 1; i <= 9; i++) {
- add("com" + i);
- add("lpt" + i);
- }
- }
- }};
- @SuppressWarnings("serial")
- private static final Set<Character> ILLEGAL_CHARS = new HashSet<Character>(){{
- add('/');
- for (char i=0 ; i<32 ; i++)
- add(i);
- if (IS_WINDOWS) {
- add('\\');
- add('>');
- add('<');
- add(':');
- add('"');
- add('|');
- add('?');
- add('*');
- } else {
- add(' '); // whitespace; too much trouble from these
- add('\t');
- add('\r');
- add('\n');
- }
- }};
- @SuppressWarnings("serial")
- private static final Set<String> ILLEGAL_PREFIXES = new HashSet<String>(){{
- if (IS_WINDOWS) {
- add("con.");
- add("prn.");
- add("nul.");
- add("aux.");
- for (int i = 1; i <= 9; i++) {
- add("com" + i + ".");
- add("lpt" + i + ".");
- }
- }
- }};
- @SuppressWarnings("serial")
- private static final Set<String> ILLEGAL_SUFFIXES = new HashSet<String>(){{
- if (IS_WINDOWS) {
- add(" ");
- add(".");
- }
- }};
-
- /**
- * Construct a file handle, applying platform-specific filename validation
- * rules in the process.
- *
- * @param dir
- * The directory acting as a root, which is assumed to be
- * correctly named. May be <tt>null</tt>.
- * @param names
- * The names of filename fragments to apply the checks to. Must
- * have at least one value.
- * @return The file handle. Never <tt>null</tt>.
- * @throws IOException
- * If validation fails.
- */
- public static File getValidatedFile(File dir, String... names)
- throws IOException {
- if (names.length == 0)
- throw new IOException("empty filename");
- File f = dir;
- for (String name : names) {
- String low = name.toLowerCase();
- if (ILLEGAL_NAMES.contains(low))
- throw new IOException("illegal filename");
- for (char c : ILLEGAL_CHARS)
- if (low.indexOf(c) >= 0)
- throw new IOException("illegal filename");
- for (String s : ILLEGAL_PREFIXES)
- if (low.startsWith(s))
- throw new IOException("illegal filename");
- for (String s : ILLEGAL_SUFFIXES)
- if (low.endsWith(s))
- throw new IOException("illegal filename");
- f = new File(f, name);
- }
- assert f != null;
- return f;
- }
-
- /**
- * Create a file handle where the underlying file must exist.
- *
- * @param dir
- * The directory that will contain the file.
- * @param name
- * The name of the file; will be validated.
- * @return The handle.
- * @throws IOException
- * If validation fails or the file doesn't exist.
- */
- public static File getValidatedExistingFile(File dir, String name)
- throws IOException {
- File f = getValidatedFile(dir, name);
- if (!f.exists())
- throw new IOException("doesn't exist");
- return f;
- }
-
- /**
- * Create a file handle where the underlying file must <i>not</i> exist.
- *
- * @param dir
- * The directory that will contain the file.
- * @param name
- * The name of the file; will be validated.
- * @return The handle. The file will not be created by this method.
- * @throws IOException
- * If validation fails or the file does exist.
- */
- public static File getValidatedNewFile(File dir, String name)
- throws IOException {
- File f = getValidatedFile(dir, name);
- if (f.exists())
- throw new IOException("already exists");
- return f;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
deleted file mode 100644
index 3dd3ac1..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.taverna.server.localworker.impl.utils;
-
-import javax.annotation.Nullable;
-
-/**
- * A class that handles running a task that can take some time.
- *
- * @author Donal Fellows
- *
- */
-public abstract class TimingOutTask extends Thread {
- public abstract void doIt() throws Exception;
-
- @Nullable
- private Exception ioe;
-
- @Override
- public final void run() {
- try {
- doIt();
- } catch (Exception ioe) {
- this.ioe = ioe;
- }
- }
-
- public TimingOutTask() {
- this.setDaemon(true);
- }
-
- public void doOrTimeOut(long timeout) throws Exception {
- start();
- try {
- join(timeout);
- } catch (InterruptedException e) {
- interrupt();
- }
- if (ioe != null)
- throw ioe;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/resources/security.policy
----------------------------------------------------------------------
diff --git a/server-worker/src/main/resources/security.policy b/server-worker/src/main/resources/security.policy
deleted file mode 100644
index 5b5c322..0000000
--- a/server-worker/src/main/resources/security.policy
+++ /dev/null
@@ -1,11 +0,0 @@
-//keystore "signers.jks";
-//grant signedBy "taverna" {
-// permission java.util.PropertyPermission "*", "read,write";
-// permission java.lang.RuntimePermission "shutdownHooks";
-// permission java.lang.RuntimePermission "exitVM";
-// permission java.io.FilePermission "<<ALL FILES>>", "read,write,execute,delete";
-// permission java.net.SocketPermission "localhost:1024-" "accept,connect,listen";
-//};
-grant {
- permission java.security.AllPermission "*:*";
-};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
----------------------------------------------------------------------
diff --git a/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java b/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
deleted file mode 100644
index 7bcd92e..0000000
--- a/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.util.UUID.randomUUID;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.taverna.server.localworker.impl.LocalWorker.DO_MKDIR;
-
-import java.io.File;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.api.WorkerFactory;
-import org.taverna.server.localworker.remote.IllegalStateTransitionException;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteInput;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-public class LocalWorkerTest {
- LocalWorker lw;
- static List<String> events;
-
- public static RemoteStatus returnThisStatus = RemoteStatus.Operating;
-
- static class DummyWorker implements Worker {
- @Override
- public RemoteListener getDefaultListener() {
- return new RemoteListener() {
- @Override
- public String getConfiguration() {
- return "RLCONFIG";
- }
-
- @Override
- public String getName() {
- return "RLNAME";
- }
-
- @Override
- public String getProperty(String propName) {
- return "RLPROP[" + propName + "]";
- }
-
- @Override
- public String getType() {
- return "RLTYPE";
- }
-
- @Override
- public String[] listProperties() {
- return new String[] { "RLP1", "RLP2" };
- }
-
- @Override
- public void setProperty(String propName, String value) {
- events.add("setProperty[");
- events.add(propName);
- events.add(value);
- events.add("]");
- }
- };
- }
-
- @Override
- public RemoteStatus getWorkerStatus() {
- events.add("status=" + returnThisStatus);
- return returnThisStatus;
- }
-
- @Override
- public boolean initWorker(LocalWorker local,
- String executeWorkflowCommand, byte[] workflow,
- File workingDir, File inputBaclava,
- Map<String, File> inputFiles, Map<String, String> inputValues,
- Map<String, String> delimiters, File outputBaclava, File cmdir,
- char[] cmpass, boolean doprov, Map<String, String> env,
- String id, List<String> conf) throws Exception {
- events.add("init[");
- events.add(executeWorkflowCommand);
- events.add(new String(workflow, "UTF-8"));
- int dirLen = workingDir.getName().length();
- events.add(Integer.toString(dirLen));
- events.add(inputBaclava == null ? "<null>" : inputBaclava
- .toString().substring(dirLen));
- Map<String, String> in = new TreeMap<>();
- for (Entry<String, File> name : inputFiles.entrySet())
- in.put(name.getKey(), name.getValue() == null ? "<null>" : name
- .getValue().getName());
- events.add(in.toString());
- events.add(new TreeMap<>(inputValues).toString());
- events.add(outputBaclava == null ? "<null>" : outputBaclava
- .getName());
- // TODO: check cmdir and cmpass
- // TODO: check doprov
- // TODO: log env
- // TODO: check delimiters
- events.add("]");
- return true;
- }
-
- @Override
- public void killWorker() throws Exception {
- events.add("kill");
- }
-
- @Override
- public void startWorker() throws Exception {
- events.add("start");
- }
-
- @Override
- public void stopWorker() throws Exception {
- events.add("stop");
- }
-
- @Override
- public void setURReceiver(UsageRecordReceiver receiver) {
- // We just ignore this
- }
-
- @Override
- public void deleteLocalResources() throws ImplementationException {
- // Nothing to do here
- }
- }
-
- WorkerFactory factory = new WorkerFactory() {
- @Override
- public Worker makeInstance() throws Exception {
- return new DummyWorker();
- }
- };
-
- @Before
- public void setUp() throws Exception {
- lw = new LocalWorker("XWC", "WF".getBytes("UTF-8"), null, randomUUID(),
- new HashMap<String, String>(), new ArrayList<String>(), factory);
- events = new ArrayList<>();
- returnThisStatus = RemoteStatus.Operating;
- }
-
- @After
- public void tearDown() throws Exception {
- lw.destroy();
- }
-
- private List<String> l(String... strings) {
- return Arrays.asList(strings);
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- @Test
- public void testDestroy1() throws Exception {
- lw.destroy();
- assertEquals(l(), events);
- }
-
- @Test
- public void testDestroy2() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.destroy();
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "kill"), events);
- }
-
- @Test
- public void testDestroy3() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.destroy();
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "stop", "kill"), events);
- }
-
- @Test
- public void testDestroy4() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "kill"), events);
- lw.destroy();
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "kill"), events);
- }
-
- @Test
- public void testAddListener() {
- Throwable t = null;
- try {
- lw.addListener(null);
- } catch (Throwable caught) {
- t = caught;
- }
- assertNotNull(t);
- assertSame(ImplementationException.class, t.getClass());
- assertNotNull(t.getMessage());
- assertEquals("not implemented", t.getMessage());
- }
-
- @Test
- public void testGetInputBaclavaFile() throws Exception {
- assertNull(lw.getInputBaclavaFile());
- lw.setInputBaclavaFile("IBaclava");
- assertNotNull(lw.getInputBaclavaFile());
- assertEquals("IBaclava", lw.getInputBaclavaFile());
- lw.makeInput("FOO").setValue("BAR");
- assertNull(lw.getInputBaclavaFile());
- }
-
- @Test
- public void testGetInputsWithValue() throws Exception {
- assertEquals(0, lw.getInputs().size());
-
- lw.makeInput("FOO").setValue("BAR");
-
- assertEquals(1, lw.getInputs().size());
- assertEquals("FOO", lw.getInputs().get(0).getName());
- assertNull(lw.getInputs().get(0).getFile());
- assertNotNull(lw.getInputs().get(0).getValue());
-
- lw.setInputBaclavaFile("BLAH");
-
- assertEquals(1, lw.getInputs().size());
- assertNull(lw.getInputs().get(0).getFile());
- assertNull(lw.getInputs().get(0).getValue());
- }
-
- @Test
- public void testGetInputsWithFile() throws Exception {
- assertEquals(0, lw.getInputs().size());
-
- lw.makeInput("BAR").setFile("FOO");
-
- assertEquals(1, lw.getInputs().size());
- assertEquals("BAR", lw.getInputs().get(0).getName());
- assertNotNull(lw.getInputs().get(0).getFile());
- assertNull(lw.getInputs().get(0).getValue());
-
- lw.setInputBaclavaFile("BLAH");
-
- assertEquals(1, lw.getInputs().size());
- assertNull(lw.getInputs().get(0).getFile());
- assertNull(lw.getInputs().get(0).getValue());
- }
-
- @Test
- public void testGetListenerTypes() {
- assertEquals("[]", lw.getListenerTypes().toString());
- }
-
- @Test
- public void testGetListeners() throws Exception {
- assertEquals(1, lw.getListeners().size());
- RemoteListener rl = lw.getListeners().get(0);
- assertEquals("RLNAME", rl.getName());
- assertEquals("RLCONFIG", rl.getConfiguration());
- assertEquals("RLTYPE", rl.getType());
- assertEquals("[RLP1, RLP2]", Arrays.asList(rl.listProperties())
- .toString());
- assertEquals("RLPROP[RLP1]", rl.getProperty("RLP1"));
- assertEquals("RLPROP[RLP2]", rl.getProperty("RLP2"));
- rl.setProperty("FOOBAR", "BARFOO");
- assertEquals(l("setProperty[", "FOOBAR", "BARFOO", "]"), events);
- }
-
- @Test
- public void testGetOutputBaclavaFile() throws Exception {
- assertNull(lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile("notnull");
- assertEquals("notnull", lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile(null);
- assertNull(lw.getOutputBaclavaFile());
- }
-
- @Test
- public void testGetSecurityContext() throws Exception {
- boolean md = DO_MKDIR;
- LocalWorker.DO_MKDIR = false; // HACK! Work around Hudson problem...
- try {
- assertNotNull(lw.getSecurityContext());
- } finally {
- LocalWorker.DO_MKDIR = md;
- }
- }
-
- @Test
- public void testGetStatusInitial() {
- assertEquals(RemoteStatus.Initialized, lw.getStatus());
- }
-
- @Test
- public void testGetStatus() throws Exception {
- assertEquals(RemoteStatus.Initialized, lw.getStatus());
- returnThisStatus = RemoteStatus.Operating;
- assertEquals(RemoteStatus.Initialized, lw.getStatus());
- lw.setStatus(RemoteStatus.Operating);
- assertEquals(RemoteStatus.Operating, lw.getStatus());
- assertEquals(RemoteStatus.Operating, lw.getStatus());
- returnThisStatus = RemoteStatus.Finished;
- assertEquals(RemoteStatus.Finished, lw.getStatus());
- returnThisStatus = RemoteStatus.Stopped;
- assertEquals(RemoteStatus.Finished, lw.getStatus());
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "status=Operating", "status=Operating",
- "status=Finished"), events);
- }
-
- @Test
- public void testGetWorkingDirectory() throws Exception {
- RemoteDirectory rd = lw.getWorkingDirectory();
- assertNotNull(rd);
- assertNotNull(rd.getContents());
- assertNull(rd.getContainingDirectory());
- assertNotNull(rd.getName());
- assertEquals(-1, rd.getName().indexOf('/'));
- assertFalse("..".equals(rd.getName()));
- assertEquals("", rd.getName());
- }
-
- @Test
- public void testValidateFilename() throws Exception {
- lw.validateFilename("foobar");
- lw.validateFilename("foo/bar");
- lw.validateFilename("foo.bar");
- lw.validateFilename("foo..bar");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad0() throws Exception {
- lw.validateFilename("./.");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad1() throws Exception {
- lw.validateFilename("/");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad2() throws Exception {
- lw.validateFilename("");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad3() throws Exception {
- lw.validateFilename(null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad4() throws Exception {
- lw.validateFilename("..");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad5() throws Exception {
- lw.validateFilename("foo/../bar");
- }
-
- @Test
- public void testMakeInput() throws Exception {
- assertEquals(0, lw.getInputs().size());
-
- RemoteInput ri = lw.makeInput("TEST");
-
- assertNotNull(ri);
- assertEquals(1, lw.getInputs().size());
- assertNotSame(ri, lw.getInputs().get(0)); // different delegates
- assertEquals("TEST", ri.getName());
- assertNull(ri.getFile());
- assertNull(ri.getValue());
-
- lw.setInputBaclavaFile("bad");
- ri.setFile("good");
- assertEquals("good", ri.getFile());
- assertNull(lw.getInputBaclavaFile());
- ri.setValue("very good");
- assertEquals("very good", ri.getValue());
- assertNull(ri.getFile());
- assertNull(lw.getInputBaclavaFile());
-
- lw.makeInput("TEST2");
- assertEquals(2, lw.getInputs().size());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testMakeInputFileSanity() throws Exception {
- lw.makeInput("foo").setFile("/../bar");
- }
-
- @Test
- public void testMakeListener() {
- Throwable t = null;
- try {
- lw.makeListener("?", "?");
- } catch (Throwable caught) {
- t = caught;
- }
- assertNotNull(t);
- assertSame(RemoteException.class, t.getClass());
- assertNotNull(t.getMessage());
- assertEquals("listener manufacturing unsupported", t.getMessage());
- }
-
- @Test
- public void testSetInputBaclavaFile1() throws Exception {
- assertNull(lw.getInputBaclavaFile());
- lw.setInputBaclavaFile("eg");
- assertEquals("eg", lw.getInputBaclavaFile());
- }
-
- @Test
- public void testSetInputBaclavaFile2() throws Exception {
- RemoteInput ri = lw.makeInput("foo");
- ri.setValue("bar");
- assertEquals("bar", ri.getValue());
- lw.setInputBaclavaFile("eg");
- assertNull(ri.getValue());
- }
-
- @Test
- public void testSetOutputBaclavaFile1() throws Exception {
- assertNull(lw.outputBaclava);
- lw.setOutputBaclavaFile("foobar");
- assertEquals("foobar", lw.outputBaclava);
- assertEquals("foobar", lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile("foo/bar");
- assertEquals("foo/bar", lw.outputBaclava);
- assertEquals("foo/bar", lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile(null);
- assertNull(lw.outputBaclava);
- assertNull(lw.getOutputBaclavaFile());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSetOutputBaclavaFile2() throws Exception {
- lw.setOutputBaclavaFile("/foobar");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSetOutputBaclavaFile3() throws Exception {
- lw.setOutputBaclavaFile("foo/../bar");
- }
-
- @Test
- public void testSetStatus0() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Finished);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "stop", "start", "kill"), events);
- }
-
- @Test
- public void testSetStatus1() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "stop", "kill"), events);
- }
-
- @Test
- public void testSetStatus2() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(l(), events);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus3() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Finished);
- lw.setStatus(RemoteStatus.Initialized);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus4() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Initialized);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus5() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Stopped);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus6() throws Exception {
- lw.setStatus(RemoteStatus.Finished);
- lw.setStatus(RemoteStatus.Stopped);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus7() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Initialized);
- }
-
- @Test
- public void testLifecycle() throws Exception {
- lw.makeInput("foo").setFile("foofile");
- lw.makeInput("bar").setValue("barvalue");
- lw.setOutputBaclavaFile("spong");
- lw.setOutputBaclavaFile("boo");
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Finished);
- // Assumes order of map, so fragile but works...
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>",
- "{bar=<null>, foo=foofile}",
- "{bar=barvalue, foo=null}", "boo", "]", "kill"), events);
- }
-}