Move this non-core project to Ace-extras.
git-svn-id: https://svn.apache.org/repos/asf/ace/trunk@1727269 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.ace.processlauncher/.classpath b/org.apache.ace.processlauncher/.classpath
deleted file mode 100644
index e3798ed..0000000
--- a/org.apache.ace.processlauncher/.classpath
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" output="bin_test" path="test"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
- <classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
- <classpathentry kind="con" path="aQute.bnd.classpath.container"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/org.apache.ace.processlauncher/.project b/org.apache.ace.processlauncher/.project
deleted file mode 100644
index b1a883e..0000000
--- a/org.apache.ace.processlauncher/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.apache.ace.processlauncher</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>bndtools.core.bndbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- <nature>bndtools.core.bndnature</nature>
- </natures>
-</projectDescription>
diff --git a/org.apache.ace.processlauncher/bnd.bnd b/org.apache.ace.processlauncher/bnd.bnd
deleted file mode 100644
index fe67b12..0000000
--- a/org.apache.ace.processlauncher/bnd.bnd
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under the terms of ASLv2 (http://www.apache.org/licenses/LICENSE-2.0).
-
--buildpath: \
- ${^-buildpath},\
- org.apache.felix.dependencymanager,\
- org.mockito.mockito-all,\
- osgi.core;version=6.0.0,\
- osgi.cmpn,\
- org.apache.ace.test;version=latest
-Private-Package: \
- org.apache.ace.processlauncher.osgi,\
- org.apache.ace.processlauncher.impl
-Bundle-Activator: \
- org.apache.ace.processlauncher.osgi.Activator
-Export-Package: \
- org.apache.ace.processlauncher,\
- org.apache.ace.processlauncher.util
-Bundle-Version: 1.0.2
-Bundle-Name: Apache ACE ProcessLauncher
-Bundle-Description: Registers a service factory and ProcessLauncher service
\ No newline at end of file
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/LaunchConfiguration.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/LaunchConfiguration.java
deleted file mode 100644
index c1322ac..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/LaunchConfiguration.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher;
-
-import java.io.File;
-
-import aQute.bnd.annotation.ProviderType;
-
-/**
- * Denotes a particular launch configuration for a process, describing what and how to launch.
- * <p>
- * You can create a new launch configuration by "pushing" a new configuration to the ConfigAdmin
- * service. If you use something like Felix FileInstall, you can do this by creating a new
- * properties file with the following contents:
- * </p>
- *
- * <pre>
- * # Denotes how many instances of the process should be started, >= 0.
- * # Optional, defaults to 1 instance.
- * #instance.count = 1
- * # What working directory should the executable start in?
- * # Optional, defaults to the current working directory.
- * #executable.workingDir = /path/to/cwd
- * # The executable to start, should be the fully qualified path to the
- * # executable.
- * # Mandatory, no default.
- * executable.name = /path/to/java
- * # The arguments for the executable.
- * # Mandatory, no default.
- * executable.args = -jar /path/to/jar
- * # The OSGi-filter clause which should resolve to a (single!)
- * # ProcessStreamListener instance. When given, it will be used to provide
- * # access to the launched process' stdin/stdout streams. NOTE: if you interact
- * # with the process this way, it could be that the process only terminates
- * # when you *explicitly* close the stdin stream.
- * # Optional, defaults to an empty/no filter.
- * #executable.processStreamListener =
- * # The OSGi-filter clause that should resolve to a ProcessLifecycleListener
- * # service-instance. When given, it will be used to provide hooks to when the
- * # executable is (re)started and stopped.
- * # Optional, defaults to an empty/no filter.
- * #executable.processLifecycleListener =
- * # When 'true' the process will automatically be restarted when it terminates
- * # with a 'abnormal' exit value (see 'executable.normalExitValue'). Any
- * # defined process stream listener will be re-invoked with the newly started
- * # process.
- * # Optional, defaults to 'false'.
- * #executable.respawnAutomatically = false
- * # Denotes what the 'normal' exit value of the process is, so the launcher can
- * # determine when a process is terminated abnormally.
- * # Optional, defaults to 0.
- * #executable.normalExitValue = 0
- * </pre>
- */
-@ProviderType
-public interface LaunchConfiguration {
-
- /**
- * Creates a fully qualified command line as array, in which the first element is the command to
- * execute, and the remainder of the array consists of the arguments that are passed to the
- * command.
- *
- * @return the command line, as array, never <code>null</code>.
- */
- String[] getCommandLine();
-
- /**
- * Returns the optional arguments that should be passed to the executable.
- *
- * @return the executable arguments, never <code>null</code>, but can be an empty array.
- * @see #getExecutableName()
- */
- String[] getExecutableArgs();
-
- /**
- * Returns the full path-name to the executable to launch.
- *
- * @return the executable name, never <code>null</code>.
- */
- String getExecutableName();
-
- /**
- * Returns the number of instances that should be launched.
- *
- * @return an instance count, >= 1.
- */
- int getInstanceCount();
-
- /**
- * Returns the exit value that indicates whether or not the process is terminated
- * successfully/normally. By convention, this is 0, but not all executables adhere to this
- * convention.
- *
- * @return the normal exit value, defaults to 0.
- */
- int getNormalExitValue();
-
- /**
- * Returns a filter-string to obtain the process' stream listener that wants to interact with
- * the process.
- * <p>
- * Only a single process stream listener should be resolved by the returned filter condition.
- * When multiple listeners are returned, the one with the highest service-ID will be used as
- * defined in the OSGi specification.
- * </p>
- *
- * @return a OSGi-filter condition, or <code>null</code> (the default) if no interaction with
- * the process is desired.
- */
- String getProcessStreamListener();
-
- /**
- * Returns a filter-string to obtain the process' lifecycle listener that wants to get notified
- * about the lifecycle of the process.
- * <p>
- * Only a single process lifecycle listener should be resolved by the returned filter condition.
- * When multiple listeners are returned, the one with the highest service-ID will be used as
- * defined in the OSGi specification.
- * </p>
- *
- * @return a OSGi-filter condition, or <code>null</code> (the default) if no notifications on
- * the process lifecycle are desired.
- */
- String getProcessLifecycleListener();
-
- /**
- * Returns the working directory to use when launching the executable.
- *
- * @return a working directory, as {@link File} object, or <code>null</code> if no working
- * directory is to be set and the default should be used.
- */
- File getWorkingDirectory();
-
- /**
- * Returns whether the process should be respawned after it terminated with a non-zero exit
- * code.
- *
- * @return <code>true</code> if the process should be respawned when it terminates with a
- * non-zero exit code, <code>false</code> to leave it as-is (terminated).
- */
- boolean isRespawnAutomatically();
-
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessLauncherService.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessLauncherService.java
deleted file mode 100644
index 6729e84..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessLauncherService.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher;
-
-import java.io.IOException;
-
-import aQute.bnd.annotation.ProviderType;
-
-/**
- * Provides a managed service factory for launching processes based on a certain launch
- * configuration.
- */
-@ProviderType
-public interface ProcessLauncherService {
-
- /** The service PID that is used for registration of this service factory. */
- String PID = "org.apache.ace.processlauncher";
-
- /**
- * Returns the number of launch configurations currently available.
- *
- * @return the number of launch configurations, >= 0.
- */
- int getLaunchConfigurationCount();
-
- /**
- * Returns the number of running processes.
- *
- * @return a running process count, >= 0.
- * @throws IOException in case of I/O problems determining the number of running processes.
- */
- int getRunningProcessCount() throws IOException;
-
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessLifecycleListener.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessLifecycleListener.java
deleted file mode 100644
index 1a60001..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessLifecycleListener.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher;
-
-import java.util.Properties;
-
-import aQute.bnd.annotation.ConsumerType;
-
-/**
- * Allows code to be run <em>before</em> a process is actually launched, and <em>after</em> a
- * process is terminated.
- * <p>
- * A typical use case for this would be that you might want to set up some process-specific
- * directories and/or configuration files for each individually launched process.
- * </p>
- */
-@ConsumerType
-public interface ProcessLifecycleListener {
-
- /**
- * Called right before the process denoted by the given launch configuration is started.
- * <p>
- * Use this method to set up directories, or pre-process (provisioned) data/configuration files
- * or other actions that need to be done in order to get the process properly up and running.
- * </p>
- * <p>
- * This method can also adjust the environment of the to-be-created process by returning a
- * populated {@link Properties} object.
- * </p>
- *
- * @param configuration the launch configuration of the process that is about to start, never
- * <code>null</code>.
- * @return the environment properties of the to-be-created process. Can be <code>null</code> if
- * no additional environment settings are wanted/desired.
- */
- Properties beforeProcessStart(LaunchConfiguration configuration);
-
- /**
- * Called right after the process denoted by the given launch configuration is terminated.
- * <p>
- * Use this method to clean up directories.
- * </p>
- *
- * @param configuration the launch configuration of the process that is just terminated, never
- * <code>null</code>.
- */
- void afterProcessEnd(LaunchConfiguration configuration);
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessStreamListener.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessStreamListener.java
deleted file mode 100644
index 11b7b2a..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/ProcessStreamListener.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import aQute.bnd.annotation.ConsumerType;
-
-/**
- * Provides a listener interface for interacting with a process' input/output stream.
- */
-@ConsumerType
-public interface ProcessStreamListener {
-
- /**
- * Returns the process' input, as input stream to allow interaction with the process itself.
- * <p>
- * NOTE: if the given output stream is <strong>closed</strong> by the implementing code, the
- * process will probably terminate. This also means that for some processes, you need to
- * explicitly close the given stream in order to let the process terminate properly.
- * </p>
- *
- * @param launchConfiguration the launch configuration for which a stdin output stream is set,
- * cannot be <code>null</code>;
- * @param outputStream the stdin {@link OutputStream} that can be used to write to the process'
- * stdin.
- * @see #wantsStdin()
- */
- void setStdin(LaunchConfiguration launchConfiguration, OutputStream outputStream);
-
- /**
- * Called with the process' stdout {@link InputStream}.
- * <p>
- * NOTE: when not interacting with the given stream, strange and unpredictable behavior might
- * occur, as the native streams that are used underneath the I/O streams in Java might
- * overflow/block!<br/>
- * Hence, <strong>always</strong> consume all bytes from this stream when implementing this
- * method!
- * </p>
- *
- * @param launchConfiguration the launch configuration for which a stdout input stream is set,
- * cannot be <code>null</code>;
- * @param inputStream the stdout {@link InputStream} that can be used to read from the process'
- * stdout and stderr.
- * @see #wantsStdout()
- */
- void setStdout(LaunchConfiguration launchConfiguration, InputStream inputStream);
-
- /**
- * Returns whether or not the standard input of the process is desired by this listener.
- *
- * @return <code>true</code> if the stdin {@link OutputStream} is to be set on this listener
- * (see {@link #setStdin(LaunchConfiguration, OutputStream)}), <code>false</code> if the
- * stdin {@link OutputStream} should be ignored.
- */
- boolean wantsStdin();
-
- /**
- * Returns whether or not the standard output of the process is desired by this listener.
- *
- * @return <code>true</code> if the stdout {@link InputStream} is to be set on this listener
- * (see {@link #setStdout(LaunchConfiguration, InputStream)}), <code>false</code> if the
- * stdout {@link InputStream} should be redirected to '/dev/null'.
- */
- boolean wantsStdout();
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/LaunchConfigurationFactory.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/LaunchConfigurationFactory.java
deleted file mode 100644
index 869ab3f..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/LaunchConfigurationFactory.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.ConfigurationException;
-
-/**
- * Provides a factory for creating new {@link LaunchConfiguration}s.
- */
-public abstract class LaunchConfigurationFactory {
- /** Denotes the number of instances to start (defaults to 1). */
- public static final String INSTANCE_COUNT = "instance.count";
- /** Denotes the working directory to start from (defaults to the current working directory). */
- public static final String WORKING_DIRECTORY = "executable.workingDir";
- /** Denotes the executable to start (fully qualified pathname). */
- public static final String EXECUTABLE_NAME = "executable.name";
- /** Denotes the executable arguments (optional). */
- public static final String EXECUTABLE_ARGS = "executable.args";
- /** Denotes the filter-clause to obtain the process stream listener (optional). */
- public static final String PROCESS_STREAM_LISTENER_FILTER = "executable.processStreamListener";
- /** Denotes the filter-clause to obtain the process lifecycle listener (optional). */
- public static final String PROCESS_LIFECYCLE_LISTENER_FILTER = "executable.processLifecycleListener";
- /**
- * Denotes whether or not the executable should be restarted upon unexpected termination
- * (defaults to false).
- */
- public static final String RESPAWN_AUTOMATICALLY = "executable.respawnAutomatically";
- /** Denotes the exit value that is to be considered normal (defaults to 0). */
- public static final String NORMAL_EXIT_VALUE = "executable.normalExitValue";
-
- /** The minimal instance count; less than one has no sense. */
- private static final int MINIMAL_INSTANCE_COUNT = 1;
-
- /**
- * Creates a new {@link LaunchConfigurationFactory} instance, never used.
- */
- private LaunchConfigurationFactory() {
- // No-op
- }
-
- /**
- * Creates a new {@link LaunchConfiguration} instance.
- *
- * @param config the configuration to create a {@link LaunchConfiguration} for, cannot be
- * <code>null</code>.
- * @return a new {@link LaunchConfiguration} instance based on the information in the given
- * configuration, never <code>null</code>.
- * @throws ConfigurationException in case the given configuration contains invalid keys and/or
- * values.
- */
- public static LaunchConfiguration create(final Dictionary<Object, Object> config) throws ConfigurationException {
- if (config == null) {
- throw new IllegalArgumentException("Config cannot be null!");
- }
-
- // Sanity check; make sure all mandatory properties are available...
- checkMandatoryProperties(config, EXECUTABLE_ARGS, EXECUTABLE_NAME);
-
- int instanceCount = 1;
- String workingDirectory = null;
- String executableName = null;
- String[] executableArgs = null;
- int normalExitValue = 0;
- String processStreamListenerFilter = null;
- String processLifecycleListenerFilter = null;
- boolean respawnAutomatically = false;
-
- Enumeration<Object> keys = config.keys();
- while (keys.hasMoreElements()) {
- Object key = keys.nextElement();
- String value = String.valueOf(config.get(key)).trim();
-
- if (INSTANCE_COUNT.equals(key)) {
- instanceCount = parseInstanceCount(value);
- }
- else if (WORKING_DIRECTORY.equals(key)) {
- workingDirectory = value.isEmpty() ? null : value;
- }
- else if (EXECUTABLE_NAME.equals(key)) {
- executableName = parseExecutableName(value);
- }
- else if (EXECUTABLE_ARGS.equals(key)) {
- executableArgs = parseExecutableArguments(value);
- }
- else if (PROCESS_STREAM_LISTENER_FILTER.equals(key)) {
- processStreamListenerFilter = parseFilter(value);
- }
- else if (PROCESS_LIFECYCLE_LISTENER_FILTER.equals(key)) {
- processLifecycleListenerFilter = parseFilter(value);
- }
- else if (RESPAWN_AUTOMATICALLY.equals(key)) {
- respawnAutomatically = Boolean.parseBoolean(value);
- }
- else if (NORMAL_EXIT_VALUE.equals(key)) {
- normalExitValue = parseExitValue(value);
- }
- }
-
- return new LaunchConfigurationImpl(instanceCount, workingDirectory, executableName, executableArgs,
- normalExitValue, processStreamListenerFilter, processLifecycleListenerFilter, respawnAutomatically);
- }
-
- /**
- * Tests whether all mandatory properties are available in a given configuration.
- *
- * @param config the configuration to test for mandatory keys;
- * @param mandatoryKeys the keys to check.
- * @throws ConfigurationException in case one of the given keys is missing from the given
- * configuration.
- */
- private static void checkMandatoryProperties(final Dictionary<Object, Object> config, final String... mandatoryKeys)
- throws ConfigurationException {
- for (String key : mandatoryKeys) {
- if (config.get(key) == null) {
- throw new ConfigurationException(key, "Missing configuration property: " + key);
- }
- }
- }
-
- /**
- * Parses the given value and splits it into a string array, taking care of quoted strings.
- *
- * @param value the value to split to a string array.
- * @return a string array, never <code>null</code>, but can be empty if the given value was
- * <code>null</code> or empty.
- */
- private static String[] parseExecutableArguments(final String value) {
- if (value == null || value.trim().isEmpty()) {
- return new String[0];
- }
- return StringSplitter.split(value);
- }
-
- /**
- * Parses the given executable name to something sensible.
- *
- * @param value the value to parse as executable name.
- * @return the executable name, never <code>null</code>.
- * @throws ConfigurationException in case the given value was <code>null</code> or empty.
- */
- private static String parseExecutableName(final String value) throws ConfigurationException {
- if (value == null || value.trim().isEmpty()) {
- throw new ConfigurationException(EXECUTABLE_NAME, "Invalid executable name!");
- }
- return value;
- }
-
- /**
- * Parses the given string value as integer exit value.
- *
- * @param value the string to parse as exit value, can be <code>null</code>.
- * @return the integer representation of the given string.
- * @throws ConfigurationException in case the given value is not an integer value, or is an
- * invalid value for instance counts.
- */
- private static int parseExitValue(String value) throws ConfigurationException {
- try {
- return Integer.parseInt(value);
- }
- catch (NumberFormatException exception) {
- throw new ConfigurationException(NORMAL_EXIT_VALUE, "Invalid exit value!");
- }
- }
-
- /**
- * Parses the given value as OSGi {@link Filter}.
- *
- * @param value the value to parse as filter, cannot be <code>null</code>.
- * @return the given input value, if it is a valid filter condition.
- * @throws ConfigurationException in case the given value consists of an invalid filter.
- */
- private static String parseFilter(String value) throws ConfigurationException {
- try {
- FrameworkUtil.createFilter(value);
- return value;
- }
- catch (InvalidSyntaxException exception) {
- throw new ConfigurationException(PROCESS_STREAM_LISTENER_FILTER, "Invalid filter syntax! Reason: "
- + exception.getMessage());
- }
- }
-
- /**
- * Parses a given string value into a numeric instance count.
- *
- * @param value the string to parse as instance count, can be <code>null</code>.
- * @return the instance count.
- * @throws ConfigurationException in case the given value is not an integer value, or is an
- * invalid value for instance counts.
- */
- private static int parseInstanceCount(final String value) throws ConfigurationException {
- int instanceCount = -1;
- try {
- instanceCount = Integer.parseInt(value);
- }
- catch (NumberFormatException exception) {
- // Ignore, will be picked up below...
- }
-
- if (instanceCount < MINIMAL_INSTANCE_COUNT) {
- throw new ConfigurationException(INSTANCE_COUNT, "Invalid instance count!");
- }
- return instanceCount;
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/LaunchConfigurationImpl.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/LaunchConfigurationImpl.java
deleted file mode 100644
index 8519638..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/LaunchConfigurationImpl.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.io.File;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.ProcessLifecycleListener;
-import org.apache.ace.processlauncher.ProcessStreamListener;
-
-/**
- * Denotes a launch configuration, describing what and how a process should be launched.
- */
-public final class LaunchConfigurationImpl implements LaunchConfiguration {
- /** The convention is to use zero as normal exit value. */
- private static final int NORMAL_EXIT_VALUE = 0;
-
- /**
- * Denotes the number of instances that will be launched for this configuration.
- */
- private final int m_instanceCount;
- /** Denotes the full path-name to the executable to launch. */
- private final String m_executableName;
- /** Denotes the arguments to pass to the executable. */
- private final String[] m_executableArgs;
- /**
- * The process stream listener that should be called for interaction with the process.
- */
- private final String m_processStreamListenerFilter;
- /**
- * The process lifecycle listener that should be called for the lifecycle changes of the
- * process.
- */
- private final String m_processLifecycleListenerFilter;
- /** Whether or not we should respawn the process once it died. */
- private final boolean m_respawnAutomatically;
- /** Which directory should be set before launching the executable. */
- private final File m_workingDirectory;
- /**
- * What exit-value is to be considered "normal" for this process? By convention, this is 0.
- */
- private final int m_normalExitValue;
-
- /**
- * Creates a new {@link LaunchConfigurationImpl} instance.
- *
- * @param instanceCount the number of instances to launch, >= 1;
- * @param workingDirectory the optional working directory to use, can be <code>null</code> if
- * the default working directory should be used;
- * @param executableName the full path-name to the executable to launch, cannot be
- * <code>null</code> or empty;
- * @param executableArgs the optional arguments to pass to the executable, can be
- * <code>null</code>;
- * @param normalExitValue the "normal" exit value to determine whether or not the process has
- * terminated normally;
- * @param processStreamListenerFilter denotes the filter to use to obtain the
- * {@link ProcessStreamListener} to redirect the process input/output to, can be
- * <code>null</code> if no interaction is desired;
- * @param processLifecycleListenerFilter denotes the filter to use to obtain the
- * {@link ProcessLifecycleListener};
- * @param respawnAutomatically <code>true</code> if the process should be respawned
- * automatically upon non-zero exit codes.
- */
- public LaunchConfigurationImpl(int instanceCount, String workingDirectory, String executableName,
- String[] executableArgs, int normalExitValue, String processStreamListenerFilter,
- String processLifecycleListenerFilter, boolean respawnAutomatically) {
- if (instanceCount <= 0) {
- throw new IllegalArgumentException("Invalid instance count!");
- }
- if (executableName == null || executableName.trim().isEmpty()) {
- throw new IllegalArgumentException("Invalid executable name!");
- }
- if (executableArgs == null) {
- throw new IllegalArgumentException("Invalid executable args!");
- }
- m_instanceCount = instanceCount;
- m_workingDirectory =
- (workingDirectory == null || workingDirectory.trim().isEmpty()) ? null : new File(workingDirectory);
- m_executableName = executableName;
- m_executableArgs = executableArgs;
- m_normalExitValue = normalExitValue;
- m_processStreamListenerFilter = processStreamListenerFilter;
- m_processLifecycleListenerFilter = processLifecycleListenerFilter;
- m_respawnAutomatically = respawnAutomatically;
- }
-
- /**
- * Creates a new {@link LaunchConfigurationImpl} instance.
- *
- * @param instanceCount the number of instances to launch, >= 1;
- * @param executableName the full path-name to the executable to launch, cannot be
- * <code>null</code> or empty;
- * @param executableArgs the optional arguments to pass to the executable, can be
- * <code>null</code>;
- * @param processStreamListenerFilter denotes the filter to use to obtain the
- * {@link ProcessStreamListener} to redirect the process input/output to, can be
- * <code>null</code> if no interaction is desired;
- * @param respawnAutomatically <code>true</code> if the process should be respawned
- * automatically upon non-zero exit codes.
- */
- public LaunchConfigurationImpl(int instanceCount, String executableName, String[] executableArgs,
- String processStreamListenerFilter, boolean respawnAutomatically) {
- this(instanceCount, null, executableName, executableArgs, NORMAL_EXIT_VALUE, processStreamListenerFilter, null,
- respawnAutomatically);
- }
-
- /**
- * {@inheritDoc}
- */
- public String[] getCommandLine() {
- int size = this.m_executableArgs.length;
- String[] result = new String[1 + size];
-
- result[0] = this.m_executableName;
- if (size > 0) {
- System.arraycopy(this.m_executableArgs, 0, result, 1, size);
- }
-
- return result;
- }
-
- /**
- * {@inheritDoc}
- */
- public String[] getExecutableArgs() {
- return m_executableArgs;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getExecutableName() {
- return m_executableName;
- }
-
- /**
- * {@inheritDoc}
- */
- public int getInstanceCount() {
- return m_instanceCount;
- }
-
- /**
- * {@inheritDoc}
- */
- public int getNormalExitValue() {
- return m_normalExitValue;
- }
-
- /**
- * {@inheritDoc}
- */
- public File getWorkingDirectory() {
- return m_workingDirectory;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getProcessStreamListener() {
- return m_processStreamListenerFilter;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getProcessLifecycleListener() {
- return m_processLifecycleListenerFilter;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isRespawnAutomatically() {
- return m_respawnAutomatically;
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessLauncher.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessLauncher.java
deleted file mode 100644
index b8324bb..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessLauncher.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.ProcessLifecycleListener;
-import org.apache.ace.processlauncher.ProcessStreamListener;
-import org.apache.ace.processlauncher.util.InputStreamRedirector;
-
-/**
- * Denotes a service that can launch a <em>single</em> process and possibly allows interaction with
- * it.
- * <p>
- * If for a process multiple instances should be launched, multiple {@link ProcessLauncher}
- * instances should be created!
- * </p>
- *
- * @author Jan Willem Janssen <janwillem.janssen@luminis.eu>
- */
-public class ProcessLauncher {
-
- private final LaunchConfiguration m_launchConfiguration;
-
- private volatile ProcessStreamListener m_processStreamListener;
- private volatile ProcessLifecycleListener m_processLifecycleListener;
- private volatile Process m_runningProcess;
-
- private InputStreamRedirector m_processStdoutRedirector;
- private InputStreamRedirector m_processStdinRedirector;
-
- /**
- * Creates a new {@link ProcessLauncher} instance which redirects all input/output of the
- * running process to the given streams.
- *
- * @param launchConfiguration the launch configuration to use, cannot be <code>null</code>;
- * @throws IllegalArgumentException in case the given launch configuration was <code>null</code>
- * .
- */
- public ProcessLauncher(LaunchConfiguration launchConfiguration) {
- if (launchConfiguration == null) {
- throw new IllegalArgumentException("Launch configuration cannot be null!");
- }
- m_launchConfiguration = launchConfiguration;
- }
-
- /**
- * Creates a new {@link ProcessLauncher} instance which redirects all input/output of the
- * running process to the given streams.
- *
- * @param launchConfiguration the launch configuration to use, cannot be <code>null</code>;
- * @param processStreamListener the input stream to redirect the process input to, can be
- * <code>null</code>;
- * @param processLifecycleListener the output stream to redirect the process output to, can be
- * <code>null</code> if the process output is not to be redirected.
- * @throws IllegalArgumentException in case the given launch configuration was <code>null</code>
- * .
- */
- public ProcessLauncher(LaunchConfiguration launchConfiguration, ProcessStreamListener processStreamListener,
- ProcessLifecycleListener processLifecycleListener) {
- if (launchConfiguration == null) {
- throw new IllegalArgumentException("Launch configuration cannot be null!");
- }
- m_launchConfiguration = launchConfiguration;
- m_processStreamListener = processStreamListener;
- m_processLifecycleListener = processLifecycleListener;
- }
-
- /**
- * If the process is finished, returns its exit value.
- *
- * @return the process' exit value, or <code>null</code> if the process is still running.
- * @see #isAlive()
- */
- public Integer getExitValue() {
- // runningProcess can only be null if #run() is not yet called!
- if ((m_runningProcess == null) || isAlive()) {
- return null;
- }
-
- return m_runningProcess.exitValue();
- }
-
- /**
- * Returns the launch configuration for this process launcher.
- *
- * @return the launch configuration, never <code>null</code>.
- */
- public LaunchConfiguration getLaunchConfiguration() {
- return m_launchConfiguration;
- }
-
- /**
- * Call to clean up the administration of this process launcher, and to invoke the proper
- * lifecycle methods on any interested listener.
- *
- * @throws IllegalStateException in case the process is still alive.
- * @see #isAlive()
- */
- public void cleanup() throws IllegalStateException {
- if (isAlive()) {
- throw new IllegalStateException("Process is still alive; cannot clean up!");
- }
-
- if (m_processLifecycleListener != null) {
- m_processLifecycleListener.afterProcessEnd(m_launchConfiguration);
- }
-
- closeProcessStreamRedirects();
- }
-
- /**
- * Kills any running processes and updates the internal administration (even if the process is
- * already killed).
- */
- public void kill() {
- if (isAlive()) {
- // This does a simple kill, which might be ignored by the running
- // process. In such situations, you should want to do something like
- // 'kill -9', but this is not easily done in Java (without doing
- // nasty hacks; see for example:
- // <http://stackoverflow.com/questions/4912282/java-tool-method-to-force-kill-a-child-process>).
- m_runningProcess.destroy();
-
- try {
- // We don't care for the result...
- waitForTermination();
- }
- catch (InterruptedException exception) {
- exception.printStackTrace();
- }
- }
- }
-
- /**
- * Creates a new process from the contained launch configuration and starts it as a new
- * {@link Process}. After this, it waits until the process is completed.
- *
- * @throws IllegalStateException in case there is already a running process that is not yet
- * finished;
- * @throws IOException if an I/O error occurs during the invocation of the process.
- */
- public void run() throws IllegalStateException, IOException {
- if (isAlive()) {
- throw new IllegalStateException("Process is still running & alive!");
- }
-
- Properties customEnv = null;
- if (m_processLifecycleListener != null) {
- customEnv = m_processLifecycleListener.beforeProcessStart(m_launchConfiguration);
- }
-
- final ProcessBuilder pb = createProcessBuilder(customEnv);
-
- // Invoke the actual executable asynchronously...
- m_runningProcess = pb.start();
-
- // Make sure we don't overflow any native buffers...
- redirectProcessStreams(m_runningProcess);
- }
-
- /**
- * Waits until the process is terminated.
- *
- * @return the exit value of the terminated process, or <code>null</code> if the process was
- * never started.
- * @throws InterruptedException in case we're interrupted while waiting for the process to
- * terminate.
- */
- public final Integer waitForTermination() throws InterruptedException {
- if (m_runningProcess != null) {
- final int result = m_runningProcess.waitFor();
-
- cleanup();
-
- return result;
- }
- return null;
- }
-
- /**
- * Interrupts and closes all process stream redirects.
- */
- private void closeProcessStreamRedirects() {
- // Make sure the redirectors are interrupted as well...
- if (m_processStdinRedirector != null) {
- try {
- m_processStdinRedirector.join(1000);
- }
- catch (InterruptedException exception) {
- exception.printStackTrace();
- }
- m_processStdinRedirector = null;
- }
- if (m_processStdoutRedirector != null) {
- try {
- m_processStdoutRedirector.join(1000);
- }
- catch (InterruptedException exception) {
- exception.printStackTrace();
- }
- m_processStdoutRedirector = null;
- }
- }
-
- /**
- * Creates the process builder and ensures all of its settings are correct to be launched.
- *
- * @param customEnv the custom environment settings of the to-be-created process, can be
- * <code>null</code> if no additional environment settings are desired.
- * @return a {@link ProcessBuilder} instance, never <code>null</code>.
- */
- private ProcessBuilder createProcessBuilder(Properties customEnv) {
- ProcessBuilder pb = new ProcessBuilder(m_launchConfiguration.getCommandLine());
- // Make sure we grab both stdout *and* stderr!
- pb.redirectErrorStream(true /* redirectErrorStream */);
- pb.directory(m_launchConfiguration.getWorkingDirectory());
- // We do *not* override/set a new environment for this process. This can
- // be easily done with shell scripting as well, if desired...
- if (customEnv != null) {
- Map<String, String> env = pb.environment();
- for (Object obj : customEnv.keySet()) {
- String key = (String) obj;
- env.put(key, customEnv.getProperty(key));
- }
- }
- return pb;
- }
-
- /**
- * Factory method for creating a {@link InputStreamRedirector} instance that redirects the stdin
- * of the given process to the contained input stream (if available).
- *
- * @param process the {@link Process} to create the input stream redirector for, can be
- * <code>null</code>.
- * @return an input stream redirector instance, never <code>null</code>.
- */
- private InputStreamRedirector createStdinRedirector(Process process) {
- if (m_processStreamListener != null && m_processStreamListener.wantsStdin()) {
- m_processStreamListener.setStdin(m_launchConfiguration, process.getOutputStream());
- }
- return null;
- }
-
- /**
- * Factory method for creating a {@link InputStreamRedirector} instance that redirects the
- * stdout of the given process to either the contained output stream, or to '/dev/null'.
- *
- * @param process the {@link Process} to create the input stream redirector for, cannot be
- * <code>null</code>.
- * @return an input stream redirector instance, never <code>null</code>.
- */
- private InputStreamRedirector createStdoutRedirector(Process process) {
- if (m_processStreamListener != null && m_processStreamListener.wantsStdout()) {
- m_processStreamListener.setStdout(m_launchConfiguration, process.getInputStream());
-
- return null;
- }
- // Redirect to /dev/null!
- return new InputStreamRedirector(process.getInputStream());
- }
-
- /**
- * Returns an indication whether or not the process is still alive and running, or already
- * terminated.
- *
- * @return <code>true</code> if the process is still running, <code>false</code> otherwise.
- */
- private boolean isAlive() {
- try {
- if (m_runningProcess != null) {
- // If the process is still alive it'll throw an exception...
- m_runningProcess.exitValue();
- }
-
- // No longer alive...
- return false;
- }
- catch (IllegalThreadStateException e) {
- return true;
- }
- }
-
- /**
- * Redirects the stdin/stdout streams of the given process.
- *
- * @param process the process to redirect the streams for, cannot be <code>null</code>.
- */
- private void redirectProcessStreams(Process process) {
- m_processStdoutRedirector = createStdoutRedirector(process);
- if (m_processStdoutRedirector != null) {
- m_processStdoutRedirector.start();
- }
- m_processStdinRedirector = createStdinRedirector(process);
- if (m_processStdinRedirector != null) {
- m_processStdinRedirector.start();
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessLauncherServiceImpl.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessLauncherServiceImpl.java
deleted file mode 100644
index d9876d0..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessLauncherServiceImpl.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.ProcessLauncherService;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
-import org.osgi.service.log.LogService;
-
-/**
- * Provides a managed service factory for launching processes based on a certain launch
- * configuration.
- */
-public class ProcessLauncherServiceImpl implements ManagedServiceFactory, ProcessLauncherService {
-
- private static final String NAME = "Launcher Service Factory";
-
- /** Contains all current launch configurations. */
- private final Map<String, LaunchConfiguration> m_launchConfigurations = new HashMap<String, LaunchConfiguration>();
- /** Manages all running processes for us. */
- private volatile ProcessManager m_processManager;
- private volatile LogService m_logger;
-
- /**
- * Returns whether or not a given PID is contained as launch configuration.
- *
- * @param pid the PID to test for, cannot be <code>null</code>.
- * @return <code>true</code> if the given PID exists as launch configuration, <code>false</code>
- * otherwise.
- */
- public boolean containsPid(String pid) {
- synchronized (m_launchConfigurations) {
- return m_launchConfigurations.containsKey(pid);
- }
- }
-
- /**
- * Called when a launch configuration with the given PID is removed from the config-admin.
- *
- * @param pid the service PID that is to be deleted, never <code>null</code>.
- * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
- */
- public final void deleted(final String pid) {
- LaunchConfiguration oldLaunchConfig = null;
-
- synchronized (m_launchConfigurations) {
- oldLaunchConfig = m_launchConfigurations.remove(pid);
- }
-
- if (oldLaunchConfig != null) {
- terminateProcesses(pid, oldLaunchConfig);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public int getLaunchConfigurationCount() {
- synchronized (m_launchConfigurations) {
- return m_launchConfigurations.size();
- }
- }
-
- /**
- * Returns the symbolic name for this service factory.
- *
- * @return a symbolic name, never <code>null</code>.
- * @see org.osgi.service.cm.ManagedServiceFactory#getName()
- */
- public final String getName() {
- return NAME;
- }
-
- /**
- * {@inheritDoc}
- */
- public int getRunningProcessCount() throws IOException {
- if (m_processManager == null) {
- return 0;
- }
- return m_processManager.getRunningProcessesCount();
- }
-
- /**
- * Sets the logging service.
- *
- * @param logger the log service to set, can be <code>null</code>.
- */
- public void setLogger(LogService logger) {
- m_logger = logger;
- }
-
- /**
- * Sets the process manager.
- *
- * @param processManager the process manager to set, cannot be <code>null</code>.
- */
- public void setProcessManager(ProcessManager processManager) {
- m_processManager = processManager;
- }
-
- /**
- * Shuts down this service and terminates all running processes.
- *
- * @throws IOException in case of problems shutting down processes.
- */
- public void shutdown() throws IOException {
- synchronized (m_launchConfigurations) {
- for (Map.Entry<String, LaunchConfiguration> entry : m_launchConfigurations.entrySet()) {
- terminateProcesses(entry.getKey(), entry.getValue());
- }
- m_launchConfigurations.clear();
- }
- // Shut down the process manager as well...
- m_processManager.shutdown();
- }
-
- /**
- * Called when a new configuration is added, or when an existing configuration is updated.
- *
- * @param pid the service PID that is added/updated, never <code>null</code>;
- * @param config the service configuration that is added/updated, can be <code>null</code>.
- * @throws ConfigurationException in case the given service configuration is incorrect.
- * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String,
- * java.util.Dictionary)
- */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public final void updated(final String pid, final Dictionary config) throws ConfigurationException {
- LaunchConfiguration oldLaunchConfig = null;
- LaunchConfiguration newLaunchConfig = null;
-
- if (config != null) {
- newLaunchConfig = createLaunchConfiguration(config);
- }
-
- synchronized (m_launchConfigurations) {
- oldLaunchConfig = m_launchConfigurations.put(pid, newLaunchConfig);
- }
-
- if (oldLaunchConfig != null) {
- terminateProcesses(pid, oldLaunchConfig);
- }
- if (newLaunchConfig != null) {
- launchProcesses(pid, newLaunchConfig);
- }
- }
-
- /**
- * Converts the given properties to a complete launch configuration.
- *
- * @param config the properties to convert to a launch configuration, cannot be
- * <code>null</code>.
- * @return a {@link LaunchConfiguration} instance, never <code>null</code>.
- * @throws ConfigurationException in case an invalid configuration property was found.
- */
- private LaunchConfiguration createLaunchConfiguration(final Dictionary<Object, Object> config)
- throws ConfigurationException {
- return LaunchConfigurationFactory.create(config);
- }
-
- /**
- * Creates a process identifier based on the given identifier and value.
- *
- * @param id the identifier part;
- * @param value the value part.
- * @return a process identifier, as String, never <code>null</code>.
- */
- private String createPID(final String id, int value) {
- return String.format("%s-%d", id, value);
- }
-
- /**
- * Executes a given launch configuration.
- *
- * @param id the identifier of the launch configuration to execute, cannot be <code>null</code>
- * or empty;
- * @param launchConfiguration the launch configuration to execute, cannot be <code>null</code>.
- */
- private void launchProcesses(final String id, final LaunchConfiguration launchConfiguration) {
-
- int count = launchConfiguration.getInstanceCount();
- while (count-- > 0) {
- String pid = createPID(id, count);
- try {
- m_processManager.launch(pid, launchConfiguration);
-
- m_logger.log(LogService.LOG_DEBUG, "Launched instance #" + count + " of process " + pid);
- }
- catch (IOException e) {
- m_logger.log(LogService.LOG_WARNING, "Process failed to launch!", e);
- }
- }
- }
-
- /**
- * Cleans up & terminates all processes of a given launch configuration.
- *
- * @param id the identifier of the launch configuration to execute, cannot be <code>null</code>
- * or empty;
- * @param launchConfiguration the launch configuration to clean up, cannot be <code>null</code>.
- */
- private void terminateProcesses(final String id, final LaunchConfiguration launchConfiguration) {
-
- int count = launchConfiguration.getInstanceCount();
- while (count-- > 0) {
- String pid = createPID(id, count);
- try {
- m_processManager.terminate(pid);
-
- m_logger.log(LogService.LOG_DEBUG, "Terminated instance #" + count + " of process " + pid);
- }
- catch (IOException e) {
- m_logger.log(LogService.LOG_WARNING, "Process failed to terminate!", e);
- }
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessManager.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessManager.java
deleted file mode 100644
index bc5d654..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessManager.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.io.IOException;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-
-/**
- * Provides a process manager service, which is able to launch a process (or multiple processes).
- */
-public interface ProcessManager {
-
- /**
- * Returns the number of currently running processes.
- * <p>
- * As a side effect, all completed processes are removed from the internal administration.
- * </p>
- *
- * @return a running process count.
- * @throws IOException in case of I/O problems.
- */
- int getRunningProcessesCount() throws IOException;
-
- /**
- * Launches a new process.
- *
- * @param pid the PID of the process to launch, used for bookkeeping;
- * @param launchConfiguration the launch configuration to use for the process to be launched.
- * @throws IOException in case of I/O problems during the launch of the process.
- */
- void launch(final String pid, final LaunchConfiguration launchConfiguration) throws IOException;
-
- /**
- * Terminates all managed processes and shuts down this process manager.
- *
- * @throws IOException in case of I/O problems during the launch of the process.
- */
- void shutdown() throws IOException;
-
- /**
- * Terminates a running process.
- *
- * @param pid the PID of the process to terminate, used for bookkeeping.
- * @throws IOException in case of I/O problems during the launch of the process.
- */
- void terminate(final String pid) throws IOException;
-
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessManagerImpl.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessManagerImpl.java
deleted file mode 100644
index 509ba06..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/ProcessManagerImpl.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.ProcessLifecycleListener;
-import org.apache.ace.processlauncher.ProcessStreamListener;
-import org.apache.felix.dm.Component;
-import org.apache.felix.dm.DependencyManager;
-import org.osgi.service.log.LogService;
-
-/**
- * Manager for launched processes.
- */
-public class ProcessManagerImpl implements ProcessManager {
-
- private final Map<String, ProcessLauncher> m_runningProcesses;
-
- private volatile DependencyManager m_dependencyManager;
- private volatile ProcessStateUpdater m_reaper;
- private volatile LogService m_logger;
-
- /**
- * Creates a new {@link ProcessManagerImpl} instance.
- */
- public ProcessManagerImpl() {
- m_runningProcesses = new HashMap<String, ProcessLauncher>();
- }
-
- /**
- * {@inheritDoc}
- */
- public int getRunningProcessesCount() throws IOException {
- int result = 0;
- synchronized (m_runningProcesses) {
- updateAdministration();
- result = m_runningProcesses.size();
- }
- return result;
- }
-
- /**
- * {@inheritDoc}
- */
- public void launch(final String pid, final LaunchConfiguration launchConfiguration) throws IOException {
- // If this is the first time we're being called, make sure there's a
- // reaper task up and running...
- if (m_reaper == null || !m_reaper.isAlive()) {
- m_reaper = new ProcessStateUpdater();
- m_reaper.start();
- }
-
- // Create the process launcher service...
- ProcessLauncher launcher = createProcessLauncher(launchConfiguration);
-
- // Update our administration...
- ProcessLauncher oldProcess = null;
- synchronized (m_runningProcesses) {
- oldProcess = m_runningProcesses.put(pid, launcher);
- }
-
- // Clean up any old processes...
- killProcess(oldProcess);
- // Submit it for execution...
- launcher.run();
- }
-
- /**
- * {@inheritDoc}
- */
- public void shutdown() throws IOException {
- synchronized (m_runningProcesses) {
- // Cancel/kill all ongoing processes...
- for (ProcessLauncher launcher : m_runningProcesses.values()) {
- killProcess(launcher);
- }
- m_runningProcesses.clear();
- }
-
- if (m_reaper != null) {
- m_reaper.interrupt();
- try {
- m_reaper.join();
- }
- catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- finally {
- m_reaper = null;
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void terminate(final String pid) {
- ProcessLauncher launcher = null;
- synchronized (m_runningProcesses) {
- launcher = m_runningProcesses.remove(pid);
- }
- killProcess(launcher);
- }
-
- /**
- * Updates the administration by cleaning up all future's that are finished.
- *
- * @throws IOException in case of I/O problems.
- */
- final void updateAdministration() throws IOException {
- synchronized (m_runningProcesses) {
- List<String> pids = new ArrayList<String>(m_runningProcesses.keySet());
- for (String pid : pids) {
- ProcessLauncher launcher = m_runningProcesses.get(pid);
- if (launcher.getExitValue() != null) {
-
- String logLine =
- String.format("Process %s (%s) terminated with code %d." + " Removing it from administration.",
- pid, launcher.getLaunchConfiguration().getExecutableName(), launcher.getExitValue());
- m_logger.log(LogService.LOG_DEBUG, logLine);
-
- launcher.cleanup();
-
- m_runningProcesses.remove(pid);
- // Take care of the termination; should it be relaunched?!
- if (processNeedsToBeRespawned(pid, launcher)) {
- launch(pid, launcher.getLaunchConfiguration());
- }
- }
- }
- }
- }
-
- /**
- * Factory method for creating a {@link ProcessLauncher} instance.
- *
- * @param launchConfiguration the launch configuration to create a launch configuration for,
- * cannot be <code>null</code>.
- * @return a new {@link ProcessLauncher} instance, never <code>null</code>.
- * @throws IOException in case the {@link ProcessLauncher} failed to instantiate.
- */
- private ProcessLauncher createProcessLauncher(LaunchConfiguration launchConfiguration) throws IOException {
- ProcessLauncher processLauncher = new ProcessLauncher(launchConfiguration);
-
- String lcFilter = launchConfiguration.getProcessLifecycleListener();
- String psFilter = launchConfiguration.getProcessStreamListener();
-
- // Create the proper service dependencies for the process launcher...
- if (lcFilter != null || psFilter != null) {
- Component comp = m_dependencyManager.createComponent().setImplementation(processLauncher);
-
- if (psFilter != null) {
- comp.add(m_dependencyManager.createServiceDependency()
- .setService(ProcessStreamListener.class, psFilter).setRequired(false));
- }
-
- if (lcFilter != null) {
- comp.add(m_dependencyManager.createServiceDependency()
- .setService(ProcessLifecycleListener.class, lcFilter).setRequired(false));
- }
-
- m_dependencyManager.add(comp);
- }
-
- return processLauncher;
- }
-
- /**
- * Determines whether or not the given exit value is "normal" indicating a successful or
- * non-successful termination.
- *
- * @param exitValue the process exit value, as integer value, can be <code>null</code>.
- * @return <code>true</code> if the process is non-successfully terminated, <code>false</code>
- * if the processes terminated successfully.
- */
- private boolean isNonSuccessfullyTerminated(LaunchConfiguration config, Integer exitValue) {
- return (exitValue != null) && (config.getNormalExitValue() != exitValue);
- }
-
- /**
- * Cancels a given future, if it is not already completed its task.
- *
- * @param launcher the process launcher to cancel, can be <code>null</code> in which case this
- * method does nothing.
- */
- private void killProcess(final ProcessLauncher launcher) {
- if (launcher != null) {
- String logLine =
- String.format("Killing process (%s)...", launcher.getLaunchConfiguration().getExecutableName());
- m_logger.log(LogService.LOG_INFO, logLine);
-
- launcher.kill();
- }
- }
-
- /**
- * Handles a given terminated process, which might need to be relaunched if it is not cleanly
- * terminated for example.
- *
- * @param pid the PID of the process that was launched, cannot be <code>null</code>;
- * @param launcher the terminated process to handle, cannot be <code>null</code>.
- * @throws IOException in case of I/O problems during the respawn of a terminated process.
- */
- private boolean processNeedsToBeRespawned(String pid, ProcessLauncher launcher) throws IOException {
- LaunchConfiguration config = launcher.getLaunchConfiguration();
- Integer exitValue = launcher.getExitValue();
-
- // Is the process non-successfully terminated?
- if (isNonSuccessfullyTerminated(config, exitValue)) {
- // If so, does it need to be respawned?
- if (config.isRespawnAutomatically()) {
- // We need to respawn the process automatically!
- String logLine =
- String.format("Process %s (%s) terminated with value %d;" + " respawning it as requested...", pid,
- config.getExecutableName(), exitValue);
- m_logger.log(LogService.LOG_INFO, logLine);
-
- // Simply relaunch the process again...
- return true;
- }
- else {
- // Don't bother restarting the process...
- String logLine =
- String.format("Process %s (%s) terminated with value %d.", pid, config.getExecutableName(),
- exitValue);
- m_logger.log(LogService.LOG_INFO, logLine);
- }
- }
- else {
- // Process ended normally...
- String logLine = String.format("Process %s (%s) terminated normally.", pid, config.getExecutableName());
- m_logger.log(LogService.LOG_INFO, logLine);
- }
-
- return false;
- }
-
- /**
- * Ensures that periodically the completed processes are removed from the administration.
- */
- final class ProcessStateUpdater extends Thread {
- /**
- * The number of milliseconds to wait before updating the status of all running processes.
- */
- private static final int DELAY = 100;
-
- /**
- * Creates a new {@link ProcessStateUpdater} instance.
- */
- public ProcessStateUpdater() {
- super("Process state update thread");
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run() {
- while (!Thread.interrupted()) {
- try {
- Thread.sleep(DELAY);
-
- m_logger.log(LogService.LOG_DEBUG, "Updating process administration...");
-
- // Update the administration...
- updateAdministration();
- }
- catch (InterruptedException e) {
- // Update the current thread's administration!
- Thread.currentThread().interrupt();
- }
- catch (IOException e) {
- m_logger.log(LogService.LOG_WARNING, "Respawn failed!", e);
- }
- }
- }
- }
-
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/StringSplitter.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/StringSplitter.java
deleted file mode 100644
index afeed41..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/impl/StringSplitter.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Splits a string on spaces and puts them into an array, taking care of single and double quotes.
- * Escaping quotes is allowed by prefixing them with a single backslash.
- */
-public final class StringSplitter {
-
- private static final char ESCAPE = '\\';
- private static final char SINGLE_QUOTE = '\'';
- private static final char DOUBLE_QUOTE = '"';
- private static final char SPACE = ' ';
- private static final char TAB = '\t';
-
- /**
- * Creates a new StringSplitter instance, never used.
- */
- private StringSplitter() {
- // No-op
- }
-
- /**
- * Splits a given input on whitespace (= tabs and/or spaces). The backslash character can be
- * used to escape stuff, for example to avoid splitting on certain spaces.
- *
- * @param input the input to split, may be <code>null</code>.
- * @return an empty array if the given input was <code>null</code> or empty, otherwise the split
- * results, never <code>null</code>.
- */
- public static String[] split(String input) {
- return split(input, true /* includeQuotes */);
- }
-
- /**
- * Splits a given input on whitespace (= tabs and/or spaces). The backslash character can be
- * used to escape stuff, for example to avoid splitting on certain spaces.
- *
- * @param input the input to split, may be <code>null</code>;
- * @param includeQuotes <code>true</code> if quotes should be included in the output,
- * <code>false</code> to omit them in the output unless they are escaped.
- * @return an empty array if the given input was <code>null</code> or empty, otherwise the split
- * results, never <code>null</code>.
- */
- public static String[] split(String input, boolean includeQuotes) {
- if (input == null || input.trim().isEmpty()) {
- return new String[0];
- }
-
- List<String> result = new ArrayList<String>();
-
- State state = State.NORMAL;
- boolean escapeSeen = false;
- StringBuilder token = new StringBuilder();
-
- for (int i = 0; i < input.length(); i++) {
- char ch = input.charAt(i);
-
- switch (ch) {
- case ESCAPE:
- if (!escapeSeen) {
- escapeSeen = true;
- }
- else {
- // Escaped escape character...
- token.append(ch);
- escapeSeen = false;
- }
- break;
-
- case SINGLE_QUOTE:
- case DOUBLE_QUOTE:
- if (!escapeSeen) {
- if ((ch == DOUBLE_QUOTE && state.isInDoubleQuote())
- || (ch == SINGLE_QUOTE && state.isInSingleQuote())) {
- state = State.NORMAL;
- }
- else if (state.isNormal()) {
- state = (ch == DOUBLE_QUOTE) ? State.IN_DOUBLE_QUOTE : State.IN_SINGLE_QUOTE;
- }
- }
- if (includeQuotes) {
- token.append(ch);
- }
- escapeSeen = false;
- break;
-
- case SPACE:
- case TAB:
- if (state.isNormal() && !escapeSeen) {
- // Whitespace seen: emit a new token and start over...
- result.add(token.toString());
- token.setLength(0);
- break;
- }
- // Fallthrough!
- default:
- token.append(ch);
- escapeSeen = false;
- break;
- }
- }
-
- if (token.length() > 0) {
- result.add(token.toString());
- }
-
- return result.toArray(new String[result.size()]);
- }
-
- private static enum State {
- NORMAL, IN_SINGLE_QUOTE, IN_DOUBLE_QUOTE;
-
- public boolean isInDoubleQuote() {
- return this == IN_DOUBLE_QUOTE;
- }
-
- public boolean isInSingleQuote() {
- return this == IN_SINGLE_QUOTE;
- }
-
- public boolean isNormal() {
- return this == NORMAL;
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/osgi/Activator.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/osgi/Activator.java
deleted file mode 100644
index 3628b3a..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/osgi/Activator.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.osgi;
-
-import java.util.Properties;
-
-import org.apache.ace.processlauncher.ProcessLauncherService;
-import org.apache.ace.processlauncher.impl.ProcessLauncherServiceImpl;
-import org.apache.ace.processlauncher.impl.ProcessManager;
-import org.apache.ace.processlauncher.impl.ProcessManagerImpl;
-import org.apache.felix.dm.DependencyActivatorBase;
-import org.apache.felix.dm.DependencyManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.service.cm.ManagedServiceFactory;
-import org.osgi.service.log.LogService;
-
-/**
- * Provides the actual bundle activator (based on Felix Dependency Manager).
- */
-public class Activator extends DependencyActivatorBase {
-
- private ProcessLauncherServiceImpl m_processLauncherService;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void destroy(BundleContext context, DependencyManager manager) throws Exception {
- m_processLauncherService.shutdown();
- m_processLauncherService = null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void init(BundleContext context, DependencyManager manager) throws Exception {
- // In the future we might want to publish this as an external service...
- ProcessManager processManager = new ProcessManagerImpl();
-
- manager.add(createComponent().setImplementation(processManager).add(
- createServiceDependency().setService(LogService.class).setRequired(false)));
-
- // We publish the service under multiple interfaces...
- String[] interfaces = { ManagedServiceFactory.class.getName(), ProcessLauncherService.class.getName() };
-
- // Service properties
- Properties props = new Properties();
- props.put(Constants.SERVICE_PID, ProcessLauncherService.PID);
-
- m_processLauncherService = new ProcessLauncherServiceImpl();
- m_processLauncherService.setProcessManager(processManager);
-
- manager.add(createComponent().setInterface(interfaces, props).setImplementation(m_processLauncherService)
- .add(createServiceDependency().setService(LogService.class).setRequired(false)));
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/packageinfo b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/packageinfo
deleted file mode 100644
index a4f1546..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/packageinfo
+++ /dev/null
@@ -1 +0,0 @@
-version 1.0
\ No newline at end of file
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/util/InputStreamRedirector.java b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/util/InputStreamRedirector.java
deleted file mode 100644
index 4c71c50..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/util/InputStreamRedirector.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-
-/**
- * Redirects an {@link InputStream} by reading all of its contents and writing this to a given
- * {@link OutputStream}.
- */
-public class InputStreamRedirector extends Thread {
-
- private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty(
- "org.apache.ace.processlauncher.debug", "false"));
-
- private static final int BUF_SIZE = 32;
-
- private final InputStream m_inputStream;
- private final OutputStream m_outputStream;
-
- /**
- * Creates a new {@link InputStreamRedirector} instance that redirects to /dev/null. Essentially
- * this means that all read data is immediately thrown away.
- *
- * @param inputStream the {@link InputStream} that is to be read, cannot be <code>null</code>.
- */
- public InputStreamRedirector(final InputStream inputStream) {
- this(inputStream, null);
- }
-
- /**
- * Creates a new {@link InputStreamRedirector} instance that redirects to a given output stream.
- *
- * @param inputStream the {@link InputStream} that is to be redirected, cannot be
- * <code>null</code>;
- * @param outputStream the {@link OutputStream} that is to be redirected to, may be
- * <code>null</code> in which case the input stream is redirected to nothing (/dev/null).
- */
- public InputStreamRedirector(final InputStream inputStream, final OutputStream outputStream) {
- this.m_inputStream = inputStream;
- this.m_outputStream = outputStream;
-
- setName("InputStreamRedirector-" + getId());
- }
-
- /**
- * Reads all bytes from the contained input stream and (optionally) writes it to the contained
- * output stream.
- */
- @Override
- public void run() {
- try {
- final byte[] buf = new byte[BUF_SIZE];
-
- while (!Thread.currentThread().isInterrupted()) {
- int read = m_inputStream.read(buf, 0, buf.length);
- if (read < 0) {
- // EOF; break out of our main loop...
- break;
- }
-
- if (DEBUG) {
- System.out.write(buf, 0, read);
- }
-
- if (m_outputStream != null) {
- m_outputStream.write(buf, 0, read);
- }
- }
- }
- catch (IOException ioe) {
- handleException(ioe);
- }
- finally {
- cleanUp();
- }
- }
-
- /**
- * Clean up of the contained output stream by closing it properly.
- */
- private void cleanUp() {
- try {
- if (this.m_outputStream != null) {
- // Ensure the last few bits are written...
- this.m_outputStream.flush();
- // Close the output stream and we're done...
- this.m_outputStream.close();
- }
- }
- catch (IOException e) {
- // Ignore; we'll assume it is being handled elsewhere...
- }
- }
-
- /**
- * Handles the given I/O exception by either printing it to the contained output stream,
- * otherwise to the stderr stream.
- *
- * @param exception the exception to handle, cannot be <code>null</code>.
- */
- private void handleException(final IOException exception) {
- if (this.m_outputStream != null) {
- exception.printStackTrace(new PrintStream(this.m_outputStream));
- }
- else {
- exception.printStackTrace(System.out);
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/util/packageinfo b/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/util/packageinfo
deleted file mode 100644
index a4f1546..0000000
--- a/org.apache.ace.processlauncher/src/org/apache/ace/processlauncher/util/packageinfo
+++ /dev/null
@@ -1 +0,0 @@
-version 1.0
\ No newline at end of file
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/LaunchConfigurationFactoryTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/LaunchConfigurationFactoryTest.java
deleted file mode 100644
index b374c5f..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/LaunchConfigurationFactoryTest.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.fail;
-
-import java.util.Properties;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.impl.LaunchConfigurationFactory;
-import org.osgi.service.cm.ConfigurationException;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link LaunchConfigurationFactory}.
- */
-public final class LaunchConfigurationFactoryTest {
-
- private static void assertArrayEquals(Object[] expected, Object[] actual) {
- assertEquals(expected.length, actual.length, "Array length mismatch!");
- for (int i = 0; i < expected.length; i++) {
- assertEquals(expected[i], actual[i], "Array element (" + i + ") mismatch!");
- }
- }
-
- /**
- * Tests whether creating a launch configuration based on a properties file works correctly.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationBasedOnPropertiesFileOk() throws Exception {
- Properties props = TestUtil.getProperties("launch.properties");
- assertNotNull(props);
-
- LaunchConfiguration config = LaunchConfigurationFactory.create(props);
- assertNotNull(config);
-
- assertEquals(2, config.getInstanceCount());
- assertEquals("/bin/sh", config.getExecutableName());
- assertArrayEquals(new String[] { "-c", "'sleep 1 && exit'", "-c", "'echo \"foo bar!\n\"'" },
- config.getExecutableArgs());
- assertNull(config.getProcessStreamListener());
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCreateWithCompleteConfigOk() throws ConfigurationException {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "(foo=bar)");
- props.put(LaunchConfigurationFactory.RESPAWN_AUTOMATICALLY, "false");
- props.put(LaunchConfigurationFactory.NORMAL_EXIT_VALUE, "2");
-
- LaunchConfiguration config = LaunchConfigurationFactory.create(props);
- assertNotNull(config);
-
- assertEquals(1, config.getInstanceCount());
- assertEquals("/path/to/foo", config.getExecutableName());
- assertArrayEquals(new String[0], config.getExecutableArgs());
- assertEquals(2, config.getNormalExitValue());
- assertNotNull(config.getProcessStreamListener());
- assertFalse(config.isRespawnAutomatically());
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateWithEmptyExecutableNameFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateWithInvalidInstanceCountFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "0");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCreateWithInvalidProcessStreamListenerFilterFail() throws ConfigurationException {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "aap"); // <=
-// incorrect!
- props.put(LaunchConfigurationFactory.RESPAWN_AUTOMATICALLY, "false");
- props.put(LaunchConfigurationFactory.NORMAL_EXIT_VALUE, "2");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException exception) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- public void testCreateWithNonNumericExitValueFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
- props.put(LaunchConfigurationFactory.NORMAL_EXIT_VALUE, "foo");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateWithNonNumericInstanceCountFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that a null configuration cannot be given to this factory.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCreateWithNullConfigFail() throws ConfigurationException {
- try {
- LaunchConfigurationFactory.create(null);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateWithNullExecutableArgumentsFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateWithNullExecutableNameFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException e) {
- // Ok...
- }
- }
-
- /**
- * Tests that an incomplete configuration causes an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateWithNullInstanceCountFail() {
- Properties props = new Properties();
- props.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- props.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- props.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "true");
-
- try {
- LaunchConfigurationFactory.create(props);
- fail("Exception expected!");
- }
- catch (ConfigurationException expected) {
- // Ok...
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/LaunchConfigurationTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/LaunchConfigurationTest.java
deleted file mode 100644
index a965036..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/LaunchConfigurationTest.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.impl.LaunchConfigurationImpl;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link LaunchConfigurationImpl}.
- */
-public final class LaunchConfigurationTest {
-
- /**
- * Test that creating a valid {@link LaunchConfigurationImpl} works.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationOk() {
- LaunchConfiguration launchConfig = new LaunchConfigurationImpl(1, "/path/to/foo", new String[0], null, false);
- assertNotNull(launchConfig);
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl} constructor validates the executable name
- * properly.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationWithEmptyExecutableNameFail() {
- try {
- new LaunchConfigurationImpl(1, "", new String[0], null, false);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl} constructor validates the instance count
- * properly.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationWithNegativeInstanceCountFail() {
- try {
- new LaunchConfigurationImpl(-1, "/path/to/foo", new String[0], null, false);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl} constructor validates the executable arguments
- * properly.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationWithNullExecutableArgsFail() {
- try {
- new LaunchConfigurationImpl(1, "/path/to/foo", null, null, false);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl} constructor validates the executable name
- * properly.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationWithNullExecutableNameFail() {
- try {
- new LaunchConfigurationImpl(1, null, new String[0], null, false);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl} constructor validates the instance count
- * properly.
- */
- @Test(groups = { UNIT })
- public void testCreateLaunchConfigurationWithZeroInstanceCountFail() {
- try {
- new LaunchConfigurationImpl(0, "/path/to/foo", new String[0], null, false);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl#getCommandLine()} method works properly when one
- * executable arguments are given.
- */
- @Test(groups = { UNIT })
- public void testGetCommandLineWithOneArgumentsOk() {
- LaunchConfiguration launchConfig =
- new LaunchConfigurationImpl(1, "/path/to/foo", new String[] { "-bar" }, null, false);
-
- String[] commandLine = launchConfig.getCommandLine();
- assertNotNull(commandLine);
- assertEquals(2, commandLine.length);
-
- assertEquals("/path/to/foo", commandLine[0]);
- assertEquals("-bar", commandLine[1]);
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl#getCommandLine()} method works properly when no
- * executable arguments are given.
- */
- @Test(groups = { UNIT })
- public void testGetCommandLineWithoutArgumentsOk() {
- LaunchConfiguration launchConfig =
- new LaunchConfigurationImpl(1, "cwd", "/path/to/foo", new String[0], 0, "(foo=bar)", "(qux=quu)", false);
-
- String[] commandLine = launchConfig.getCommandLine();
- assertNotNull(commandLine);
- assertEquals(1, commandLine.length);
-
- assertEquals("/path/to/foo", commandLine[0]);
- assertEquals("cwd", launchConfig.getWorkingDirectory().getName());
- assertNotNull(launchConfig.getProcessStreamListener());
- assertFalse(launchConfig.isRespawnAutomatically());
- }
-
- /**
- * Test that the {@link LaunchConfigurationImpl#getCommandLine()} method works properly when two
- * executable arguments are given.
- */
- @Test(groups = { UNIT })
- public void testGetCommandLineWithTwoArgumentsOk() {
- LaunchConfiguration launchConfig =
- new LaunchConfigurationImpl(1, "/path/to/foo", new String[] { "-qux", "-bar" }, null, true);
-
- String[] commandLine = launchConfig.getCommandLine();
- assertNotNull(commandLine);
- assertEquals(3, commandLine.length);
-
- assertEquals("/path/to/foo", commandLine[0]);
- assertEquals("-qux", commandLine[1]);
- assertEquals("-bar", commandLine[2]);
- assertNull(launchConfig.getProcessStreamListener());
- assertTrue(launchConfig.isRespawnAutomatically());
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessLauncherServiceImplTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessLauncherServiceImplTest.java
deleted file mode 100644
index 34e4821..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessLauncherServiceImplTest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Dictionary;
-import java.util.Properties;
-
-import org.apache.ace.processlauncher.impl.LaunchConfigurationFactory;
-import org.apache.ace.processlauncher.impl.ProcessLauncherServiceImpl;
-import org.apache.ace.processlauncher.impl.ProcessManager;
-import org.apache.ace.processlauncher.impl.ProcessManagerImpl;
-import org.apache.ace.test.utils.TestUtils;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.log.LogService;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link ProcessLauncherServiceImpl}.
- */
-public class ProcessLauncherServiceImplTest {
-
- private ProcessLauncherServiceImpl m_service;
- private Dictionary<Object, Object> m_launchConfig;
-
- /**
- * Tests that adding/inserting a new launch configuration causes a configuration entry to be
- * created.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testAddConfigurationWorksOk() throws ConfigurationException {
- final String pid = "existing-pid";
-
- assertEquals(0, m_service.getLaunchConfigurationCount());
-
- m_service.updated(pid, m_launchConfig);
- assertEquals(1, m_service.getLaunchConfigurationCount());
- }
-
- /**
- * Tests that deleting an existing launch configuration works & doesn't cause an exception.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testDeleteExistingConfigurationOk() throws ConfigurationException {
- final String pid = "existing-pid";
-
- m_service.updated(pid, m_launchConfig);
- assertTrue(m_service.containsPid(pid));
-
- m_service.deleted(pid);
- assertFalse(m_service.containsPid(pid));
- }
-
- /**
- * Tests that deleting a non-existing launch configuration doesn't cause an exception.
- */
- @Test(groups = { UNIT })
- public void testDeleteNonExistingConfigurationOk() {
- m_service.deleted("non-existing-pid");
- }
-
- /**
- * Tests that the getName method doesn't return <code>null</code>.
- */
- @Test(groups = { UNIT })
- public void testGetNameOk() {
- assertNotNull(m_service.getName());
- }
-
- /**
- * Tests the running process count is obtained from the (mocked) process manager.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testGetRunningProcessCountOk() throws Exception {
- final String pid = "existing-pid";
-
- m_service.updated(pid, m_launchConfig);
- assertEquals(2, m_service.getRunningProcessCount());
- }
-
- /**
- * Tests that updating an existing launch configuration cause the original configuration entry
- * to be updated.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testReplacingConfigurationWorksOk() throws ConfigurationException {
- final String pid = "existing-pid";
-
- assertEquals(0, m_service.getLaunchConfigurationCount());
-
- m_service.updated(pid, m_launchConfig);
- assertEquals(1, m_service.getLaunchConfigurationCount());
-
- m_service.updated(pid, m_launchConfig);
- assertEquals(1, m_service.getLaunchConfigurationCount());
- }
-
- /**
- * Tests that all existing launch configurations are removed when the service shutdown method is
- * called.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testShutdownRemovesAllConfigurationsOk() throws Exception {
- assertEquals(0, m_service.getLaunchConfigurationCount());
-
- m_service.updated("pid1", m_launchConfig);
- m_service.updated("pid2", m_launchConfig);
-
- assertEquals(2, m_service.getLaunchConfigurationCount());
-
- m_service.shutdown();
-
- assertEquals(0, m_service.getLaunchConfigurationCount());
- }
-
- /**
- * Tests that updating an existing launch configuration cause the original configuration entry
- * to be updated.
- *
- * @throws ConfigurationException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testUpdateConfigurationWorksOk() throws ConfigurationException {
- final String pid = "existing-pid";
-
- assertEquals(0, m_service.getLaunchConfigurationCount());
-
- m_service.updated(pid, null);
- assertEquals(1, m_service.getLaunchConfigurationCount());
-
- m_service.updated(pid, m_launchConfig);
- assertEquals(1, m_service.getLaunchConfigurationCount());
- }
-
- /**
- * Set up for each test case.
- *
- * @throws Exception not part of this test case.
- */
- @BeforeMethod
- protected void setUp() throws Exception {
- m_service = new ProcessLauncherServiceImpl();
- m_service.setLogger(TestUtils.createNullObject(LogService.class));
-
- ProcessManager processManager = mock(ProcessManagerImpl.class);
- when(processManager.getRunningProcessesCount()).thenReturn(2);
- m_service.setProcessManager(processManager);
-
- m_launchConfig = new Properties();
- m_launchConfig.put(LaunchConfigurationFactory.INSTANCE_COUNT, "1");
- m_launchConfig.put(LaunchConfigurationFactory.EXECUTABLE_NAME, "/path/to/foo");
- m_launchConfig.put(LaunchConfigurationFactory.EXECUTABLE_ARGS, "");
- m_launchConfig.put(LaunchConfigurationFactory.PROCESS_STREAM_LISTENER_FILTER, "(foo=bar)");
- m_launchConfig.put(LaunchConfigurationFactory.RESPAWN_AUTOMATICALLY, "false");
- m_launchConfig.put(LaunchConfigurationFactory.NORMAL_EXIT_VALUE, "0");
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessLauncherTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessLauncherTest.java
deleted file mode 100644
index 5b8a65e..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessLauncherTest.java
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import static org.apache.ace.processlauncher.test.impl.TestUtil.getOSName;
-import static org.apache.ace.processlauncher.test.impl.TestUtil.sleep;
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Properties;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.ProcessLifecycleListener;
-import org.apache.ace.processlauncher.ProcessStreamListener;
-import org.apache.ace.processlauncher.impl.LaunchConfigurationImpl;
-import org.apache.ace.processlauncher.impl.ProcessLauncher;
-import org.apache.ace.processlauncher.util.InputStreamRedirector;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link ProcessLauncher}.
- */
-public class ProcessLauncherTest {
-
- /**
- * Tests that an existing executable (Java) can be called with valid arguments and its output
- * can be read.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallAlreadyRunningProcessCausesExceptionFail() throws Exception {
- String execName = determineJavaExecutable();
-
- TestProcessStreamListener psl = new TestProcessStreamListener(false /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName);
-
- launcher.run();
-
- try {
- launcher.run(); // should fail!
- fail("Exception expected!");
- }
- catch (IllegalStateException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that for a given {@link ProcessLifecycleListener} the lifecycle methods are called.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testLifecycleMethodsAreCalledOk() throws Exception {
- String execName = determineJavaExecutable();
-
- TestProcessStreamListener psl = new TestProcessStreamListener(false /* wantsStdout */);
- TestProcessLifecycleListener pll = new TestProcessLifecycleListener();
-
- ProcessLauncher launcher = createProcessLauncher(psl, pll, execName);
-
- launcher.run();
-
- assertTrue(pll.m_beforeCalled);
-
- // Will wait until process is finished and calls our lifecycle method...
- launcher.waitForTermination();
-
- assertTrue(pll.m_afterCalled);
- }
-
- /**
- * Tests that calling {@link ProcessLauncher#cleanup()} will cause an exception if the process
- * is not yet terminated.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallCleanupOnRunningProcessFails() throws Exception {
- String execName = determineJavaExecutable();
-
- TestProcessStreamListener psl = new TestProcessStreamListener(false /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName);
-
- launcher.run();
-
- try {
- launcher.cleanup(); // should fail!
- fail("Exception expected!");
- }
- catch (IllegalStateException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that calling {@link ProcessLauncher#cleanup()} will cause no exception if the process
- * is terminated.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallCleanupOnTerminatedProcessOk() throws Exception {
- String execName = determineJavaExecutable();
-
- TestProcessStreamListener psl = new TestProcessStreamListener(false /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName);
-
- launcher.run();
-
- sleep(500);
-
- launcher.cleanup();
- }
-
- /**
- * Tests that an existing executable (Java) can be called with valid arguments and its output
- * can be read.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallExistingExecutableWithoutArgumentOk() throws Exception {
- String execName = determineJavaExecutable();
-
- TestProcessStreamListener psl = new TestProcessStreamListener(true /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName);
-
- launcher.run();
- Integer exitValue = launcher.waitForTermination();
-
- assertNotNull(exitValue);
- assertEquals(1, exitValue.intValue());
- // Both methods should return the same exit value!
- assertEquals(exitValue, launcher.getExitValue());
-
- String stdout = psl.slurpStdout();
- assertNotNull(stdout);
- assertTrue(stdout.length() > 0);
-
- // Make sure the test doesn't fail when the usage text is translated or
- // something...
- assertTrue(stdout.contains("Usage: java"), stdout);
- }
-
- /**
- * Tests that an existing executable (Java) can be called with invalid arguments and its output
- * can be read.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallExistingExecutableWithUnknownArgumentsOk() throws Exception {
- String execName = determineJavaExecutable();
- String execArgs = "-nonExistingArg";
-
- ProcessLauncher launcher = createProcessLauncher(execName, execArgs);
-
- launcher.run();
- Integer exitValue = launcher.waitForTermination();
-
- assertNotNull(exitValue);
- assertFalse(0 == exitValue.intValue());
- // Both methods should return the same exit value!
- assertEquals(exitValue, launcher.getExitValue());
- }
-
- /**
- * Tests that an existing executable (Java) can be called with valid arguments and its output
- * can be read.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallExistingExecutableWithValidArgumentOk() throws Exception {
- String execName = determineJavaExecutable();
- String execArgs = "-version";
-
- TestProcessStreamListener psl = new TestProcessStreamListener(true /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName, execArgs);
-
- launcher.run();
- Integer exitValue = launcher.waitForTermination();
-
- assertNotNull(exitValue);
- assertEquals(0, exitValue.intValue());
-
- String stdout = psl.slurpStdout();
- assertNotNull(stdout);
- assertTrue(stdout.length() > 0);
-
- // Make sure the test doesn't fail when the usage text is translated or
- // something...
- assertTrue(stdout.contains("java version"), stdout);
- }
-
- /**
- * Tests that an existing executable (Java) can be called and its output can be read.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testCallNonExistingExecutableOk() throws Exception {
- String execName = "/path/to/java";
- String execArgs = "-version";
-
- ProcessLauncher launcher = createProcessLauncher(execName, execArgs);
-
- try {
- launcher.run(); // should fail!
- fail("Exception expected!");
- }
- catch (IOException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that attempting to create a new {@link ProcessLauncher} without a valid launch
- * configuration yields an exception.
- */
- @Test(groups = { UNIT })
- public void testCreateProcessLauncherWithoutLaunchConfigurationFail() {
- try {
- new ProcessLauncher(null);
- fail("Exception expected!");
- }
- catch (IllegalArgumentException expected) {
- // Ok...
- }
- }
-
- /**
- * Tests that attempting to obtain the exit value without a launched process yields a null
- * value.
- */
- @Test(groups = { UNIT })
- public void testGetExitValueWithoutLaunchedProcessReturnsNull() {
- String execName = determineJavaExecutable();
- String execArgs = "-version";
-
- ProcessLauncher launcher = createProcessLauncher(execName, execArgs);
-
- assertNull(launcher.getExitValue());
- }
-
- /**
- * Tests that we can send commands to a running process and capture the results of these
- * commands.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testInteractWithProcessOk() throws Exception {
- // Test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- String execName = "/bin/sh";
- String input = "echo '1'\nls $0\nsleep 1\n";
-
- TestProcessStreamListener psl = new TestProcessStreamListener(true /* wantsStdin */, true /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName);
-
- launcher.run();
-
- psl.writeToStdin(input);
- psl.closeStdin();
-
- Integer exitValue = launcher.waitForTermination();
-
- assertNotNull(exitValue);
- assertEquals(0, exitValue.intValue());
-
- String stdout = psl.slurpStdout();
- assertNotNull(stdout);
- assertTrue(stdout.length() > 0);
-
- // Make sure the test doesn't fail when the usage text is translated or
- // something...
- assertEquals("1\n/bin/sh\n", stdout);
- }
-
- /**
- * Tests that we can send commands to a running process and capture the results of these
- * commands.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testInteractWithProcessThroughArgumentsOk() throws Exception {
- // Test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- String execName = "/bin/sh";
- String[] execArgs = { "-c", "echo '1'\nls $0\nsleep 1\n" };
-
- TestProcessStreamListener psl = new TestProcessStreamListener(false /* wantsStdin */, true /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName, execArgs);
-
- launcher.run();
-
- Integer exitValue = launcher.waitForTermination();
-
- String stdout = psl.slurpStdout();
- assertNotNull(stdout);
- assertTrue(stdout.length() > 0);
-
- assertNotNull(exitValue);
- assertEquals(0, exitValue.intValue());
-
- assertEquals("1\n/bin/sh\n", stdout);
- }
-
- /**
- * Tests that we can send commands to a running cat-process and capture the results of these
- * commands.
- * <p>
- * The cat-command is a somewhat "nasty" command as it won't exit until its input stream is
- * properly closed.
- * </p>
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testProcessStdinIsProperlyClosedOk() throws Exception {
- // Test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- String execName = "/bin/cat";
- String input = "echo '1'\nls $0\nqux qoo\n";
-
- TestProcessStreamListener psl = new TestProcessStreamListener(true /* wantsStdin */, true /* wantsStdout */);
-
- ProcessLauncher launcher = createProcessLauncher(psl, null, execName);
-
- launcher.run();
-
- // Issue the command...
- psl.writeToStdin(input);
-
- sleep(1000);
-
- psl.closeStdin();
-
- Integer exitValue = launcher.waitForTermination();
-
- assertNotNull(exitValue);
- assertEquals(0, exitValue.intValue());
-
- String stdout = psl.slurpStdout();
- assertNotNull(stdout);
- assertTrue(stdout.length() > 0);
-
- // We should get the exact same output as we've put into the command...
- assertEquals(input, stdout);
- }
-
- /**
- * Creates a new launch configuration for the given executable and arguments.
- *
- * @param captureProcessOutput <code>true</code> if the process output is to be captured,
- * <code>false</code> otherwise;
- * @param execName the name of the executable;
- * @param execArgs the (optional) arguments.
- * @return a {@link LaunchConfigurationImpl} instance, never <code>null</code>.
- */
- private LaunchConfiguration createLaunchConfiguration(boolean respawnAutomatically, String execName,
- String... execArgs) {
- return new LaunchConfigurationImpl(1, execName, execArgs, null, respawnAutomatically);
- }
-
- /**
- * Creates a new process launcher instance for the given executable and arguments.
- *
- * @param execName the name of the executable;
- * @param execArgs the (optional) arguments.
- * @return a {@link ProcessLauncher} instance, never <code>null</code>.
- */
- private ProcessLauncher createProcessLauncher(ProcessStreamListener processStreamListener,
- ProcessLifecycleListener processLifecycleListener, String execName, String... execArgs) {
- return new ProcessLauncher(createLaunchConfiguration(false, execName, execArgs), processStreamListener,
- processLifecycleListener);
- }
-
- /**
- * Creates a new process launcher instance for the given executable and arguments.
- *
- * @param execName the name of the executable;
- * @param execArgs the (optional) arguments.
- * @return a {@link ProcessLauncher} instance, never <code>null</code>.
- */
- private ProcessLauncher createProcessLauncher(String execName, String... execArgs) {
- return new ProcessLauncher(createLaunchConfiguration(false, execName, execArgs));
- }
-
- /**
- * Returns the full path to the java executable (the one that is used to invoke this test).
- *
- * @return a full path to the executable, never <code>null</code>.
- */
- private String determineJavaExecutable() {
- StringBuilder sb = new StringBuilder(System.getProperty("java.home"));
- sb.append(File.separatorChar).append("bin").append(File.separatorChar).append("java");
- return sb.toString();
- }
-
- /**
- * Test implementation of {@link ProcessLifecycleListener}.
- *
- * @author jwjanssen
- */
- static final class TestProcessLifecycleListener implements ProcessLifecycleListener {
- private volatile boolean m_beforeCalled;
- private volatile boolean m_afterCalled;
-
- /**
- * {@inheritDoc}
- */
- public void afterProcessEnd(LaunchConfiguration configuration) {
- m_afterCalled = true;
- }
-
- /**
- * {@inheritDoc}
- */
- public Properties beforeProcessStart(LaunchConfiguration configuration) {
- m_beforeCalled = true;
- return null;
- }
- }
-
- /**
- * Provides a mock implementation of {@link ProcessStreamListener} that is used in the various
- * test cases.
- *
- * @author jwjanssen
- */
- static final class TestProcessStreamListener implements ProcessStreamListener {
- private final boolean m_wantsStdin;
- private final boolean m_wantsStdout;
-
- private OutputStream m_stdin;
- private OutputStream m_stdout;
-
- public TestProcessStreamListener(boolean wantsStdout) {
- this(false /* wantsStdin */, wantsStdout);
- }
-
- public TestProcessStreamListener(boolean wantsStdin, boolean wantsStdout) {
- m_wantsStdin = wantsStdin;
- m_wantsStdout = wantsStdout;
- }
-
- public synchronized void closeStdin() throws IOException {
- m_stdin.flush();
- m_stdin.close();
- }
-
- public void setStdin(LaunchConfiguration launchConfiguration, OutputStream outputStream) {
- m_stdin = outputStream;
- }
-
- public void setStdout(LaunchConfiguration launchConfiguration, InputStream inputStream) {
- m_stdout = new ByteArrayOutputStream(1024);
- InputStreamRedirector isr = new InputStreamRedirector(inputStream, m_stdout);
- isr.start();
- }
-
- public String slurpStdout() throws IOException {
- assertNotNull(m_stdout);
- m_stdout.flush();
- return m_stdout.toString();
- }
-
- public boolean wantsStdin() {
- return m_wantsStdin;
- }
-
- public boolean wantsStdout() {
- return m_wantsStdout;
- }
-
- public void writeToStdin(String commands) throws IOException {
- assertNotNull(m_stdin);
- m_stdin.write(commands.getBytes());
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessManagerImplTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessManagerImplTest.java
deleted file mode 100644
index b55cf40..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/ProcessManagerImplTest.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import static org.apache.ace.processlauncher.test.impl.TestUtil.createTempDir;
-import static org.apache.ace.processlauncher.test.impl.TestUtil.getOSName;
-import static org.apache.ace.processlauncher.test.impl.TestUtil.sleep;
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.File;
-
-import org.apache.ace.processlauncher.LaunchConfiguration;
-import org.apache.ace.processlauncher.impl.LaunchConfigurationImpl;
-import org.apache.ace.processlauncher.impl.ProcessManager;
-import org.apache.ace.processlauncher.impl.ProcessManagerImpl;
-import org.apache.ace.test.utils.TestUtils;
-import org.osgi.service.log.LogService;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link ProcessManager}.
- */
-public class ProcessManagerImplTest {
-
- private ProcessManagerImpl m_processManager;
-
- /**
- * Tests that launching a simple process works for a UNIX-derived operating system.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testLaunchProcessOnUnixDerivativeOk() throws Exception {
- // This test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- LaunchConfiguration launchConfig = createLaunchConfiguration("/bin/sh", "-c", "sleep 1 && exit 1");
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- m_processManager.launch("myPid", launchConfig);
-
- // make sure we sleep a little to ensure the process is started
- sleep(100);
-
- int processCountAfter = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfter > processCountBefore);
-
- assertEquals(processCountAfter, m_processManager.getRunningProcessesCount());
-
- // make sure we sleep a little longer to allow the process to finish...
- sleep(1000);
-
- assertEquals(processCountBefore, m_processManager.getRunningProcessesCount());
- }
-
- /**
- * Tests that launching a simple process works for a Windows operating system.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testLaunchProcessOnWindowsOk() throws Exception {
- // This test will only work on Windows!
- if (!getOSName().contains("windows")) {
- return;
- }
-
- LaunchConfiguration launchConfig = createLaunchConfiguration("PING", "-n", "2", "127.0.0.1");
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- m_processManager.launch("myPid", launchConfig);
-
- // make sure we sleep a little to ensure the process is started
- sleep(100);
-
- int processCountAfter = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfter > processCountBefore);
-
- assertEquals(processCountAfter, m_processManager.getRunningProcessesCount());
-
- // make sure we sleep a little longer to allow the process to finish...
- sleep(1000);
-
- assertEquals(processCountBefore, m_processManager.getRunningProcessesCount());
- }
-
- /**
- * Tests that respawning a simple process works for a UNIX-derived operating system.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testRespawnProcessOnUnixDerivativeOk() throws Exception {
- // This test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- int count = 2;
- File tmpFile = File.createTempFile("ace", null);
- String tmpFilename = tmpFile.getAbsolutePath();
-
- // Seems daunting, but what this command does is simply count the number
- // of lines in a given file (= tmpFile), and append this to that same
- // file; it uses this number to create an exit value, which counts from
- // <count> back to 0. This way, we can test whether the respawn
- // functionality works, as this currently checks for certain exit
- // values...
- String script =
- String.format("L=$(cat %1$s | wc -l)" + "&& echo $L >> %1$s && exit $((%2$d-$L))", tmpFilename, count);
-
- LaunchConfiguration launchConfig =
- createLaunchConfiguration(true /* respawnAutomatically */, "/bin/bash", "-c", script);
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- m_processManager.launch("myPid", launchConfig);
-
- // sleep a little to ensure the process is started...
- sleep(10);
-
- assertEquals(processCountBefore + 1, m_processManager.getRunningProcessesCount());
-
- // make sure we sleep a little longer to allow the process to finish...
- sleep(500);
-
- assertEquals(processCountBefore, m_processManager.getRunningProcessesCount());
-
- String testResult = TestUtil.slurpFile(tmpFile);
- assertTrue(testResult.matches("(?s)^0\n1\n2\n$"), testResult);
- }
-
- /**
- * Tests that terminating all running processes works.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testShutdownOnUnixDerivativeOk() throws Exception {
- // This test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- LaunchConfiguration launchConfig = createLaunchConfiguration("/bin/sh", "-c", "sleep 10");
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- for (int i = 0; i < 5; i++) {
- m_processManager.launch(String.format("myPid%d", i), launchConfig);
- }
-
- // make sure we sleep a little to ensure the processes are started
- sleep(100);
-
- int processCountAfter = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfter > processCountBefore);
-
- // Shut down the process manager; should terminate all running
- // processes...
- m_processManager.shutdown();
-
- assertEquals(processCountBefore, m_processManager.getRunningProcessesCount());
- }
-
- /**
- * Tests that terminating all running processes works.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testShutdownOnWindowsOk() throws Exception {
- // This test will only work on Windows!
- if (!getOSName().contains("windows")) {
- return;
- }
-
- LaunchConfiguration launchConfig = createLaunchConfiguration("PING", "-n", "11", "127.0.0.1");
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- for (int i = 0; i < 5; i++) {
- m_processManager.launch(String.format("myPid%d", i), launchConfig);
- }
-
- // make sure we sleep a little to ensure the processes are started
- sleep(100);
-
- int processCountAfter = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfter > processCountBefore);
-
- // Shut down the process manager; should terminate all running
- // processes...
- m_processManager.shutdown();
-
- assertEquals(processCountBefore, m_processManager.getRunningProcessesCount());
- }
-
- /**
- * Tests that terminating a single process works.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testTerminateProcessOnUnixDerivativeOk() throws Exception {
- // This test will not work on Windows!
- if (getOSName().contains("windows")) {
- return;
- }
-
- LaunchConfiguration launchConfig = createLaunchConfiguration("/bin/sh", "-c", "sleep 10");
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- final String pid = "myPid";
- m_processManager.launch(pid, launchConfig);
-
- // make sure we sleep a little to ensure the process is started
- sleep(100);
-
- int processCountAfterLaunch = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfterLaunch > processCountBefore);
-
- m_processManager.terminate(pid);
-
- int processCountAfterTerminate = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfterTerminate == processCountBefore);
- }
-
- /**
- * Tests that terminating a single process works.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testTerminateProcessOnWindowsOk() throws Exception {
- // This test will not work on Windows!
- if (!getOSName().contains("windows")) {
- return;
- }
-
- LaunchConfiguration launchConfig = createLaunchConfiguration("PING", "-n", "11", "127.0.0.1");
-
- int processCountBefore = m_processManager.getRunningProcessesCount();
-
- final String pid = "myPid";
- m_processManager.launch(pid, launchConfig);
-
- // make sure we sleep a little to ensure the process is started
- sleep(100);
-
- int processCountAfterLaunch = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfterLaunch > processCountBefore);
-
- m_processManager.terminate(pid);
-
- int processCountAfterTerminate = m_processManager.getRunningProcessesCount();
-
- assertTrue(processCountAfterTerminate == processCountBefore);
- }
-
- /**
- * Set up for this test case.
- */
- @BeforeTest
- protected void setUp() {
- m_processManager = new ProcessManagerImpl();
- TestUtils.configureObject(m_processManager, LogService.class);
- }
-
- /**
- * Creates a new launch configuration for the given executable and arguments.
- *
- * @param respawnAutomatically <code>true</code> if the process should be respawned
- * automatically upon a non-zero exit value;
- * @param execName the name of the executable;
- * @param execArgs the (optional) arguments.
- *
- * @return a {@link LaunchConfigurationImpl} instance, never <code>null</code>.
- */
- private LaunchConfiguration createLaunchConfiguration(boolean respawnAutomatically, String execName,
- String... execArgs) throws Exception {
- return new LaunchConfigurationImpl(1, createTempDir().getAbsolutePath(), execName, execArgs, 0, null /* processStreamListenerFilter */,
- null /* processLifecycleListenerFilter */, respawnAutomatically);
- }
-
- /**
- * Creates a new launch configuration for the given executable and arguments.
- *
- * @param execName the name of the executable;
- * @param execArgs the (optional) arguments.
- *
- * @return a {@link LaunchConfigurationImpl} instance, never <code>null</code>.
- */
- private LaunchConfiguration createLaunchConfiguration(String execName, String... execArgs) throws Exception {
- return createLaunchConfiguration(false /* respawnAutomatically */, execName, execArgs);
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/StringSplitterTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/StringSplitterTest.java
deleted file mode 100644
index 033a7f7..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/StringSplitterTest.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import static org.apache.ace.processlauncher.impl.StringSplitter.split;
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.testng.Assert.assertEquals;
-
-import org.apache.ace.processlauncher.impl.StringSplitter;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link StringSplitter}.
- */
-public class StringSplitterTest {
-
- /**
- * Test double quoted command line argument.
- */
- @Test(groups = { UNIT })
- public void testDoubleQuotedCommandLineArgumentOk() {
- String[] result =
- split("\\\"fwOption=org.osgi.framework.system.packages.extra=org.w3c.dom.tral,org.w3c.dom.html,org.w3c.dom.ranges,sun.reflect,org.osgi.service.deploymentadmin;version=\"1.0\",org.osgi.service.deploymentadmin.spi;version=\"1.0\",org.osgi.service.cm;version=\"1.3\",org.osgi.service.event;version=\"1.2\",org.osgi.service.log;version=\"1.3\",org.osgi.service.metatype;version=\"1.1\",org.apache.ace.log;version=\"0.8.0\"\\\"");
- assertArrayEquals(
- new String[] { "\"fwOption=org.osgi.framework.system.packages.extra=org.w3c.dom.tral,org.w3c.dom.html,org.w3c.dom.ranges,sun.reflect,org.osgi.service.deploymentadmin;version=\"1.0\",org.osgi.service.deploymentadmin.spi;version=\"1.0\",org.osgi.service.cm;version=\"1.3\",org.osgi.service.event;version=\"1.2\",org.osgi.service.log;version=\"1.3\",org.osgi.service.metatype;version=\"1.1\",org.apache.ace.log;version=\"0.8.0\"\"" },
- result);
- }
-
- /**
- * Test double quoted string.
- */
- @Test(groups = { UNIT })
- public void testDoubleQuotedStringOk() {
- String[] result = split("\"hello world\"");
- assertArrayEquals(new String[] { "\"hello world\"" }, result);
- }
-
- /**
- * Test double quoted string with trailing text.
- */
- @Test(groups = { UNIT })
- public void testDoubleQuotedStringWithTrailingTextOk() {
- String[] result = split("\"hello world\" foo-bar");
- assertArrayEquals(new String[] { "\"hello world\"", "foo-bar" }, result);
- }
-
- /**
- * Test double quoted words.
- */
- @Test(groups = { UNIT })
- public void testDoubleQuotedWordsOk() {
- String[] result = split("\"hello\" \"world\"");
- assertArrayEquals(new String[] { "\"hello\"", "\"world\"" }, result);
- }
-
- /**
- * Test double quoted words omit quotes.
- */
- @Test(groups = { UNIT })
- public void testDoubleQuotedWordsOmitQuotesOk() {
- String[] result = split("\"hello\" \"world\"", false /* includeQuotes */);
- assertArrayEquals(new String[] { "hello", "world" }, result);
- }
-
- /**
- * Test escaped backslash in string.
- */
- @Test(groups = { UNIT })
- public void testEscapedBackslashInStringOk() {
- String[] result = split("hello\\\\ world");
- assertArrayEquals(new String[] { "hello\\", "world" }, result);
- }
-
- /**
- * Test escaped backslash string in double quotes.
- */
- @Test(groups = { UNIT })
- public void testEscapedBackslashStringInDoubleQuotesOk() {
- String[] result = split("\"hello\\\\ world\"");
- assertArrayEquals(new String[] { "\"hello\\ world\"" }, result);
- }
-
- /**
- * Test escaped double quoted in single quoted string.
- */
- @Test(groups = { UNIT })
- public void testEscapedDoubleQuotedInSingleQuotedStringOk() {
- String[] result = split("'\"hello world\"'");
- assertArrayEquals(new String[] { "'\"hello world\"'" }, result);
- }
-
- /**
- * Test escaped double quoted string.
- */
- @Test(groups = { UNIT })
- public void testEscapedDoubleQuotedStringOk() {
- String[] result = split("\\\"hello world\\\"");
- assertArrayEquals(new String[] { "\"hello", "world\"" }, result);
- }
-
- /**
- * Test escaped key value pair.
- */
- @Test(groups = { UNIT })
- public void testEscapedKeyValuePairOk() {
- String[] result = split("key=\\'qux qoo\\'");
- assertArrayEquals(new String[] { "key='qux", "qoo'" }, result);
- }
-
- /**
- * Test escaped single quoted in double quoted string.
- */
- @Test(groups = { UNIT })
- public void testEscapedSingleQuotedInDoubleQuotedStringOk() {
- String[] result = split("\"\\'hello world\\'\"");
- assertArrayEquals(new String[] { "\"'hello world'\"" }, result);
- }
-
- /**
- * Test escaped single quoted string.
- */
- @Test(groups = { UNIT })
- public void testEscapedSingleQuotedStringOk() {
- String[] result = split("\\'hello world\\'");
- assertArrayEquals(new String[] { "\'hello", "world\'" }, result);
- }
-
- /**
- * Test escaped space string in double quotes.
- */
- @Test(groups = { UNIT })
- public void testEscapedSpaceStringInDoubleQuotesOk() {
- String[] result = split("\"hello\\ world\"");
- assertArrayEquals(new String[] { "\"hello world\"" }, result);
- }
-
- /**
- * Test escaped space string.
- */
- @Test(groups = { UNIT })
- public void testEscapedSpaceStringOk() {
- String[] result = split("hello\\ world");
- assertArrayEquals(new String[] { "hello world" }, result);
- }
-
- /**
- * Test key value pair in double quotes.
- */
- @Test(groups = { UNIT })
- public void testKeyValuePairInDoubleQuotesOk() {
- String[] result = split("\"key=\\\"qux qoo\\\"\"");
- assertArrayEquals(new String[] { "\"key=\"qux qoo\"\"" }, result);
- }
-
- /**
- * Test key value pair.
- */
- @Test(groups = { UNIT })
- public void testKeyValuePairOk() {
- String[] result = split("key='qux qoo'");
- assertArrayEquals(new String[] { "key='qux qoo'" }, result);
- }
-
- /**
- * Test os gi import package value.
- */
- @Test(groups = { UNIT })
- public void testOSGiImportPackageValueOk() {
- String[] result = split("\"org.foo.bar;version=\"1\",org.qux.quu;version=\"2\"\"");
- assertArrayEquals(new String[] { "\"org.foo.bar;version=\"1\",org.qux.quu;version=\"2\"\"" }, result);
- }
-
- /**
- * Test single quoted string.
- */
- @Test(groups = { UNIT })
- public void testSingleQuotedStringOk() {
- String[] result = split("'hello world'");
- assertArrayEquals(new String[] { "'hello world'" }, result);
- }
-
- /**
- * Test single quoted words.
- */
- @Test(groups = { UNIT })
- public void testSingleQuotedWordsOk() {
- String[] result = split("'hello' 'world'");
- assertArrayEquals(new String[] { "'hello'", "'world'" }, result);
- }
-
- /**
- * Test single quoted words omit quotes.
- */
- @Test(groups = { UNIT })
- public void testSingleQuotedWordsOmitQuotesOk() {
- String[] result = split("'hello' 'world'", false /* includeQuotes */);
- assertArrayEquals(new String[] { "hello", "world" }, result);
- }
-
- /**
- * Test split empty string.
- */
- @Test(groups = { UNIT })
- public void testSplitEmptyStringOk() {
- String[] result = split("");
- assertArrayEquals(new String[0], result);
- }
-
- /**
- * Test split null value.
- */
- @Test(groups = { UNIT })
- public void testSplitNullValueOk() {
- String[] result = split(null);
- assertArrayEquals(new String[0], result);
- }
-
- /**
- * Test split on tab.
- */
- @Test(groups = { UNIT })
- public void testSplitOnTabOk() {
- String[] result = split("hello\tworld");
- assertArrayEquals(new String[] { "hello", "world" }, result);
- }
-
- /**
- * Test split whitespaces only.
- */
- @Test(groups = { UNIT })
- public void testSplitWhitespacesOnlyOk() {
- String[] result = split(" \t ");
- assertArrayEquals(new String[0], result);
- }
-
- /**
- * Test unquoted command line argument.
- */
- @Test(groups = { UNIT })
- public void testUnquotedCommandLineArgumentOk() {
- String[] result =
- split("fwOption=org.osgi.framework.system.packages.extra=org.w3c.dom.tral,org.w3c.dom.html,org.w3c.dom.ranges,sun.reflect,org.osgi.service.deploymentadmin;version=\"1.0\",org.osgi.service.deploymentadmin.spi;version=\"1.0\",org.osgi.service.cm;version=\"1.3\",org.osgi.service.event;version=\"1.2\",org.osgi.service.log;version=\"1.3\",org.osgi.service.metatype;version=\"1.1\",org.apache.ace.log;version=\"0.8.0\"");
- assertArrayEquals(
- new String[] { "fwOption=org.osgi.framework.system.packages.extra=org.w3c.dom.tral,org.w3c.dom.html,org.w3c.dom.ranges,sun.reflect,org.osgi.service.deploymentadmin;version=\"1.0\",org.osgi.service.deploymentadmin.spi;version=\"1.0\",org.osgi.service.cm;version=\"1.3\",org.osgi.service.event;version=\"1.2\",org.osgi.service.log;version=\"1.3\",org.osgi.service.metatype;version=\"1.1\",org.apache.ace.log;version=\"0.8.0\"" },
- result);
- }
-
- /**
- * Test unquoted string.
- */
- @Test(groups = { UNIT })
- public void testUnquotedStringOk() {
- String[] result = split("hello world");
- assertArrayEquals(new String[] { "hello", "world" }, result);
- }
-
- /**
- * Assert array equals.
- *
- * @param expected the expected
- * @param actual the actual
- */
- private void assertArrayEquals(Object[] expected, Object[] actual) {
- assertEquals(expected.length, actual.length);
- for (int i = 0; i < expected.length; i++) {
- assertEquals(expected[i], actual[i]);
- }
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/TestUtil.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/TestUtil.java
deleted file mode 100644
index 3db79a4..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/TestUtil.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.impl;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-
-/**
- * Provides some convenience methods commonly used in the unit tests of ace-launcher.
- */
-public final class TestUtil {
-
- /**
- * Creates a new {@link TestUtil} instance, not used.
- */
- private TestUtil() {
- // No-op
- }
-
- /**
- * Returns the name of the running operating system.
- *
- * @return the OS-name, in lower case.
- */
- public static String getOSName() {
- return System.getProperty("os.name", "").toLowerCase();
- }
-
- /**
- * Obtains the file denoted by the given path as resource, and treats it as properties file.
- *
- * @param path the path to the resource to load, cannot be <code>null</code>.
- * @return a properties file, never <code>null</code>.
- * @throws IOException in case of I/O problems reading the properties file;
- * @throws RuntimeException in case the given path is not a valid resource file.
- */
- public static Properties getProperties(String path) throws IOException {
- InputStream is = TestUtil.class.getResourceAsStream(path);
- if (is == null) {
- throw new RuntimeException("File not found: " + path);
- }
- try {
- Properties props = new Properties();
- props.load(is);
- return props;
- }
- finally {
- is.close();
- }
- }
-
- /**
- * Sleeps for a given amount of milliseconds.
- *
- * @param delayInMillis the delay to sleep, in milliseconds.
- */
- public static void sleep(int delayInMillis) {
- try {
- Thread.sleep(delayInMillis);
- }
- catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- /**
- * Reads an entire file denoted by the given argument and returns its content as string.
- *
- * @param file the file to read, cannot be <code>null</code>.
- * @return the file contents, never <code>null</code>.
- * @throws IOException in case of I/O problems reading the file.
- */
- public static String slurpFile(File file) throws IOException {
- StringBuilder sb = new StringBuilder();
- FileReader fr = new FileReader(file);
- int ch;
- try {
- while ((ch = fr.read()) >= 0) {
- sb.append((char) ch);
- }
- }
- finally {
- fr.close();
- }
- return sb.toString();
- }
-
- /**
- * Creates a unique temporary directory.
- *
- * @return the unique temporary directory
- */
- public static File createTempDir() throws IOException {
-
- File baseDir = new File(System.getProperty("java.io.tmpdir"));
- String baseName = System.currentTimeMillis() + "-";
-
- for (int counter = 0; counter < 1000; counter++) {
- File tempDir = new File(baseDir, baseName + counter);
- if (tempDir.mkdir()) {
- return tempDir;
- }
- }
- throw new IOException("Failed to create tmp directory");
- }
-}
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/launch.properties b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/launch.properties
deleted file mode 100644
index fe21626..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/impl/launch.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-instance.count = 2
-executable.name = /bin/sh
-executable.args = -c 'sleep 1 && exit' -c 'echo "foo bar!\n"'
-executable.executable.processStreamListener = (foo=bar)
-executable.workingDir = /tmp
-executable.respawnAutomatically = false
-
-# Licensed to the Apache Software Foundation (ASF) under the terms of ASLv2 (http://www.apache.org/licenses/LICENSE-2.0).
\ No newline at end of file
diff --git a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/util/InputStreamRedirectorTest.java b/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/util/InputStreamRedirectorTest.java
deleted file mode 100644
index 412f1a6..0000000
--- a/org.apache.ace.processlauncher/test/org/apache/ace/processlauncher/test/util/InputStreamRedirectorTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.
- */
-package org.apache.ace.processlauncher.test.util;
-
-import static org.apache.ace.processlauncher.test.impl.TestUtil.sleep;
-import static org.apache.ace.test.utils.TestUtils.UNIT;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.ace.processlauncher.util.InputStreamRedirector;
-import org.mockito.Mockito;
-import org.testng.annotations.Test;
-
-/**
- * Test cases for {@link InputStreamRedirector}.
- */
-public class InputStreamRedirectorTest {
-
- /**
- * Tests that when an EOF is read on the input stream, the output stream is closed as well.
- *
- * @throws IOException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testInputStreamEOFCausesOutputStreamToBeClosedOk() throws IOException {
- InputStream myIS = new ByteArrayInputStream("hello world!".getBytes());
- OutputStream mockOS = mock(OutputStream.class);
-
- InputStreamRedirector redirector = new InputStreamRedirector(myIS, mockOS);
- redirector.run();
-
- verify(mockOS).close();
- }
-
- /**
- * Tests that the input stream is 1:1 copied to the given output stream.
- *
- * @throws IOException not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testInputStreamIsVerbatimelyCopiedToOutputStreamOk() throws IOException {
- String input = "hello world!";
-
- InputStream myIS = new ByteArrayInputStream(input.getBytes());
- ByteArrayOutputStream myOS = new ByteArrayOutputStream();
-
- InputStreamRedirector redirector = new InputStreamRedirector(myIS, myOS);
- redirector.run();
-
- assertEquals(input, myOS.toString());
- }
-
- /**
- * Tests that we can interrupt a redirector and that it ceases its work.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testInterruptRedirectorOk() throws Exception {
- InputStream myIS = createBlockingInputStream();
- OutputStream myOS = mock(OutputStream.class);
-
- InputStreamRedirector redirector = new InputStreamRedirector(myIS, myOS);
-
- Thread redirectorThread = new Thread(redirector);
- redirectorThread.start();
-
- // Sleep for a little while to ensure everything is up and running...
- sleep(100);
-
- redirectorThread.interrupt();
-
- // Wait until the thread is really finished...
- redirectorThread.join(1000);
-
- verify(myIS, atLeast(1)).read(Mockito.<byte[]>any(), anyInt(), anyInt());
- verify(myOS).close();
- }
-
- /**
- * Tests that we can recover when the input stream throws an I/O exception.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testRecoverFromExceptionInInputStreamWithoutOutputStreamOk() throws Exception {
- InputStream myIS = createExceptionThrowingInputStream();
- ByteArrayOutputStream myOS = new ByteArrayOutputStream();
-
- InputStreamRedirector redirector = new InputStreamRedirector(myIS, myOS);
-
- redirector.run();
-
- verify(myIS, atLeast(1)).read(Mockito.<byte[]>any(), anyInt(), anyInt());
-
- // Verify that the exception is indeed logged...
- String stdout = myOS.toString();
-
- assertTrue(stdout.contains("IGNORE ME! TEST EXCEPTION!"));
- }
-
- /**
- * Tests that we can recover when the input stream throws an I/O exception.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testRecoverFromExceptionInInputStreamWithOutputStreamOk() throws Exception {
- InputStream myIS = createExceptionThrowingInputStream();
- OutputStream myOS = mock(OutputStream.class);
-
- InputStreamRedirector redirector = new InputStreamRedirector(myIS, myOS);
-
- redirector.run();
-
- verify(myIS, atLeast(1)).read(Mockito.<byte[]>any(), anyInt(), anyInt());
- verify(myOS).close();
- }
-
- /**
- * Tests that we can recover when the input stream throws an I/O exception.
- *
- * @throws Exception not part of this test case.
- */
- @Test(groups = { UNIT })
- public void testWithoutOutputStreamOk() throws Exception {
- InputStream myIS = new ByteArrayInputStream("hello world!".getBytes());
-
- InputStreamRedirector redirector = new InputStreamRedirector(myIS);
-
- redirector.run();
- }
-
- /**
- * Creates an input stream that keeps pretending its returning data when its
- * {@link InputStream#read(byte[])} method is called.
- *
- * @return a mocked {@link InputStream} instance, never <code>null</code>.
- */
- private InputStream createBlockingInputStream() throws IOException {
- InputStream is = mock(InputStream.class);
- when(is.read(Mockito.<byte[]>any(), anyInt(), anyInt())).thenReturn(Integer.valueOf(10));
- return is;
- }
-
- /**
- * Creates an input stream that keeps pretending its returning data when its
- * {@link InputStream#read(byte[])} method is called.
- *
- * @return a mocked {@link InputStream} instance, never <code>null</code>.
- */
- private InputStream createExceptionThrowingInputStream() throws IOException {
- InputStream is = mock(InputStream.class);
- when(is.read(Mockito.<byte[]>any(), anyInt(), anyInt())).thenThrow(
- new IOException("IGNORE ME! TEST EXCEPTION!"));
- return is;
- }
-}