--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.application.process;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
+
+abstract class AbstractProcessMonitor implements ProcessMonitor {
+ protected final Process process;
+
+ protected AbstractProcessMonitor(Process process) {
+ this.process = process;
+ }
+
+ public InputStream getInputStream() {
+ return process.getInputStream();
+ }
+
+ public void closeStreams() {
+ closeQuietly(process.getInputStream());
+ closeQuietly(process.getOutputStream());
+ closeQuietly(process.getErrorStream());
+ }
+
+ private static void closeQuietly(@Nullable Closeable closeable) {
+ try {
+ if (closeable != null) {
+ closeable.close();
+ }
+ } catch (IOException ignored) {
+ // ignore
+ }
+ }
+
+ public boolean isAlive() {
+ return process.isAlive();
+ }
+
+ public void destroyForcibly() {
+ process.destroyForcibly();
+ }
+
+ public void waitFor() throws InterruptedException {
+ process.waitFor();
+ }
+
+ public void waitFor(long timeout, TimeUnit unit) throws InterruptedException {
+ process.waitFor(timeout, unit);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.application.process;
+
+import org.sonar.process.ProcessCommands;
+
+import static java.util.Objects.requireNonNull;
+
+class ProcessCommandsProcessMonitor extends AbstractProcessMonitor {
+
+ private final ProcessCommands commands;
+
+ ProcessCommandsProcessMonitor(Process process, ProcessCommands commands) {
+ super(process);
+ this.commands = requireNonNull(commands, "commands can't be null");
+ }
+
+ /**
+ * Whether the process has set the operational flag (in ipc shared memory)
+ */
+ @Override
+ public boolean isOperational() {
+ return commands.isOperational();
+ }
+
+ /**
+ * Send request to gracefully stop to the process (via ipc shared memory)
+ */
+ @Override
+ public void askForStop() {
+ commands.askForStop();
+ }
+
+ /**
+ * Whether the process asked for a full restart (via ipc shared memory)
+ */
+ @Override
+ public boolean askedForRestart() {
+ return commands.askedForRestart();
+ }
+
+ /**
+ * Removes the flag in ipc shared memory so that next call to {@link #askedForRestart()}
+ * returns {@code false}, except if meanwhile process asks again for restart.
+ */
+ @Override
+ public void acknowledgeAskForRestart() {
+ commands.acknowledgeAskForRestart();
+ }
+
+}
ProcessBuilder processBuilder = create(javaCommand);
LOG.info("Launch process[{}]: {}", javaCommand.getProcessId().getKey(), String.join(" ", processBuilder.command()));
process = processBuilder.start();
- return new ProcessMonitorImpl(process, commands);
+ return new ProcessCommandsProcessMonitor(process, commands);
} catch (Exception e) {
// just in case
void waitFor(long timeout, TimeUnit timeoutUnit) throws InterruptedException;
/**
- * Whether the process has set the operational flag (in ipc shared memory)
+ * Whether the process has reach operational state after startup.
*/
boolean isOperational();
/**
- * Send request to gracefully stop to the process (via ipc shared memory)
+ * Send request to gracefully stop to the process
*/
void askForStop();
/**
- * Whether the process asked for a full restart (via ipc shared memory)
+ * Whether the process asked for a full restart
*/
boolean askedForRestart();
/**
- * Removes the flag in ipc shared memory so that next call to {@link #askedForRestart()}
- * returns {@code false}, except if meanwhile process asks again for restart.
+ * Sends a signal to the process to acknowledge that the parent process received the request to restart from the
+ * child process send via {@link #askedForRestart()}.
+ * <br/>
+ * Child process will typically stop sending the signal requesting restart from now on.
*/
void acknowledgeAskForRestart();
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.application.process;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.TimeUnit;
-import javax.annotation.Nullable;
-import org.sonar.process.ProcessCommands;
-
-import static java.util.Objects.requireNonNull;
-
-class ProcessMonitorImpl implements ProcessMonitor {
-
- private final Process process;
- private final ProcessCommands commands;
-
- ProcessMonitorImpl(Process process, ProcessCommands commands) {
- this.process = requireNonNull(process, "process can't be null");
- this.commands = requireNonNull(commands, "commands can't be null");
- }
-
- @Override
- public InputStream getInputStream() {
- return process.getInputStream();
- }
-
- @Override
- public void closeStreams() {
- closeQuietly(process.getInputStream());
- closeQuietly(process.getOutputStream());
- closeQuietly(process.getErrorStream());
- }
-
- @Override
- public boolean isAlive() {
- return process.isAlive();
- }
-
- @Override
- public void destroyForcibly() {
- process.destroyForcibly();
- }
-
- @Override
- public void waitFor() throws InterruptedException {
- process.waitFor();
- }
-
- @Override
- public void waitFor(long timeout, TimeUnit unit) throws InterruptedException {
- process.waitFor(timeout, unit);
- }
-
- @Override
- public boolean isOperational() {
- return commands.isOperational();
- }
-
- @Override
- public void askForStop() {
- commands.askForStop();
- }
-
- @Override
- public boolean askedForRestart() {
- return commands.askedForRestart();
- }
-
- @Override
- public void acknowledgeAskForRestart() {
- commands.acknowledgeAskForRestart();
- }
-
- private static void closeQuietly(@Nullable Closeable closeable) {
- try {
- if (closeable != null) {
- closeable.close();
- }
- } catch (IOException ignored) {
- // ignore
- }
- }
-
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.application.process;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.sonar.process.ProcessCommands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+public class ProcessCommandsProcessMonitorTest {
+
+ @Test
+ public void ProcessMonitorImpl_is_a_proxy_of_Process() throws Exception {
+ Process process = mock(Process.class, RETURNS_DEEP_STUBS);
+ ProcessCommands commands = mock(ProcessCommands.class, RETURNS_DEEP_STUBS);
+
+ ProcessCommandsProcessMonitor underTest = new ProcessCommandsProcessMonitor(process, commands);
+
+ underTest.waitFor();
+ verify(process).waitFor();
+
+ underTest.closeStreams();
+ verify(process.getErrorStream()).close();
+ verify(process.getInputStream()).close();
+ verify(process.getOutputStream()).close();
+
+ underTest.destroyForcibly();
+ verify(process).destroyForcibly();
+
+ assertThat(underTest.getInputStream()).isNotNull();
+
+ underTest.isAlive();
+ verify(process).isAlive();
+
+ underTest.waitFor(123, TimeUnit.MILLISECONDS);
+ verify(process).waitFor(123, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void ProcessMonitorImpl_is_a_proxy_of_Commands() throws Exception {
+ Process process = mock(Process.class, RETURNS_DEEP_STUBS);
+ ProcessCommands commands = mock(ProcessCommands.class, RETURNS_DEEP_STUBS);
+
+ ProcessCommandsProcessMonitor underTest = new ProcessCommandsProcessMonitor(process, commands);
+
+ underTest.askForStop();
+ verify(commands).askForStop();
+
+ underTest.acknowledgeAskForRestart();
+ verify(commands).acknowledgeAskForRestart();
+
+ underTest.askedForRestart();
+ verify(commands).askedForRestart();
+
+ underTest.isOperational();
+ verify(commands).isOperational();
+ }
+
+ @Test
+ public void closeStreams_ignores_null_stream() {
+ ProcessCommands commands = mock(ProcessCommands.class);
+ Process process = mock(Process.class);
+ when(process.getInputStream()).thenReturn(null);
+
+ ProcessCommandsProcessMonitor underTest = new ProcessCommandsProcessMonitor(process, commands);
+
+ // no failures
+ underTest.closeStreams();
+ }
+
+ @Test
+ public void closeStreams_ignores_failure_if_stream_fails_to_be_closed() throws Exception {
+ InputStream stream = mock(InputStream.class);
+ doThrow(new IOException("error")).when(stream).close();
+ Process process = mock(Process.class);
+ when(process.getInputStream()).thenReturn(stream);
+
+ ProcessCommandsProcessMonitor underTest = new ProcessCommandsProcessMonitor(process, mock(ProcessCommands.class, Mockito.RETURNS_MOCKS));
+
+ // no failures
+ underTest.closeStreams();
+ }
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.application.process;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.TimeUnit;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.sonar.application.process.ProcessMonitorImpl;
-import org.sonar.process.ProcessCommands;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-
-public class ProcessMonitorImplTest {
-
- @Test
- public void ProcessMonitorImpl_is_a_proxy_of_Process() throws Exception {
- Process process = mock(Process.class, RETURNS_DEEP_STUBS);
- ProcessCommands commands = mock(ProcessCommands.class, RETURNS_DEEP_STUBS);
-
- ProcessMonitorImpl underTest = new ProcessMonitorImpl(process, commands);
-
- underTest.waitFor();
- verify(process).waitFor();
-
- underTest.closeStreams();
- verify(process.getErrorStream()).close();
- verify(process.getInputStream()).close();
- verify(process.getOutputStream()).close();
-
- underTest.destroyForcibly();
- verify(process).destroyForcibly();
-
- assertThat(underTest.getInputStream()).isNotNull();
-
- underTest.isAlive();
- verify(process).isAlive();
-
- underTest.waitFor(123, TimeUnit.MILLISECONDS);
- verify(process).waitFor(123, TimeUnit.MILLISECONDS);
- }
-
- @Test
- public void ProcessMonitorImpl_is_a_proxy_of_Commands() throws Exception {
- Process process = mock(Process.class, RETURNS_DEEP_STUBS);
- ProcessCommands commands = mock(ProcessCommands.class, RETURNS_DEEP_STUBS);
-
- ProcessMonitorImpl underTest = new ProcessMonitorImpl(process, commands);
-
- underTest.askForStop();
- verify(commands).askForStop();
-
- underTest.acknowledgeAskForRestart();
- verify(commands).acknowledgeAskForRestart();
-
- underTest.askedForRestart();
- verify(commands).askedForRestart();
-
- underTest.isOperational();
- verify(commands).isOperational();
- }
-
- @Test
- public void closeStreams_ignores_null_stream() {
- ProcessCommands commands = mock(ProcessCommands.class);
- Process process = mock(Process.class);
- when(process.getInputStream()).thenReturn(null);
-
- ProcessMonitorImpl underTest = new ProcessMonitorImpl(process, commands);
-
- // no failures
- underTest.closeStreams();
- }
-
- @Test
- public void closeStreams_ignores_failure_if_stream_fails_to_be_closed() throws Exception {
- InputStream stream = mock(InputStream.class);
- doThrow(new IOException("error")).when(stream).close();
- Process process = mock(Process.class);
- when(process.getInputStream()).thenReturn(stream);
-
- ProcessMonitorImpl underTest = new ProcessMonitorImpl(process, mock(ProcessCommands.class, Mockito.RETURNS_MOCKS));
-
- // no failures
- underTest.closeStreams();
- }
-}