Skip to content

Commit

Permalink
fix #4 kill existing office process before start
Browse files Browse the repository at this point in the history
if killExistingProcess is on.
  • Loading branch information
buzztaiki committed Jan 22, 2015
1 parent a1e6973 commit 8e7903d
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class DefaultOfficeManagerConfiguration {
private long retryTimeout = DEFAULT_RETRY_TIMEOUT;
private OutputStream redirectStdout;
private OutputStream redirectStderr;
private boolean killExistingProcess;

private ProcessManager processManager = null; // lazily initialised

Expand Down Expand Up @@ -169,6 +170,14 @@ public DefaultOfficeManagerConfiguration setRedirectStderr(OutputStream redirect
return this;
}

/**
* Kill exising office process before start.
*/
public DefaultOfficeManagerConfiguration setKillExistingProcess(boolean killExistingProcess) {
this.killExistingProcess = killExistingProcess;
return this;
}

public OfficeManager buildOfficeManager() throws IllegalStateException {
if (officeHome == null) {
throw new IllegalStateException("officeHome not set and could not be auto-detected");
Expand All @@ -193,7 +202,7 @@ public OfficeManager buildOfficeManager() throws IllegalStateException {
for (int i = 0; i < numInstances; i++) {
unoUrls[i] = (connectionProtocol == OfficeConnectionProtocol.PIPE) ? UnoUrl.pipe(pipeNames[i]) : UnoUrl.socket(portNumbers[i]);
}
return new ProcessPoolOfficeManager(officeHome, unoUrls, runAsArgs, templateProfileDir, workDir, retryTimeout, taskQueueTimeout, taskExecutionTimeout, maxTasksPerProcess, processManager, redirectStdout, redirectStderr);
return new ProcessPoolOfficeManager(officeHome, unoUrls, runAsArgs, templateProfileDir, workDir, retryTimeout, taskQueueTimeout, taskExecutionTimeout, maxTasksPerProcess, processManager, redirectStdout, redirectStderr, killExistingProcess);
}

private ProcessManager findBestProcessManager() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ public ManagedOfficeProcess(ManagedOfficeProcessSettings settings) throws Office
// for unit test
ManagedOfficeProcess(ManagedOfficeProcessSettings settings, String[] overrideArgs) throws OfficeException {
this.settings = settings;
process = new OfficeProcess(settings.getOfficeHome(), settings.getUnoUrl(), settings.getRunAsArgs(), settings.getTemplateProfileDir(), settings.getWorkDir(), settings
.getProcessManager(), settings.getRedirectStdout(), settings.getRedirectStderr(), overrideArgs);
process = new OfficeProcess(
settings.getOfficeHome(), settings.getUnoUrl(), settings.getRunAsArgs(), settings.getTemplateProfileDir(), settings.getWorkDir(),
settings.getProcessManager(), settings.getRedirectStdout(), settings.getRedirectStderr(), settings.isKillExistingProcess(), overrideArgs);
connection = new OfficeConnection(settings.getUnoUrl());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ManagedOfficeProcessSettings {
private long retryInterval = DEFAULT_RETRY_INTERVAL;
private OutputStream redirectStdout;
private OutputStream redirectStderr;
private boolean killExistingProcess;

public ManagedOfficeProcessSettings(UnoUrl unoUrl) {
this.unoUrl = unoUrl;
Expand Down Expand Up @@ -112,4 +113,12 @@ public void setRedirectStderr(OutputStream redirectStderr) {
public OutputStream getRedirectStderr() {
return redirectStderr;
}

public void setKillExistingProcess(boolean killExistingProcess) {
this.killExistingProcess = killExistingProcess;
}

public boolean isKillExistingProcess() {
return killExistingProcess;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class OfficeProcess {
private final ProcessManager processManager;
private final OutputStream stdout;
private final OutputStream stderr;
private final boolean killExistingProcess;
private final String[] overrideArgs;

private Process process;
Expand All @@ -49,7 +50,7 @@ class OfficeProcess {

private final Logger logger = Logger.getLogger(getClass().getName());

public OfficeProcess(File officeHome, UnoUrl unoUrl, String[] runAsArgs, File templateProfileDir, File workDir, ProcessManager processManager, OutputStream stdout, OutputStream stderr, String[] overrideArgs) {
public OfficeProcess(File officeHome, UnoUrl unoUrl, String[] runAsArgs, File templateProfileDir, File workDir, ProcessManager processManager, OutputStream stdout, OutputStream stderr, boolean killExistingProcess, String[] overrideArgs) {
this.officeHome = officeHome;
this.unoUrl = unoUrl;
this.runAsArgs = runAsArgs;
Expand All @@ -58,20 +59,35 @@ public OfficeProcess(File officeHome, UnoUrl unoUrl, String[] runAsArgs, File te
this.processManager = processManager;
this.stdout = stdout;
this.stderr = stderr;
this.killExistingProcess = killExistingProcess;
this.overrideArgs = overrideArgs;
}

public void start() throws IOException {
start(false);
}

public void start(boolean restart) throws IOException {
ProcessQuery processQuery = new ProcessQuery("soffice.bin", unoUrl.getAcceptString());
private void checkExistingProcess(ProcessQuery processQuery) throws IOException {
long existingPid = processManager.findPid(processQuery);
if (!(existingPid == PID_NOT_FOUND || existingPid == PID_UNKNOWN)) {
throw new IllegalStateException(String.format("a process with acceptString '%s' is already running; pid %d",
unoUrl.getAcceptString(), existingPid));
if (!(existingPid == PID_NOT_FOUND || existingPid == PID_UNKNOWN) && killExistingProcess) {
logger.warning(String.format("a process with acceptString '%s' is already running; pid %d", unoUrl.getAcceptString(), existingPid));
processManager.kill(null, existingPid);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
existingPid = processManager.findPid(processQuery);
}
if (!(existingPid == PID_NOT_FOUND || existingPid == PID_UNKNOWN)) {
throw new IllegalStateException(
String.format("a process with acceptString '%s' is already running; pid %d", unoUrl.getAcceptString(), existingPid));
}
}

public void start(boolean restart) throws IOException {
ProcessQuery processQuery = new ProcessQuery("soffice.bin", unoUrl.getAcceptString());
checkExistingProcess(processQuery);
if (!restart) {
prepareInstanceProfileDir();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class ProcessPoolOfficeManager implements OfficeManager {

public ProcessPoolOfficeManager(File officeHome, UnoUrl[] unoUrls, String[] runAsArgs, File templateProfileDir, File workDir,
long retryTimeout, long taskQueueTimeout, long taskExecutionTimeout, int maxTasksPerProcess,
ProcessManager processManager, OutputStream redirectStdout, OutputStream redirectStderr) {
ProcessManager processManager, OutputStream redirectStdout, OutputStream redirectStderr, boolean killExistingProcess) {
this.taskQueueTimeout = taskQueueTimeout;
pool = new ArrayBlockingQueue<PooledOfficeManager>(unoUrls.length);
pooledManagers = new PooledOfficeManager[unoUrls.length];
Expand All @@ -49,6 +49,7 @@ public ProcessPoolOfficeManager(File officeHome, UnoUrl[] unoUrls, String[] runA
settings.setProcessManager(processManager);
settings.setRedirectStdout(redirectStdout);
settings.setRedirectStderr(redirectStderr);
settings.setKillExistingProcess(killExistingProcess);
pooledManagers[i] = new PooledOfficeManager(settings);
}
logger.info("ProcessManager implementation is " + processManager.getClass().getSimpleName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class ExternalOfficeManagerTest {
public void executeTask() throws Exception {
UnoUrl unoUrl = UnoUrl.socket(2002);
OfficeProcess officeProcess = new OfficeProcess(OfficeUtils.getDefaultOfficeHome(), unoUrl,
null, null, new File(System.getProperty("java.io.tmpdir")), new PureJavaProcessManager(), null, null, null);
null, null, new File(System.getProperty("java.io.tmpdir")), new PureJavaProcessManager(), null, null, false, null);
officeProcess.start();
Thread.sleep(2000);
Integer exitCode = officeProcess.getExitCode();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//
// JODConverter - Java OpenDocument Converter
// Copyright 2004-2012 Mirko Nasato and contributors
//
// JODConverter is Open Source software, you can redistribute it and/or
// modify it under either (at your option) of the following licenses
//
// 1. The GNU Lesser General Public License v3 (or later)
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
// 2. The Apache License, Version 2.0
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
//
package org.artofsolving.jodconverter.office;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.charset.Charset;

import org.artofsolving.jodconverter.ReflectionUtils;
import org.artofsolving.jodconverter.process.LinuxProcessManager;
import org.artofsolving.jodconverter.process.ProcessManager;
import org.artofsolving.jodconverter.process.ProcessQuery;
import org.artofsolving.jodconverter.util.PlatformUtils;
import org.testng.SkipException;
import org.testng.annotations.Test;

@Test
public class OfficeProcessTest {

public void dontShowWarnings() throws IOException {
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
ManagedOfficeProcessSettings settings = new ManagedOfficeProcessSettings(UnoUrl.socket(2022));
settings.setRedirectStdout(stdout);
settings.setRedirectStderr(stderr);
ManagedOfficeProcess proc = new ManagedOfficeProcess(settings);
try {
proc.startAndWait();
} finally {
proc.stopAndWait();
}
assertEquals(stdout.toByteArray(), new byte[0]);
assertEquals(stderr.toByteArray(), new byte[0]);
}

public void pumpOutput() throws IOException, InterruptedException {
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
ManagedOfficeProcessSettings settings = new ManagedOfficeProcessSettings(UnoUrl.socket(2022));
settings.setRedirectStdout(stdout);
settings.setRedirectStderr(stderr);
ManagedOfficeProcess proc = new ManagedOfficeProcess(settings, new String[]{"--version", "--headless"});
try {
proc.startAndWait();
} catch (OfficeException e) {
// ignore
} finally {
proc.stopAndWait();
}

String executable = OfficeUtils.getOfficeExecutable(OfficeUtils.getDefaultOfficeHome()).getAbsolutePath();
Process expected = new ProcessBuilder(executable, "--version", "--headless").start();
expected.waitFor();

assertEquals(stdout.toByteArray(), readFully(expected.getInputStream()));
assertEquals(stderr.toByteArray(), readFully(expected.getErrorStream()));
}

public void foundExistingProcessAndKill_Linux() throws Exception {
if (!PlatformUtils.isLinux()) {
throw new SkipException("LinuxProcessManager can only be tested on Linux");
}

UnoUrl unoUrl = UnoUrl.socket(2022);
ProcessQuery processQuery = new ProcessQuery("soffice.bin", unoUrl.getAcceptString());
ManagedOfficeProcessSettings settings = new ManagedOfficeProcessSettings(unoUrl);
settings.setProcessManager(new LinuxProcessManager());
settings.setKillExistingProcess(true);
ManagedOfficeProcess proc = new ManagedOfficeProcess(settings);
try {
proc.startAndWait();

long procPid = settings.getProcessManager().findPid(processQuery);
assertNotEquals(procPid, ProcessManager.PID_NOT_FOUND);
assertNotEquals(procPid, ProcessManager.PID_UNKNOWN);

ManagedOfficeProcess proc2 = new ManagedOfficeProcess(settings);
try {
proc2.startAndWait();
long proc2Pid = settings.getProcessManager().findPid(processQuery);
assertNotEquals(proc2Pid, ProcessManager.PID_NOT_FOUND);
assertNotEquals(proc2Pid, ProcessManager.PID_UNKNOWN);
assertFalse(((OfficeProcess) ReflectionUtils.getPrivateField(proc, "process")).isRunning());
} finally {
proc2.stopAndWait();
}

} finally {
proc.stopAndWait();
}
}

public void foundExistingProcessAndError_Linux() throws Exception {
if (!PlatformUtils.isLinux()) {
throw new SkipException("LinuxProcessManager can only be tested on Linux");
}

UnoUrl unoUrl = UnoUrl.socket(2022);
ProcessQuery processQuery = new ProcessQuery("soffice.bin", unoUrl.getAcceptString());
ManagedOfficeProcessSettings settings = new ManagedOfficeProcessSettings(unoUrl);
settings.setProcessManager(new LinuxProcessManager());
settings.setKillExistingProcess(false);
ManagedOfficeProcess proc = new ManagedOfficeProcess(settings);
try {
proc.startAndWait();

long procPid = settings.getProcessManager().findPid(processQuery);
assertNotEquals(procPid, ProcessManager.PID_NOT_FOUND);
assertNotEquals(procPid, ProcessManager.PID_UNKNOWN);

ManagedOfficeProcess proc2 = new ManagedOfficeProcess(settings);
try {
proc2.startAndWait();
fail();
} catch (OfficeException e) {
// ok
} finally {
try {
proc2.stopAndWait();
} catch (Exception e) {}
}

} finally {
proc.stopAndWait();
}
}

private static byte[] readFully(InputStream in) throws IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
for (int n = in.read(); n >= 0; n = in.read()) {
bytes.write(n);
}
return bytes.toByteArray();
}
}

0 comments on commit 8e7903d

Please sign in to comment.